From bf1dec110d517755e66125d4b8699f50b8e6dfcf Mon Sep 17 00:00:00 2001 From: Manel Caro Date: Thu, 7 Mar 2019 20:13:19 +0100 Subject: Calibrator and uim Initial Commit --- uim_rfkill/readme.txt | 25 ++ uim_rfkill/uim.c | 924 ++++++++++++++++++++++++++++++++++++++++++++++++++ uim_rfkill/uim.h | 154 +++++++++ 3 files changed, 1103 insertions(+) create mode 100644 uim_rfkill/readme.txt create mode 100644 uim_rfkill/uim.c create mode 100644 uim_rfkill/uim.h (limited to 'uim_rfkill') diff --git a/uim_rfkill/readme.txt b/uim_rfkill/readme.txt new file mode 100644 index 0000000..9d108a3 --- /dev/null +++ b/uim_rfkill/readme.txt @@ -0,0 +1,25 @@ +This is UIM utility required for TI's shared transport driver in order +to open UART and to deliver the control of it to the driver. + +The author of the utility is Pavan Savoy + +--- Running UIM utility + +It needs to be run at boot, Since linux flavors might require Bluetooth or +GPS to be turned on at boot. For this have the UIM entry in your either one +of your rc.S files or you can have special udev rule based on the platform +driver addition of device "kim". + +For Android, the following entry in init.rc should suffice, +service uim /system/bin/uim-sysfs + user root + group media bluetooth + oneshot +[edit] + +For Angstrom, the following command should be done, +./uim /dev/ttyO1 3686400 none 22 & + +--- Building UIM utility +make uim + diff --git a/uim_rfkill/uim.c b/uim_rfkill/uim.c new file mode 100644 index 0000000..9fd42bf --- /dev/null +++ b/uim_rfkill/uim.c @@ -0,0 +1,924 @@ +/* + * User Mode Init manager - For TI shared transport + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program;if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#include +#endif + +#ifdef ANDROID +#include /* for ppoll */ +#endif +#include "uim.h" + +#ifndef ANDROID +#define INCLUDE_FM 0 +#endif + +/* Maintains the exit state of UIM*/ +static int exiting; + +/* UART configuration parameters*/ +int uart_flow_control; +int cust_baud_rate; +char uart_dev_name[15]; +unsigned int uart_baud_rate; +struct termios ti; +int line_discipline; + +/* BD address as string and a pointer to array of hex bytes */ +char uim_bd_address[17]; +bdaddr_t *bd_addr; + +/* File descriptor for the UART device*/ +int dev_fd; + +/* Maintains the state of N_TI_WL line discipline installation*/ +unsigned char st_state = UNINSTALL_N_TI_WL; +unsigned char prev_st_state = UNINSTALL_N_TI_WL; + +/* from kernel's include/linux/rfkill.h + * the header in itself not included because of the + * version mismatch of android kernel headers project + */ + +/** + * enum rfkill_operation - operation types + * @RFKILL_OP_ADD: a device was added + * @RFKILL_OP_DEL: a device was removed + * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device + * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all) + */ +enum rfkill_operation { + RFKILL_OP_ADD = 0, + RFKILL_OP_DEL, + RFKILL_OP_CHANGE, + RFKILL_OP_CHANGE_ALL, +}; + +/** + * struct rfkill_event - events for userspace on /dev/rfkill + * @idx: index of dev rfkill + * @type: type of the rfkill struct + * @op: operation code + * @hard: hard state (0/1) + * @soft: soft state (0/1) + * + * Structure used for userspace communication on /dev/rfkill, + * used for events from the kernel and control to the kernel. + */ +#ifdef ANDROID +struct rfkill_event { + __u32 idx; + __u8 type; + __u8 op; + __u8 soft, hard; +} __packed; +#else +struct rfkill_event { + uint32_t idx; + uint8_t type; + uint8_t op; + uint8_t soft, hard; +} __packed; +#endif /* ANDROID */ + +/* to read events and filter notifications for us */ +struct rfkill_event rf_event; +unsigned int rfkill_idx; + +/*****************************************************************************/ +#ifdef UIM_DEBUG +/* Function to Read the firmware version + * module into the system. Currently used for + * debugging purpose, whenever the baud rate is changed + */ +void read_firmware_version() +{ + int index = 0; + char resp_buffer[20] = { 0 }; + unsigned char buffer[] = { 0x01, 0x01, 0x10, 0x00 }; + + UIM_START_FUNC(); + UIM_VER(" wrote %d bytes", (int)write(dev_fd, buffer, 4)); + UIM_VER(" reading %d bytes", (int)read(dev_fd, resp_buffer, 15)); + + for (index = 0; index < 15; index++) + UIM_VER(" %x ", resp_buffer[index]); + + printf("\n"); +} +#endif + +/*****************************************************************************/ +#ifdef ANDROID /* library for android to do insmod/rmmod */ + +/* Function to insert the kernel module into the system*/ +static int insmod(const char *filename, const char *args) +{ + void *module; + unsigned int size; + int ret = -1; + + UIM_START_FUNC(); + + module = (void *)load_file(filename, &size); + if (!module) + return ret; + + ret = init_module(module, size, args); + free(module); + + return ret; +} + +/* Function to remove the kernel module from the system*/ +static int rmmod(const char *modname) +{ + int ret = -1; + int maxtry = MAX_TRY; + + UIM_START_FUNC(); + + /* Retry MAX_TRY number of times in case of + * failure + */ + while (maxtry-- > 0) { + ret = delete_module(modname, O_NONBLOCK | O_EXCL); + if (ret < 0 && errno == EAGAIN) + sleep(1); + else + break; + } + + /* Failed to remove the module + */ + if (ret != 0) + UIM_ERR("Unable to unload driver module \"%s\": %s", + modname, strerror(errno)); + return ret; +} +#endif /*ANDROID*/ + +/*****************************************************************************/ +/* Function to read the HCI event from the given file descriptor + * + * This will parse the response received and returns error + * if the required response is not received + */ +int read_hci_event(int fd, unsigned char *buf, int size) +{ + int remain, rd; + int count = 0; + int reading = 1; + int rd_retry_count = 0; + struct timespec tm = {0, 50*1000*1000}; + + UIM_START_FUNC(); + + UIM_VER(" read_hci_event"); + if (size <= 0) + return -1; + + /* The first byte identifies the packet type. For HCI event packets, it + * should be 0x04, so we read until we get to the 0x04. */ + while (reading) { + rd = read(fd, buf, 1); + if (rd <= 0 && rd_retry_count++ < 4) { + nanosleep(&tm, NULL); + continue; + } else if (rd_retry_count >= 4) { + return -1; + } + + if (buf[0] == RESP_PREFIX) { + break; + } + } + count++; + + /* The next two bytes are the event code and parameter total length. */ + while (count < 3) { + rd = read(fd, buf + count, 3 - count); + if (rd <= 0) + return -1; + count += rd; + } + + /* Now we read the parameters. */ + if (buf[2] < (size - 3)) + remain = buf[2]; + else + remain = size - 3; + + while ((count - 3) < remain) { + rd = read(fd, buf + count, remain - (count - 3)); + if (rd <= 0) + return -1; + count += rd; + } + + return count; +} + +/* Function to read the Command complete event + * + * This will read the response for the change speed + * command that was sent to configure the UART speed + * with the custom baud rate + */ +static int read_command_complete(int fd, unsigned short opcode) +{ + command_complete_t resp; + + UIM_START_FUNC(); + + UIM_VER(" Command complete started"); + if (read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0) { + UIM_ERR(" Invalid response"); + return -1; + } + + /* Response should be an event packet */ + if (resp.uart_prefix != HCI_EVENT_PKT) { + UIM_ERR + (" Error in response: not an event packet, but 0x%02x!", + resp.uart_prefix); + return -1; + } + + /* Response should be a command complete event */ + if (resp.hci_hdr.evt != EVT_CMD_COMPLETE) { + /* event must be event-complete */ + UIM_ERR + (" Error in response: not a cmd-complete event,but 0x%02x!", + resp.hci_hdr.evt); + return -1; + } + + if (resp.hci_hdr.plen < 4) { + /* plen >= 4 for EVT_CMD_COMPLETE */ + UIM_ERR(" Error in response: plen is not >= 4, but 0x%02x!", + resp.hci_hdr.plen); + return -1; + } + + if (resp.cmd_complete.opcode != (unsigned short)opcode) { + UIM_ERR(" Error in response: opcode is 0x%04x, not 0x%04x!", + resp.cmd_complete.opcode, opcode); + return -1; + } + + UIM_DBG(" Command complete done"); + return resp.status == 0 ? 0 : -1; +} + +/* Function to set the default baud rate + * + * The default baud rate of 115200 is set to the UART from the host side + * by making a call to this function.This function is also called before + * making a call to set the custom baud rate + */ +static int set_baud_rate() +{ + UIM_START_FUNC(); + + tcflush(dev_fd, TCIOFLUSH); + + /* Get the attributes of UART */ + if (tcgetattr(dev_fd, &ti) < 0) { + UIM_ERR(" Can't get port settings"); + return -1; + } + + /* Change the UART attributes before + * setting the default baud rate*/ + cfmakeraw(&ti); + + ti.c_cflag |= 1; + ti.c_cflag |= CRTSCTS; + + /* Set the attributes of UART after making + * the above changes + */ + tcsetattr(dev_fd, TCSANOW, &ti); + + /* Set the actual default baud rate */ + cfsetospeed(&ti, B115200); + cfsetispeed(&ti, B115200); + tcsetattr(dev_fd, TCSANOW, &ti); + + tcflush(dev_fd, TCIOFLUSH); + UIM_DBG(" set_baud_rate() done"); + + return 0; +} + +/* Function to set the UART custom baud rate. + * + * The UART baud rate has already been + * set to default value 115200 before calling this function. + * The baud rate is then changed to custom baud rate by this function*/ +static int set_custom_baud_rate() +{ + UIM_START_FUNC(); + + struct termios2 ti2; + + UIM_VER(" Changing baud rate to %u, flow control to %u", + cust_baud_rate, uart_flow_control); + + /* Flush non-transmitted output data, + * non-read input data or both*/ + tcflush(dev_fd, TCIOFLUSH); + + /*Set the UART flow control */ + if (uart_flow_control) + ti.c_cflag |= CRTSCTS; + else + ti.c_cflag &= ~CRTSCTS; + + /* + * Set the parameters associated with the UART + * The change will occur immediately by using TCSANOW + */ + if (tcsetattr(dev_fd, TCSANOW, &ti) < 0) { + UIM_ERR(" Can't set port settings"); + return -1; + } + + tcflush(dev_fd, TCIOFLUSH); + + /*Set the actual baud rate */ + ioctl(dev_fd, TCGETS2, &ti2); + ti2.c_cflag &= ~CBAUD; + ti2.c_cflag |= BOTHER; + ti2.c_ospeed = cust_baud_rate; + ioctl(dev_fd, TCSETS2, &ti2); + + UIM_DBG(" set_custom_baud_rate() done"); + return 0; +} + +/* + * Handling the Signals sent from the Kernel Init Manager. + * After receiving the signals, configure the baud rate, flow + * control and Install the N_TI_WL line discipline + */ +int st_sig_handler(int signo) +{ + int ldisc, len; + uim_speed_change_cmd cmd; + + uim_bdaddr_change_cmd addr_cmd; + + UIM_START_FUNC(); + + /* Raise a signal after when UIM is killed. + * This will exit UIM, and remove the inserted kernel + * modules + */ + if (signo == SIGINT) { + UIM_DBG(" Exiting. . ."); + exiting = 1; + return -1; + } + + /* Install the line discipline when the signal is received by UIM. + * Whenever the first protocol tries to register with the ST core, the + * ST KIM will send a signal SIGUSR2 to the UIM to install the N_TI_WL + * line discipline and do the host side UART configurations. + * + * On failure, ST KIM's line discipline installation times out, and the + * relevant protocol register fails + */ + if (st_state == INSTALL_N_TI_WL) { + UIM_VER(" signal received, opening %s", uart_dev_name); + dev_fd = open(uart_dev_name, O_RDWR); + if (dev_fd < 0) { + UIM_ERR(" Can't open %s", uart_dev_name); + return -1; + } + /* + * Set only the default baud rate. + * This will set the baud rate to default 115200 + */ + if (set_baud_rate() < 0) { + UIM_ERR(" set_baudrate() failed"); + close(dev_fd); + return -1; + } + + fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK); + /* Set only thecustom baud rate */ + if (cust_baud_rate) { + + /* Forming the packet for Change speed command */ + cmd.uart_prefix = HCI_COMMAND_PKT; + cmd.hci_hdr.opcode = HCI_HDR_OPCODE; + cmd.hci_hdr.plen = sizeof(unsigned long); + cmd.speed = cust_baud_rate; + + /* Writing the change speed command to the UART + * This will change the UART speed at the controller + * side + */ + UIM_VER(" Setting speed to %d", cust_baud_rate); + len = write(dev_fd, &cmd, sizeof(cmd)); + if (len < 0) { + UIM_ERR(" Failed to write speed-set command"); + close(dev_fd); + return -1; + } + + /* Read the response for the Change speed command */ + if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) { + close(dev_fd); + return -1; + } + + UIM_VER(" Speed changed to %d", cust_baud_rate); + + /* Set the actual custom baud rate at the host side */ + if (set_custom_baud_rate() < 0) { + UIM_ERR(" set_custom_baud_rate() failed"); + close(dev_fd); + + return -1; + } + + /* Set the uim BD address */ + if (uim_bd_address[0] != 0) { + + memset(&addr_cmd, 0, sizeof(addr_cmd)); + /* Forming the packet for change BD address command*/ + addr_cmd.uart_prefix = HCI_COMMAND_PKT; + addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE; + addr_cmd.hci_hdr.plen = sizeof(bdaddr_t); + memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t)); + + /* Writing the change BD address command to the UART + * This will change the change BD address at the controller + * side + */ + len = write(dev_fd, &addr_cmd, sizeof(addr_cmd)); + if (len < 0) { + UIM_ERR(" Failed to write BD address command"); + close(dev_fd); + return -1; + } + + /* Read the response for the change BD address command */ + if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) { + close(dev_fd); + return -1; + } + + UIM_VER(" BD address changed to %s", uim_bd_address); + } +#ifdef UIM_DEBUG + read_firmware_version(); +#endif + } + + /* After the UART speed has been changed, the IOCTL is + * is called to set the line discipline to N_TI_WL + */ + ldisc = line_discipline; + if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) { + UIM_ERR(" Can't set line discipline"); + close(dev_fd); + return -1; + } + + UIM_DBG(" Installed N_TI_WL Line displine"); + } + else { + UIM_DBG(" Un-Installed N_TI_WL Line displine"); + /* UNINSTALL_N_TI_WL - When the Signal is received from KIM */ + /* closing UART fd */ + close(dev_fd); + } + prev_st_state = st_state; + return 0; +} +int remove_modules() +{ + int err = 0; + +#ifdef ANDROID + UIM_VER(" Removing gps_drv "); + if (rmmod("gps_drv") != 0) { + UIM_ERR(" Error removing gps_drv module"); + err = -1; + } else { + UIM_DBG(" Removed gps_drv module"); + } + + UIM_VER(" Removing fm_drv "); + if (rmmod("fm_drv") != 0) { + UIM_ERR(" Error removing fm_drv module"); + err = -1; + } else { + UIM_DBG(" Removed fm_drv module"); + } + UIM_DBG(" Removed fm_drv module"); + + UIM_VER(" Removing bt_drv "); + + if (rmmod("bt_drv") != 0) { + UIM_ERR(" Error removing bt_drv module"); + err = -1; + } else { + UIM_DBG(" Removed bt_drv module"); + } + UIM_DBG(" Removed bt_drv module"); + + /*Remove the Shared Transport */ + UIM_VER(" Removing st_drv "); + + if (rmmod("st_drv") != 0) { + UIM_ERR(" Error removing st_drv module"); + err = -1; + } else { + UIM_DBG(" Removed st_drv module "); + } + UIM_DBG(" Removed st_drv module "); +#else +#if INCLUDE_FM + UIM_VER(" Removing fm_drv "); + if (system("rmmod fm_drv") != 0) { + UIM_ERR(" Error removing fm_drv module"); + err = -1; + } else { + UIM_DBG(" Removed fm_drv module"); + } +#endif /* INCLUDE_FM */ + UIM_VER(" Removing bt_drv "); + if (system("rmmod bt_drv") != 0) { + UIM_ERR(" Error removing bt_drv module"); + err = -1; + } else { + UIM_DBG(" Removed bt_drv module"); + } + + /*Remove the Shared Transport */ + UIM_VER(" Removing st_drv "); + + if (system("rmmod st_drv") != 0) { + UIM_ERR(" Error removing st_drv module"); + err = -1; + } else { + UIM_DBG(" Removed st_drv module "); + } +#endif + return err; +} + +int change_rfkill_perms(void) +{ + int fd, id, sz; + char path[64]; + char buf[16]; + for (id = 0; id < 50; id++) { + snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); + fd = open(path, O_RDONLY); + if (fd < 0) { + UIM_DBG("open(%s) failed: %s (%d)\n", path, strerror(errno), errno); + continue; + } + sz = read(fd, &buf, sizeof(buf)); + close(fd); + if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) { + UIM_DBG("found bluetooth rfkill entry @ %d\n", id); + rfkill_idx = id; + break; + } + } + if (id == 50) { + return -1; + } +#ifdef ANDROID + sprintf(path, "/sys/class/rfkill/rfkill%d/state", id); + sz = chown(path, AID_BLUETOOTH, AID_BLUETOOTH); + if (sz < 0) { + UIM_ERR("change mode failed for %s (%d)\n", path, errno); + return -1; + } +#endif /* ANDROID */ + /* + * bluetooth group's user system needs write permission + */ + sz = chmod(path, 0660); + if (sz < 0) { + UIM_ERR("change mode failed for %s (%d)\n", path, errno); + return -1; + } + UIM_DBG("changed permissions for %s(%d) \n", path, sz); + /* end of change_perms */ + + return 0; +} + +void *bt_malloc(size_t size) +{ + return malloc(size); +} + +/* Function to convert the BD address from ascii to hex value */ +bdaddr_t *strtoba(const char *str) +{ + const char *ptr = str; + int i; + + uint8_t *ba = bt_malloc(sizeof(bdaddr_t)); + if (!ba) + return NULL; + + for (i = 0; i < 6; i++) { + ba[i] = (uint8_t) strtol(ptr, NULL, 16); + if (i != 5 && !(ptr = strchr(ptr, ':'))) + ptr = ":00:00:00:00:00"; + ptr++; + } + + return (bdaddr_t *) ba; +} + +/*****************************************************************************/ +int main(int argc, char *argv[]) +{ + int st_fd,err; + struct stat file_stat; +#ifndef ANDROID /* used on ubuntu */ + char *tist_ko_path; + struct utsname name; +#endif + struct pollfd p; + sigset_t sigs; + + UIM_START_FUNC(); + err = 0; + + /* Parse the user input */ + if ((argc == 5) || (argc == 6)) { + strcpy(uart_dev_name, argv[1]); + uart_baud_rate = atoi(argv[2]); + uart_flow_control = atoi(argv[3]); + line_discipline = atoi(argv[4]); + + /* Depending upon the baud rate value, differentiate + * the custom baud rate and default baud rate + */ + switch (uart_baud_rate) { + case 115200: + UIM_VER(" Baudrate 115200"); + break; + case 9600: + case 19200: + case 38400: + case 57600: + case 230400: + case 460800: + case 500000: + case 576000: + case 921600: + case 1000000: + case 1152000: + case 1500000: + case 2000000: + case 2500000: + case 3000000: + case 3500000: + case 3686400: + case 4000000: + cust_baud_rate = uart_baud_rate; + UIM_VER(" Baudrate %d", cust_baud_rate); + break; + default: + UIM_ERR(" Inavalid Baud Rate"); + break; + } + + memset(&uim_bd_address, 0, sizeof(uim_bd_address)); + } else { + UIM_ERR(" Invalid arguements"); + UIM_ERR(" Usage: uim [Uart device] [Baud rate] [Flow control] [Line discipline] "); + return -1; + } + if (argc == 6) { + /* BD address passed as string in xx:xx:xx:xx:xx:xx format */ + strcpy(uim_bd_address, argv[5]); + bd_addr = strtoba(uim_bd_address); + } + + +#ifndef ANDROID + if (uname (&name) == -1) { + UIM_ERR("cannot get kernel release name"); + return -1; + } +#else /* if ANDROID */ + + if (0 == lstat("/st_drv.ko", &file_stat)) { + if (insmod("/st_drv.ko", "") < 0) { + UIM_ERR(" Error inserting st_drv module"); + return -1; + } else { + UIM_DBG(" Inserted st_drv module"); + } + } else { + if (0 == lstat("/dev/rfkill", &file_stat)) { + UIM_DBG("ST built into the kernel ?"); + } else { + UIM_ERR("BT/FM/GPS would be unavailable on system"); + UIM_ERR(" rfkill device '/dev/rfkill' not found "); + return -1; + } + } +#endif + +#ifndef ANDROID + /*-- Insmod of ST driver --*/ + asprintf(&tist_ko_path, + "/lib/modules/%s/kernel/drivers/misc/ti-st/st_drv.ko",name.release); + if (0 == lstat(tist_ko_path, &file_stat)) { + if (system("insmod /lib/modules/`uname -r`/kernel/drivers/misc/ti-st/st_drv.ko") != 0) { + UIM_ERR(" Error inserting st_drv module"); + free(tist_ko_path); + return -1; + } else { + UIM_DBG(" Inserted st_drv module"); + } + } else { + UIM_ERR("ST driver built into the kernel ?"); + } + free(tist_ko_path); +#endif + + if (change_rfkill_perms() < 0) { + /* possible error condition */ + UIM_ERR("rfkill not enabled in st_drv - BT on from UI might fail\n"); + } + +#ifndef ANDROID + /*-- Insmod of BT driver --*/ + asprintf(&tist_ko_path, + "/lib/modules/%s/kernel/drivers/staging/ti-st/bt_drv.ko",name.release); + if (0 == lstat(tist_ko_path, &file_stat)) { + if (system("insmod /lib/modules/`uname -r`/kernel/drivers/staging/ti-st/bt_drv.ko") != 0) { + UIM_ERR(" Error inserting bt_drv module"); + system("rmmod st_drv"); + free(tist_ko_path); + return -1; + } else { + UIM_DBG(" Inserted bt_drv module"); + } + } else { + UIM_ERR("BT driver built into the kernel ?"); + } + free(tist_ko_path); + +#if INCLUDE_FM + /*-- Insmod of FM driver --*/ + asprintf(&tist_ko_path, + "/lib/modules/%s/kernel/drivers/staging/ti-st/fm_drv.ko",name.release); + if (0 == lstat(tist_ko_path, &file_stat)) { + if (system("insmod /lib/modules/`uname -r`/kernel/drivers/staging/ti-st/fm_drv.ko") != 0) { + UIM_ERR(" Error inserting fm_drv module"); + system("rmmod bt_drv"); + system("rmmod st_drv"); + free(tist_ko_path); + return -1; + } else { + UIM_DBG(" Inserted fm_drv module"); + } + } else { + UIM_ERR("FM driver built into the kernel ?"); + } + free(tist_ko_path); +#endif /* INCLUDE_FM */ +#else /* if ANDROID */ + if (0 == lstat("/bt_drv.ko", &file_stat)) { + if (insmod("/bt_drv.ko", "") < 0) { + UIM_ERR(" Error inserting bt_drv module, NO BT? "); + } else { + UIM_DBG(" Inserted bt_drv module"); + } + } else { + UIM_DBG("BT driver module un-available... "); + UIM_DBG("BT driver built into the kernel ?"); + } + + if (0 == lstat("/fm_drv.ko", &file_stat)) { + if (insmod("/fm_drv.ko", "") < 0) { + UIM_ERR(" Error inserting fm_drv module, NO FM? "); + } else { + UIM_DBG(" Inserted fm_drv module"); + } + } else { + UIM_DBG("FM driver module un-available... "); + UIM_DBG("FM driver built into the kernel ?"); + } + + if (0 == lstat("/gps_drv.ko", &file_stat)) { + if (insmod("/gps_drv.ko", "") < 0) { + UIM_ERR(" Error inserting gps_drv module, NO GPS? "); + } else { + UIM_DBG(" Inserted gps_drv module"); + } + } else { + UIM_DBG("GPS driver module un-available... "); + UIM_DBG("GPS driver built into the kernel ?"); + } + + if (chmod("/dev/tifm", 0666) < 0) { + UIM_ERR("unable to chmod /dev/tifm"); + } +#endif + /* rfkill device's open/poll/read */ + st_fd = open("/dev/rfkill", O_RDONLY); + if (st_fd < 0) { + UIM_DBG("unable to open /dev/rfkill (%s)", strerror(errno)); + remove_modules(); + return -1; + } + + + p.fd = st_fd; + p.events = POLLERR | POLLHUP | POLLOUT | POLLIN; + + sigfillset(&sigs); + sigdelset(&sigs, SIGCHLD); + sigdelset(&sigs, SIGPIPE); + sigdelset(&sigs, SIGTERM); + sigdelset(&sigs, SIGINT); + sigdelset(&sigs, SIGHUP); + +RE_POLL: + while (!exiting) { + p.revents = 0; +#ifdef ANDROID + err = ppoll(&p, 1, NULL, &sigs); +#else + err = poll(&p, 1, -1); +#endif /* ANDROID */ + if (err < 0 && errno == EINTR) + continue; + if (err) + break; + } + if (!exiting) + { + err = read(st_fd, &rf_event, sizeof(rf_event)); + UIM_DBG("rf_event: %d, %d, %d, %d, %d\n", rf_event.idx, + rf_event.type, rf_event.op ,rf_event.hard, + rf_event.soft); + if ((rf_event.op == RFKILL_OP_CHANGE) && + (rf_event.idx == rfkill_idx)) { + if (rf_event.hard == 1) /* hard blocked */ + st_state = UNINSTALL_N_TI_WL; + else /* unblocked */ + st_state = INSTALL_N_TI_WL; + + if (prev_st_state != st_state) + st_sig_handler(SIGUSR2); + } + goto RE_POLL; + } + + if(remove_modules() < 0) { + UIM_ERR(" Error removing modules "); + close(st_fd); + return -1; + } + + close(st_fd); + return 0; +} diff --git a/uim_rfkill/uim.h b/uim_rfkill/uim.h new file mode 100644 index 0000000..8797db1 --- /dev/null +++ b/uim_rfkill/uim.h @@ -0,0 +1,154 @@ +/* + * User Mode Init manager - For shared transport + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program;if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UIM_H +#define UIM_H + +/* Paramaters to set the baud rate*/ +#define FLOW_CTL 0x0001 +#define BOTHER 0x00001000 +#define ARM_NCCS 19 + +#define TCGETS2 _IOR('T',0x2A, struct termios2) +#define TCSETS2 _IOW('T',0x2B, struct termios2) + +/*HCI Command and Event information*/ +#define HCI_HDR_OPCODE 0xff36 +#define WRITE_BD_ADDR_OPCODE 0xFC06 +#define RESP_PREFIX 0x04 +#define MAX_TRY 10 + +/* HCI Packet types */ +#define HCI_COMMAND_PKT 0x01 +#define HCI_EVENT_PKT 0x04 + +/* HCI command macros*/ +#define HCI_EVENT_HDR_SIZE 2 +#define HCI_COMMAND_HDR_SIZE 3 +#define UIM_WRITE_BD_ADDR_CP_SIZE 6 + + +/* HCI event macros*/ +#define EVT_CMD_COMPLETE_SIZE 3 +#define EVT_CMD_STATUS_SIZE 4 +#define EVT_CMD_COMPLETE 0x0E +#define EVT_CMD_STATUS 0x0F + + +#define VERBOSE +#ifndef ANDROID +#define LOGE printf +#endif /* ANDROID */ +#define LOG_TAG "uim-rfkill: " +#define UIM_ERR(fmt, arg...) LOGE("uim:"fmt"\n" , ##arg) +#if defined(UIM_DEBUG) /* limited debug messages */ +#define UIM_START_FUNC() LOGE("uim: Inside %s\n", __FUNCTION__) +#define UIM_DBG(fmt, arg...) LOGE("uim:"fmt"\n" , ## arg) +#define UIM_VER(fmt, arg...) +#elif defined(VERBOSE) /* very verbose */ +#define UIM_START_FUNC() LOGE("uim: Inside %s\n", __FUNCTION__) +#define UIM_DBG(fmt, arg...) LOGE("uim:"fmt"\n" , ## arg) +#define UIM_VER(fmt, arg...) LOGE("uim:"fmt"\n" , ## arg) +#else /* error msgs only */ +#define UIM_START_FUNC() +#define UIM_DBG(fmt, arg...) +#define UIM_VER(fmt, arg...) +#endif + +/*Termios2 structure for setting the Custom baud rate*/ +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[ARM_NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* HCI command header*/ +typedef struct { + uint16_t opcode; /* OCF & OGF */ + uint8_t plen; +} __attribute__ ((packed)) hci_command_hdr; + +/* HCI event header*/ +typedef struct { + uint8_t evt; + uint8_t plen; +} __attribute__ ((packed)) hci_event_hdr; + +/* HCI command complete event*/ +typedef struct { + uint8_t ncmd; + uint16_t opcode; +} __attribute__ ((packed)) evt_cmd_complete; + +/* HCI event status*/ +typedef struct { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __attribute__ ((packed)) evt_cmd_status; + +/* HCI Event structure to set the cusrom baud rate*/ +typedef struct { + uint8_t uart_prefix; + hci_event_hdr hci_hdr; + evt_cmd_complete cmd_complete; + uint8_t status; + uint8_t data[16]; +} __attribute__ ((packed)) command_complete_t; + +/* HCI Command structure to set the cusrom baud rate*/ +typedef struct { + uint8_t uart_prefix; + hci_command_hdr hci_hdr; + uint32_t speed; +} __attribute__ ((packed)) uim_speed_change_cmd; + +/* BD address structure to set the uim BD address*/ +typedef struct { + unsigned char b[6]; +} __attribute__((packed)) bdaddr_t; + +/* HCI Command structure to set the uim BD address*/ +typedef struct { + uint8_t uart_prefix; + hci_command_hdr hci_hdr; + bdaddr_t addr; +} __attribute__ ((packed)) uim_bdaddr_change_cmd; + +/* Signal received from KIM will install line discipline at first, + * the next signal received from KIM will un-install the + * line discipline*/ +enum { + /* expecting signal from KIM to setup uart fd for ST */ + INSTALL_N_TI_WL, + + /* expecting signal from KIM to close uart fd */ + UNINSTALL_N_TI_WL, +}; + +/* Functions to insert and remove the kernel modules from the system*/ +extern int init_module(void *, unsigned int, const char *); +extern int delete_module(const char *, unsigned int); +extern int load_file(const char *, unsigned int *); + +#endif /* UIM_H */ -- cgit v1.1