Home | History | Annotate | Download | only in ulinux
      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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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  *******************************************************************************/
    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 
    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  *******************************************************************************/
    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  *******************************************************************************/
    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  *******************************************************************************/
    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 
    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+n_read, len-n_read, 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 
    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