1 /* 2 * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 * Not a Contribution. 4 * Copyright 2012 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /****************************************************************************** 20 * 21 * Filename: userial_vendor.c 22 * 23 * Description: Contains vendor-specific userial functions 24 * 25 ******************************************************************************/ 26 27 #define LOG_TAG "bt_vendor" 28 29 #include <utils/Log.h> 30 #include <termios.h> 31 #include <fcntl.h> 32 #include <errno.h> 33 #include <stdio.h> 34 #include "bt_vendor_qcom.h" 35 #include "hci_uart.h" 36 #include <string.h> 37 38 /****************************************************************************** 39 ** Constants & Macros 40 ******************************************************************************/ 41 42 #ifndef VNDUSERIAL_DBG 43 #define VNDUSERIAL_DBG TRUE 44 #endif 45 46 #if (VNDUSERIAL_DBG == TRUE) 47 #define VNDUSERIALDBG(param, ...) {ALOGI(param, ## __VA_ARGS__);} 48 #else 49 #define VNDUSERIALDBG(param, ...) {} 50 #endif 51 52 #define RESERVED(p) if(p) ALOGI( "%s: reserved param", __FUNCTION__); 53 54 /****************************************************************************** 55 ** Global variables 56 ******************************************************************************/ 57 vnd_userial_cb_t vnd_userial; 58 59 /***************************************************************************** 60 ** Functions 61 *****************************************************************************/ 62 63 /******************************************************************************* 64 ** 65 ** Function userial_to_tcio_baud 66 ** 67 ** Description helper function converts USERIAL baud rates into TCIO 68 ** conforming baud rates 69 ** 70 ** Returns TRUE/FALSE 71 ** 72 *******************************************************************************/ 73 uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud) 74 { 75 if (cfg_baud == USERIAL_BAUD_115200) 76 *baud = B115200; 77 else if (cfg_baud == USERIAL_BAUD_4M) 78 *baud = B4000000; 79 else if (cfg_baud == USERIAL_BAUD_3M) 80 *baud = B3000000; 81 else if (cfg_baud == USERIAL_BAUD_2M) 82 *baud = B2000000; 83 else if (cfg_baud == USERIAL_BAUD_1M) 84 *baud = B1000000; 85 else if (cfg_baud == USERIAL_BAUD_921600) 86 *baud = B921600; 87 else if (cfg_baud == USERIAL_BAUD_460800) 88 *baud = B460800; 89 else if (cfg_baud == USERIAL_BAUD_230400) 90 *baud = B230400; 91 else if (cfg_baud == USERIAL_BAUD_57600) 92 *baud = B57600; 93 else if (cfg_baud == USERIAL_BAUD_19200) 94 *baud = B19200; 95 else if (cfg_baud == USERIAL_BAUD_9600) 96 *baud = B9600; 97 else if (cfg_baud == USERIAL_BAUD_1200) 98 *baud = B1200; 99 else if (cfg_baud == USERIAL_BAUD_600) 100 *baud = B600; 101 else 102 { 103 ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud); 104 *baud = B115200; 105 return FALSE; 106 } 107 108 return TRUE; 109 } 110 111 /******************************************************************************* 112 ** 113 ** Function userial_to_baud_tcio 114 ** 115 ** Description helper function converts TCIO baud rate into integer 116 ** 117 ** Returns uint32_t 118 ** 119 *******************************************************************************/ 120 int userial_tcio_baud_to_int(uint32_t baud) 121 { 122 int baud_rate =0; 123 124 switch (baud) 125 { 126 case B600: 127 baud_rate = 600; 128 break; 129 case B1200: 130 baud_rate = 1200; 131 break; 132 case B9600: 133 baud_rate = 9600; 134 break; 135 case B19200: 136 baud_rate = 19200; 137 break; 138 case B57600: 139 baud_rate = 57600; 140 break; 141 case B115200: 142 baud_rate = 115200; 143 break; 144 case B230400: 145 baud_rate = 230400; 146 break; 147 case B460800: 148 baud_rate = 460800; 149 break; 150 case B921600: 151 baud_rate = 921600; 152 break; 153 case B1000000: 154 baud_rate = 1000000; 155 break; 156 case B2000000: 157 baud_rate = 2000000; 158 break; 159 case B3000000: 160 baud_rate = 3000000; 161 break; 162 case B4000000: 163 baud_rate = 4000000; 164 break; 165 default: 166 ALOGE( "%s: unsupported baud %d", __FUNCTION__, baud); 167 break; 168 } 169 170 ALOGI( "%s: Current Baudrate = %d bps", __FUNCTION__, baud_rate); 171 return baud_rate; 172 } 173 174 175 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 176 /******************************************************************************* 177 ** 178 ** Function userial_ioctl_init_bt_wake 179 ** 180 ** Description helper function to set the open state of the bt_wake if ioctl 181 ** is used. it should not hurt in the rfkill case but it might 182 ** be better to compile it out. 183 ** 184 ** Returns none 185 ** 186 *******************************************************************************/ 187 void userial_ioctl_init_bt_wake(int fd) 188 { 189 uint32_t bt_wake_state; 190 191 /* assert BT_WAKE through ioctl */ 192 ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 193 ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state); 194 VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \ 195 bt_wake_state); 196 } 197 #endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 198 199 200 /***************************************************************************** 201 ** Userial Vendor API Functions 202 *****************************************************************************/ 203 204 /******************************************************************************* 205 ** 206 ** Function userial_vendor_init 207 ** 208 ** Description Initialize userial vendor-specific control block 209 ** 210 ** Returns None 211 ** 212 *******************************************************************************/ 213 void userial_vendor_init(void) 214 { 215 vnd_userial.fd = -1; 216 snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", BT_HS_UART_DEVICE); 217 } 218 219 /******************************************************************************* 220 ** 221 ** Function userial_vendor_open 222 ** 223 ** Description Open the serial port with the given configuration 224 ** 225 ** Returns device fd 226 ** 227 *******************************************************************************/ 228 int userial_vendor_open(tUSERIAL_CFG *p_cfg) 229 { 230 uint32_t baud; 231 uint8_t data_bits; 232 uint16_t parity; 233 uint8_t stop_bits; 234 235 vnd_userial.fd = -1; 236 237 if (!userial_to_tcio_baud(p_cfg->baud, &baud)) 238 { 239 return -1; 240 } 241 242 if(p_cfg->fmt & USERIAL_DATABITS_8) 243 data_bits = CS8; 244 else if(p_cfg->fmt & USERIAL_DATABITS_7) 245 data_bits = CS7; 246 else if(p_cfg->fmt & USERIAL_DATABITS_6) 247 data_bits = CS6; 248 else if(p_cfg->fmt & USERIAL_DATABITS_5) 249 data_bits = CS5; 250 else 251 { 252 ALOGE("userial vendor open: unsupported data bits"); 253 return -1; 254 } 255 256 if(p_cfg->fmt & USERIAL_PARITY_NONE) 257 parity = 0; 258 else if(p_cfg->fmt & USERIAL_PARITY_EVEN) 259 parity = PARENB; 260 else if(p_cfg->fmt & USERIAL_PARITY_ODD) 261 parity = (PARENB | PARODD); 262 else 263 { 264 ALOGE("userial vendor open: unsupported parity bit mode"); 265 return -1; 266 } 267 268 if(p_cfg->fmt & USERIAL_STOPBITS_1) 269 stop_bits = 0; 270 else if(p_cfg->fmt & USERIAL_STOPBITS_2) 271 stop_bits = CSTOPB; 272 else 273 { 274 ALOGE("userial vendor open: unsupported stop bits"); 275 return -1; 276 } 277 278 ALOGI("userial vendor open: opening %s", vnd_userial.port_name); 279 280 if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR|O_NOCTTY)) == -1) 281 { 282 ALOGE("userial vendor open: unable to open %s: %s(%d)", vnd_userial.port_name, 283 strerror(errno), errno); 284 return -1; 285 } 286 287 tcflush(vnd_userial.fd, TCIOFLUSH); 288 289 tcgetattr(vnd_userial.fd, &vnd_userial.termios); 290 cfmakeraw(&vnd_userial.termios); 291 292 /* Set UART Control Modes */ 293 vnd_userial.termios.c_cflag |= CLOCAL; 294 vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits); 295 296 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 297 298 /* set input/output baudrate */ 299 cfsetospeed(&vnd_userial.termios, baud); 300 cfsetispeed(&vnd_userial.termios, baud); 301 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 302 303 tcflush(vnd_userial.fd, TCIOFLUSH); 304 305 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 306 userial_ioctl_init_bt_wake(vnd_userial.fd); 307 #endif 308 309 ALOGI("device fd = %d open", vnd_userial.fd); 310 311 return vnd_userial.fd; 312 } 313 314 /******************************************************************************* 315 ** 316 ** Function userial_vendor_close 317 ** 318 ** Description Conduct vendor-specific close work 319 ** 320 ** Returns None 321 ** 322 *******************************************************************************/ 323 void userial_vendor_close(void) 324 { 325 int result; 326 327 if (vnd_userial.fd == -1) 328 return; 329 330 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 331 /* de-assert bt_wake BEFORE closing port */ 332 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 333 #endif 334 335 ALOGI("device fd = %d close", vnd_userial.fd); 336 337 if ((result = close(vnd_userial.fd)) < 0) 338 ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result); 339 340 vnd_userial.fd = -1; 341 } 342 343 /******************************************************************************* 344 ** 345 ** Function userial_vendor_set_baud 346 ** 347 ** Description Set new baud rate 348 ** 349 ** Returns None 350 ** 351 *******************************************************************************/ 352 void userial_vendor_set_baud(uint8_t userial_baud) 353 { 354 uint32_t tcio_baud; 355 356 VNDUSERIALDBG("## userial_vendor_set_baud: %d", userial_baud); 357 358 userial_to_tcio_baud(userial_baud, &tcio_baud); 359 360 cfsetospeed(&vnd_userial.termios, tcio_baud); 361 cfsetispeed(&vnd_userial.termios, tcio_baud); 362 tcsetattr(vnd_userial.fd, TCSADRAIN, &vnd_userial.termios); /* don't change speed until last write done */ 363 // tcflush(vnd_userial.fd, TCIOFLUSH); 364 } 365 366 /******************************************************************************* 367 ** 368 ** Function userial_vendor_get_baud 369 ** 370 ** Description Get current baud rate 371 ** 372 ** Returns int 373 ** 374 *******************************************************************************/ 375 int userial_vendor_get_baud(void) 376 { 377 if (vnd_userial.fd == -1) 378 { 379 ALOGE( "%s: uart port(%s) has not been opened", __FUNCTION__, BT_HS_UART_DEVICE ); 380 return -1; 381 } 382 383 return userial_tcio_baud_to_int(cfgetispeed(&vnd_userial.termios)); 384 } 385 386 /******************************************************************************* 387 ** 388 ** Function userial_vendor_ioctl 389 ** 390 ** Description ioctl inteface 391 ** 392 ** Returns None 393 ** 394 *******************************************************************************/ 395 int userial_vendor_ioctl(userial_vendor_ioctl_op_t op, int *p_data) 396 { 397 int err = -1; 398 399 switch(op) 400 { 401 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 402 case USERIAL_OP_ASSERT_BT_WAKE: 403 VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); 404 err = ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 405 break; 406 407 case USERIAL_OP_DEASSERT_BT_WAKE: 408 VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); 409 err = ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 410 break; 411 412 case USERIAL_OP_GET_BT_WAKE_STATE: 413 err = ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); 414 break; 415 #endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 416 case USERIAL_OP_FLOW_ON: 417 ALOGI("## userial_vendor_ioctl: UART Flow On "); 418 *p_data |=TIOCM_RTS; 419 err = ioctl(vnd_userial.fd, TIOCMSET, p_data); 420 break; 421 422 case USERIAL_OP_FLOW_OFF: 423 ALOGI("## userial_vendor_ioctl: UART Flow Off "); 424 ioctl(vnd_userial.fd, TIOCMGET, p_data); 425 *p_data &= ~TIOCM_RTS; 426 err = ioctl(vnd_userial.fd, TIOCMSET, p_data); 427 break; 428 429 default: 430 break; 431 } 432 433 return err; 434 } 435 436 /******************************************************************************* 437 ** 438 ** Function userial_set_port 439 ** 440 ** Description Configure UART port name 441 ** 442 ** Returns 0 : Success 443 ** Otherwise : Fail 444 ** 445 *******************************************************************************/ 446 int userial_set_port(char *p_conf_name, char *p_conf_value, int param) 447 { 448 RESERVED(p_conf_name); 449 RESERVED(param); 450 strlcpy(vnd_userial.port_name, p_conf_value, VND_PORT_NAME_MAXLEN); 451 452 return 0; 453 } 454 455 /******************************************************************************* 456 ** 457 ** Function read_hci_event 458 ** 459 ** Description Read HCI event during vendor initialization 460 ** 461 ** Returns int: size to read 462 ** 463 *******************************************************************************/ 464 int read_hci_event(int fd, unsigned char* buf, int size) 465 { 466 int remain, r; 467 int count = 0; 468 469 if (size <= 0) { 470 ALOGE("Invalid size arguement!"); 471 return -1; 472 } 473 474 ALOGI("%s: Wait for Command Compete Event from SOC", __FUNCTION__); 475 476 /* The first byte identifies the packet type. For HCI event packets, it 477 * should be 0x04, so we read until we get to the 0x04. */ 478 while (1) { 479 r = read(fd, buf, 1); 480 if (r <= 0) 481 return -1; 482 if (buf[0] == 0x04) 483 break; 484 } 485 count++; 486 487 /* The next two bytes are the event code and parameter total length. */ 488 while (count < 3) { 489 r = read(fd, buf + count, 3 - count); 490 if (r <= 0) 491 return -1; 492 count += r; 493 } 494 495 /* Now we read the parameters. */ 496 if (buf[2] < (size - 3)) 497 remain = buf[2]; 498 else 499 remain = size - 3; 500 501 while ((count - 3) < remain) { 502 r = read(fd, buf + count, remain - (count - 3)); 503 if (r <= 0) 504 return -1; 505 count += r; 506 } 507 return count; 508 } 509 510 int userial_clock_operation(int fd, int cmd) 511 { 512 int ret = 0; 513 514 switch (cmd) 515 { 516 case USERIAL_OP_CLK_ON: 517 case USERIAL_OP_CLK_OFF: 518 ioctl(fd, cmd); 519 break; 520 case USERIAL_OP_CLK_STATE: 521 ret = ioctl(fd, cmd); 522 break; 523 } 524 525 return ret; 526 } 527