1 /* 2 * User Mode Init manager - For TI shared transport 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program;if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 #include <stdio.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <signal.h> 23 #include <sys/ioctl.h> 24 #include <termios.h> 25 #include <poll.h> 26 #include <stdint.h> 27 #include <stdlib.h> 28 #include <sys/stat.h> 29 #include <sys/utsname.h> 30 #ifdef ANDROID 31 #include <private/android_filesystem_config.h> 32 #include <cutils/log.h> 33 #endif 34 35 #ifdef ANDROID 36 #include <common/ppoll.h> /* for ppoll */ 37 #endif 38 #include "uim.h" 39 40 #ifndef ANDROID 41 #define INCLUDE_FM 0 42 #endif 43 44 /* Maintains the exit state of UIM*/ 45 static int exiting; 46 47 /* UART configuration parameters*/ 48 int uart_flow_control; 49 int cust_baud_rate; 50 char uart_dev_name[15]; 51 unsigned int uart_baud_rate; 52 struct termios ti; 53 int line_discipline; 54 55 /* BD address as string and a pointer to array of hex bytes */ 56 char uim_bd_address[17]; 57 bdaddr_t *bd_addr; 58 59 /* File descriptor for the UART device*/ 60 int dev_fd; 61 62 /* Maintains the state of N_TI_WL line discipline installation*/ 63 unsigned char st_state = UNINSTALL_N_TI_WL; 64 unsigned char prev_st_state = UNINSTALL_N_TI_WL; 65 66 /* from kernel's include/linux/rfkill.h 67 * the header in itself not included because of the 68 * version mismatch of android kernel headers project 69 */ 70 71 /** 72 * enum rfkill_operation - operation types 73 * @RFKILL_OP_ADD: a device was added 74 * @RFKILL_OP_DEL: a device was removed 75 * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device 76 * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all) 77 */ 78 enum rfkill_operation { 79 RFKILL_OP_ADD = 0, 80 RFKILL_OP_DEL, 81 RFKILL_OP_CHANGE, 82 RFKILL_OP_CHANGE_ALL, 83 }; 84 85 /** 86 * struct rfkill_event - events for userspace on /dev/rfkill 87 * @idx: index of dev rfkill 88 * @type: type of the rfkill struct 89 * @op: operation code 90 * @hard: hard state (0/1) 91 * @soft: soft state (0/1) 92 * 93 * Structure used for userspace communication on /dev/rfkill, 94 * used for events from the kernel and control to the kernel. 95 */ 96 #ifdef ANDROID 97 struct rfkill_event { 98 __u32 idx; 99 __u8 type; 100 __u8 op; 101 __u8 soft, hard; 102 } __packed; 103 #else 104 struct rfkill_event { 105 uint32_t idx; 106 uint8_t type; 107 uint8_t op; 108 uint8_t soft, hard; 109 } __packed; 110 #endif /* ANDROID */ 111 112 /* to read events and filter notifications for us */ 113 struct rfkill_event rf_event; 114 unsigned int rfkill_idx; 115 116 /*****************************************************************************/ 117 #ifdef UIM_DEBUG 118 /* Function to Read the firmware version 119 * module into the system. Currently used for 120 * debugging purpose, whenever the baud rate is changed 121 */ 122 void read_firmware_version() 123 { 124 int index = 0; 125 char resp_buffer[20] = { 0 }; 126 unsigned char buffer[] = { 0x01, 0x01, 0x10, 0x00 }; 127 128 UIM_START_FUNC(); 129 UIM_VER(" wrote %d bytes", (int)write(dev_fd, buffer, 4)); 130 UIM_VER(" reading %d bytes", (int)read(dev_fd, resp_buffer, 15)); 131 132 for (index = 0; index < 15; index++) { 133 UIM_VER(" %x ", resp_buffer[index]); 134 } 135 136 printf("\n"); 137 } 138 #endif 139 140 /*****************************************************************************/ 141 #ifdef ANDROID /* library for android to do insmod/rmmod */ 142 143 /* Function to insert the kernel module into the system*/ 144 static int insmod(const char *filename, const char *args) 145 { 146 void *module; 147 unsigned int size; 148 int ret = -1; 149 150 UIM_START_FUNC(); 151 152 module = (void *)load_file(filename, &size); 153 if (!module) { 154 return ret; 155 } 156 157 ret = init_module(module, size, args); 158 free(module); 159 160 return ret; 161 } 162 163 /* Function to remove the kernel module from the system*/ 164 static int rmmod(const char *modname) 165 { 166 int ret = -1; 167 int maxtry = MAX_TRY; 168 169 UIM_START_FUNC(); 170 171 /* Retry MAX_TRY number of times in case of 172 * failure 173 */ 174 while (maxtry-- > 0) { 175 ret = delete_module(modname, O_NONBLOCK | O_EXCL); 176 if (ret < 0 && errno == EAGAIN) { 177 sleep(1); 178 } 179 else 180 break; 181 } 182 183 /* Failed to remove the module 184 */ 185 if (ret != 0) { 186 UIM_ERR("Unable to unload driver module \"%s\": %s", 187 modname, strerror(errno)); 188 } 189 return ret; 190 } 191 #endif /*ANDROID*/ 192 193 /*****************************************************************************/ 194 /* Function to read the HCI event from the given file descriptor 195 * 196 * This will parse the response received and returns error 197 * if the required response is not received 198 */ 199 int read_hci_event(int fd, unsigned char *buf, int size) 200 { 201 int remain, rd; 202 int count = 0; 203 int reading = 1; 204 int rd_retry_count = 0; 205 struct timespec tm = {0, 50*1000*1000}; 206 207 UIM_START_FUNC(); 208 209 UIM_VER(" read_hci_event"); 210 if (size <= 0) { 211 return -1; 212 } 213 214 /* The first byte identifies the packet type. For HCI event packets, it 215 * should be 0x04, so we read until we get to the 0x04. */ 216 while (reading) { 217 rd = read(fd, buf, 1); 218 if (rd <= 0 && rd_retry_count++ < 4) { 219 nanosleep(&tm, NULL); 220 continue; 221 } else if (rd_retry_count >= 4) { 222 return -1; 223 } 224 225 if (buf[0] == RESP_PREFIX) { 226 break; 227 } 228 } 229 count++; 230 231 /* The next two bytes are the event code and parameter total length. */ 232 while (count < 3) { 233 rd = read(fd, buf + count, 3 - count); 234 if (rd <= 0) { 235 return -1; 236 } 237 count += rd; 238 } 239 240 /* Now we read the parameters. */ 241 if (buf[2] < (size - 3)) { 242 remain = buf[2]; 243 } else { 244 remain = size - 3; 245 } 246 247 while ((count - 3) < remain) { 248 rd = read(fd, buf + count, remain - (count - 3)); 249 if (rd <= 0) { 250 return -1; 251 } 252 count += rd; 253 } 254 255 return count; 256 } 257 258 /* Function to read the Command complete event 259 * 260 * This will read the response for the change speed 261 * command that was sent to configure the UART speed 262 * with the custom baud rate 263 */ 264 static int read_command_complete(int fd, unsigned short opcode) 265 { 266 command_complete_t resp; 267 268 UIM_START_FUNC(); 269 270 UIM_VER(" Command complete started"); 271 if (read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0) { 272 UIM_ERR(" Invalid response"); 273 return -1; 274 } 275 276 /* Response should be an event packet */ 277 if (resp.uart_prefix != HCI_EVENT_PKT) { 278 UIM_ERR 279 (" Error in response: not an event packet, but 0x%02x!", 280 resp.uart_prefix); 281 return -1; 282 } 283 284 /* Response should be a command complete event */ 285 if (resp.hci_hdr.evt != EVT_CMD_COMPLETE) { 286 /* event must be event-complete */ 287 UIM_ERR 288 (" Error in response: not a cmd-complete event,but 0x%02x!", 289 resp.hci_hdr.evt); 290 return -1; 291 } 292 293 if (resp.hci_hdr.plen < 4) { 294 /* plen >= 4 for EVT_CMD_COMPLETE */ 295 UIM_ERR(" Error in response: plen is not >= 4, but 0x%02x!", 296 resp.hci_hdr.plen); 297 return -1; 298 } 299 300 if (resp.cmd_complete.opcode != (unsigned short)opcode) { 301 UIM_ERR(" Error in response: opcode is 0x%04x, not 0x%04x!", 302 resp.cmd_complete.opcode, opcode); 303 return -1; 304 } 305 306 UIM_DBG(" Command complete done"); 307 return resp.status == 0 ? 0 : -1; 308 } 309 310 /* Function to set the default baud rate 311 * 312 * The default baud rate of 115200 is set to the UART from the host side 313 * by making a call to this function.This function is also called before 314 * making a call to set the custom baud rate 315 */ 316 static int set_baud_rate() 317 { 318 UIM_START_FUNC(); 319 320 tcflush(dev_fd, TCIOFLUSH); 321 322 /* Get the attributes of UART */ 323 if (tcgetattr(dev_fd, &ti) < 0) { 324 UIM_ERR(" Can't get port settings"); 325 return -1; 326 } 327 328 /* Change the UART attributes before 329 * setting the default baud rate*/ 330 cfmakeraw(&ti); 331 332 ti.c_cflag |= 1; 333 ti.c_cflag |= CRTSCTS; 334 335 /* Set the attributes of UART after making 336 * the above changes 337 */ 338 tcsetattr(dev_fd, TCSANOW, &ti); 339 340 /* Set the actual default baud rate */ 341 cfsetospeed(&ti, B115200); 342 cfsetispeed(&ti, B115200); 343 tcsetattr(dev_fd, TCSANOW, &ti); 344 345 tcflush(dev_fd, TCIOFLUSH); 346 UIM_DBG(" set_baud_rate() done"); 347 348 return 0; 349 } 350 351 /* Function to set the UART custom baud rate. 352 * 353 * The UART baud rate has already been 354 * set to default value 115200 before calling this function. 355 * The baud rate is then changed to custom baud rate by this function*/ 356 static int set_custom_baud_rate() 357 { 358 UIM_START_FUNC(); 359 360 struct termios2 ti2; 361 362 UIM_VER(" Changing baud rate to %u, flow control to %u", 363 cust_baud_rate, uart_flow_control); 364 365 /* Flush non-transmitted output data, 366 * non-read input data or both*/ 367 tcflush(dev_fd, TCIOFLUSH); 368 369 /*Set the UART flow control */ 370 if (uart_flow_control) { 371 ti.c_cflag |= CRTSCTS; 372 } else { 373 ti.c_cflag &= ~CRTSCTS; 374 } 375 376 /* 377 * Set the parameters associated with the UART 378 * The change will occur immediately by using TCSANOW 379 */ 380 if (tcsetattr(dev_fd, TCSANOW, &ti) < 0) { 381 UIM_ERR(" Can't set port settings"); 382 return -1; 383 } 384 385 tcflush(dev_fd, TCIOFLUSH); 386 387 /*Set the actual baud rate */ 388 ioctl(dev_fd, TCGETS2, &ti2); 389 ti2.c_cflag &= ~CBAUD; 390 ti2.c_cflag |= BOTHER; 391 ti2.c_ospeed = cust_baud_rate; 392 ioctl(dev_fd, TCSETS2, &ti2); 393 394 UIM_DBG(" set_custom_baud_rate() done"); 395 return 0; 396 } 397 398 /* 399 * Handling the Signals sent from the Kernel Init Manager. 400 * After receiving the signals, configure the baud rate, flow 401 * control and Install the N_TI_WL line discipline 402 */ 403 int st_sig_handler(int signo) 404 { 405 int ldisc, len; 406 uim_speed_change_cmd cmd; 407 408 uim_bdaddr_change_cmd addr_cmd; 409 410 UIM_START_FUNC(); 411 412 /* Raise a signal after when UIM is killed. 413 * This will exit UIM, and remove the inserted kernel 414 * modules 415 */ 416 if (signo == SIGINT) { 417 UIM_DBG(" Exiting. . ."); 418 exiting = 1; 419 return -1; 420 } 421 422 /* Install the line discipline when the signal is received by UIM. 423 * Whenever the first protocol tries to register with the ST core, the 424 * ST KIM will send a signal SIGUSR2 to the UIM to install the N_TI_WL 425 * line discipline and do the host side UART configurations. 426 * 427 * On failure, ST KIM's line discipline installation times out, and the 428 * relevant protocol register fails 429 */ 430 if (st_state == INSTALL_N_TI_WL) { 431 UIM_VER(" signal received, opening %s", uart_dev_name); 432 dev_fd = open(uart_dev_name, O_RDWR); 433 if (dev_fd < 0) { 434 UIM_ERR(" Can't open %s", uart_dev_name); 435 return -1; 436 } 437 /* 438 * Set only the default baud rate. 439 * This will set the baud rate to default 115200 440 */ 441 if (set_baud_rate() < 0) { 442 UIM_ERR(" set_baudrate() failed"); 443 close(dev_fd); 444 return -1; 445 } 446 447 fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK); 448 /* Set only thecustom baud rate */ 449 if (cust_baud_rate) { 450 451 /* Forming the packet for Change speed command */ 452 cmd.uart_prefix = HCI_COMMAND_PKT; 453 cmd.hci_hdr.opcode = HCI_HDR_OPCODE; 454 cmd.hci_hdr.plen = sizeof(unsigned long); 455 cmd.speed = cust_baud_rate; 456 457 /* Writing the change speed command to the UART 458 * This will change the UART speed at the controller 459 * side 460 */ 461 UIM_VER(" Setting speed to %d", cust_baud_rate); 462 len = write(dev_fd, &cmd, sizeof(cmd)); 463 if (len < 0) { 464 UIM_ERR(" Failed to write speed-set command"); 465 close(dev_fd); 466 return -1; 467 } 468 469 /* Read the response for the Change speed command */ 470 if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) { 471 close(dev_fd); 472 return -1; 473 } 474 475 UIM_VER(" Speed changed to %d", cust_baud_rate); 476 477 /* Set the actual custom baud rate at the host side */ 478 if (set_custom_baud_rate() < 0) { 479 UIM_ERR(" set_custom_baud_rate() failed"); 480 close(dev_fd); 481 482 return -1; 483 } 484 485 /* Set the uim BD address */ 486 if (uim_bd_address[0] != 0) { 487 488 memset(&addr_cmd, 0, sizeof(addr_cmd)); 489 /* Forming the packet for change BD address command*/ 490 addr_cmd.uart_prefix = HCI_COMMAND_PKT; 491 addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE; 492 addr_cmd.hci_hdr.plen = sizeof(bdaddr_t); 493 memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t)); 494 495 /* Writing the change BD address command to the UART 496 * This will change the change BD address at the controller 497 * side 498 */ 499 len = write(dev_fd, &addr_cmd, sizeof(addr_cmd)); 500 if (len < 0) { 501 UIM_ERR(" Failed to write BD address command"); 502 close(dev_fd); 503 return -1; 504 } 505 506 /* Read the response for the change BD address command */ 507 if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) { 508 close(dev_fd); 509 return -1; 510 } 511 512 UIM_VER(" BD address changed to %s", uim_bd_address); 513 } 514 #ifdef UIM_DEBUG 515 read_firmware_version(); 516 #endif 517 } 518 519 /* After the UART speed has been changed, the IOCTL is 520 * is called to set the line discipline to N_TI_WL 521 */ 522 ldisc = line_discipline; 523 if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) { 524 UIM_ERR(" Can't set line discipline"); 525 close(dev_fd); 526 return -1; 527 } 528 529 UIM_DBG(" Installed N_TI_WL Line displine"); 530 } 531 else { 532 UIM_DBG(" Un-Installed N_TI_WL Line displine"); 533 /* UNINSTALL_N_TI_WL - When the Signal is received from KIM */ 534 /* closing UART fd */ 535 close(dev_fd); 536 } 537 prev_st_state = st_state; 538 return 0; 539 } 540 int remove_modules() 541 { 542 int err = 0; 543 544 #ifdef ANDROID 545 UIM_VER(" Removing gps_drv "); 546 if (rmmod("gps_drv") != 0) { 547 UIM_ERR(" Error removing gps_drv module"); 548 err = -1; 549 } else { 550 UIM_DBG(" Removed gps_drv module"); 551 } 552 553 UIM_VER(" Removing fm_drv "); 554 if (rmmod("fm_drv") != 0) { 555 UIM_ERR(" Error removing fm_drv module"); 556 err = -1; 557 } else { 558 UIM_DBG(" Removed fm_drv module"); 559 } 560 UIM_DBG(" Removed fm_drv module"); 561 562 UIM_VER(" Removing bt_drv "); 563 564 if (rmmod("bt_drv") != 0) { 565 UIM_ERR(" Error removing bt_drv module"); 566 err = -1; 567 } else { 568 UIM_DBG(" Removed bt_drv module"); 569 } 570 UIM_DBG(" Removed bt_drv module"); 571 572 /*Remove the Shared Transport */ 573 UIM_VER(" Removing st_drv "); 574 575 if (rmmod("st_drv") != 0) { 576 UIM_ERR(" Error removing st_drv module"); 577 err = -1; 578 } else { 579 UIM_DBG(" Removed st_drv module "); 580 } 581 UIM_DBG(" Removed st_drv module "); 582 #else 583 #if INCLUDE_FM 584 UIM_VER(" Removing fm_drv "); 585 if (system("rmmod fm_drv") != 0) { 586 UIM_ERR(" Error removing fm_drv module"); 587 err = -1; 588 } else { 589 UIM_DBG(" Removed fm_drv module"); 590 } 591 #endif /* INCLUDE_FM */ 592 UIM_VER(" Removing bt_drv "); 593 if (system("rmmod bt_drv") != 0) { 594 UIM_ERR(" Error removing bt_drv module"); 595 err = -1; 596 } else { 597 UIM_DBG(" Removed bt_drv module"); 598 } 599 600 /*Remove the Shared Transport */ 601 UIM_VER(" Removing st_drv "); 602 603 if (system("rmmod st_drv") != 0) { 604 UIM_ERR(" Error removing st_drv module"); 605 err = -1; 606 } else { 607 UIM_DBG(" Removed st_drv module "); 608 } 609 #endif 610 return err; 611 } 612 613 int change_rfkill_perms(void) 614 { 615 int fd, id, sz; 616 char path[64]; 617 char buf[16]; 618 for (id = 0; id < 50; id++) { 619 snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); 620 fd = open(path, O_RDONLY); 621 if (fd < 0) { 622 UIM_DBG("open(%s) failed: %s (%d)\n", path, strerror(errno), errno); 623 continue; 624 } 625 sz = read(fd, &buf, sizeof(buf)); 626 close(fd); 627 if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) { 628 UIM_DBG("found bluetooth rfkill entry @ %d\n", id); 629 rfkill_idx = id; 630 break; 631 } 632 } 633 if (id == 50) { 634 return -1; 635 } 636 #ifdef ANDROID 637 sprintf(path, "/sys/class/rfkill/rfkill%d/state", id); 638 sz = chown(path, AID_BLUETOOTH, AID_BLUETOOTH); 639 if (sz < 0) { 640 UIM_ERR("change mode failed for %s (%d)\n", path, errno); 641 return -1; 642 } 643 #endif /* ANDROID */ 644 /* 645 * bluetooth group's user system needs write permission 646 */ 647 sz = chmod(path, 0660); 648 if (sz < 0) { 649 UIM_ERR("change mode failed for %s (%d)\n", path, errno); 650 return -1; 651 } 652 UIM_DBG("changed permissions for %s(%d) \n", path, sz); 653 /* end of change_perms */ 654 655 return 0; 656 } 657 658 void *bt_malloc(size_t size) 659 { 660 return malloc(size); 661 } 662 663 /* Function to convert the BD address from ascii to hex value */ 664 bdaddr_t *strtoba(const char *str) 665 { 666 const char *ptr = str; 667 int i; 668 669 uint8_t *ba = bt_malloc(sizeof(bdaddr_t)); 670 if (!ba) { 671 return NULL; 672 } 673 674 for (i = 0; i < 6; i++) { 675 ba[i] = (uint8_t) strtol(ptr, NULL, 16); 676 if (i != 5 && !(ptr = strchr(ptr, ':'))) { 677 ptr = ":00:00:00:00:00"; 678 } 679 ptr++; 680 } 681 682 return (bdaddr_t *) ba; 683 } 684 685 /*****************************************************************************/ 686 int main(int argc, char *argv[]) 687 { 688 int st_fd,err; 689 struct stat file_stat; 690 #ifndef ANDROID /* used on ubuntu */ 691 char *tist_ko_path; 692 struct utsname name; 693 #endif 694 struct pollfd p; 695 sigset_t sigs; 696 697 UIM_START_FUNC(); 698 err = 0; 699 700 /* Parse the user input */ 701 if ((argc == 5) || (argc == 6)) { 702 strcpy(uart_dev_name, argv[1]); 703 uart_baud_rate = atoi(argv[2]); 704 uart_flow_control = atoi(argv[3]); 705 line_discipline = atoi(argv[4]); 706 707 /* Depending upon the baud rate value, differentiate 708 * the custom baud rate and default baud rate 709 */ 710 switch (uart_baud_rate) { 711 case 115200: 712 UIM_VER(" Baudrate 115200"); 713 break; 714 case 9600: 715 case 19200: 716 case 38400: 717 case 57600: 718 case 230400: 719 case 460800: 720 case 500000: 721 case 576000: 722 case 921600: 723 case 1000000: 724 case 1152000: 725 case 1500000: 726 case 2000000: 727 case 2500000: 728 case 3000000: 729 case 3500000: 730 case 3686400: 731 case 4000000: 732 cust_baud_rate = uart_baud_rate; 733 UIM_VER(" Baudrate %d", cust_baud_rate); 734 break; 735 default: 736 UIM_ERR(" Inavalid Baud Rate"); 737 break; 738 } 739 740 memset(&uim_bd_address, 0, sizeof(uim_bd_address)); 741 } else { 742 UIM_ERR(" Invalid arguements"); 743 UIM_ERR(" Usage: uim [Uart device] [Baud rate] [Flow control] [Line discipline] <bd address>"); 744 return -1; 745 } 746 if (argc == 6) { 747 /* BD address passed as string in xx:xx:xx:xx:xx:xx format */ 748 strcpy(uim_bd_address, argv[5]); 749 bd_addr = strtoba(uim_bd_address); 750 } 751 752 753 #ifndef ANDROID 754 if (uname (&name) == -1) { 755 UIM_ERR("cannot get kernel release name"); 756 return -1; 757 } 758 #else /* if ANDROID */ 759 760 if (0 == lstat("/st_drv.ko", &file_stat)) { 761 if (insmod("/st_drv.ko", "") < 0) { 762 UIM_ERR(" Error inserting st_drv module"); 763 return -1; 764 } else { 765 UIM_DBG(" Inserted st_drv module"); 766 } 767 } else { 768 if (0 == lstat("/dev/rfkill", &file_stat)) { 769 UIM_DBG("ST built into the kernel ?"); 770 } else { 771 UIM_ERR("BT/FM/GPS would be unavailable on system"); 772 UIM_ERR(" rfkill device '/dev/rfkill' not found "); 773 return -1; 774 } 775 } 776 #endif 777 778 #ifndef ANDROID 779 /*-- Insmod of ST driver --*/ 780 asprintf(&tist_ko_path, 781 "/lib/modules/%s/kernel/drivers/misc/ti-st/st_drv.ko",name.release); 782 if (0 == lstat(tist_ko_path, &file_stat)) { 783 if (system("insmod /lib/modules/`uname -r`/kernel/drivers/misc/ti-st/st_drv.ko") != 0) { 784 UIM_ERR(" Error inserting st_drv module"); 785 free(tist_ko_path); 786 return -1; 787 } else { 788 UIM_DBG(" Inserted st_drv module"); 789 } 790 } else { 791 UIM_ERR("ST driver built into the kernel ?"); 792 } 793 free(tist_ko_path); 794 #endif 795 796 if (change_rfkill_perms() < 0) { 797 /* possible error condition */ 798 UIM_ERR("rfkill not enabled in st_drv - BT on from UI might fail\n"); 799 } 800 801 #ifndef ANDROID 802 /*-- Insmod of BT driver --*/ 803 asprintf(&tist_ko_path, 804 "/lib/modules/%s/kernel/drivers/staging/ti-st/bt_drv.ko",name.release); 805 if (0 == lstat(tist_ko_path, &file_stat)) { 806 if (system("insmod /lib/modules/`uname -r`/kernel/drivers/staging/ti-st/bt_drv.ko") != 0) { 807 UIM_ERR(" Error inserting bt_drv module"); 808 system("rmmod st_drv"); 809 free(tist_ko_path); 810 return -1; 811 } else { 812 UIM_DBG(" Inserted bt_drv module"); 813 } 814 } else { 815 UIM_ERR("BT driver built into the kernel ?"); 816 } 817 free(tist_ko_path); 818 819 #if INCLUDE_FM 820 /*-- Insmod of FM driver --*/ 821 asprintf(&tist_ko_path, 822 "/lib/modules/%s/kernel/drivers/staging/ti-st/fm_drv.ko",name.release); 823 if (0 == lstat(tist_ko_path, &file_stat)) { 824 if (system("insmod /lib/modules/`uname -r`/kernel/drivers/staging/ti-st/fm_drv.ko") != 0) { 825 UIM_ERR(" Error inserting fm_drv module"); 826 system("rmmod bt_drv"); 827 system("rmmod st_drv"); 828 free(tist_ko_path); 829 return -1; 830 } else { 831 UIM_DBG(" Inserted fm_drv module"); 832 } 833 } else { 834 UIM_ERR("FM driver built into the kernel ?"); 835 } 836 free(tist_ko_path); 837 #endif /* INCLUDE_FM */ 838 #else /* if ANDROID */ 839 if (0 == lstat("/bt_drv.ko", &file_stat)) { 840 if (insmod("/bt_drv.ko", "") < 0) { 841 UIM_ERR(" Error inserting bt_drv module, NO BT? "); 842 } else { 843 UIM_DBG(" Inserted bt_drv module"); 844 } 845 } else { 846 UIM_DBG("BT driver module un-available... "); 847 UIM_DBG("BT driver built into the kernel ?"); 848 } 849 850 if (0 == lstat("/fm_drv.ko", &file_stat)) { 851 if (insmod("/fm_drv.ko", "") < 0) { 852 UIM_ERR(" Error inserting fm_drv module, NO FM? "); 853 } else { 854 UIM_DBG(" Inserted fm_drv module"); 855 } 856 } else { 857 UIM_DBG("FM driver module un-available... "); 858 UIM_DBG("FM driver built into the kernel ?"); 859 } 860 861 if (0 == lstat("/gps_drv.ko", &file_stat)) { 862 if (insmod("/gps_drv.ko", "") < 0) { 863 UIM_ERR(" Error inserting gps_drv module, NO GPS? "); 864 } else { 865 UIM_DBG(" Inserted gps_drv module"); 866 } 867 } else { 868 UIM_DBG("GPS driver module un-available... "); 869 UIM_DBG("GPS driver built into the kernel ?"); 870 } 871 872 if (chmod("/dev/tifm", 0666) < 0) { 873 UIM_ERR("unable to chmod /dev/tifm"); 874 } 875 #endif 876 /* rfkill device's open/poll/read */ 877 st_fd = open("/dev/rfkill", O_RDONLY); 878 if (st_fd < 0) { 879 UIM_DBG("unable to open /dev/rfkill (%s)", strerror(errno)); 880 remove_modules(); 881 return -1; 882 } 883 884 885 p.fd = st_fd; 886 p.events = POLLERR | POLLHUP | POLLOUT | POLLIN; 887 888 sigfillset(&sigs); 889 sigdelset(&sigs, SIGCHLD); 890 sigdelset(&sigs, SIGPIPE); 891 sigdelset(&sigs, SIGTERM); 892 sigdelset(&sigs, SIGINT); 893 sigdelset(&sigs, SIGHUP); 894 895 RE_POLL: 896 while (!exiting) { 897 p.revents = 0; 898 #ifdef ANDROID 899 err = ppoll(&p, 1, NULL, &sigs); 900 #else 901 err = poll(&p, 1, -1); 902 #endif /* ANDROID */ 903 if (err < 0 && errno == EINTR) { 904 continue; 905 } 906 if (err) { 907 break; 908 } 909 } 910 if (!exiting) { 911 err = read(st_fd, &rf_event, sizeof(rf_event)); 912 UIM_DBG("rf_event: %d, %d, %d, %d, %d\n", rf_event.idx, 913 rf_event.type, rf_event.op ,rf_event.hard, 914 rf_event.soft); 915 if ((rf_event.op == RFKILL_OP_CHANGE) && 916 (rf_event.idx == rfkill_idx)) { 917 if (rf_event.hard == 1) /* hard blocked */ { 918 st_state = UNINSTALL_N_TI_WL; 919 } else /* unblocked */ { 920 st_state = INSTALL_N_TI_WL; 921 } 922 923 if (prev_st_state != st_state) { 924 st_sig_handler(SIGUSR2); 925 } 926 } 927 goto RE_POLL; 928 } 929 930 if(remove_modules() < 0) { 931 UIM_ERR(" Error removing modules "); 932 close(st_fd); 933 return -1; 934 } 935 936 close(st_fd); 937 return 0; 938 } 939