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