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