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
dump_uipc_event(tUIPC_EVENT event)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
create_server_socket(const char * name)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
accept_server_socket(int sfd)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
uipc_main_init(void)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
uipc_main_cleanup(void)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 */
uipc_check_task_flags_locked(void)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
uipc_check_fd_locked(tUIPC_CH_ID ch_id)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
uipc_check_interrupt_locked(void)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
uipc_wakeup_locked(void)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
uipc_setup_server_locked(tUIPC_CH_ID ch_id,char * name,tUIPC_RCV_CBACK * cback)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
uipc_flush_ch_locked(tUIPC_CH_ID ch_id)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
uipc_flush_locked(tUIPC_CH_ID ch_id)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
uipc_close_ch_locked(tUIPC_CH_ID ch_id)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
uipc_close_locked(tUIPC_CH_ID ch_id)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
uipc_read_task(void * arg)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
uipc_start_main_server_thread(void)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 */
uipc_stop_main_server_thread(void)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
UIPC_Init(void * p_data)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 *******************************************************************************/
UIPC_Open(tUIPC_CH_ID ch_id,tUIPC_RCV_CBACK * p_cback)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
UIPC_Close(tUIPC_CH_ID ch_id)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 *******************************************************************************/
UIPC_SendBuf(tUIPC_CH_ID ch_id,BT_HDR * p_msg)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 *******************************************************************************/
UIPC_Send(tUIPC_CH_ID ch_id,UINT16 msg_evt,UINT8 * p_buf,UINT16 msglen)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 *******************************************************************************/
UIPC_ReadBuf(tUIPC_CH_ID ch_id,BT_HDR * p_msg)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
UIPC_Read(tUIPC_CH_ID ch_id,UINT16 * p_msg_evt,UINT8 * p_buf,UINT32 len)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
UIPC_Ioctl(tUIPC_CH_ID ch_id,UINT32 request,void * param)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