Home | History | Annotate | Download | only in uim_rfkill
      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