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