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******************************************************************************/ 61vnd_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*******************************************************************************/ 77uint8_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*******************************************************************************/ 124int 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*******************************************************************************/ 191void 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*******************************************************************************/ 217void 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*******************************************************************************/ 232int 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*******************************************************************************/ 327void 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*******************************************************************************/ 356void 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*******************************************************************************/ 379int 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*******************************************************************************/ 399int 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*******************************************************************************/ 450int 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*******************************************************************************/ 468int 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 514int 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