• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
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 
19 /******************************************************************************
20  *
21  *  Filename:      userial_mct.c
22  *
23  *  Description:   Contains open/read/write/close functions on multi-channels
24  *
25  ******************************************************************************/
26 
27 #define LOG_TAG "bt_userial_mct"
28 
29 #include <utils/Log.h>
30 #include <pthread.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <sys/socket.h>
35 #include "bt_hci_bdroid.h"
36 #include "userial.h"
37 #include "utils.h"
38 #include "vendor.h"
39 #include "bt_vendor_lib.h"
40 #include "bt_utils.h"
41 
42 /******************************************************************************
43 **  Constants & Macros
44 ******************************************************************************/
45 
46 #define USERIAL_DBG TRUE
47 
48 #ifndef USERIAL_DBG
49 #define USERIAL_DBG FALSE
50 #endif
51 
52 #if (USERIAL_DBG == TRUE)
53 #define USERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
54 #else
55 #define USERIALDBG(param, ...) {}
56 #endif
57 
58 #define MAX_SERIAL_PORT (USERIAL_PORT_3 + 1)
59 
60 enum {
61     USERIAL_RX_EXIT,
62 };
63 
64 /******************************************************************************
65 **  Externs
66 ******************************************************************************/
67 uint16_t hci_mct_receive_evt_msg(void);
68 uint16_t hci_mct_receive_acl_msg(void);
69 
70 
71 /******************************************************************************
72 **  Local type definitions
73 ******************************************************************************/
74 
75 typedef struct
76 {
77     int             fd[CH_MAX];
78     uint8_t         port;
79     pthread_t       read_thread;
80     BUFFER_Q        rx_q;
81     HC_BT_HDR      *p_rx_hdr;
82 } tUSERIAL_CB;
83 
84 /******************************************************************************
85 **  Static variables
86 ******************************************************************************/
87 
88 static tUSERIAL_CB userial_cb;
89 static volatile uint8_t userial_running = 0;
90 
91 /******************************************************************************
92 **  Static functions
93 ******************************************************************************/
94 
95 /*****************************************************************************
96 **   Socket signal functions to wake up userial_read_thread for termination
97 **
98 **   creating an unnamed pair of connected sockets
99 **      - signal_fds[0]: join fd_set in select call of userial_read_thread
100 **      - signal_fds[1]: trigger from userial_close
101 *****************************************************************************/
102 static int signal_fds[2]={0,1};
create_signal_fds(fd_set * set)103 static inline int create_signal_fds(fd_set* set)
104 {
105     if(signal_fds[0]==0 && socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fds)<0)
106     {
107         ALOGE("create_signal_sockets:socketpair failed, errno: %d", errno);
108         return -1;
109     }
110     FD_SET(signal_fds[0], set);
111     return signal_fds[0];
112 }
send_wakeup_signal(char sig_cmd)113 static inline int send_wakeup_signal(char sig_cmd)
114 {
115     return send(signal_fds[1], &sig_cmd, sizeof(sig_cmd), 0);
116 }
reset_signal()117 static inline char reset_signal()
118 {
119     char sig_recv = -1;
120     recv(signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
121     return sig_recv;
122 }
is_signaled(fd_set * set)123 static inline int is_signaled(fd_set* set)
124 {
125     return FD_ISSET(signal_fds[0], set);
126 }
127 
128 /*******************************************************************************
129 **
130 ** Function        userial_evt_read_thread
131 **
132 ** Description     The reading thread on EVT and ACL_IN channels
133 **
134 ** Returns         void *
135 **
136 *******************************************************************************/
userial_read_thread(void * arg)137 static void *userial_read_thread(void *arg)
138 {
139     UNUSED(arg);
140 
141     fd_set input;
142     int n;
143     char reason = 0;
144 
145     USERIALDBG("Entering userial_read_thread()");
146 
147     userial_running = 1;
148 
149     raise_priority_a2dp(TASK_HIGH_USERIAL_READ);
150 
151     while (userial_running)
152     {
153         /* Initialize the input fd set */
154         FD_ZERO(&input);
155         FD_SET(userial_cb.fd[CH_EVT], &input);
156         FD_SET(userial_cb.fd[CH_ACL_IN], &input);
157 
158         int fd_max = create_signal_fds(&input);
159         fd_max = (fd_max>userial_cb.fd[CH_EVT]) ? fd_max : userial_cb.fd[CH_EVT];
160         fd_max = (fd_max>userial_cb.fd[CH_ACL_IN]) ? fd_max : userial_cb.fd[CH_ACL_IN];
161 
162         /* Do the select */
163         n = 0;
164         n = select(fd_max+1, &input, NULL, NULL, NULL);
165         if(is_signaled(&input))
166         {
167             reason = reset_signal();
168             if (reason == USERIAL_RX_EXIT)
169             {
170                 ALOGI("exiting userial_read_thread");
171                 userial_running = 0;
172                 break;
173             }
174         }
175 
176         if (n > 0)
177         {
178             /* We might have input */
179             if (FD_ISSET(userial_cb.fd[CH_EVT], &input))
180             {
181                 hci_mct_receive_evt_msg();
182             }
183 
184             if (FD_ISSET(userial_cb.fd[CH_ACL_IN], &input))
185             {
186                 hci_mct_receive_acl_msg();
187             }
188         }
189         else if (n < 0)
190             ALOGW( "select() Failed");
191         else if (n == 0)
192             ALOGW( "Got a select() TIMEOUT");
193     } /* while */
194 
195     userial_running = 0;
196     USERIALDBG("Leaving userial_evt_read_thread()");
197     pthread_exit(NULL);
198 
199     return NULL;    // Compiler friendly
200 }
201 
202 
203 /*****************************************************************************
204 **   Userial API Functions
205 *****************************************************************************/
206 
207 /*******************************************************************************
208 **
209 ** Function        userial_init
210 **
211 ** Description     Initializes the userial driver
212 **
213 *******************************************************************************/
userial_init(void)214 bool userial_init(void)
215 {
216     int idx;
217 
218     USERIALDBG("userial_init");
219     memset(&userial_cb, 0, sizeof(tUSERIAL_CB));
220     for (idx=0; idx < CH_MAX; idx++)
221         userial_cb.fd[idx] = -1;
222     utils_queue_init(&(userial_cb.rx_q));
223     return true;
224 }
225 
226 
227 /*******************************************************************************
228 **
229 ** Function        userial_open
230 **
231 ** Description     Open Bluetooth device with the port ID
232 **
233 *******************************************************************************/
userial_open(userial_port_t port)234 bool userial_open(userial_port_t port)
235 {
236     int result;
237 
238     USERIALDBG("userial_open(port:%d)", port);
239 
240     if (userial_running)
241     {
242         /* Userial is open; close it first */
243         userial_close();
244         utils_delay(50);
245     }
246 
247     if (port >= MAX_SERIAL_PORT)
248     {
249         ALOGE("Port > MAX_SERIAL_PORT");
250         return false;
251     }
252 
253     result = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &userial_cb.fd);
254     if ((result != 2) && (result != 4))
255     {
256         ALOGE("userial_open: wrong numbers of open fd in vendor lib [%d]!",
257                 result);
258         ALOGE("userial_open: HCI MCT expects 2 or 4 open file descriptors");
259         vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL);
260         return false;
261     }
262 
263     ALOGI("CMD=%d, EVT=%d, ACL_Out=%d, ACL_In=%d", \
264         userial_cb.fd[CH_CMD], userial_cb.fd[CH_EVT], \
265         userial_cb.fd[CH_ACL_OUT], userial_cb.fd[CH_ACL_IN]);
266 
267     if ((userial_cb.fd[CH_CMD] == -1) || (userial_cb.fd[CH_EVT] == -1) ||
268         (userial_cb.fd[CH_ACL_OUT] == -1) || (userial_cb.fd[CH_ACL_IN] == -1))
269     {
270         ALOGE("userial_open: failed to open BT transport");
271         vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL);
272         return false;
273     }
274 
275     userial_cb.port = port;
276 
277     /* Start listening thread */
278     if (pthread_create(&userial_cb.read_thread, NULL, userial_read_thread, NULL) != 0)
279     {
280         ALOGE("pthread_create failed!");
281         vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL);
282         return false;
283     }
284 
285     return true;
286 }
287 
288 /*******************************************************************************
289 **
290 ** Function        userial_read
291 **
292 ** Description     Read data from the userial channel
293 **
294 ** Returns         Number of bytes actually read from the userial port and
295 **                 copied into p_data.  This may be less than len.
296 **
297 *******************************************************************************/
userial_read(uint16_t msg_id,uint8_t * p_buffer,uint16_t len)298 uint16_t userial_read(uint16_t msg_id, uint8_t *p_buffer, uint16_t len)
299 {
300     int ret = -1;
301     int ch_idx = (msg_id == MSG_HC_TO_STACK_HCI_EVT) ? CH_EVT : CH_ACL_IN;
302 
303     ret = read(userial_cb.fd[ch_idx], p_buffer, (size_t)len);
304     if (ret <= 0)
305         ALOGW( "userial_read: read() returned %d!", ret);
306 
307     return (uint16_t) ((ret >= 0) ? ret : 0);
308 }
309 
310 /*******************************************************************************
311 **
312 ** Function        userial_write
313 **
314 ** Description     Write data to the userial port
315 **
316 ** Returns         Number of bytes actually written to the userial port. This
317 **                 may be less than len.
318 **
319 *******************************************************************************/
userial_write(uint16_t msg_id,const uint8_t * p_data,uint16_t len)320 uint16_t userial_write(uint16_t msg_id, const uint8_t *p_data, uint16_t len)
321 {
322     int ret, total = 0;
323     int ch_idx = (msg_id == MSG_STACK_TO_HC_HCI_CMD) ? CH_CMD : CH_ACL_OUT;
324 
325     while(len != 0)
326     {
327         ret = write(userial_cb.fd[ch_idx], p_data+total, len);
328         total += ret;
329         len -= ret;
330     }
331 
332     return ((uint16_t)total);
333 }
334 
userial_close_reader(void)335 void userial_close_reader(void) {
336     // Join the reader thread if it is still running.
337     if (userial_running) {
338         send_wakeup_signal(USERIAL_RX_EXIT);
339         int result = pthread_join(userial_cb.read_thread, NULL);
340         USERIALDBG("%s Joined userial reader thread: %d", __func__, result);
341         if (result)
342             ALOGE("%s failed to join reader thread: %d", __func__, result);
343         return;
344     }
345     ALOGW("%s Already closed userial reader thread", __func__);
346 }
347 
348 /*******************************************************************************
349 **
350 ** Function        userial_close
351 **
352 ** Description     Close the userial port
353 **
354 *******************************************************************************/
userial_close(void)355 void userial_close(void)
356 {
357     int idx, result;
358 
359     USERIALDBG("userial_close");
360 
361     if (userial_running)
362         send_wakeup_signal(USERIAL_RX_EXIT);
363 
364     if ((result=pthread_join(userial_cb.read_thread, NULL)) < 0)
365         ALOGE( "pthread_join() FAILED result:%d", result);
366 
367     vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL);
368 
369     for (idx=0; idx < CH_MAX; idx++)
370         userial_cb.fd[idx] = -1;
371 }
372