1 /******************************************************************************
3 * Copyright (C) 2009-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /*****************************************************************************
23 * Description: UIPC implementation for bluedroid
25 *****************************************************************************/
36 #include <sys/prctl.h>
37 #include <sys/select.h>
38 #include <sys/socket.h>
43 #include "audio_a2dp_hw.h"
47 #include "osi/include/socket_utils/sockets.h"
50 /*****************************************************************************
52 ******************************************************************************/
54 #define PCM_FILENAME "/data/test.pcm"
56 #define MAX(a,b) ((a)>(b)?(a):(b))
58 #define CASE_RETURN_STR(const) case const: return #const;
60 #define UIPC_DISCONNECTED (-1)
62 #define UIPC_LOCK() /*BTIF_TRACE_EVENT(" %s lock", __FUNCTION__);*/ pthread_mutex_lock(&uipc_main.mutex);
63 #define UIPC_UNLOCK() /*BTIF_TRACE_EVENT("%s unlock", __FUNCTION__);*/ pthread_mutex_unlock(&uipc_main.mutex);
65 #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? FALSE : FD_ISSET((fd), (set)))
67 #define UIPC_FLUSH_BUFFER_SIZE 1024
69 /*****************************************************************************
70 ** Local type definitions
71 ******************************************************************************/
74 UIPC_TASK_FLAG_DISCONNECT_CHAN = 0x1,
81 int task_evt_flags; /* event flags pending to be processed in read task */
82 tUIPC_EVENT cond_flags;
83 pthread_mutex_t cond_mutex;
85 tUIPC_RCV_CBACK *cback;
89 pthread_t tid; /* main thread id */
91 pthread_mutex_t mutex;
98 tUIPC_CHAN ch[UIPC_CH_NUM];
102 /*****************************************************************************
104 ******************************************************************************/
106 static tUIPC_MAIN uipc_main;
109 /*****************************************************************************
111 ******************************************************************************/
113 static int uipc_close_ch_locked(tUIPC_CH_ID ch_id);
115 /*****************************************************************************
117 ******************************************************************************/
120 /*****************************************************************************
122 ******************************************************************************/
125 const char* dump_uipc_event(tUIPC_EVENT event)
129 CASE_RETURN_STR(UIPC_OPEN_EVT)
130 CASE_RETURN_STR(UIPC_CLOSE_EVT)
131 CASE_RETURN_STR(UIPC_RX_DATA_EVT)
132 CASE_RETURN_STR(UIPC_RX_DATA_READY_EVT)
133 CASE_RETURN_STR(UIPC_TX_DATA_READY_EVT)
135 return "UNKNOWN MSG ID";
139 /*****************************************************************************
140 ** socket helper functions
141 *****************************************************************************/
143 static inline int create_server_socket(const char* name)
145 int s = socket(AF_LOCAL, SOCK_STREAM, 0);
149 BTIF_TRACE_EVENT("create_server_socket %s", name);
151 if(osi_socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
153 BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno));
160 BTIF_TRACE_EVENT("listen failed", strerror(errno));
165 BTIF_TRACE_EVENT("created socket fd %d", s);
169 static int accept_server_socket(int sfd)
171 struct sockaddr_un remote;
174 socklen_t len = sizeof(struct sockaddr_un);
176 BTIF_TRACE_EVENT("accept fd %d", sfd);
178 /* make sure there is data to process */
182 if (poll(&pfd, 1, 0) == 0)
184 BTIF_TRACE_EVENT("accept poll timeout");
188 //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents);
190 if ((fd = accept(sfd, (struct sockaddr *)&remote, &len)) == -1)
192 BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno));
196 //BTIF_TRACE_EVENT("new fd %d", fd);
201 /*****************************************************************************
203 ** uipc helper functions
205 *****************************************************************************/
207 static int uipc_main_init(void)
210 pthread_mutexattr_t attr;
211 pthread_mutexattr_init(&attr);
212 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
213 pthread_mutex_init(&uipc_main.mutex, &attr);
215 BTIF_TRACE_EVENT("### uipc_main_init ###");
217 /* setup interrupt socket pair */
218 if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0)
223 FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set);
224 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]);
226 for (i=0; i< UIPC_CH_NUM; i++)
228 tUIPC_CHAN *p = &uipc_main.ch[i];
229 p->srvfd = UIPC_DISCONNECTED;
230 p->fd = UIPC_DISCONNECTED;
231 p->task_evt_flags = 0;
232 pthread_cond_init(&p->cond, NULL);
233 pthread_mutex_init(&p->cond_mutex, NULL);
240 void uipc_main_cleanup(void)
244 BTIF_TRACE_EVENT("uipc_main_cleanup");
246 close(uipc_main.signal_fds[0]);
247 close(uipc_main.signal_fds[1]);
249 /* close any open channels */
250 for (i=0; i<UIPC_CH_NUM; i++)
251 uipc_close_ch_locked(i);
256 /* check pending events in read task */
257 static void uipc_check_task_flags_locked(void)
261 for (i=0; i<UIPC_CH_NUM; i++)
263 //BTIF_TRACE_EVENT("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN);
264 if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN)
266 uipc_main.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN;
267 uipc_close_ch_locked(i);
276 static int uipc_check_fd_locked(tUIPC_CH_ID ch_id)
278 if (ch_id >= UIPC_CH_NUM)
281 //BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id);
283 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set))
285 BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id);
287 uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd);
289 BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd);
291 if ((uipc_main.ch[ch_id].fd > 0) && uipc_main.ch[ch_id].cback)
293 /* if we have a callback we should add this fd to the active set
294 and notify user with callback event */
295 BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd);
296 FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
297 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd);
300 if (uipc_main.ch[ch_id].fd < 0)
302 BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno));
306 if (uipc_main.ch[ch_id].cback)
307 uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT);
310 //BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id);
312 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set))
314 //BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id);
316 if (uipc_main.ch[ch_id].cback)
317 uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
322 static void uipc_check_interrupt_locked(void)
324 if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set))
327 //BTIF_TRACE_EVENT("UIPC INTERRUPT");
328 recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
332 static inline void uipc_wakeup_locked(void)
335 BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
336 send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0);
339 static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
343 BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id);
345 if (ch_id >= UIPC_CH_NUM)
350 fd = create_server_socket(name);
354 BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno));
359 BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd);
360 FD_SET(fd, &uipc_main.active_set);
361 uipc_main.max_fd = MAX(uipc_main.max_fd, fd);
363 uipc_main.ch[ch_id].srvfd = fd;
364 uipc_main.ch[ch_id].cback = cback;
365 uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS;
367 /* trigger main thread to update read set */
368 uipc_wakeup_locked();
375 static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id)
377 char buf[UIPC_FLUSH_BUFFER_SIZE];
382 pfd.fd = uipc_main.ch[ch_id].fd;
384 if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED)
386 BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__);
392 ret = poll(&pfd, 1, 1);
393 BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d",
394 __FUNCTION__, pfd.fd, pfd.revents, ret);
396 if (pfd.revents & (POLLERR|POLLHUP))
398 BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__);
404 BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret);
408 /* read sufficiently large buffer to ensure flush empties socket faster than
409 it is getting refilled */
410 read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE);
415 static void uipc_flush_locked(tUIPC_CH_ID ch_id)
417 if (ch_id >= UIPC_CH_NUM)
422 case UIPC_CH_ID_AV_CTRL:
423 uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL);
426 case UIPC_CH_ID_AV_AUDIO:
427 uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO);
433 static int uipc_close_ch_locked(tUIPC_CH_ID ch_id)
437 BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id);
439 if (ch_id >= UIPC_CH_NUM)
442 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
444 BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd);
445 close(uipc_main.ch[ch_id].srvfd);
446 FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set);
447 uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED;
451 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
453 BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd);
454 close(uipc_main.ch[ch_id].fd);
455 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
456 uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED;
460 /* notify this connection is closed */
461 if (uipc_main.ch[ch_id].cback)
462 uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT);
464 /* trigger main thread update if something was updated */
466 uipc_wakeup_locked();
472 void uipc_close_locked(tUIPC_CH_ID ch_id)
474 if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED)
476 BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id);
480 /* schedule close on this channel */
481 uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN;
482 uipc_wakeup_locked();
486 static void uipc_read_task(void *arg)
492 prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0);
494 raise_priority_a2dp(TASK_UIPC_READ);
496 while (uipc_main.running)
498 uipc_main.read_set = uipc_main.active_set;
500 result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL);
504 BTIF_TRACE_EVENT("select timeout");
509 BTIF_TRACE_EVENT("select failed %s", strerror(errno));
515 /* clear any wakeup interrupt */
516 uipc_check_interrupt_locked();
518 /* check pending task events */
519 uipc_check_task_flags_locked();
521 /* make sure we service audio channel first */
522 uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
524 /* check for other connections */
525 for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++)
527 if (ch_id != UIPC_CH_ID_AV_AUDIO)
528 uipc_check_fd_locked(ch_id);
534 BTIF_TRACE_EVENT("UIPC READ THREAD EXITING");
540 BTIF_TRACE_EVENT("UIPC READ THREAD DONE");
544 int uipc_start_main_server_thread(void)
546 uipc_main.running = 1;
548 if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0)
550 BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
558 void uipc_stop_main_server_thread(void)
560 /* request shutdown of read thread */
562 uipc_main.running = 0;
563 uipc_wakeup_locked();
566 /* wait until read thread is fully terminated */
567 /* tid might hold pointer value where it's value
568 is negative vaule with singed bit is set, so
569 corrected the logic to check zero or non zero */
571 pthread_join(uipc_main.tid, NULL);
574 /*******************************************************************************
576 ** Function UIPC_Init
578 ** Description Initialize UIPC module
582 *******************************************************************************/
584 void UIPC_Init(void *p_data)
588 BTIF_TRACE_DEBUG("UIPC_Init");
590 memset(&uipc_main, 0, sizeof(tUIPC_MAIN));
594 uipc_start_main_server_thread();
597 /*******************************************************************************
599 ** Function UIPC_Open
601 ** Description Open UIPC interface
603 ** Returns TRUE in case of success, FALSE in case of failure.
605 *******************************************************************************/
606 BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback)
608 BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback);
612 if (ch_id >= UIPC_CH_NUM)
618 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED)
620 BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id);
627 case UIPC_CH_ID_AV_CTRL:
628 uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback);
631 case UIPC_CH_ID_AV_AUDIO:
632 uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback);
641 /*******************************************************************************
643 ** Function UIPC_Close
645 ** Description Close UIPC interface
649 *******************************************************************************/
651 void UIPC_Close(tUIPC_CH_ID ch_id)
653 BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id);
655 /* special case handling uipc shutdown */
656 if (ch_id != UIPC_CH_ID_ALL)
659 uipc_close_locked(ch_id);
664 BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete");
665 uipc_stop_main_server_thread();
666 BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete");
670 /*******************************************************************************
672 ** Function UIPC_SendBuf
674 ** Description Called to transmit a message over UIPC.
675 ** Message buffer will be freed by UIPC_SendBuf.
677 ** Returns TRUE in case of success, FALSE in case of failure.
679 *******************************************************************************/
680 BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
684 BTIF_TRACE_DEBUG("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id);
688 /* currently not used */
695 /*******************************************************************************
697 ** Function UIPC_Send
699 ** Description Called to transmit a message over UIPC.
701 ** Returns TRUE in case of success, FALSE in case of failure.
703 *******************************************************************************/
704 BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf,
709 BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen);
713 if (write(uipc_main.ch[ch_id].fd, p_buf, msglen) < 0)
715 BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
723 /*******************************************************************************
725 ** Function UIPC_ReadBuf
727 ** Description Called to read a message from UIPC.
731 *******************************************************************************/
732 void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg)
736 BTIF_TRACE_DEBUG("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id);
742 /*******************************************************************************
744 ** Function UIPC_Read
746 ** Description Called to read a message from UIPC.
748 ** Returns return the number of bytes read.
750 *******************************************************************************/
752 UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len)
756 int fd = uipc_main.ch[ch_id].fd;
760 if (ch_id >= UIPC_CH_NUM)
762 BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
766 if (fd == UIPC_DISCONNECTED)
768 BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
772 //BTIF_TRACE_DEBUG("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len,
773 // fd, uipc_main.ch[ch_id].read_poll_tmo_ms);
775 while (n_read < (int)len)
778 pfd.events = POLLIN|POLLHUP;
780 /* make sure there is data prior to attempting read to avoid blocking
781 a read for more than poll timeout */
782 if (poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms) == 0)
784 BTIF_TRACE_EVENT("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms);
788 //BTIF_TRACE_EVENT("poll revents %x", pfd.revents);
790 if (pfd.revents & (POLLHUP|POLLNVAL) )
792 BTIF_TRACE_EVENT("poll : channel detached remotely");
794 uipc_close_locked(ch_id);
799 n = recv(fd, p_buf+n_read, len-n_read, 0);
801 //BTIF_TRACE_EVENT("read %d bytes", n);
805 BTIF_TRACE_EVENT("UIPC_Read : channel detached remotely");
807 uipc_close_locked(ch_id);
814 BTIF_TRACE_EVENT("UIPC_Read : read failed (%s)", strerror(errno));
825 /*******************************************************************************
827 ** Function UIPC_Ioctl
829 ** Description Called to control UIPC.
833 *******************************************************************************/
835 extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param)
837 BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request);
843 case UIPC_REQ_RX_FLUSH:
844 uipc_flush_locked(ch_id);
848 //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);
849 uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param;
852 case UIPC_REG_REMOVE_ACTIVE_READSET:
854 /* user will read data directly and not use select loop */
855 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED)
857 /* remove this channel from active set */
858 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set);
860 /* refresh active set */
861 uipc_wakeup_locked();
865 case UIPC_SET_READ_POLL_TMO:
866 uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param;
867 BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id, uipc_main.ch[ch_id].read_poll_tmo_ms );
871 BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request);