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