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******************************************************************************/ 55vnd_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*******************************************************************************/ 71uint8_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*******************************************************************************/ 118int 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*******************************************************************************/ 185void 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*******************************************************************************/ 211void 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*******************************************************************************/ 226int 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*******************************************************************************/ 320void 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*******************************************************************************/ 349void 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*******************************************************************************/ 372int 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*******************************************************************************/ 392int 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*******************************************************************************/ 443int 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*******************************************************************************/ 459int 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 505int 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