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