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