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