OSDN Git Service

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