Home | History | Annotate | Download | only in ulinux
      1 /******************************************************************************
      2  *
      3  *  Copyright 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.cc
     22  *
     23  *  Description:   UIPC implementation for fluoride
     24  *
     25  *****************************************************************************/
     26 
     27 #include <errno.h>
     28 #include <fcntl.h>
     29 #include <signal.h>
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <sys/mman.h>
     34 #include <sys/poll.h>
     35 #include <sys/prctl.h>
     36 #include <sys/select.h>
     37 #include <sys/socket.h>
     38 #include <sys/stat.h>
     39 #include <sys/un.h>
     40 #include <unistd.h>
     41 #include <mutex>
     42 #include <set>
     43 
     44 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
     45 #include "bt_common.h"
     46 #include "bt_types.h"
     47 #include "bt_utils.h"
     48 #include "osi/include/osi.h"
     49 #include "osi/include/socket_utils/sockets.h"
     50 #include "uipc.h"
     51 
     52 /*****************************************************************************
     53  *  Constants & Macros
     54  *****************************************************************************/
     55 
     56 #define PCM_FILENAME "/data/test.pcm"
     57 
     58 #define MAX(a, b) ((a) > (b) ? (a) : (b))
     59 
     60 #define CASE_RETURN_STR(const) \
     61   case const:                  \
     62     return #const;
     63 
     64 #define UIPC_DISCONNECTED (-1)
     65 
     66 #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? false : FD_ISSET((fd), (set)))
     67 
     68 #define UIPC_FLUSH_BUFFER_SIZE 1024
     69 
     70 /*****************************************************************************
     71  *  Local type definitions
     72  *****************************************************************************/
     73 
     74 typedef enum {
     75   UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
     76 } tUIPC_TASK_FLAGS;
     77 
     78 /*****************************************************************************
     79  *  Static functions
     80  *****************************************************************************/
     81 static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id);
     82 
     83 /*****************************************************************************
     84  *  Externs
     85  *****************************************************************************/
     86 
     87 /*****************************************************************************
     88  *   Helper functions
     89  *****************************************************************************/
     90 
     91 const char* dump_uipc_event(tUIPC_EVENT event) {
     92   switch (event) {
     93     CASE_RETURN_STR(UIPC_OPEN_EVT)
     94     CASE_RETURN_STR(UIPC_CLOSE_EVT)
     95     CASE_RETURN_STR(UIPC_RX_DATA_EVT)
     96     CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
     97     CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
     98     default:
     99       return "UNKNOWN MSG ID";
    100   }
    101 }
    102 
    103 /*****************************************************************************
    104  *   socket helper functions
    105  ****************************************************************************/
    106 
    107 static inline int create_server_socket(const char* name) {
    108   int s = socket(AF_LOCAL, SOCK_STREAM, 0);
    109   if (s < 0) return -1;
    110 
    111   BTIF_TRACE_EVENT("create_server_socket %s", name);
    112 
    113   if (osi_socket_local_server_bind(s, name,
    114 #if defined(OS_GENERIC)
    115                                    ANDROID_SOCKET_NAMESPACE_FILESYSTEM
    116 #else   // !defined(OS_GENERIC)
    117                                    ANDROID_SOCKET_NAMESPACE_ABSTRACT
    118 #endif  // defined(OS_GENERIC)
    119                                    ) < 0) {
    120     BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno));
    121     close(s);
    122     return -1;
    123   }
    124 
    125   if (listen(s, 5) < 0) {
    126     BTIF_TRACE_EVENT("listen failed", strerror(errno));
    127     close(s);
    128     return -1;
    129   }
    130 
    131   BTIF_TRACE_EVENT("created socket fd %d", s);
    132   return s;
    133 }
    134 
    135 static int accept_server_socket(int sfd) {
    136   struct sockaddr_un remote;
    137   struct pollfd pfd;
    138   int fd;
    139   socklen_t len = sizeof(struct sockaddr_un);
    140 
    141   BTIF_TRACE_EVENT("accept fd %d", sfd);
    142 
    143   /* make sure there is data to process */
    144   pfd.fd = sfd;
    145   pfd.events = POLLIN;
    146 
    147   int poll_ret;
    148   OSI_NO_INTR(poll_ret = poll(&pfd, 1, 0));
    149   if (poll_ret == 0) {
    150     BTIF_TRACE_WARNING("accept poll timeout");
    151     return -1;
    152   }
    153 
    154   // BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents);
    155 
    156   OSI_NO_INTR(fd = accept(sfd, (struct sockaddr*)&remote, &len));
    157   if (fd == -1) {
    158     BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno));
    159     return -1;
    160   }
    161 
    162   // match socket buffer size option with client
    163   const int size = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
    164   int ret =
    165       setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
    166   if (ret < 0) {
    167     BTIF_TRACE_ERROR("setsockopt failed (%s)", strerror(errno));
    168   }
    169 
    170   // BTIF_TRACE_EVENT("new fd %d", fd);
    171 
    172   return fd;
    173 }
    174 
    175 /*****************************************************************************
    176  *
    177  *   uipc helper functions
    178  *
    179  ****************************************************************************/
    180 
    181 static int uipc_main_init(tUIPC_STATE& uipc) {
    182   int i;
    183 
    184   BTIF_TRACE_EVENT("### uipc_main_init ###");
    185 
    186   uipc.tid = 0;
    187   uipc.running = 0;
    188   memset(&uipc.active_set, 0, sizeof(uipc.active_set));
    189   memset(&uipc.read_set, 0, sizeof(uipc.read_set));
    190   uipc.max_fd = 0;
    191   memset(&uipc.signal_fds, 0, sizeof(uipc.signal_fds));
    192   memset(&uipc.ch, 0, sizeof(uipc.ch));
    193 
    194   /* setup interrupt socket pair */
    195   if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc.signal_fds) < 0) {
    196     return -1;
    197   }
    198 
    199   FD_SET(uipc.signal_fds[0], &uipc.active_set);
    200   uipc.max_fd = MAX(uipc.max_fd, uipc.signal_fds[0]);
    201 
    202   for (i = 0; i < UIPC_CH_NUM; i++) {
    203     tUIPC_CHAN* p = &uipc.ch[i];
    204     p->srvfd = UIPC_DISCONNECTED;
    205     p->fd = UIPC_DISCONNECTED;
    206     p->task_evt_flags = 0;
    207     p->cback = NULL;
    208   }
    209 
    210   return 0;
    211 }
    212 
    213 void uipc_main_cleanup(tUIPC_STATE& uipc) {
    214   int i;
    215 
    216   BTIF_TRACE_EVENT("uipc_main_cleanup");
    217 
    218   close(uipc.signal_fds[0]);
    219   close(uipc.signal_fds[1]);
    220 
    221   /* close any open channels */
    222   for (i = 0; i < UIPC_CH_NUM; i++) uipc_close_ch_locked(uipc, i);
    223 }
    224 
    225 /* check pending events in read task */
    226 static void uipc_check_task_flags_locked(tUIPC_STATE& uipc) {
    227   int i;
    228 
    229   for (i = 0; i < UIPC_CH_NUM; i++) {
    230     if (uipc.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) {
    231       uipc.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
    232       uipc_close_ch_locked(uipc, i);
    233     }
    234 
    235     /* add here */
    236   }
    237 }
    238 
    239 static int uipc_check_fd_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    240   if (ch_id >= UIPC_CH_NUM) return -1;
    241 
    242   // BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc.ch[ch_id].srvfd,
    243   // ch_id);
    244 
    245   if (SAFE_FD_ISSET(uipc.ch[ch_id].srvfd, &uipc.read_set)) {
    246     BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id);
    247 
    248     // Close the previous connection
    249     if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
    250       BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc.ch[ch_id].fd);
    251       close(uipc.ch[ch_id].fd);
    252       FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
    253       uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
    254     }
    255 
    256     uipc.ch[ch_id].fd = accept_server_socket(uipc.ch[ch_id].srvfd);
    257 
    258     BTIF_TRACE_EVENT("NEW FD %d", uipc.ch[ch_id].fd);
    259 
    260     if ((uipc.ch[ch_id].fd >= 0) && uipc.ch[ch_id].cback) {
    261       /*  if we have a callback we should add this fd to the active set
    262           and notify user with callback event */
    263       BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc.ch[ch_id].fd);
    264       FD_SET(uipc.ch[ch_id].fd, &uipc.active_set);
    265       uipc.max_fd = MAX(uipc.max_fd, uipc.ch[ch_id].fd);
    266     }
    267 
    268     if (uipc.ch[ch_id].fd < 0) {
    269       BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d", ch_id);
    270       return -1;
    271     }
    272 
    273     if (uipc.ch[ch_id].cback) uipc.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
    274   }
    275 
    276   // BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc.ch[ch_id].fd, ch_id);
    277 
    278   if (SAFE_FD_ISSET(uipc.ch[ch_id].fd, &uipc.read_set)) {
    279     // BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id);
    280 
    281     if (uipc.ch[ch_id].cback)
    282       uipc.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
    283   }
    284   return 0;
    285 }
    286 
    287 static void uipc_check_interrupt_locked(tUIPC_STATE& uipc) {
    288   if (SAFE_FD_ISSET(uipc.signal_fds[0], &uipc.read_set)) {
    289     char sig_recv = 0;
    290     OSI_NO_INTR(
    291         recv(uipc.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL));
    292   }
    293 }
    294 
    295 static inline void uipc_wakeup_locked(tUIPC_STATE& uipc) {
    296   char sig_on = 1;
    297   BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
    298 
    299   OSI_NO_INTR(send(uipc.signal_fds[1], &sig_on, sizeof(sig_on), 0));
    300 }
    301 
    302 static int uipc_setup_server_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
    303                                     const char* name, tUIPC_RCV_CBACK* cback) {
    304   int fd;
    305 
    306   BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
    307 
    308   if (ch_id >= UIPC_CH_NUM) return -1;
    309 
    310   std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
    311 
    312   fd = create_server_socket(name);
    313 
    314   if (fd < 0) {
    315     BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno));
    316     return -1;
    317   }
    318 
    319   BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd);
    320   FD_SET(fd, &uipc.active_set);
    321   uipc.max_fd = MAX(uipc.max_fd, fd);
    322 
    323   uipc.ch[ch_id].srvfd = fd;
    324   uipc.ch[ch_id].cback = cback;
    325   uipc.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
    326 
    327   /* trigger main thread to update read set */
    328   uipc_wakeup_locked(uipc);
    329 
    330   return 0;
    331 }
    332 
    333 static void uipc_flush_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    334   char buf[UIPC_FLUSH_BUFFER_SIZE];
    335   struct pollfd pfd;
    336 
    337   pfd.events = POLLIN;
    338   pfd.fd = uipc.ch[ch_id].fd;
    339 
    340   if (uipc.ch[ch_id].fd == UIPC_DISCONNECTED) {
    341     BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __func__);
    342     return;
    343   }
    344 
    345   while (1) {
    346     int ret;
    347     OSI_NO_INTR(ret = poll(&pfd, 1, 1));
    348     if (ret == 0) {
    349       BTIF_TRACE_VERBOSE("%s(): poll() timeout - nothing to do. Exiting",
    350                          __func__);
    351       return;
    352     }
    353     if (ret < 0) {
    354       BTIF_TRACE_WARNING(
    355           "%s() - poll() failed: return %d errno %d (%s). Exiting", __func__,
    356           ret, errno, strerror(errno));
    357       return;
    358     }
    359     BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d", __func__,
    360                        pfd.fd, pfd.revents, ret);
    361     if (pfd.revents & (POLLERR | POLLHUP)) {
    362       BTIF_TRACE_WARNING("%s() - POLLERR or POLLHUP. Exiting", __func__);
    363       return;
    364     }
    365 
    366     /* read sufficiently large buffer to ensure flush empties socket faster than
    367        it is getting refilled */
    368     read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE);
    369   }
    370 }
    371 
    372 static void uipc_flush_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    373   if (ch_id >= UIPC_CH_NUM) return;
    374 
    375   switch (ch_id) {
    376     case UIPC_CH_ID_AV_CTRL:
    377       uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_CTRL);
    378       break;
    379 
    380     case UIPC_CH_ID_AV_AUDIO:
    381       uipc_flush_ch_locked(uipc, UIPC_CH_ID_AV_AUDIO);
    382       break;
    383   }
    384 }
    385 
    386 static int uipc_close_ch_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    387   int wakeup = 0;
    388 
    389   BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id);
    390 
    391   if (ch_id >= UIPC_CH_NUM) return -1;
    392 
    393   if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
    394     BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc.ch[ch_id].srvfd);
    395     close(uipc.ch[ch_id].srvfd);
    396     FD_CLR(uipc.ch[ch_id].srvfd, &uipc.active_set);
    397     uipc.ch[ch_id].srvfd = UIPC_DISCONNECTED;
    398     wakeup = 1;
    399   }
    400 
    401   if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
    402     BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc.ch[ch_id].fd);
    403     close(uipc.ch[ch_id].fd);
    404     FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
    405     uipc.ch[ch_id].fd = UIPC_DISCONNECTED;
    406     wakeup = 1;
    407   }
    408 
    409   /* notify this connection is closed */
    410   if (uipc.ch[ch_id].cback) uipc.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
    411 
    412   /* trigger main thread update if something was updated */
    413   if (wakeup) uipc_wakeup_locked(uipc);
    414 
    415   return 0;
    416 }
    417 
    418 void uipc_close_locked(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    419   if (uipc.ch[ch_id].srvfd == UIPC_DISCONNECTED) {
    420     BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id);
    421     return;
    422   }
    423 
    424   /* schedule close on this channel */
    425   uipc.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
    426   uipc_wakeup_locked(uipc);
    427 }
    428 
    429 static void* uipc_read_task(void* arg) {
    430   tUIPC_STATE& uipc = *((tUIPC_STATE*)arg);
    431   int ch_id;
    432   int result;
    433 
    434   prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
    435 
    436   raise_priority_a2dp(TASK_UIPC_READ);
    437 
    438   while (uipc.running) {
    439     uipc.read_set = uipc.active_set;
    440 
    441     result = select(uipc.max_fd + 1, &uipc.read_set, NULL, NULL, NULL);
    442 
    443     if (result == 0) {
    444       BTIF_TRACE_EVENT("select timeout");
    445       continue;
    446     }
    447     if (result < 0) {
    448       if (errno != EINTR) {
    449         BTIF_TRACE_EVENT("select failed %s", strerror(errno));
    450       }
    451       continue;
    452     }
    453 
    454     {
    455       std::lock_guard<std::recursive_mutex> guard(uipc.mutex);
    456 
    457       /* clear any wakeup interrupt */
    458       uipc_check_interrupt_locked(uipc);
    459 
    460       /* check pending task events */
    461       uipc_check_task_flags_locked(uipc);
    462 
    463       /* make sure we service audio channel first */
    464       uipc_check_fd_locked(uipc, UIPC_CH_ID_AV_AUDIO);
    465 
    466       /* check for other connections */
    467       for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++) {
    468         if (ch_id != UIPC_CH_ID_AV_AUDIO) uipc_check_fd_locked(uipc, ch_id);
    469       }
    470     }
    471   }
    472 
    473   BTIF_TRACE_EVENT("UIPC READ THREAD EXITING");
    474 
    475   uipc_main_cleanup(uipc);
    476 
    477   uipc.tid = 0;
    478 
    479   BTIF_TRACE_EVENT("UIPC READ THREAD DONE");
    480 
    481   return nullptr;
    482 }
    483 
    484 int uipc_start_main_server_thread(tUIPC_STATE& uipc) {
    485   uipc.running = 1;
    486 
    487   if (pthread_create(&uipc.tid, (const pthread_attr_t*)NULL, uipc_read_task,
    488                      &uipc) < 0) {
    489     BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
    490     return -1;
    491   }
    492 
    493   return 0;
    494 }
    495 
    496 /* blocking call */
    497 void uipc_stop_main_server_thread(tUIPC_STATE& uipc) {
    498   /* request shutdown of read thread */
    499   {
    500     std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    501     uipc.running = 0;
    502     uipc_wakeup_locked(uipc);
    503   }
    504 
    505   /* wait until read thread is fully terminated */
    506   /* tid might hold pointer value where it's value
    507      is negative vaule with singed bit is set, so
    508      corrected the logic to check zero or non zero */
    509   if (uipc.tid) pthread_join(uipc.tid, NULL);
    510 }
    511 
    512 /*******************************************************************************
    513  **
    514  ** Function         UIPC_Init
    515  **
    516  ** Description      Initialize UIPC module
    517  **
    518  ** Returns          void
    519  **
    520  ******************************************************************************/
    521 std::unique_ptr<tUIPC_STATE> UIPC_Init() {
    522   std::unique_ptr<tUIPC_STATE> uipc = std::make_unique<tUIPC_STATE>();
    523   BTIF_TRACE_DEBUG("UIPC_Init");
    524 
    525   std::lock_guard<std::recursive_mutex> lock(uipc->mutex);
    526 
    527   uipc_main_init(*uipc);
    528   uipc_start_main_server_thread(*uipc);
    529 
    530   return uipc;
    531 }
    532 
    533 /*******************************************************************************
    534  **
    535  ** Function         UIPC_Open
    536  **
    537  ** Description      Open UIPC interface
    538  **
    539  ** Returns          true in case of success, false in case of failure.
    540  **
    541  ******************************************************************************/
    542 bool UIPC_Open(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK* p_cback,
    543                const char* socket_path) {
    544   BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
    545 
    546   std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    547 
    548   if (ch_id >= UIPC_CH_NUM) {
    549     return false;
    550   }
    551 
    552   if (uipc.ch[ch_id].srvfd != UIPC_DISCONNECTED) {
    553     BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id);
    554     return 0;
    555   }
    556 
    557   uipc_setup_server_locked(uipc, ch_id, socket_path, p_cback);
    558 
    559   return true;
    560 }
    561 
    562 /*******************************************************************************
    563  **
    564  ** Function         UIPC_Close
    565  **
    566  ** Description      Close UIPC interface
    567  **
    568  ** Returns          void
    569  **
    570  ******************************************************************************/
    571 void UIPC_Close(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id) {
    572   BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id);
    573 
    574   /* special case handling uipc shutdown */
    575   if (ch_id != UIPC_CH_ID_ALL) {
    576     std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    577     uipc_close_locked(uipc, ch_id);
    578     return;
    579   }
    580 
    581   BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete");
    582   uipc_stop_main_server_thread(uipc);
    583   BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete");
    584 }
    585 
    586 /*******************************************************************************
    587  **
    588  ** Function         UIPC_Send
    589  **
    590  ** Description      Called to transmit a message over UIPC.
    591  **
    592  ** Returns          true in case of success, false in case of failure.
    593  **
    594  ******************************************************************************/
    595 bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
    596                UNUSED_ATTR uint16_t msg_evt, const uint8_t* p_buf,
    597                uint16_t msglen) {
    598   BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
    599 
    600   std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    601 
    602   ssize_t ret;
    603   OSI_NO_INTR(ret = write(uipc.ch[ch_id].fd, p_buf, msglen));
    604   if (ret < 0) {
    605     BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
    606   }
    607 
    608   return false;
    609 }
    610 
    611 /*******************************************************************************
    612  **
    613  ** Function         UIPC_Read
    614  **
    615  ** Description      Called to read a message from UIPC.
    616  **
    617  ** Returns          return the number of bytes read.
    618  **
    619  ******************************************************************************/
    620 
    621 uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
    622                    UNUSED_ATTR uint16_t* p_msg_evt, uint8_t* p_buf,
    623                    uint32_t len) {
    624   int n_read = 0;
    625   int fd = uipc.ch[ch_id].fd;
    626   struct pollfd pfd;
    627 
    628   if (ch_id >= UIPC_CH_NUM) {
    629     BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
    630     return 0;
    631   }
    632 
    633   if (fd == UIPC_DISCONNECTED) {
    634     BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
    635     return 0;
    636   }
    637 
    638   while (n_read < (int)len) {
    639     pfd.fd = fd;
    640     pfd.events = POLLIN | POLLHUP;
    641 
    642     /* make sure there is data prior to attempting read to avoid blocking
    643        a read for more than poll timeout */
    644 
    645     int poll_ret;
    646     OSI_NO_INTR(poll_ret = poll(&pfd, 1, uipc.ch[ch_id].read_poll_tmo_ms));
    647     if (poll_ret == 0) {
    648       BTIF_TRACE_WARNING("poll timeout (%d ms)",
    649                          uipc.ch[ch_id].read_poll_tmo_ms);
    650       break;
    651     }
    652     if (poll_ret < 0) {
    653       BTIF_TRACE_ERROR("%s(): poll() failed: return %d errno %d (%s)", __func__,
    654                        poll_ret, errno, strerror(errno));
    655       break;
    656     }
    657 
    658     // BTIF_TRACE_EVENT("poll revents %x", pfd.revents);
    659 
    660     if (pfd.revents & (POLLHUP | POLLNVAL)) {
    661       BTIF_TRACE_WARNING("poll : channel detached remotely");
    662       std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    663       uipc_close_locked(uipc, ch_id);
    664       return 0;
    665     }
    666 
    667     ssize_t n;
    668     OSI_NO_INTR(n = recv(fd, p_buf + n_read, len - n_read, 0));
    669 
    670     // BTIF_TRACE_EVENT("read %d bytes", n);
    671 
    672     if (n == 0) {
    673       BTIF_TRACE_WARNING("UIPC_Read : channel detached remotely");
    674       std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    675       uipc_close_locked(uipc, ch_id);
    676       return 0;
    677     }
    678 
    679     if (n < 0) {
    680       BTIF_TRACE_WARNING("UIPC_Read : read failed (%s)", strerror(errno));
    681       return 0;
    682     }
    683 
    684     n_read += n;
    685   }
    686 
    687   return n_read;
    688 }
    689 
    690 /*******************************************************************************
    691  *
    692  * Function         UIPC_Ioctl
    693  *
    694  * Description      Called to control UIPC.
    695  *
    696  * Returns          void
    697  *
    698  ******************************************************************************/
    699 
    700 extern bool UIPC_Ioctl(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id, uint32_t request,
    701                        void* param) {
    702   BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id,
    703                    request);
    704   std::lock_guard<std::recursive_mutex> lock(uipc.mutex);
    705 
    706   switch (request) {
    707     case UIPC_REQ_RX_FLUSH:
    708       uipc_flush_locked(uipc, ch_id);
    709       break;
    710 
    711     case UIPC_REG_CBACK:
    712       // BTIF_TRACE_EVENT("register callback ch %d srvfd %d, fd %d", ch_id,
    713       // uipc.ch[ch_id].srvfd, uipc.ch[ch_id].fd);
    714       uipc.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
    715       break;
    716 
    717     case UIPC_REG_REMOVE_ACTIVE_READSET:
    718       /* user will read data directly and not use select loop */
    719       if (uipc.ch[ch_id].fd != UIPC_DISCONNECTED) {
    720         /* remove this channel from active set */
    721         FD_CLR(uipc.ch[ch_id].fd, &uipc.active_set);
    722 
    723         /* refresh active set */
    724         uipc_wakeup_locked(uipc);
    725       }
    726       break;
    727 
    728     case UIPC_SET_READ_POLL_TMO:
    729       uipc.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
    730       BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id,
    731                        uipc.ch[ch_id].read_poll_tmo_ms);
    732       break;
    733 
    734     default:
    735       BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request);
    736       break;
    737   }
    738 
    739   return false;
    740 }
    741