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