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 #include "uim.h" 31 #ifdef ANDROID 32 #include <private/android_filesystem_config.h> 33 #include <cutils/log.h> 34 #endif 35 36 37 /* Maintains the exit state of UIM*/ 38 static int exiting; 39 40 /* BD address as string and a pointer to array of hex bytes */ 41 char uim_bd_address[17]; 42 bdaddr_t *bd_addr; 43 44 /* File descriptor for the UART device*/ 45 int dev_fd; 46 47 static inline void cleanup(int failed) 48 { 49 /* for future use */ 50 (void)failed; 51 52 if (dev_fd == -1) 53 return; 54 55 UIM_DBG("%s", __func__); 56 57 close(dev_fd); 58 dev_fd = -1; 59 /* unused failed for future reference */ 60 } 61 62 /*****************************************************************************/ 63 #ifdef UIM_DEBUG 64 /* Function to Read the firmware version 65 * module into the system. Currently used for 66 * debugging purpose, whenever the baud rate is changed 67 */ 68 void read_firmware_version() 69 { 70 int index = 0; 71 char resp_buffer[20] = { 0 }; 72 unsigned char buffer[] = { 0x01, 0x01, 0x10, 0x00 }; 73 74 UIM_START_FUNC(); 75 UIM_VER(" wrote %d bytes", (int)write(dev_fd, buffer, 4)); 76 UIM_VER(" reading %d bytes", (int)read(dev_fd, resp_buffer, 15)); 77 78 for (index = 0; index < 15; index++) 79 UIM_VER(" %x ", resp_buffer[index]); 80 81 printf("\n"); 82 } 83 #endif /* UIM_DEBUG */ 84 85 /*****************************************************************************/ 86 #ifdef ANDROID /* library for android to do insmod/rmmod */ 87 88 /* Function to insert the kernel module into the system*/ 89 static int insmod(const char *filename, const char *args) 90 { 91 void *module; 92 unsigned int size; 93 int ret = -1; 94 95 UIM_START_FUNC(); 96 97 module = (void *)load_file(filename, &size); 98 if (!module) 99 return ret; 100 101 ret = init_module(module, size, args); 102 free(module); 103 104 return ret; 105 } 106 107 /* Function to remove the kernel module from the system*/ 108 static int rmmod(const char *modname) 109 { 110 int ret = -1; 111 int maxtry = MAX_TRY; 112 113 UIM_START_FUNC(); 114 115 /* Retry MAX_TRY number of times in case of 116 * failure 117 */ 118 while (maxtry-- > 0) { 119 ret = delete_module(modname, O_NONBLOCK | O_EXCL); 120 if (ret < 0 && errno == EAGAIN) 121 sleep(1); 122 else 123 break; 124 } 125 126 /* Failed to remove the module 127 */ 128 if (ret != 0) 129 UIM_ERR("Unable to unload driver module \"%s\": %s", 130 modname, strerror(errno)); 131 return ret; 132 } 133 #endif /* ANDROID */ 134 135 /*****************************************************************************/ 136 /* Function to read the HCI event from the given file descriptor 137 * 138 * This will parse the response received and returns error 139 * if the required response is not received 140 */ 141 int read_hci_event(int fd, unsigned char *buf, int size) 142 { 143 int remain, rd; 144 int count = 0; 145 int reading = 1; 146 int rd_retry_count = 0; 147 struct timespec tm = {0, 50*1000*1000}; 148 149 UIM_START_FUNC(); 150 151 UIM_VER(" read_hci_event"); 152 if (size <= 0) 153 return -1; 154 155 /* The first byte identifies the packet type. For HCI event packets, it 156 * should be 0x04, so we read until we get to the 0x04. */ 157 while (reading) { 158 rd = read(fd, buf, 1); 159 if (rd <= 0 && rd_retry_count++ < 4) { 160 nanosleep(&tm, NULL); 161 continue; 162 } else if (rd_retry_count >= 4) { 163 return -1; 164 } 165 166 if (buf[0] == RESP_PREFIX) { 167 break; 168 } 169 } 170 count++; 171 172 /* The next two bytes are the event code and parameter total length. */ 173 while (count < 3) { 174 rd = read(fd, buf + count, 3 - count); 175 if (rd <= 0) 176 return -1; 177 count += rd; 178 } 179 180 /* Now we read the parameters. */ 181 if (buf[2] < (size - 3)) 182 remain = buf[2]; 183 else 184 remain = size - 3; 185 186 while ((count - 3) < remain) { 187 rd = read(fd, buf + count, remain - (count - 3)); 188 if (rd <= 0) 189 return -1; 190 count += rd; 191 } 192 193 return count; 194 } 195 196 /* Function to read the Command complete event 197 * 198 * This will read the response for the change speed 199 * command that was sent to configure the UART speed 200 * with the custom baud rate 201 */ 202 static int read_command_complete(int fd, unsigned short opcode) 203 { 204 command_complete_t resp; 205 206 UIM_START_FUNC(); 207 208 UIM_VER(" Command complete started"); 209 if (read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0) { 210 UIM_ERR(" Invalid response"); 211 return -1; 212 } 213 214 /* Response should be an event packet */ 215 if (resp.uart_prefix != HCI_EVENT_PKT) { 216 UIM_ERR 217 (" Error in response: not an event packet, but 0x%02x!", 218 resp.uart_prefix); 219 return -1; 220 } 221 222 /* Response should be a command complete event */ 223 if (resp.hci_hdr.evt != EVT_CMD_COMPLETE) { 224 /* event must be event-complete */ 225 UIM_ERR 226 (" Error in response: not a cmd-complete event,but 0x%02x!", 227 resp.hci_hdr.evt); 228 return -1; 229 } 230 231 if (resp.hci_hdr.plen < 4) { 232 /* plen >= 4 for EVT_CMD_COMPLETE */ 233 UIM_ERR(" Error in response: plen is not >= 4, but 0x%02x!", 234 resp.hci_hdr.plen); 235 return -1; 236 } 237 238 if (resp.cmd_complete.opcode != (unsigned short)opcode) { 239 UIM_ERR(" Error in response: opcode is 0x%04x, not 0x%04x!", 240 resp.cmd_complete.opcode, opcode); 241 return -1; 242 } 243 244 UIM_DBG(" Command complete done"); 245 return resp.status == 0 ? 0 : -1; 246 } 247 248 /* Function to set the default baud rate 249 * 250 * The default baud rate of 115200 is set to the UART from the host side 251 * by making a call to this function.This function is also called before 252 * making a call to set the custom baud rate 253 */ 254 static int set_baud_rate() 255 { 256 struct termios ti; 257 258 UIM_START_FUNC(); 259 260 tcflush(dev_fd, TCIOFLUSH); 261 262 /* Get the attributes of UART */ 263 if (tcgetattr(dev_fd, &ti) < 0) { 264 UIM_ERR(" Can't get port settings"); 265 return -1; 266 } 267 268 /* Change the UART attributes before 269 * setting the default baud rate*/ 270 cfmakeraw(&ti); 271 272 ti.c_cflag |= 1; 273 ti.c_cflag |= CRTSCTS; 274 275 /* Set the attributes of UART after making 276 * the above changes 277 */ 278 tcsetattr(dev_fd, TCSANOW, &ti); 279 280 /* Set the actual default baud rate */ 281 cfsetospeed(&ti, B115200); 282 cfsetispeed(&ti, B115200); 283 tcsetattr(dev_fd, TCSANOW, &ti); 284 285 tcflush(dev_fd, TCIOFLUSH); 286 UIM_DBG(" set_baud_rate() done"); 287 288 return 0; 289 } 290 291 /* Function to set the UART custom baud rate. 292 * 293 * The UART baud rate has already been 294 * set to default value 115200 before calling this function. 295 * The baud rate is then changed to custom baud rate by this function*/ 296 static int set_custom_baud_rate(int cust_baud_rate, unsigned char flow_ctrl) 297 { 298 UIM_START_FUNC(); 299 300 struct termios ti; 301 struct termios2 ti2; 302 303 /* Get the attributes of UART */ 304 if (tcgetattr(dev_fd, &ti) < 0) { 305 UIM_ERR(" Can't get port settings"); 306 return -1; 307 } 308 309 UIM_VER(" Changing baud rate to %u, flow control to %u", 310 cust_baud_rate, flow_ctrl); 311 312 /* Flush non-transmitted output data, 313 * non-read input data or both*/ 314 tcflush(dev_fd, TCIOFLUSH); 315 316 /*Set the UART flow control */ 317 if (flow_ctrl) 318 ti.c_cflag |= CRTSCTS; 319 else 320 ti.c_cflag &= ~CRTSCTS; 321 322 /* 323 * Set the parameters associated with the UART 324 * The change will occur immediately by using TCSANOW 325 */ 326 if (tcsetattr(dev_fd, TCSANOW, &ti) < 0) { 327 UIM_ERR(" Can't set port settings"); 328 return -1; 329 } 330 331 tcflush(dev_fd, TCIOFLUSH); 332 333 /*Set the actual baud rate */ 334 ioctl(dev_fd, TCGETS2, &ti2); 335 ti2.c_cflag &= ~CBAUD; 336 ti2.c_cflag |= BOTHER; 337 ti2.c_ospeed = cust_baud_rate; 338 ioctl(dev_fd, TCSETS2, &ti2); 339 340 UIM_DBG(" set_custom_baud_rate() done"); 341 return 0; 342 } 343 344 /* 345 * Handling the Signals sent from the Kernel Init Manager. 346 * After receiving the indication from rfkill subsystem, configure the 347 * baud rate, flow control and Install the N_TI_WL line discipline 348 */ 349 int st_uart_config(unsigned char install) 350 { 351 int ldisc, len, fd; 352 unsigned char uart_dev_name[32]; 353 unsigned char buf[32]; 354 unsigned long cust_baud_rate; 355 unsigned int flow_ctrl; 356 357 uim_speed_change_cmd cmd; 358 uim_bdaddr_change_cmd addr_cmd; 359 360 UIM_START_FUNC(); 361 362 if (install == '1') { 363 UIM_DBG("install set to 1"); 364 memset(buf, 0, 32); 365 fd = open(DEV_NAME_SYSFS, O_RDONLY); 366 if (fd < 0) { 367 UIM_ERR("Can't open %s", DEV_NAME_SYSFS); 368 return -1; 369 } 370 len = read(fd, buf, 32); 371 if (len < 0) { 372 UIM_ERR("read err (%s)", strerror(errno)); 373 close(fd); 374 return len; 375 } 376 sscanf((const char*)buf, "%s", uart_dev_name); 377 close(fd); 378 379 memset(buf, 0, 32); 380 fd = open(BAUD_RATE_SYSFS, O_RDONLY); 381 if (fd < 0) { 382 UIM_ERR("Can't open %s", BAUD_RATE_SYSFS); 383 return -1; 384 } 385 len = read(fd, buf, 32); 386 if (len < 0) { 387 UIM_ERR("read err (%s)", strerror(errno)); 388 close(fd); 389 return len; 390 } 391 close(fd); 392 sscanf((const char*)buf, "%ld", &cust_baud_rate); 393 394 memset(buf, 0, 32); 395 fd = open(FLOW_CTRL_SYSFS, O_RDONLY); 396 if (fd < 0) { 397 UIM_ERR("Can't open %s", FLOW_CTRL_SYSFS); 398 close(fd); 399 return -1; 400 } 401 len = read(fd, buf, 32); 402 if (len < 0) { 403 UIM_ERR("read err (%s)", strerror(errno)); 404 close(fd); 405 return len; 406 } 407 close(fd); 408 sscanf((const char*)buf, "%u", &flow_ctrl); 409 410 if (dev_fd != -1) { 411 UIM_ERR("opening %s, while already open", uart_dev_name); 412 cleanup(-1); 413 } 414 415 dev_fd = open((const char*) uart_dev_name, O_RDWR); 416 if (dev_fd < 0) { 417 UIM_ERR(" Can't open %s", uart_dev_name); 418 return -1; 419 } 420 /* 421 * Set only the default baud rate. 422 * This will set the baud rate to default 115200 423 */ 424 if (set_baud_rate() < 0) { 425 UIM_ERR(" set_baudrate() failed"); 426 cleanup(-1); 427 return -1; 428 } 429 430 fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK); 431 /* Set only thecustom baud rate */ 432 if (cust_baud_rate != 115200) { 433 434 /* Forming the packet for Change speed command */ 435 cmd.uart_prefix = HCI_COMMAND_PKT; 436 cmd.hci_hdr.opcode = HCI_HDR_OPCODE; 437 cmd.hci_hdr.plen = sizeof(unsigned long); 438 cmd.speed = cust_baud_rate; 439 440 /* Writing the change speed command to the UART 441 * This will change the UART speed at the controller 442 * side 443 */ 444 UIM_VER(" Setting speed to %ld", cust_baud_rate); 445 len = write(dev_fd, &cmd, sizeof(cmd)); 446 if (len < 0) { 447 UIM_ERR(" Failed to write speed-set command"); 448 cleanup(-1); 449 return -1; 450 } 451 452 /* Read the response for the Change speed command */ 453 if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) { 454 cleanup(-1); 455 return -1; 456 } 457 458 UIM_VER(" Speed changed to %ld", cust_baud_rate); 459 460 /* Set the actual custom baud rate at the host side */ 461 if (set_custom_baud_rate(cust_baud_rate, flow_ctrl) < 0) { 462 UIM_ERR(" set_custom_baud_rate() failed"); 463 cleanup(-1); 464 return -1; 465 } 466 467 /* Set the uim BD address */ 468 if (uim_bd_address[0] != 0) { 469 470 memset(&addr_cmd, 0, sizeof(addr_cmd)); 471 /* Forming the packet for change BD address command*/ 472 addr_cmd.uart_prefix = HCI_COMMAND_PKT; 473 addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE; 474 addr_cmd.hci_hdr.plen = sizeof(bdaddr_t); 475 memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t)); 476 477 /* Writing the change BD address command to the UART 478 * This will change the change BD address at the controller 479 * side 480 */ 481 len = write(dev_fd, &addr_cmd, sizeof(addr_cmd)); 482 if (len < 0) { 483 UIM_ERR(" Failed to write BD address command"); 484 cleanup(-1); 485 return -1; 486 } 487 488 /* Read the response for the change BD address command */ 489 if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) { 490 cleanup(-1); 491 return -1; 492 } 493 494 UIM_VER(" BD address changed to %s", uim_bd_address); 495 } 496 #ifdef UIM_DEBUG 497 read_firmware_version(); 498 #endif 499 } 500 501 /* After the UART speed has been changed, the IOCTL is 502 * is called to set the line discipline to N_TI_WL 503 */ 504 ldisc = 22; 505 if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) { 506 UIM_ERR(" Can't set line discipline"); 507 cleanup(-1); 508 return -1; 509 } 510 UIM_DBG(" Installed N_TI_WL Line displine"); 511 } 512 else { 513 UIM_DBG(" Un-Installed N_TI_WL Line displine"); 514 /* UNINSTALL_N_TI_WL - When the Signal is received from KIM */ 515 /* closing UART fd */ 516 cleanup(0); 517 dev_fd = -1; 518 } 519 return 0; 520 } 521 522 int remove_modules() 523 { 524 int err = 0; 525 526 #ifdef ANDROID 527 UIM_VER(" Removing gps_drv "); 528 if (rmmod("gps_drv") != 0) { 529 UIM_ERR(" Error removing gps_drv module"); 530 err = -1; 531 } else { 532 UIM_DBG(" Removed gps_drv module"); 533 } 534 535 UIM_VER(" Removing fm_drv "); 536 if (rmmod("fm_drv") != 0) { 537 UIM_ERR(" Error removing fm_drv module"); 538 err = -1; 539 } else { 540 UIM_DBG(" Removed fm_drv module"); 541 } 542 UIM_DBG(" Removed fm_drv module"); 543 544 UIM_VER(" Removing btwilink "); 545 if (rmmod("btwilink") != 0) { 546 UIM_ERR(" Error removing btwilink module"); 547 err = -1; 548 } else { 549 UIM_DBG(" Removed btwilink module"); 550 } 551 UIM_DBG(" Removed btwilink module"); 552 553 /*Remove the Shared Transport */ 554 UIM_VER(" Removing st_drv "); 555 if (rmmod("st_drv") != 0) { 556 UIM_ERR(" Error removing st_drv module"); 557 err = -1; 558 } else { 559 UIM_DBG(" Removed st_drv module "); 560 } 561 UIM_DBG(" Removed st_drv module "); 562 #else 563 UIM_VER(" Removing btwilink "); 564 if (system("rmmod btwilink") != 0) { 565 UIM_ERR(" Error removing btwilink module"); 566 err = -1; 567 } else { 568 UIM_DBG(" Removed btwilink module"); 569 } 570 571 UIM_VER(" Removing fm_drv "); 572 if (system("rmmod fm_drv") != 0) { 573 UIM_ERR(" Error removing fm_drv module"); 574 err = -1; 575 } else { 576 UIM_DBG(" Removed fm_drv module "); 577 } 578 579 /*Remove the Shared Transport */ 580 UIM_VER(" Removing st_drv "); 581 if (system("rmmod st_drv") != 0) { 582 UIM_ERR(" Error removing st_drv module"); 583 err = -1; 584 } else { 585 UIM_DBG(" Removed st_drv module "); 586 } 587 #endif 588 return err; 589 } 590 591 int change_rfkill_perms(void) 592 { 593 int fd, id, sz; 594 char path[64]; 595 char buf[16]; 596 for (id = 0; id < 50; id++) { 597 snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); 598 fd = open(path, O_RDONLY); 599 if (fd < 0) { 600 UIM_DBG("open(%s) failed: %s (%d)\n", path, strerror(errno), errno); 601 continue; 602 } 603 sz = read(fd, &buf, sizeof(buf)); 604 close(fd); 605 if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) { 606 UIM_DBG("found bluetooth rfkill entry @ %d\n", id); 607 break; 608 } 609 } 610 if (id == 50) { 611 return -1; 612 } 613 #ifdef ANDROID 614 sprintf(path, "/sys/class/rfkill/rfkill%d/state", id); 615 sz = chown(path, AID_BLUETOOTH, AID_BLUETOOTH); 616 if (sz < 0) { 617 UIM_ERR("change mode failed for %s (%d)\n", path, errno); 618 return -1; 619 } 620 #endif 621 /* 622 * bluetooth group's user system needs write permission 623 */ 624 sz = chmod(path, 0660); 625 if (sz < 0) { 626 UIM_ERR("change mode failed for %s (%d)\n", path, errno); 627 return -1; 628 } 629 UIM_DBG("changed permissions for %s(%d) \n", path, sz); 630 /* end of change_perms */ 631 632 return 0; 633 } 634 635 void *bt_malloc(size_t size) 636 { 637 return malloc(size); 638 } 639 640 /* Function to convert the BD address from ascii to hex value */ 641 bdaddr_t *strtoba(const char *str) 642 { 643 const char *ptr = str; 644 int i; 645 646 uint8_t *ba = bt_malloc(sizeof(bdaddr_t)); 647 if (!ba) 648 return NULL; 649 650 for (i = 0; i < 6; i++) { 651 ba[i] = (uint8_t) strtol(ptr, NULL, 16); 652 if (i != 5 && !(ptr = strchr(ptr, ':'))) 653 ptr = ":00:00:00:00:00"; 654 ptr++; 655 } 656 657 return (bdaddr_t *) ba; 658 } 659 660 /*****************************************************************************/ 661 int main(int argc, char *argv[]) 662 { 663 int st_fd,err; 664 struct stat file_stat; 665 #ifndef ANDROID /* used on ubuntu */ 666 char *tist_ko_path; 667 struct utsname name; 668 #endif 669 struct pollfd p; 670 unsigned char install; 671 672 UIM_START_FUNC(); 673 err = 0; 674 675 /* Parse the user input */ 676 if (argc == 2) { 677 memset(&uim_bd_address, 0, sizeof(uim_bd_address)); 678 /* BD address passed as string in xx:xx:xx:xx:xx:xx format */ 679 strcpy(uim_bd_address, argv[1]); 680 bd_addr = strtoba(uim_bd_address); 681 } else if (argc != 1) { 682 UIM_ERR(" Invalid arguements"); 683 UIM_ERR(" Usage: uim <bd address>"); 684 return -1; 685 } 686 687 #ifndef ANDROID 688 if (uname (&name) == -1) { 689 UIM_ERR("cannot get kernel release name"); 690 return -1; 691 } 692 #else /* if ANDROID */ 693 694 if (0 == lstat("/st_drv.ko", &file_stat)) { 695 if (insmod("/st_drv.ko", "") < 0) { 696 UIM_ERR(" Error inserting st_drv module"); 697 return -1; 698 } else { 699 UIM_DBG(" Inserted st_drv module"); 700 } 701 } else { 702 if (0 == lstat(INSTALL_SYSFS_ENTRY, &file_stat)) { 703 UIM_DBG("ST built into the kernel ?"); 704 } else { 705 UIM_ERR("BT/FM/GPS would be unavailable on system"); 706 return -1; 707 } 708 } 709 710 if (0 == lstat("/btwilink.ko", &file_stat)) { 711 if (insmod("/btwilink.ko", "") < 0) { 712 UIM_ERR(" Error inserting btwilink module, NO BT? "); 713 } else { 714 UIM_DBG(" Inserted btwilink module"); 715 } 716 } else { 717 UIM_DBG("BT driver module un-available... "); 718 UIM_DBG("BT driver built into the kernel ?"); 719 } 720 721 if (0 == lstat("/fm_drv.ko", &file_stat)) { 722 if (insmod("/fm_drv.ko", "") < 0) { 723 UIM_ERR(" Error inserting fm_drv module, NO FM? "); 724 } else { 725 UIM_DBG(" Inserted fm_drv module"); 726 } 727 } else { 728 UIM_DBG("FM driver module un-available... "); 729 UIM_DBG("FM driver built into the kernel ?"); 730 } 731 732 if (0 == lstat("/gps_drv.ko", &file_stat)) { 733 if (insmod("/gps_drv.ko", "") < 0) { 734 UIM_ERR(" Error inserting gps_drv module, NO GPS? "); 735 } else { 736 UIM_DBG(" Inserted gps_drv module"); 737 } 738 } else { 739 UIM_DBG("GPS driver module un-available... "); 740 UIM_DBG("GPS driver built into the kernel ?"); 741 } 742 743 if (0 == lstat("/fm_v4l2_drv.ko", &file_stat)) { 744 if (insmod("/fm_v4l2_drv.ko", "") < 0) { 745 UIM_ERR(" Error inserting fm_v4l2_drv module, NO FM? "); 746 } else { 747 UIM_DBG(" Inserted fm_v4l2_drv module"); 748 } 749 } else { 750 UIM_DBG("FM V4L2 driver module un-available... "); 751 UIM_DBG("FM V4L2 driver built into the kernel ?"); 752 } 753 /* Change the permissions for v4l2 Fm device node */ 754 if ((0 == lstat("/dev/radio0", &file_stat)) && chmod("/dev/radio0", 0666) < 0) { 755 UIM_ERR("unable to chmod /dev/radio0, might not exist"); 756 } 757 if ((0 == lstat("/dev/tifm", &file_stat)) && chmod("/dev/tifm", 0666) < 0) { 758 UIM_ERR("unable to chmod /dev/tifm, might not exist"); 759 } 760 /* change rfkill perms after insertion of BT driver which asks 761 * the Bluetooth sub-system to create the rfkill device of type 762 * "bluetooth" 763 */ 764 if (change_rfkill_perms() < 0) { 765 /* possible error condition */ 766 UIM_ERR("rfkill not enabled in st_drv - BT on from UI might fail\n"); 767 } 768 769 #endif /* ANDROID */ 770 /* rfkill device's open/poll/read */ 771 st_fd = open(INSTALL_SYSFS_ENTRY, O_RDONLY); 772 if (st_fd < 0) { 773 UIM_DBG("unable to open %s (%s)", INSTALL_SYSFS_ENTRY, 774 strerror(errno)); 775 remove_modules(); 776 return -1; 777 } 778 779 RE_POLL: 780 err = read(st_fd, &install, 1); 781 if ((err > 0) && (install == '1')) { 782 UIM_DBG("install already set"); 783 st_uart_config(install); 784 } 785 786 memset(&p, 0, sizeof(p)); 787 p.fd = st_fd; 788 /* sysfs entries can only break poll for following events */ 789 p.events = POLLERR | POLLHUP; 790 791 while (!exiting) { 792 p.revents = 0; 793 err = poll(&p, 1, -1); 794 if (err < 0 && errno == EINTR) 795 continue; 796 if (err) 797 break; 798 } 799 800 close(st_fd); 801 st_fd = open(INSTALL_SYSFS_ENTRY, O_RDONLY); 802 if (st_fd < 0) { 803 UIM_ERR("re-opening %s failed: %s", INSTALL_SYSFS_ENTRY, 804 strerror(errno)); 805 return -1; 806 } 807 808 if (!exiting) 809 { 810 err = read(st_fd, &install, 1); 811 if (err <= 0) { 812 UIM_ERR("reading %s failed: %s", INSTALL_SYSFS_ENTRY, 813 strerror(errno)); 814 goto RE_POLL; 815 } 816 st_uart_config(install); 817 goto RE_POLL; 818 } 819 820 if(remove_modules() < 0) { 821 UIM_ERR(" Error removing modules "); 822 close(st_fd); 823 return -1; 824 } 825 826 close(st_fd); 827 return 0; 828 } 829