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