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