1/****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 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_userial_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 <string.h> 35#include "bt_vendor_brcm.h" 36#include "userial.h" 37#include "userial_vendor.h" 38 39/****************************************************************************** 40** Constants & Macros 41******************************************************************************/ 42 43#ifndef VNDUSERIAL_DBG 44#define VNDUSERIAL_DBG FALSE 45#endif 46 47#if (VNDUSERIAL_DBG == TRUE) 48#define VNDUSERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} 49#else 50#define VNDUSERIALDBG(param, ...) {} 51#endif 52 53#define VND_PORT_NAME_MAXLEN 256 54 55/****************************************************************************** 56** Local type definitions 57******************************************************************************/ 58 59/* vendor serial control block */ 60typedef struct 61{ 62 int fd; /* fd to Bluetooth device */ 63 struct termios termios; /* serial terminal of BT port */ 64 char port_name[VND_PORT_NAME_MAXLEN]; 65} vnd_userial_cb_t; 66 67/****************************************************************************** 68** Static variables 69******************************************************************************/ 70 71static vnd_userial_cb_t vnd_userial; 72 73/***************************************************************************** 74** Helper Functions 75*****************************************************************************/ 76 77/******************************************************************************* 78** 79** Function userial_to_tcio_baud 80** 81** Description helper function converts USERIAL baud rates into TCIO 82** conforming baud rates 83** 84** Returns TRUE/FALSE 85** 86*******************************************************************************/ 87uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud) 88{ 89 if (cfg_baud == USERIAL_BAUD_115200) 90 *baud = B115200; 91 else if (cfg_baud == USERIAL_BAUD_4M) 92 *baud = B4000000; 93 else if (cfg_baud == USERIAL_BAUD_3M) 94 *baud = B3000000; 95 else if (cfg_baud == USERIAL_BAUD_2M) 96 *baud = B2000000; 97 else if (cfg_baud == USERIAL_BAUD_1M) 98 *baud = B1000000; 99 else if (cfg_baud == USERIAL_BAUD_921600) 100 *baud = B921600; 101 else if (cfg_baud == USERIAL_BAUD_460800) 102 *baud = B460800; 103 else if (cfg_baud == USERIAL_BAUD_230400) 104 *baud = B230400; 105 else if (cfg_baud == USERIAL_BAUD_57600) 106 *baud = B57600; 107 else if (cfg_baud == USERIAL_BAUD_19200) 108 *baud = B19200; 109 else if (cfg_baud == USERIAL_BAUD_9600) 110 *baud = B9600; 111 else if (cfg_baud == USERIAL_BAUD_1200) 112 *baud = B1200; 113 else if (cfg_baud == USERIAL_BAUD_600) 114 *baud = B600; 115 else 116 { 117 ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud); 118 *baud = B115200; 119 return FALSE; 120 } 121 122 return TRUE; 123} 124 125#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 126/******************************************************************************* 127** 128** Function userial_ioctl_init_bt_wake 129** 130** Description helper function to set the open state of the bt_wake if ioctl 131** is used. it should not hurt in the rfkill case but it might 132** be better to compile it out. 133** 134** Returns none 135** 136*******************************************************************************/ 137void userial_ioctl_init_bt_wake(int fd) 138{ 139 uint32_t bt_wake_state; 140 141#if (BT_WAKE_USERIAL_LDISC==TRUE) 142 int ldisc = N_BRCM_HCI; /* brcm sleep mode support line discipline */ 143 144 /* attempt to load enable discipline driver */ 145 if (ioctl(vnd_userial.fd, TIOCSETD, &ldisc) < 0) 146 { 147 VNDUSERIALDBG("USERIAL_Open():fd %d, TIOCSETD failed: error %d for ldisc: %d", 148 fd, errno, ldisc); 149 } 150#endif 151 152 153 154 /* assert BT_WAKE through ioctl */ 155 ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 156 ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state); 157 VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \ 158 bt_wake_state); 159} 160#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 161 162 163/***************************************************************************** 164** Userial Vendor API Functions 165*****************************************************************************/ 166 167/******************************************************************************* 168** 169** Function userial_vendor_init 170** 171** Description Initialize userial vendor-specific control block 172** 173** Returns None 174** 175*******************************************************************************/ 176void userial_vendor_init(void) 177{ 178 vnd_userial.fd = -1; 179 snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \ 180 BLUETOOTH_UART_DEVICE_PORT); 181} 182 183/******************************************************************************* 184** 185** Function userial_vendor_open 186** 187** Description Open the serial port with the given configuration 188** 189** Returns device fd 190** 191*******************************************************************************/ 192int userial_vendor_open(tUSERIAL_CFG *p_cfg) 193{ 194 uint32_t baud; 195 uint8_t data_bits; 196 uint16_t parity; 197 uint8_t stop_bits; 198 199 vnd_userial.fd = -1; 200 201 if (!userial_to_tcio_baud(p_cfg->baud, &baud)) 202 { 203 return -1; 204 } 205 206 if(p_cfg->fmt & USERIAL_DATABITS_8) 207 data_bits = CS8; 208 else if(p_cfg->fmt & USERIAL_DATABITS_7) 209 data_bits = CS7; 210 else if(p_cfg->fmt & USERIAL_DATABITS_6) 211 data_bits = CS6; 212 else if(p_cfg->fmt & USERIAL_DATABITS_5) 213 data_bits = CS5; 214 else 215 { 216 ALOGE("userial vendor open: unsupported data bits"); 217 return -1; 218 } 219 220 if(p_cfg->fmt & USERIAL_PARITY_NONE) 221 parity = 0; 222 else if(p_cfg->fmt & USERIAL_PARITY_EVEN) 223 parity = PARENB; 224 else if(p_cfg->fmt & USERIAL_PARITY_ODD) 225 parity = (PARENB | PARODD); 226 else 227 { 228 ALOGE("userial vendor open: unsupported parity bit mode"); 229 return -1; 230 } 231 232 if(p_cfg->fmt & USERIAL_STOPBITS_1) 233 stop_bits = 0; 234 else if(p_cfg->fmt & USERIAL_STOPBITS_2) 235 stop_bits = CSTOPB; 236 else 237 { 238 ALOGE("userial vendor open: unsupported stop bits"); 239 return -1; 240 } 241 242 ALOGI("userial vendor open: opening %s", vnd_userial.port_name); 243 244 if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) 245 { 246 ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name); 247 return -1; 248 } 249 250 tcflush(vnd_userial.fd, TCIOFLUSH); 251 252 tcgetattr(vnd_userial.fd, &vnd_userial.termios); 253 cfmakeraw(&vnd_userial.termios); 254 vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits); 255 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 256 tcflush(vnd_userial.fd, TCIOFLUSH); 257 258 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 259 tcflush(vnd_userial.fd, TCIOFLUSH); 260 tcflush(vnd_userial.fd, TCIOFLUSH); 261 262 /* set input/output baudrate */ 263 cfsetospeed(&vnd_userial.termios, baud); 264 cfsetispeed(&vnd_userial.termios, baud); 265 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 266 267#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 268 userial_ioctl_init_bt_wake(vnd_userial.fd); 269#endif 270 271 ALOGI("device fd = %d open", vnd_userial.fd); 272 273 return vnd_userial.fd; 274} 275 276/******************************************************************************* 277** 278** Function userial_vendor_close 279** 280** Description Conduct vendor-specific close work 281** 282** Returns None 283** 284*******************************************************************************/ 285void userial_vendor_close(void) 286{ 287 int result; 288 289 if (vnd_userial.fd == -1) 290 return; 291 292#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 293 /* de-assert bt_wake BEFORE closing port */ 294 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 295#endif 296 297 ALOGI("device fd = %d close", vnd_userial.fd); 298 // flush Tx before close to make sure no chars in buffer 299 tcflush(vnd_userial.fd, TCIOFLUSH); 300 if ((result = close(vnd_userial.fd)) < 0) 301 ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result); 302 303 vnd_userial.fd = -1; 304} 305 306/******************************************************************************* 307** 308** Function userial_vendor_set_baud 309** 310** Description Set new baud rate 311** 312** Returns None 313** 314*******************************************************************************/ 315void userial_vendor_set_baud(uint8_t userial_baud) 316{ 317 uint32_t tcio_baud; 318 319 userial_to_tcio_baud(userial_baud, &tcio_baud); 320 321 cfsetospeed(&vnd_userial.termios, tcio_baud); 322 cfsetispeed(&vnd_userial.termios, tcio_baud); 323 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 324} 325 326/******************************************************************************* 327** 328** Function userial_vendor_ioctl 329** 330** Description ioctl inteface 331** 332** Returns None 333** 334*******************************************************************************/ 335void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data) 336{ 337 switch(op) 338 { 339#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 340 case USERIAL_OP_ASSERT_BT_WAKE: 341 VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); 342 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 343 break; 344 345 case USERIAL_OP_DEASSERT_BT_WAKE: 346 VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); 347 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 348 break; 349 350 case USERIAL_OP_GET_BT_WAKE_STATE: 351 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); 352 break; 353#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 354 355 default: 356 break; 357 } 358} 359 360/******************************************************************************* 361** 362** Function userial_set_port 363** 364** Description Configure UART port name 365** 366** Returns 0 : Success 367** Otherwise : Fail 368** 369*******************************************************************************/ 370int userial_set_port(char *p_conf_name, char *p_conf_value, int param) 371{ 372 strcpy(vnd_userial.port_name, p_conf_value); 373 374 return 0; 375} 376 377