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