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: uipc.c
22 *
23 * Description: UIPC implementation for bluedroid
24 *
25 *****************************************************************************/
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34
35 #include <sys/socket.h>
36 #include <sys/un.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <pthread.h>
40 #include <sys/select.h>
41 #include <sys/poll.h>
42 #include <sys/mman.h>
43 #include <sys/stat.h>
44 #include <sys/prctl.h>
45
46
47 #include "gki.h"
48 #include "bt_types.h"
49 #include "uipc.h"
50
51 #include <cutils/sockets.h>
52 #include "audio_a2dp_hw.h"
53 #include "bt_utils.h"
54
55 /*****************************************************************************
56 ** Constants & Macros
57 ******************************************************************************/
58
59 #define PCM_FILENAME "/data/test.pcm"
60
61 #define MAX(a,b) ((a)>(b)?(a):(b))
62
63 #define CASE_RETURN_STR(const) case const: return #const;
64
65 #define UIPC_DISCONNECTED (-1)
66
67 #define UIPC_LOCK() /*BTIF_TRACE_EVENT(" %s lock", __FUNCTION__);*/ pthread_mutex_lock(&uipc_main.mutex);
68 #define UIPC_UNLOCK() /*BTIF_TRACE_EVENT("%s unlock", __FUNCTION__);*/ pthread_mutex_unlock(&uipc_main.mutex);
69
70 #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? FALSE : FD_ISSET((fd), (set)))
71
72 #define UIPC_FLUSH_BUFFER_SIZE 1024
73
74 /*****************************************************************************
75 ** Local type definitions
76 ******************************************************************************/
77
78 typedef enum {
79 UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
80 } tUIPC_TASK_FLAGS;
81
82 typedef struct {
83 int srvfd;
84 int fd;
85 int read_poll_tmo_ms;
86 int task_evt_flags; /* event flags pending to be processed in read task */
87 tUIPC_EVENT cond_flags;
88 pthread_mutex_t cond_mutex;
89 pthread_cond_t cond;
90 tUIPC_RCV_CBACK *cback;
91 } tUIPC_CHAN;
92
93 typedef struct {
94 pthread_t tid; /* main thread id */
95 int running;
96 pthread_mutex_t mutex;
97
98 fd_set active_set;
99 fd_set read_set;
100 int max_fd;
101 int signal_fds[2];
102
103 tUIPC_CHAN ch[UIPC_CH_NUM];
104 } tUIPC_MAIN;
105
106
107 /*****************************************************************************
108 ** Static variables
109 ******************************************************************************/
110
111 static tUIPC_MAIN uipc_main;
112
113
114 /*****************************************************************************
115 ** Static functions
116 ******************************************************************************/
117
118 static int uipc_close_ch_locked(tUIPC_CH_ID ch_id);
119
120 /*****************************************************************************
121 ** Externs
122 ******************************************************************************/
123
124
125 /*****************************************************************************
126 ** Helper functions
127 ******************************************************************************/
128
129
dump_uipc_event(tUIPC_EVENT event)130 const char* dump_uipc_event(tUIPC_EVENT event)
131 {
132 switch(event)
133 {
134 CASE_RETURN_STR(UIPC_OPEN_EVT)
135 CASE_RETURN_STR(UIPC_CLOSE_EVT)
136 CASE_RETURN_STR(UIPC_RX_DATA_EVT)
137 CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
138 CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
139 default:
140 return "UNKNOWN MSG ID";
141 }
142 }
143
144 /*****************************************************************************
145 ** socket helper functions
146 *****************************************************************************/
147
create_server_socket(const char * name)148 static inline int create_server_socket(const char* name)
149 {
150 int s = socket(AF_LOCAL, SOCK_STREAM, 0);
151 if (s < 0)
152 return -1;
153
154 BTIF_TRACE_EVENT("create_server_socket %s", name);
155
156 if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
157 {
158 BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno));
159 close(s);
160 return -1;
161 }
162
163 if(listen(s, 5) < 0)
164 {
165 BTIF_TRACE_EVENT("listen failed", strerror(errno));
166 close(s);
167 return -1;
168 }
169
170 BTIF_TRACE_EVENT("created socket fd %d", s);
171 return s;
172 }
173
accept_server_socket(int sfd)174 static int accept_server_socket(int sfd)
175 {
176 struct sockaddr_un remote;
177 struct pollfd pfd;
178 int fd;
179 socklen_t len = sizeof(struct sockaddr_un);
180
181 BTIF_TRACE_EVENT("accept fd %d", sfd);
182
183 /* make sure there is data to process */
184 pfd.fd = sfd;
185 pfd.events = POLLIN;
186
187 if (poll(&pfd, 1, 0) == 0)
188 {
189 BTIF_TRACE_EVENT("accept poll timeout");
190 return -1;
191 }
192
193 //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents);
194
195 if ((fd = accept(sfd, (struct sockaddr *)&remote, &len)) == -1)
196 {
197 BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno));
198 return -1;
199 }
200
201 //BTIF_TRACE_EVENT("new fd %d", fd);
202
203 return fd;
204 }
205
206 /*****************************************************************************
207 **
208 ** uipc helper functions
209 **
210 *****************************************************************************/
211
uipc_main_init(void)212 static int uipc_main_init(void)
213 {
214 int i;
215 pthread_mutexattr_t attr;
216 pthread_mutexattr_init(&attr);
217 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
218 pthread_mutex_init(&uipc_main.mutex, &attr);
219
220 BTIF_TRACE_EVENT("### uipc_main_init ###");
221
222 /* setup interrupt socket pair */
223 if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0)
224 {
225 return -1;
226 }
227
228 FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set);
229 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]);
230
231 for (i=0; i< UIPC_CH_NUM; i++)
232 {
233 tUIPC_CHAN *p = &uipc_main.ch[i];
234 p->srvfd = UIPC_DISCONNECTED;
235 p->fd = UIPC_DISCONNECTED;
236 p->task_evt_flags = 0;
237 pthread_cond_init(&p->cond, NULL);
238 pthread_mutex_init(&p->cond_mutex, NULL);
239 p->cback = NULL;
240 }
241
242 return 0;
243 }
244
uipc_main_cleanup(void)245 void uipc_main_cleanup(void)
246 {
247 int i;
248
249 BTIF_TRACE_EVENT("uipc_main_cleanup");
250
251 close(uipc_main.signal_fds[0]);
252 close(uipc_main.signal_fds[1]);
253
254 /* close any open channels */
255 for (i=0; i<UIPC_CH_NUM; i++)
256 uipc_close_ch_locked(i);
257 }
258
259
260
261 /* check pending events in read task */
uipc_check_task_flags_locked(void)262 static void uipc_check_task_flags_locked(void)
263 {
264 int i;
265
266 for (i=0; i<UIPC_CH_NUM; i++)
267 {
268 //BTIF_TRACE_EVENT("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN);
269 if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN)
270 {
271 uipc_main.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
272 uipc_close_ch_locked(i);
273 }
274
275 /* add here */
276
277 }
278 }
279
280
uipc_check_fd_locked(tUIPC_CH_ID ch_id)281 static int uipc_check_fd_locked(tUIPC_CH_ID ch_id)
282 {
283 if (ch_id >= UIPC_CH_NUM)
284 return -1;
285
286 //BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id);
287
288 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set))
289 {
290 BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id);
291
292 uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd);
293
294 BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd);
295
296 if ((uipc_main.ch[ch_id].fd > 0) && uipc_main.ch[ch_id].cback)
297 {
298 /* if we have a callback we should add this fd to the active set
299 and notify user with callback event */
300 BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd);
301 FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
302 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd);
303 }
304
305 if (uipc_main.ch[ch_id].fd < 0)
306 {
307 BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno));
308 return -1;
309 }
310
311 if (uipc_main.ch[ch_id].cback)
312 uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
313 }
314
315 //BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id);
316
317 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set))
318 {
319 //BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id);
320
321 if (uipc_main.ch[ch_id].cback)
322 uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
323 }
324 return 0;
325 }
326
uipc_check_interrupt_locked(void)327 static void uipc_check_interrupt_locked(void)
328 {
329 if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set))
330 {
331 char sig_recv = 0;
332 //BTIF_TRACE_EVENT("UIPC INTERRUPT");
333 recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
334 }
335 }
336
uipc_wakeup_locked(void)337 static inline void uipc_wakeup_locked(void)
338 {
339 char sig_on = 1;
340 BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
341 send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0);
342 }
343
uipc_setup_server_locked(tUIPC_CH_ID ch_id,char * name,tUIPC_RCV_CBACK * cback)344 static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
345 {
346 int fd;
347
348 BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
349
350 if (ch_id >= UIPC_CH_NUM)
351 return -1;
352
353 UIPC_LOCK();
354
355 fd = create_server_socket(name);
356
357 if (fd < 0)
358 {
359 BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno));
360 UIPC_UNLOCK();
361 return -1;
362 }
363
364 BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd);
365 FD_SET(fd, &uipc_main.active_set);
366 uipc_main.max_fd = MAX(uipc_main.max_fd, fd);
367
368 uipc_main.ch[ch_id].srvfd = fd;
369 uipc_main.ch[ch_id].cback = cback;
370 uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
371
372 /* trigger main thread to update read set */
373 uipc_wakeup_locked();
374
375 UIPC_UNLOCK();
376
377 return 0;
378 }
379
uipc_flush_ch_locked(tUIPC_CH_ID ch_id)380 static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id)
381 {
382 char buf[UIPC_FLUSH_BUFFER_SIZE];
383 struct pollfd pfd;
384 int ret;
385
386 pfd.events = POLLIN;
387 pfd.fd = uipc_main.ch[ch_id].fd;
388
389 if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED)
390 {
391 BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__);
392 return;
393 }
394
395 while (1)
396 {
397 ret = poll(&pfd, 1, 1);
398 BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d",
399 __FUNCTION__, pfd.fd, pfd.revents, ret);
400
401 if (pfd.revents & (POLLERR|POLLHUP))
402 {
403 BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__);
404 return;
405 }
406
407 if (ret <= 0)
408 {
409 BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret);
410 return;
411 }
412
413 /* read sufficiently large buffer to ensure flush empties socket faster than
414 it is getting refilled */
415 read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE);
416 }
417 }
418
419
uipc_flush_locked(tUIPC_CH_ID ch_id)420 static void uipc_flush_locked(tUIPC_CH_ID ch_id)
421 {
422 if (ch_id >= UIPC_CH_NUM)
423 return;
424
425 switch(ch_id)
426 {
427 case UIPC_CH_ID_AV_CTRL:
428 uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
429 break;
430
431 case UIPC_CH_ID_AV_AUDIO:
432 uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
433 break;
434 }
435 }
436
437
uipc_close_ch_locked(tUIPC_CH_ID ch_id)438 static int uipc_close_ch_locked(tUIPC_CH_ID ch_id)
439 {
440 int wakeup = 0;
441
442 BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id);
443
444 if (ch_id >= UIPC_CH_NUM)
445 return -1;
446
447 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
448 {
449 BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd);
450 close(uipc_main.ch[ch_id].srvfd);
451 FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set);
452 uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED;
453 wakeup = 1;
454 }
455
456 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
457 {
458 BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
459 close(uipc_main.ch[ch_id].fd);
460 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
461 uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
462 wakeup = 1;
463 }
464
465 /* notify this connection is closed */
466 if (uipc_main.ch[ch_id].cback)
467 uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
468
469 /* trigger main thread update if something was updated */
470 if (wakeup)
471 uipc_wakeup_locked();
472
473 return 0;
474 }
475
476
uipc_close_locked(tUIPC_CH_ID ch_id)477 void uipc_close_locked(tUIPC_CH_ID ch_id)
478 {
479 if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED)
480 {
481 BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id);
482 return;
483 }
484
485 /* schedule close on this channel */
486 uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
487 uipc_wakeup_locked();
488 }
489
490
uipc_read_task(void * arg)491 static void uipc_read_task(void *arg)
492 {
493 int ch_id;
494 int result;
495 UNUSED(arg);
496
497 prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
498
499 raise_priority_a2dp(TASK_UIPC_READ);
500
501 while (uipc_main.running)
502 {
503 uipc_main.read_set = uipc_main.active_set;
504
505 result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL);
506
507 if (result == 0)
508 {
509 BTIF_TRACE_EVENT("select timeout");
510 continue;
511 }
512 else if (result < 0)
513 {
514 BTIF_TRACE_EVENT("select failed %s", strerror(errno));
515 continue;
516 }
517
518 UIPC_LOCK();
519
520 /* clear any wakeup interrupt */
521 uipc_check_interrupt_locked();
522
523 /* check pending task events */
524 uipc_check_task_flags_locked();
525
526 /* make sure we service audio channel first */
527 uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
528
529 /* check for other connections */
530 for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++)
531 {
532 if (ch_id != UIPC_CH_ID_AV_AUDIO)
533 uipc_check_fd_locked(ch_id);
534 }
535
536 UIPC_UNLOCK();
537 }
538
539 BTIF_TRACE_EVENT("UIPC READ THREAD EXITING");
540
541 uipc_main_cleanup();
542
543 uipc_main.tid = 0;
544
545 BTIF_TRACE_EVENT("UIPC READ THREAD DONE");
546 }
547
548
uipc_start_main_server_thread(void)549 int uipc_start_main_server_thread(void)
550 {
551 uipc_main.running = 1;
552
553 if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0)
554 {
555 BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
556 return -1;
557 }
558
559 return 0;
560 }
561
562 /* blocking call */
uipc_stop_main_server_thread(void)563 void uipc_stop_main_server_thread(void)
564 {
565 /* request shutdown of read thread */
566 UIPC_LOCK();
567 uipc_main.running = 0;
568 uipc_wakeup_locked();
569 UIPC_UNLOCK();
570
571 /* wait until read thread is fully terminated */
572 /* tid might hold pointer value where it's value
573 is negative vaule with singed bit is set, so
574 corrected the logic to check zero or non zero */
575 if (uipc_main.tid)
576 pthread_join(uipc_main.tid, NULL);
577 }
578
579 /*******************************************************************************
580 **
581 ** Function UIPC_Init
582 **
583 ** Description Initialize UIPC module
584 **
585 ** Returns void
586 **
587 *******************************************************************************/
588
UIPC_Init(void * p_data)589 void UIPC_Init(void *p_data)
590 {
591 UNUSED(p_data);
592
593 BTIF_TRACE_DEBUG("UIPC_Init");
594
595 memset(&uipc_main, 0, sizeof(tUIPC_MAIN));
596
597 uipc_main_init();
598
599 uipc_start_main_server_thread();
600 }
601
602 /*******************************************************************************
603 **
604 ** Function UIPC_Open
605 **
606 ** Description Open UIPC interface
607 **
608 ** Returns TRUE in case of success, FALSE in case of failure.
609 **
610 *******************************************************************************/
UIPC_Open(tUIPC_CH_ID ch_id,tUIPC_RCV_CBACK * p_cback)611 BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback)
612 {
613 BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
614
615 UIPC_LOCK();
616
617 if (ch_id >= UIPC_CH_NUM)
618 {
619 UIPC_UNLOCK();
620 return FALSE;
621 }
622
623 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
624 {
625 BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id);
626 UIPC_UNLOCK();
627 return 0;
628 }
629
630 switch(ch_id)
631 {
632 case UIPC_CH_ID_AV_CTRL:
633 uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);
634 break;
635
636 case UIPC_CH_ID_AV_AUDIO:
637 uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
638 break;
639 }
640
641 UIPC_UNLOCK();
642
643 return TRUE;
644 }
645
646 /*******************************************************************************
647 **
648 ** Function UIPC_Close
649 **
650 ** Description Close UIPC interface
651 **
652 ** Returns void
653 **
654 *******************************************************************************/
655
UIPC_Close(tUIPC_CH_ID ch_id)656 void UIPC_Close(tUIPC_CH_ID ch_id)
657 {
658 BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id);
659
660 /* special case handling uipc shutdown */
661 if (ch_id != UIPC_CH_ID_ALL)
662 {
663 UIPC_LOCK();
664 uipc_close_locked(ch_id);
665 UIPC_UNLOCK();
666 }
667 else
668 {
669 BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete");
670 uipc_stop_main_server_thread();
671 BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete");
672 }
673 }
674
675 /*******************************************************************************
676 **
677 ** Function UIPC_SendBuf
678 **
679 ** Description Called to transmit a message over UIPC.
680 ** Message buffer will be freed by UIPC_SendBuf.
681 **
682 ** Returns TRUE in case of success, FALSE in case of failure.
683 **
684 *******************************************************************************/
UIPC_SendBuf(tUIPC_CH_ID ch_id,BT_HDR * p_msg)685 BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
686 {
687 UNUSED(p_msg);
688
689 BTIF_TRACE_DEBUG("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id);
690
691 UIPC_LOCK();
692
693 /* currently not used */
694
695 UIPC_UNLOCK();
696
697 return FALSE;
698 }
699
700 /*******************************************************************************
701 **
702 ** Function UIPC_Send
703 **
704 ** Description Called to transmit a message over UIPC.
705 **
706 ** Returns TRUE in case of success, FALSE in case of failure.
707 **
708 *******************************************************************************/
UIPC_Send(tUIPC_CH_ID ch_id,UINT16 msg_evt,UINT8 * p_buf,UINT16 msglen)709 BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf,
710 UINT16 msglen)
711 {
712 UNUSED(msg_evt);
713
714 BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
715
716 UIPC_LOCK();
717
718 if (write(uipc_main.ch[ch_id].fd, p_buf, msglen) < 0)
719 {
720 BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
721 }
722
723 UIPC_UNLOCK();
724
725 return FALSE;
726 }
727
728 /*******************************************************************************
729 **
730 ** Function UIPC_ReadBuf
731 **
732 ** Description Called to read a message from UIPC.
733 **
734 ** Returns void
735 **
736 *******************************************************************************/
UIPC_ReadBuf(tUIPC_CH_ID ch_id,BT_HDR * p_msg)737 void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
738 {
739 UNUSED(p_msg);
740
741 BTIF_TRACE_DEBUG("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id);
742
743 UIPC_LOCK();
744 UIPC_UNLOCK();
745 }
746
747 /*******************************************************************************
748 **
749 ** Function UIPC_Read
750 **
751 ** Description Called to read a message from UIPC.
752 **
753 ** Returns return the number of bytes read.
754 **
755 *******************************************************************************/
756
UIPC_Read(tUIPC_CH_ID ch_id,UINT16 * p_msg_evt,UINT8 * p_buf,UINT32 len)757 UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len)
758 {
759 int n;
760 int n_read = 0;
761 int fd = uipc_main.ch[ch_id].fd;
762 struct pollfd pfd;
763 UNUSED(p_msg_evt);
764
765 if (ch_id >= UIPC_CH_NUM)
766 {
767 BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
768 return 0;
769 }
770
771 if (fd == UIPC_DISCONNECTED)
772 {
773 BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
774 return 0;
775 }
776
777 //BTIF_TRACE_DEBUG("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len,
778 // fd, uipc_main.ch[ch_id].read_poll_tmo_ms);
779
780 while (n_read < (int)len)
781 {
782 pfd.fd = fd;
783 pfd.events = POLLIN|POLLHUP;
784
785 /* make sure there is data prior to attempting read to avoid blocking
786 a read for more than poll timeout */
787 if (poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms) == 0)
788 {
789 BTIF_TRACE_EVENT("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms);
790 break;
791 }
792
793 //BTIF_TRACE_EVENT("poll revents %x", pfd.revents);
794
795 if (pfd.revents & (POLLHUP|POLLNVAL) )
796 {
797 BTIF_TRACE_EVENT("poll : channel detached remotely");
798 UIPC_LOCK();
799 uipc_close_locked(ch_id);
800 UIPC_UNLOCK();
801 return 0;
802 }
803
804 n = recv(fd, p_buf+n_read, len-n_read, 0);
805
806 //BTIF_TRACE_EVENT("read %d bytes", n);
807
808 if (n == 0)
809 {
810 BTIF_TRACE_EVENT("UIPC_Read : channel detached remotely");
811 UIPC_LOCK();
812 uipc_close_locked(ch_id);
813 UIPC_UNLOCK();
814 return 0;
815 }
816
817 if (n < 0)
818 {
819 BTIF_TRACE_EVENT("UIPC_Read : read failed (%s)", strerror(errno));
820 return 0;
821 }
822
823 n_read+=n;
824
825 }
826
827 return n_read;
828 }
829
830 /*******************************************************************************
831 **
832 ** Function UIPC_Ioctl
833 **
834 ** Description Called to control UIPC.
835 **
836 ** Returns void
837 **
838 *******************************************************************************/
839
UIPC_Ioctl(tUIPC_CH_ID ch_id,UINT32 request,void * param)840 extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param)
841 {
842 BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request);
843
844 UIPC_LOCK();
845
846 switch(request)
847 {
848 case UIPC_REQ_RX_FLUSH:
849 uipc_flush_locked(ch_id);
850 break;
851
852 case UIPC_REG_CBACK:
853 //BTIF_TRACE_EVENT("register callback ch %d srvfd %d, fd %d", ch_id, uipc_main.ch[ch_id].srvfd, uipc_main.ch[ch_id].fd);
854 uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
855 break;
856
857 case UIPC_REG_REMOVE_ACTIVE_READSET:
858
859 /* user will read data directly and not use select loop */
860 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
861 {
862 /* remove this channel from active set */
863 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
864
865 /* refresh active set */
866 uipc_wakeup_locked();
867 }
868 break;
869
870 case UIPC_SET_READ_POLL_TMO:
871 uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
872 BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id, uipc_main.ch[ch_id].read_poll_tmo_ms );
873 break;
874
875 default:
876 BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request);
877 break;
878 }
879
880 UIPC_UNLOCK();
881
882 return FALSE;
883 }
884
885