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