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