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