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 31 #include <unistd.h> 32 #include <time.h> 33 34 #include "uim.h" 35 36 /* Maintains the exit state of UIM*/ 37 static int exiting; 38 static int line_discipline; 39 static int dev_fd; 40 41 /* BD address as string and a pointer to array of hex bytes */ 42 char uim_bd_address[BD_ADDR_LEN]; 43 bdaddr_t *bd_addr; 44 45 /* kim Sysfs path */ 46 static char *sysfs_install_entry = INSTALL_SYSFS_ENTRY; 47 static char *sysfs_dev_name = DEV_NAME_SYSFS; 48 static char *sysfs_baud_rate = BAUD_RATE_SYSFS; 49 static char *sysfs_flow_ctrl = FLOW_CTRL_SYSFS; 50 51 /*****************************************************************************/ 52 #ifdef UIM_DEBUG 53 /* Function to Read the firmware version 54 * module into the system. Currently used for 55 * debugging purpose, whenever the baud rate is changed 56 */ 57 void read_firmware_version(int dev_fd) 58 { 59 int index = 0; 60 char resp_buffer[20] = { 0 }; 61 unsigned char buffer[] = { 0x01, 0x01, 0x10, 0x00 }; 62 63 UIM_START_FUNC(); 64 UIM_VER(" wrote %d bytes", (int)write(dev_fd, buffer, 4)); 65 UIM_VER(" reading %d bytes", (int)read(dev_fd, resp_buffer, 15)); 66 67 for (index = 0; index < 15; index++) 68 UIM_VER(" %x ", resp_buffer[index]); 69 70 printf("\n"); 71 } 72 #endif 73 74 void sysfs_entry_fallback(void) 75 { 76 sysfs_install_entry = INSTALL_SYSFS_ENTRY_OLD; 77 sysfs_dev_name = DEV_NAME_SYSFS_OLD; 78 sysfs_baud_rate = BAUD_RATE_SYSFS_OLD; 79 sysfs_flow_ctrl = FLOW_CTRL_SYSFS_OLD; 80 } 81 82 /*****************************************************************************/ 83 /* Function to read the HCI event from the given file descriptor 84 * 85 * This will parse the response received and returns error 86 * if the required response is not received 87 */ 88 int read_hci_event(int fd, unsigned char *buf, int size) 89 { 90 int remain, rd; 91 int count = 0; 92 int reading = 1; 93 int rd_retry_count = 0; 94 struct timespec tm = {0, 50*1000*1000}; 95 96 UIM_START_FUNC(); 97 98 UIM_VER(" read_hci_event"); 99 if (size <= 0) 100 return -1; 101 102 /* The first byte identifies the packet type. For HCI event packets, it 103 * should be 0x04, so we read until we get to the 0x04. */ 104 while (reading) { 105 rd = read(fd, buf, 1); 106 if (rd <= 0 && rd_retry_count++ < 4) { 107 nanosleep(&tm, NULL); 108 continue; 109 } else if (rd_retry_count >= 4) { 110 return -1; 111 } 112 113 if (buf[0] == RESP_PREFIX) { 114 break; 115 } 116 } 117 count++; 118 119 /* The next two bytes are the event code and parameter total length. */ 120 while (count < 3) { 121 rd = read(fd, buf + count, 3 - count); 122 if (rd <= 0) 123 return -1; 124 count += rd; 125 } 126 127 /* Now we read the parameters. */ 128 if (buf[2] < (size - 3)) 129 remain = buf[2]; 130 else 131 remain = size - 3; 132 133 while ((count - 3) < remain) { 134 rd = read(fd, buf + count, remain - (count - 3)); 135 if (rd <= 0) 136 return -1; 137 count += rd; 138 } 139 140 return count; 141 } 142 143 /* Function to read the Command complete event 144 * 145 * This will read the response for the change speed 146 * command that was sent to configure the UART speed 147 * with the custom baud rate 148 */ 149 static int read_command_complete(int fd, unsigned short opcode) 150 { 151 command_complete_t resp; 152 153 UIM_START_FUNC(); 154 155 UIM_VER(" Command complete started"); 156 if (read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0) { 157 UIM_ERR("Invalid response"); 158 return -1; 159 } 160 161 /* Response should be an event packet */ 162 if (resp.uart_prefix != HCI_EVENT_PKT) { 163 UIM_ERR ("Error in response: not an event packet, 0x%02x!", 164 resp.uart_prefix); 165 return -1; 166 } 167 168 /* Response should be a command complete event */ 169 if (resp.hci_hdr.evt != EVT_CMD_COMPLETE) { 170 /* event must be event-complete */ 171 UIM_ERR("Error in response: not a cmd-complete event,0x%02x!", 172 resp.hci_hdr.evt); 173 return -1; 174 } 175 176 if (resp.hci_hdr.plen < 4) { 177 /* plen >= 4 for EVT_CMD_COMPLETE */ 178 UIM_ERR("Error in response: plen is not >= 4, but 0x%02x!", 179 resp.hci_hdr.plen); 180 return -1; 181 } 182 183 if (resp.cmd_complete.opcode != (unsigned short)opcode) { 184 UIM_ERR("Error in response: opcode is 0x%04x, not 0x%04x!", 185 resp.cmd_complete.opcode, opcode); 186 return -1; 187 } 188 189 UIM_DBG("Command complete done"); 190 return resp.status == 0 ? 0 : -1; 191 } 192 193 /* Function to set the default baud rate 194 * 195 * The default baud rate of 115200 is set to the UART from the host side 196 * by making a call to this function.This function is also called before 197 * making a call to set the custom baud rate 198 */ 199 static int set_baud_rate(int dev_fd) 200 { 201 UIM_START_FUNC(); 202 struct termios ti; 203 204 tcflush(dev_fd, TCIOFLUSH); 205 206 /* Get the attributes of UART */ 207 if (tcgetattr(dev_fd, &ti) < 0) { 208 UIM_ERR(" Can't get port settings"); 209 return -1; 210 } 211 212 /* Change the UART attributes before 213 * setting the default baud rate*/ 214 cfmakeraw(&ti); 215 216 ti.c_cflag |= 1; 217 ti.c_cflag |= CRTSCTS; 218 219 /* Set the attributes of UART after making 220 * the above changes 221 */ 222 tcsetattr(dev_fd, TCSANOW, &ti); 223 224 /* Set the actual default baud rate */ 225 cfsetospeed(&ti, B115200); 226 cfsetispeed(&ti, B115200); 227 tcsetattr(dev_fd, TCSANOW, &ti); 228 229 tcflush(dev_fd, TCIOFLUSH); 230 UIM_DBG("set_baud_rate() done"); 231 232 return 0; 233 } 234 235 236 /* Function to set the UART custom baud rate. 237 * 238 * The UART baud rate has already been 239 * set to default value 115200 before calling this function. 240 * The baud rate is then changed to custom baud rate by this function*/ 241 static int set_custom_baud_rate(int dev_fd, int baud_rate, int flow_ctrl) 242 { 243 UIM_START_FUNC(); 244 245 struct termios ti; 246 struct termios2 ti2; 247 248 tcflush(dev_fd, TCIOFLUSH); 249 /* Get the attributes of UART */ 250 if (tcgetattr(dev_fd, &ti) < 0) { 251 UIM_ERR(" Can't get port settings"); 252 return -1; 253 } 254 255 /*Set the UART flow control */ 256 if (flow_ctrl) 257 ti.c_cflag |= CRTSCTS; 258 else 259 ti.c_cflag &= ~CRTSCTS; 260 261 /* 262 * Set the parameters associated with the UART 263 * The change will occur immediately by using TCSANOW 264 */ 265 if (tcsetattr(dev_fd, TCSANOW, &ti) < 0) { 266 UIM_ERR(" Can't set port settings"); 267 return -1; 268 } 269 270 tcflush(dev_fd, TCIOFLUSH); 271 272 /*Set the actual baud rate */ 273 ioctl(dev_fd, TCGETS2, &ti2); 274 ti2.c_cflag &= ~CBAUD; 275 ti2.c_cflag |= BOTHER; 276 ti2.c_ospeed = baud_rate; 277 ioctl(dev_fd, TCSETS2, &ti2); 278 279 return 0; 280 } 281 282 /* Function to configure the UART 283 * on receiving a notification from the ST KIM driver to install the line 284 * discipline, this function does UART configuration necessary for the STK 285 */ 286 int st_uart_config(unsigned char install) 287 { 288 int ldisc, len, fd, flow_ctrl; 289 unsigned char buf[UART_DEV_NAME_LEN]; 290 uim_speed_change_cmd cmd; 291 char uart_dev_name[UART_DEV_NAME_LEN]; 292 unsigned int cust_baud_rate; 293 294 uim_bdaddr_change_cmd addr_cmd; 295 296 UIM_START_FUNC(); 297 298 if (install == '1') { 299 memset(buf, 0, UART_DEV_NAME_LEN); 300 fd = open(sysfs_dev_name, O_RDONLY); 301 if (fd < 0) { 302 UIM_ERR("Can't open %s", sysfs_dev_name); 303 return -1; 304 } 305 len = read(fd, buf, UART_DEV_NAME_LEN); 306 if (len < 0) { 307 UIM_ERR("read err (%s)", strerror(errno)); 308 close(fd); 309 return len; 310 } 311 sscanf((const char*)buf, "%s", uart_dev_name); 312 close(fd); 313 314 memset(buf, 0, UART_DEV_NAME_LEN); 315 fd = open(sysfs_baud_rate, O_RDONLY); 316 if (fd < 0) { 317 UIM_ERR("Can't open %s", sysfs_baud_rate); 318 return -1; 319 } 320 len = read(fd, buf, UART_DEV_NAME_LEN); 321 if (len < 0) { 322 UIM_ERR("read err (%s)", strerror(errno)); 323 close(fd); 324 return len; 325 } 326 close(fd); 327 sscanf((const char*)buf, "%d", &cust_baud_rate); 328 329 memset(buf, 0, UART_DEV_NAME_LEN); 330 fd = open(sysfs_flow_ctrl, O_RDONLY); 331 if (fd < 0) { 332 UIM_ERR("Can't open %s", sysfs_flow_ctrl); 333 close(fd); 334 return -1; 335 } 336 len = read(fd, buf, UART_DEV_NAME_LEN); 337 if (len < 0) { 338 UIM_ERR("read err (%s)", strerror(errno)); 339 close(fd); 340 return len; 341 } 342 close(fd); 343 sscanf((const char*)buf, "%d", &flow_ctrl); 344 345 UIM_VER(" signal received, opening %s", uart_dev_name); 346 347 dev_fd = open(uart_dev_name, O_RDWR); 348 if (dev_fd < 0) { 349 UIM_ERR("Can't open %s", uart_dev_name); 350 return -1; 351 } 352 353 /* 354 * Set only the default baud rate. 355 * This will set the baud rate to default 115200 356 */ 357 if (set_baud_rate(dev_fd) < 0) { 358 UIM_ERR("set_baudrate() failed"); 359 close(dev_fd); 360 return -1; 361 } 362 363 fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK); 364 /* Set only the custom baud rate */ 365 if (cust_baud_rate != 115200) { 366 367 UIM_VER("Setting speed to %d", cust_baud_rate); 368 /* Forming the packet for Change speed command */ 369 cmd.uart_prefix = HCI_COMMAND_PKT; 370 cmd.hci_hdr.opcode = HCI_HDR_OPCODE; 371 cmd.hci_hdr.plen = sizeof(unsigned int); 372 cmd.speed = cust_baud_rate; 373 374 /* Writing the change speed command to the UART 375 * This will change the UART speed at the controller 376 * side 377 */ 378 len = write(dev_fd, &cmd, sizeof(cmd)); 379 if (len < 0) { 380 UIM_ERR("Failed to write speed-set command"); 381 close(dev_fd); 382 return -1; 383 } 384 385 /* Read the response for the Change speed command */ 386 if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) { 387 close(dev_fd); 388 return -1; 389 } 390 391 UIM_VER("Speed changing to %d, %d", cust_baud_rate, flow_ctrl); 392 /* Set the actual custom baud rate at the host side */ 393 if (set_custom_baud_rate(dev_fd, cust_baud_rate, flow_ctrl) < 0) { 394 UIM_ERR("set_custom_baud_rate() failed"); 395 close(dev_fd); 396 return -1; 397 } 398 399 /* Set the uim BD address */ 400 if (uim_bd_address[0] != 0) { 401 402 memset(&addr_cmd, 0, sizeof(addr_cmd)); 403 /* Forming the packet for change BD address command*/ 404 addr_cmd.uart_prefix = HCI_COMMAND_PKT; 405 addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE; 406 addr_cmd.hci_hdr.plen = sizeof(bdaddr_t); 407 memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t)); 408 409 /* Writing the change BD address command to the UART 410 * This will change the change BD address at the controller 411 * side 412 */ 413 len = write(dev_fd, &addr_cmd, sizeof(addr_cmd)); 414 if (len < 0) { 415 UIM_ERR("Failed to write BD address command"); 416 close(dev_fd); 417 return -1; 418 } 419 420 /* Read the response for the change BD address command */ 421 if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) { 422 close(dev_fd); 423 return -1; 424 } 425 UIM_VER("BD address changed to %s", uim_bd_address); 426 } 427 #ifdef UIM_DEBUG 428 read_firmware_version(dev_fd); 429 #endif 430 } 431 432 /* After the UART speed has been changed, the IOCTL is 433 * is called to set the line discipline to N_TI_WL 434 */ 435 ldisc = N_TI_WL; 436 if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) { 437 UIM_ERR(" Can't set line discipline"); 438 close(dev_fd); 439 return -1; 440 } 441 UIM_DBG("Installed N_TI_WL Line displine"); 442 } 443 else { 444 UIM_DBG("Un-Installed N_TI_WL Line displine"); 445 /* UNINSTALL_N_TI_WL - When the Signal is received from KIM */ 446 /* closing UART fd */ 447 close(dev_fd); 448 } 449 return 0; 450 } 451 452 /* Function to convert the BD address from ascii to hex value */ 453 bdaddr_t *strtoba(const char *str) 454 { 455 const char *ptr = str; 456 int i; 457 458 uint8_t *ba = malloc(sizeof(bdaddr_t)); 459 if (!ba) 460 return NULL; 461 462 for (i = 0; i < 6; i++) { 463 ba[i] = (uint8_t) strtol(ptr, NULL, 16); 464 if (i != 5 && !(ptr = strchr(ptr, ':'))) 465 ptr = ":00:00:00:00:00"; 466 ptr++; 467 } 468 469 return (bdaddr_t *) ba; 470 } 471 472 /*****************************************************************************/ 473 int main(int argc, char *argv[]) 474 { 475 int st_fd, err,trials; 476 unsigned char install; 477 struct pollfd p; 478 479 UIM_START_FUNC(); 480 err = 0; 481 trials = 5; 482 483 /* Parse the user input */ 484 if ((argc > 2)) { 485 UIM_ERR("Invalid arguements"); 486 UIM_ERR("Usage: uim <bd address>"); 487 return -1; 488 } 489 if (argc == 2) { 490 if (strlen(argv[2]) != BD_ADDR_LEN) { 491 UIM_ERR("Usage: uim XX:XX:XX:XX:XX:XX"); 492 return -1; 493 } 494 /* BD address passed as string in xx:xx:xx:xx:xx:xx format */ 495 strncpy(uim_bd_address, argv[2], sizeof(uim_bd_address)); 496 bd_addr = strtoba(uim_bd_address); 497 } 498 499 line_discipline = N_TI_WL; 500 501 /* sysfs entry may get populated after service is started so we retry if it fails*/ 502 while (trials > 0) { 503 st_fd = open(sysfs_install_entry, O_RDONLY); 504 if(st_fd > 0) 505 break; 506 if (trials == 3) 507 sysfs_entry_fallback(); 508 else 509 usleep(500000); 510 --trials; 511 } 512 if (st_fd < 0) { 513 UIM_DBG("unable to open %s(%s)", sysfs_install_entry, strerror(errno)); 514 return -1; 515 } 516 517 RE_POLL: 518 /* read to start proper poll */ 519 err = read(st_fd, &install, 1); 520 /* special case where bluetoothd starts before the UIM, and UIM 521 * needs to turn on bluetooth because of that. 522 */ 523 if ((err > 0) && install == '1') { 524 UIM_DBG("install set previously..."); 525 st_uart_config(install); 526 } 527 528 UIM_DBG("begin polling..."); 529 530 memset(&p, 0, sizeof(p)); 531 p.fd = st_fd; 532 p.events = POLLERR | POLLPRI; 533 534 while (!exiting) { 535 p.revents = 0; 536 err = poll(&p, 1, -1); 537 UIM_DBG("poll broke due to event %d(PRI:%d/ERR:%d)\n", p.revents, POLLPRI, POLLERR); 538 if (err < 0 && errno == EINTR) 539 continue; 540 if (err) 541 break; 542 } 543 544 close(st_fd); 545 st_fd = open(sysfs_install_entry, O_RDONLY); 546 if (st_fd < 0) { 547 UIM_DBG("unable to open %s (%s)", sysfs_install_entry, strerror(errno)); 548 return -1; 549 } 550 551 if (!exiting) 552 { 553 err = read(st_fd, &install, 1); 554 UIM_DBG("read %c from install \n", install); 555 if (err > 0) 556 st_uart_config(install); 557 goto RE_POLL; 558 } 559 560 close(st_fd); 561 return 0; 562 } 563