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