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 #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 152 BTIF_TRACE_EVENT("create_server_socket %s", name); 153 154 if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0) 155 { 156 BTIF_TRACE_EVENT("socket failed to create (%s)", strerror(errno)); 157 close(s); 158 return -1; 159 } 160 161 if(listen(s, 5) < 0) 162 { 163 BTIF_TRACE_EVENT("listen failed", strerror(errno)); 164 close(s); 165 return -1; 166 } 167 168 BTIF_TRACE_EVENT("created socket fd %d", s); 169 return s; 170 } 171 172 static int accept_server_socket(int sfd) 173 { 174 struct sockaddr_un remote; 175 struct pollfd pfd; 176 int fd; 177 socklen_t len = sizeof(struct sockaddr_un); 178 179 BTIF_TRACE_EVENT("accept fd %d", sfd); 180 181 /* make sure there is data to process */ 182 pfd.fd = sfd; 183 pfd.events = POLLIN; 184 185 if (poll(&pfd, 1, 0) == 0) 186 { 187 BTIF_TRACE_EVENT("accept poll timeout"); 188 return -1; 189 } 190 191 //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents); 192 193 if ((fd = accept(sfd, (struct sockaddr *)&remote, &len)) == -1) 194 { 195 BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno)); 196 return -1; 197 } 198 199 //BTIF_TRACE_EVENT("new fd %d", fd); 200 201 return fd; 202 } 203 204 /***************************************************************************** 205 ** 206 ** uipc helper functions 207 ** 208 *****************************************************************************/ 209 210 static int uipc_main_init(void) 211 { 212 int i; 213 const pthread_mutexattr_t attr = PTHREAD_MUTEX_RECURSIVE; 214 pthread_mutex_init(&uipc_main.mutex, &attr); 215 216 BTIF_TRACE_EVENT("### uipc_main_init ###"); 217 218 /* setup interrupt socket pair */ 219 if (socketpair(AF_UNIX, SOCK_STREAM, 0, uipc_main.signal_fds) < 0) 220 { 221 return -1; 222 } 223 224 FD_SET(uipc_main.signal_fds[0], &uipc_main.active_set); 225 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.signal_fds[0]); 226 227 for (i=0; i< UIPC_CH_NUM; i++) 228 { 229 tUIPC_CHAN *p = &uipc_main.ch[i]; 230 p->srvfd = UIPC_DISCONNECTED; 231 p->fd = UIPC_DISCONNECTED; 232 p->task_evt_flags = 0; 233 pthread_cond_init(&p->cond, NULL); 234 pthread_mutex_init(&p->cond_mutex, NULL); 235 p->cback = NULL; 236 } 237 238 return 0; 239 } 240 241 void uipc_main_cleanup(void) 242 { 243 int i; 244 245 BTIF_TRACE_EVENT("uipc_main_cleanup"); 246 247 close(uipc_main.signal_fds[0]); 248 close(uipc_main.signal_fds[1]); 249 250 /* close any open channels */ 251 for (i=0; i<UIPC_CH_NUM; i++) 252 uipc_close_ch_locked(i); 253 } 254 255 256 257 /* check pending events in read task */ 258 static void uipc_check_task_flags_locked(void) 259 { 260 int i; 261 262 for (i=0; i<UIPC_CH_NUM; i++) 263 { 264 //BTIF_TRACE_EVENT("CHECK TASK FLAGS %x %x", uipc_main.ch[i].task_evt_flags, UIPC_TASK_FLAG_DISCONNECT_CHAN); 265 if (uipc_main.ch[i].task_evt_flags & UIPC_TASK_FLAG_DISCONNECT_CHAN) 266 { 267 uipc_main.ch[i].task_evt_flags &= ~UIPC_TASK_FLAG_DISCONNECT_CHAN; 268 uipc_close_ch_locked(i); 269 } 270 271 /* add here */ 272 273 } 274 } 275 276 277 static int uipc_check_fd_locked(tUIPC_CH_ID ch_id) 278 { 279 if (ch_id >= UIPC_CH_NUM) 280 return -1; 281 282 //BTIF_TRACE_EVENT("CHECK SRVFD %d (ch %d)", uipc_main.ch[ch_id].srvfd, ch_id); 283 284 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].srvfd, &uipc_main.read_set)) 285 { 286 BTIF_TRACE_EVENT("INCOMING CONNECTION ON CH %d", ch_id); 287 288 uipc_main.ch[ch_id].fd = accept_server_socket(uipc_main.ch[ch_id].srvfd); 289 290 BTIF_TRACE_EVENT("NEW FD %d", uipc_main.ch[ch_id].fd); 291 292 if ((uipc_main.ch[ch_id].fd > 0) && uipc_main.ch[ch_id].cback) 293 { 294 /* if we have a callback we should add this fd to the active set 295 and notify user with callback event */ 296 BTIF_TRACE_EVENT("ADD FD %d TO ACTIVE SET", uipc_main.ch[ch_id].fd); 297 FD_SET(uipc_main.ch[ch_id].fd, &uipc_main.active_set); 298 uipc_main.max_fd = MAX(uipc_main.max_fd, uipc_main.ch[ch_id].fd); 299 } 300 301 if (uipc_main.ch[ch_id].fd < 0) 302 { 303 BTIF_TRACE_ERROR("FAILED TO ACCEPT CH %d (%s)", ch_id, strerror(errno)); 304 return -1; 305 } 306 307 if (uipc_main.ch[ch_id].cback) 308 uipc_main.ch[ch_id].cback(ch_id, UIPC_OPEN_EVT); 309 } 310 311 //BTIF_TRACE_EVENT("CHECK FD %d (ch %d)", uipc_main.ch[ch_id].fd, ch_id); 312 313 if (SAFE_FD_ISSET(uipc_main.ch[ch_id].fd, &uipc_main.read_set)) 314 { 315 //BTIF_TRACE_EVENT("INCOMING DATA ON CH %d", ch_id); 316 317 if (uipc_main.ch[ch_id].cback) 318 uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT); 319 } 320 return 0; 321 } 322 323 static void uipc_check_interrupt_locked(void) 324 { 325 if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set)) 326 { 327 char sig_recv = 0; 328 //BTIF_TRACE_EVENT("UIPC INTERRUPT"); 329 recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL); 330 } 331 } 332 333 static inline void uipc_wakeup_locked(void) 334 { 335 char sig_on = 1; 336 BTIF_TRACE_EVENT("UIPC SEND WAKE UP"); 337 send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0); 338 } 339 340 static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback) 341 { 342 int fd; 343 344 BTIF_TRACE_EVENT("SETUP CHANNEL SERVER %d", ch_id); 345 346 if (ch_id >= UIPC_CH_NUM) 347 return -1; 348 349 UIPC_LOCK(); 350 351 fd = create_server_socket(name); 352 353 if (fd < 0) 354 { 355 BTIF_TRACE_ERROR("failed to setup %s", name, strerror(errno)); 356 UIPC_UNLOCK(); 357 return -1; 358 } 359 360 BTIF_TRACE_EVENT("ADD SERVER FD TO ACTIVE SET %d", fd); 361 FD_SET(fd, &uipc_main.active_set); 362 uipc_main.max_fd = MAX(uipc_main.max_fd, fd); 363 364 uipc_main.ch[ch_id].srvfd = fd; 365 uipc_main.ch[ch_id].cback = cback; 366 uipc_main.ch[ch_id].read_poll_tmo_ms = DEFAULT_READ_POLL_TMO_MS; 367 368 /* trigger main thread to update read set */ 369 uipc_wakeup_locked(); 370 371 UIPC_UNLOCK(); 372 373 return 0; 374 } 375 376 static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id) 377 { 378 char buf[UIPC_FLUSH_BUFFER_SIZE]; 379 struct pollfd pfd; 380 int ret; 381 382 pfd.events = POLLIN; 383 pfd.fd = uipc_main.ch[ch_id].fd; 384 385 if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED) 386 { 387 BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__); 388 return; 389 } 390 391 while (1) 392 { 393 ret = poll(&pfd, 1, 1); 394 BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d", 395 __FUNCTION__, pfd.fd, pfd.revents, ret); 396 397 if (pfd.revents & (POLLERR|POLLHUP)) 398 { 399 BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__); 400 return; 401 } 402 403 if (ret <= 0) 404 { 405 BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret); 406 return; 407 } 408 409 /* read sufficiently large buffer to ensure flush empties socket faster than 410 it is getting refilled */ 411 read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE); 412 } 413 } 414 415 416 static void uipc_flush_locked(tUIPC_CH_ID ch_id) 417 { 418 if (ch_id >= UIPC_CH_NUM) 419 return; 420 421 switch(ch_id) 422 { 423 case UIPC_CH_ID_AV_CTRL: 424 uipc_flush_ch_locked(UIPC_CH_ID_AV_CTRL); 425 break; 426 427 case UIPC_CH_ID_AV_AUDIO: 428 uipc_flush_ch_locked(UIPC_CH_ID_AV_AUDIO); 429 break; 430 } 431 } 432 433 434 static int uipc_close_ch_locked(tUIPC_CH_ID ch_id) 435 { 436 int wakeup = 0; 437 438 BTIF_TRACE_EVENT("CLOSE CHANNEL %d", ch_id); 439 440 if (ch_id >= UIPC_CH_NUM) 441 return -1; 442 443 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED) 444 { 445 BTIF_TRACE_EVENT("CLOSE SERVER (FD %d)", uipc_main.ch[ch_id].srvfd); 446 close(uipc_main.ch[ch_id].srvfd); 447 FD_CLR(uipc_main.ch[ch_id].srvfd, &uipc_main.active_set); 448 uipc_main.ch[ch_id].srvfd = UIPC_DISCONNECTED; 449 wakeup = 1; 450 } 451 452 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED) 453 { 454 BTIF_TRACE_EVENT("CLOSE CONNECTION (FD %d)", uipc_main.ch[ch_id].fd); 455 close(uipc_main.ch[ch_id].fd); 456 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set); 457 uipc_main.ch[ch_id].fd = UIPC_DISCONNECTED; 458 wakeup = 1; 459 } 460 461 /* notify this connection is closed */ 462 if (uipc_main.ch[ch_id].cback) 463 uipc_main.ch[ch_id].cback(ch_id, UIPC_CLOSE_EVT); 464 465 /* trigger main thread update if something was updated */ 466 if (wakeup) 467 uipc_wakeup_locked(); 468 469 return 0; 470 } 471 472 473 void uipc_close_locked(tUIPC_CH_ID ch_id) 474 { 475 if (uipc_main.ch[ch_id].srvfd == UIPC_DISCONNECTED) 476 { 477 BTIF_TRACE_EVENT("CHANNEL %d ALREADY CLOSED", ch_id); 478 return; 479 } 480 481 /* schedule close on this channel */ 482 uipc_main.ch[ch_id].task_evt_flags |= UIPC_TASK_FLAG_DISCONNECT_CHAN; 483 uipc_wakeup_locked(); 484 } 485 486 487 static void uipc_read_task(void *arg) 488 { 489 int ch_id; 490 int result; 491 UNUSED(arg); 492 493 prctl(PR_SET_NAME, (unsigned long)"uipc-main", 0, 0, 0); 494 495 raise_priority_a2dp(TASK_UIPC_READ); 496 497 while (uipc_main.running) 498 { 499 uipc_main.read_set = uipc_main.active_set; 500 501 result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL); 502 503 if (result == 0) 504 { 505 BTIF_TRACE_EVENT("select timeout"); 506 continue; 507 } 508 else if (result < 0) 509 { 510 BTIF_TRACE_EVENT("select failed %s", strerror(errno)); 511 continue; 512 } 513 514 UIPC_LOCK(); 515 516 /* clear any wakeup interrupt */ 517 uipc_check_interrupt_locked(); 518 519 /* check pending task events */ 520 uipc_check_task_flags_locked(); 521 522 /* make sure we service audio channel first */ 523 uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO); 524 525 /* check for other connections */ 526 for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++) 527 { 528 if (ch_id != UIPC_CH_ID_AV_AUDIO) 529 uipc_check_fd_locked(ch_id); 530 } 531 532 UIPC_UNLOCK(); 533 } 534 535 BTIF_TRACE_EVENT("UIPC READ THREAD EXITING"); 536 537 uipc_main_cleanup(); 538 539 uipc_main.tid = 0; 540 541 BTIF_TRACE_EVENT("UIPC READ THREAD DONE"); 542 } 543 544 545 int uipc_start_main_server_thread(void) 546 { 547 uipc_main.running = 1; 548 549 if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0) 550 { 551 BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno); 552 return -1; 553 } 554 555 return 0; 556 } 557 558 /* blocking call */ 559 void uipc_stop_main_server_thread(void) 560 { 561 /* request shutdown of read thread */ 562 UIPC_LOCK(); 563 uipc_main.running = 0; 564 uipc_wakeup_locked(); 565 UIPC_UNLOCK(); 566 567 /* wait until read thread is fully terminated */ 568 if (uipc_main.tid > 0) 569 pthread_join(uipc_main.tid, NULL); 570 } 571 572 /******************************************************************************* 573 ** 574 ** Function UIPC_Init 575 ** 576 ** Description Initialize UIPC module 577 ** 578 ** Returns void 579 ** 580 *******************************************************************************/ 581 582 UDRV_API void UIPC_Init(void *p_data) 583 { 584 UNUSED(p_data); 585 586 BTIF_TRACE_DEBUG("UIPC_Init"); 587 588 memset(&uipc_main, 0, sizeof(tUIPC_MAIN)); 589 590 uipc_main_init(); 591 592 uipc_start_main_server_thread(); 593 } 594 595 /******************************************************************************* 596 ** 597 ** Function UIPC_Open 598 ** 599 ** Description Open UIPC interface 600 ** 601 ** Returns TRUE in case of success, FALSE in case of failure. 602 ** 603 *******************************************************************************/ 604 UDRV_API BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback) 605 { 606 BTIF_TRACE_DEBUG("UIPC_Open : ch_id %d, p_cback %x", ch_id, p_cback); 607 608 UIPC_LOCK(); 609 610 if (ch_id >= UIPC_CH_NUM) 611 { 612 UIPC_UNLOCK(); 613 return FALSE; 614 } 615 616 if (uipc_main.ch[ch_id].srvfd != UIPC_DISCONNECTED) 617 { 618 BTIF_TRACE_EVENT("CHANNEL %d ALREADY OPEN", ch_id); 619 UIPC_UNLOCK(); 620 return 0; 621 } 622 623 switch(ch_id) 624 { 625 case UIPC_CH_ID_AV_CTRL: 626 uipc_setup_server_locked(ch_id, A2DP_CTRL_PATH, p_cback); 627 break; 628 629 case UIPC_CH_ID_AV_AUDIO: 630 uipc_setup_server_locked(ch_id, A2DP_DATA_PATH, p_cback); 631 break; 632 } 633 634 UIPC_UNLOCK(); 635 636 return TRUE; 637 } 638 639 /******************************************************************************* 640 ** 641 ** Function UIPC_Close 642 ** 643 ** Description Close UIPC interface 644 ** 645 ** Returns void 646 ** 647 *******************************************************************************/ 648 649 UDRV_API void UIPC_Close(tUIPC_CH_ID ch_id) 650 { 651 BTIF_TRACE_DEBUG("UIPC_Close : ch_id %d", ch_id); 652 653 /* special case handling uipc shutdown */ 654 if (ch_id != UIPC_CH_ID_ALL) 655 { 656 UIPC_LOCK(); 657 uipc_close_locked(ch_id); 658 UIPC_UNLOCK(); 659 } 660 else 661 { 662 BTIF_TRACE_DEBUG("UIPC_Close : waiting for shutdown to complete"); 663 uipc_stop_main_server_thread(); 664 BTIF_TRACE_DEBUG("UIPC_Close : shutdown complete"); 665 } 666 } 667 668 /******************************************************************************* 669 ** 670 ** Function UIPC_SendBuf 671 ** 672 ** Description Called to transmit a message over UIPC. 673 ** Message buffer will be freed by UIPC_SendBuf. 674 ** 675 ** Returns TRUE in case of success, FALSE in case of failure. 676 ** 677 *******************************************************************************/ 678 UDRV_API BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg) 679 { 680 UNUSED(p_msg); 681 682 BTIF_TRACE_DEBUG("UIPC_SendBuf : ch_id %d NOT IMPLEMENTED", ch_id); 683 684 UIPC_LOCK(); 685 686 /* currently not used */ 687 688 UIPC_UNLOCK(); 689 690 return FALSE; 691 } 692 693 /******************************************************************************* 694 ** 695 ** Function UIPC_Send 696 ** 697 ** Description Called to transmit a message over UIPC. 698 ** 699 ** Returns TRUE in case of success, FALSE in case of failure. 700 ** 701 *******************************************************************************/ 702 UDRV_API BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf, 703 UINT16 msglen) 704 { 705 int n; 706 UNUSED(msg_evt); 707 708 BTIF_TRACE_DEBUG("UIPC_Send : ch_id:%d %d bytes", ch_id, msglen); 709 710 UIPC_LOCK(); 711 712 if (write(uipc_main.ch[ch_id].fd, p_buf, msglen) < 0) 713 { 714 BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno)); 715 } 716 717 UIPC_UNLOCK(); 718 719 return FALSE; 720 } 721 722 /******************************************************************************* 723 ** 724 ** Function UIPC_ReadBuf 725 ** 726 ** Description Called to read a message from UIPC. 727 ** 728 ** Returns void 729 ** 730 *******************************************************************************/ 731 UDRV_API void UIPC_ReadBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg) 732 { 733 UNUSED(p_msg); 734 735 BTIF_TRACE_DEBUG("UIPC_ReadBuf : ch_id:%d NOT IMPLEMENTED", ch_id); 736 737 UIPC_LOCK(); 738 UIPC_UNLOCK(); 739 } 740 741 /******************************************************************************* 742 ** 743 ** Function UIPC_Read 744 ** 745 ** Description Called to read a message from UIPC. 746 ** 747 ** Returns return the number of bytes read. 748 ** 749 *******************************************************************************/ 750 751 UDRV_API UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len) 752 { 753 int n; 754 int n_read = 0; 755 int fd = uipc_main.ch[ch_id].fd; 756 struct pollfd pfd; 757 UNUSED(p_msg_evt); 758 759 if (ch_id >= UIPC_CH_NUM) 760 { 761 BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id); 762 return 0; 763 } 764 765 if (fd == UIPC_DISCONNECTED) 766 { 767 BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id); 768 return 0; 769 } 770 771 //BTIF_TRACE_DEBUG("UIPC_Read : ch_id %d, len %d, fd %d, polltmo %d", ch_id, len, 772 // fd, uipc_main.ch[ch_id].read_poll_tmo_ms); 773 774 while (n_read < (int)len) 775 { 776 pfd.fd = fd; 777 pfd.events = POLLIN|POLLHUP; 778 779 /* make sure there is data prior to attempting read to avoid blocking 780 a read for more than poll timeout */ 781 if (poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms) == 0) 782 { 783 BTIF_TRACE_EVENT("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms); 784 break; 785 } 786 787 //BTIF_TRACE_EVENT("poll revents %x", pfd.revents); 788 789 if (pfd.revents & (POLLHUP|POLLNVAL) ) 790 { 791 BTIF_TRACE_EVENT("poll : channel detached remotely"); 792 UIPC_LOCK(); 793 uipc_close_locked(ch_id); 794 UIPC_UNLOCK(); 795 return 0; 796 } 797 798 n = recv(fd, p_buf+n_read, len-n_read, 0); 799 800 //BTIF_TRACE_EVENT("read %d bytes", n); 801 802 if (n == 0) 803 { 804 BTIF_TRACE_EVENT("UIPC_Read : channel detached remotely"); 805 UIPC_LOCK(); 806 uipc_close_locked(ch_id); 807 UIPC_UNLOCK(); 808 return 0; 809 } 810 811 if (n < 0) 812 { 813 BTIF_TRACE_EVENT("UIPC_Read : read failed (%s)", strerror(errno)); 814 return 0; 815 } 816 817 n_read+=n; 818 819 } 820 821 return n_read; 822 } 823 824 /******************************************************************************* 825 ** 826 ** Function UIPC_Ioctl 827 ** 828 ** Description Called to control UIPC. 829 ** 830 ** Returns void 831 ** 832 *******************************************************************************/ 833 834 UDRV_API extern BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param) 835 { 836 BTIF_TRACE_DEBUG("#### UIPC_Ioctl : ch_id %d, request %d ####", ch_id, request); 837 838 UIPC_LOCK(); 839 840 switch(request) 841 { 842 case UIPC_REQ_RX_FLUSH: 843 uipc_flush_locked(ch_id); 844 break; 845 846 case UIPC_REG_CBACK: 847 //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); 848 uipc_main.ch[ch_id].cback = (tUIPC_RCV_CBACK*)param; 849 break; 850 851 case UIPC_REG_REMOVE_ACTIVE_READSET: 852 853 /* user will read data directly and not use select loop */ 854 if (uipc_main.ch[ch_id].fd != UIPC_DISCONNECTED) 855 { 856 /* remove this channel from active set */ 857 FD_CLR(uipc_main.ch[ch_id].fd, &uipc_main.active_set); 858 859 /* refresh active set */ 860 uipc_wakeup_locked(); 861 } 862 break; 863 864 case UIPC_SET_READ_POLL_TMO: 865 uipc_main.ch[ch_id].read_poll_tmo_ms = (intptr_t)param; 866 BTIF_TRACE_EVENT("UIPC_SET_READ_POLL_TMO : CH %d, TMO %d ms", ch_id, uipc_main.ch[ch_id].read_poll_tmo_ms ); 867 break; 868 869 default: 870 BTIF_TRACE_EVENT("UIPC_Ioctl : request not handled (%d)", request); 871 break; 872 } 873 874 UIPC_UNLOCK(); 875 876 return FALSE; 877 } 878 879