1 /******************************************************************************
2  *
3  *  Copyright (C) 2012 Marvell International Ltd.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #define LOG_TAG "bt_vendor_mrvl"
19 
20 #include <time.h>
21 #include <errno.h>
22 #include <sched.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <termios.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <sys/types.h>
32 #include <sys/select.h>
33 #include <sys/mman.h>
34 #include <pthread.h>
35 #include <utils/Log.h>
36 
37 #include "bt_vendor_lib.h"
38 
39 
40 /* ioctl command to release the read thread before driver close */
41 #define MBTCHAR_IOCTL_RELEASE _IO('M', 1)
42 
43 #define VERSION "M002"
44 
45 
46 /***********************************************************
47  *  Externs
48  ***********************************************************
49  */
50 void hw_mrvl_config_start(void);
51 void hw_mrvl_sco_config(void);
52 
53 /***********************************************************
54  *  Local variables
55  ***********************************************************
56  */
57 static const char mchar_port[] = "/dev/mbtchar0";
58 static int mchar_fd = -1;
59 
60 /***********************************************************
61  *  Global variables
62  ***********************************************************
63  */
64 bt_vendor_callbacks_t *vnd_cb;
65 unsigned char bdaddr[6];
66 
67 /***********************************************************
68  *  Local functions
69  ***********************************************************
70  */
bt_vnd_mrvl_if_init(const bt_vendor_callbacks_t * p_cb,unsigned char * local_bdaddr)71 static int bt_vnd_mrvl_if_init(const bt_vendor_callbacks_t *p_cb,
72 		unsigned char *local_bdaddr)
73 {
74 	ALOGI("Marvell BT Vendor Lib: ver %s", VERSION);
75 	vnd_cb = (bt_vendor_callbacks_t *) p_cb;
76 	memcpy(bdaddr, local_bdaddr, sizeof(bdaddr));
77 	return 0;
78 }
79 
bt_vnd_mrvl_if_op(bt_vendor_opcode_t opcode,void * param)80 static int bt_vnd_mrvl_if_op(bt_vendor_opcode_t opcode, void *param)
81 {
82 	int ret = 0;
83 	int *power_state = NULL;
84 	int local_st = 0;
85 
86 	/* ALOGD("opcode = %d", opcode); */
87 	switch (opcode) {
88 	case BT_VND_OP_POWER_CTRL:
89 		power_state = (int *)param;
90 		if (BT_VND_PWR_OFF == *power_state) {
91 			ALOGD("Power off");
92 		} else if (BT_VND_PWR_ON == *power_state) {
93 			ALOGD("Power on");
94 		} else {
95 			ret = -1;
96 		}
97 		break;
98 	case BT_VND_OP_FW_CFG:
99 		hw_mrvl_config_start();
100 		break;
101 	case BT_VND_OP_SCO_CFG:
102 		hw_mrvl_sco_config();
103 		break;
104 	case BT_VND_OP_USERIAL_OPEN:
105 		mchar_fd = open(mchar_port, O_RDWR|O_NOCTTY);
106 		if (mchar_fd < 0) {
107 			ALOGE("Fail to open port %s", mchar_port);
108 			ret = -1;
109 		} else {
110 			ALOGD("open port %s success", mchar_port);
111 			ret = 1;
112 		}
113 		((int *)param)[0] = mchar_fd;
114 		break;
115 	case BT_VND_OP_USERIAL_CLOSE:
116 		if (mchar_fd < 0) {
117 			ret = -1;
118 		} else {
119 			/* mbtchar port is blocked on read. Release the port
120 			 * before we close it.
121 			 */
122 			ioctl(mchar_fd, MBTCHAR_IOCTL_RELEASE, &local_st);
123 			/* Give it sometime before we close the mbtchar */
124 			usleep(1000);
125 			ALOGD("close port %s", mchar_port);
126 			if (close(mchar_fd) < 0) {
127 				ALOGE("Fail to close port %s", mchar_port);
128 				ret = -1;
129 			} else {
130 				mchar_fd = -1; /* closed successfully */
131 			}
132 		}
133 		break;
134 	case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
135 		break;
136 	case BT_VND_OP_LPM_SET_MODE:
137 		/* TODO: Enable or disable LPM mode on BT Controller.
138 		 * ret = xx;
139 		 */
140 		if (vnd_cb)
141 			vnd_cb->lpm_cb(ret);
142 
143 		break;
144 	case BT_VND_OP_LPM_WAKE_SET_STATE:
145 		break;
146 	case BT_VND_OP_EPILOG:
147 		if (vnd_cb)
148 			vnd_cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
149 		break;
150 	default:
151 		ret = -1;
152 		break;
153 	} /* switch (opcode) */
154 
155 	return ret;
156 }
157 
bt_vnd_mrvl_if_cleanup(void)158 static void bt_vnd_mrvl_if_cleanup(void)
159 {
160 	return;
161 }
162 
163 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
164 	sizeof(bt_vendor_interface_t),
165 	bt_vnd_mrvl_if_init,
166 	bt_vnd_mrvl_if_op,
167 	bt_vnd_mrvl_if_cleanup,
168 };
169 
170