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 stop_bits; 199 200 vnd_userial.fd = -1; 201 202 if (!userial_to_tcio_baud(p_cfg->baud, &baud)) { 203 return -1; 204 } 205 206 207 if (p_cfg->fmt & USERIAL_STOPBITS_1) 208 stop_bits = 0; 209 else if (p_cfg->fmt & USERIAL_STOPBITS_2) 210 stop_bits = CSTOPB; 211 212 HILOGI("userial vendor open: opening %s", vnd_userial.port_name); 213 214 if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) { 215 return -1; 216 } 217 218 tcflush(vnd_userial.fd, TCIOFLUSH); 219 220 tcgetattr(vnd_userial.fd, &vnd_userial.termios); 221 cfmakeraw(&vnd_userial.termios); 222 vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits); 223 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 224 tcflush(vnd_userial.fd, TCIOFLUSH); 225 226 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 227 tcflush(vnd_userial.fd, TCIOFLUSH); 228 tcflush(vnd_userial.fd, TCIOFLUSH); 229 230 /* set input/output baudrate */ 231 cfsetospeed(&vnd_userial.termios, baud); 232 cfsetispeed(&vnd_userial.termios, baud); 233 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 234 235#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 236 userial_ioctl_init_bt_wake(vnd_userial.fd); 237#endif 238 239 HILOGI("device fd = %d open", vnd_userial.fd); 240 return vnd_userial.fd; 241} 242 243/******************************************************************************* 244** 245** Function userial_vendor_close 246** 247** Description Conduct vendor-specific close work 248** 249** Returns None 250** 251*******************************************************************************/ 252void userial_vendor_close(void) 253{ 254 int result; 255 256 if (vnd_userial.fd == -1) { 257 return; 258 } 259 260#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 261 /* de-assert bt_wake BEFORE closing port */ 262 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 263#endif 264 265 HILOGI("device fd = %d close", vnd_userial.fd); 266 // flush Tx before close to make sure no chars in buffer 267 tcflush(vnd_userial.fd, TCIOFLUSH); 268 if ((result = close(vnd_userial.fd)) < 0) { 269 HILOGE("close(fd:%d) FAILED result:%d", vnd_userial.fd, result); 270 } 271 272 vnd_userial.fd = -1; 273} 274 275/******************************************************************************* 276** 277** Function userial_vendor_set_baud 278** 279** Description Set new baud rate 280** 281** Returns None 282** 283*******************************************************************************/ 284void userial_vendor_set_baud(uint8_t userial_baud) 285{ 286 uint32_t tcio_baud; 287 288 if (USERIAL_VENDOR_SET_BAUD_DELAY_US > 0) { 289 usleep(USERIAL_VENDOR_SET_BAUD_DELAY_US); 290 } 291 292 userial_to_tcio_baud(userial_baud, &tcio_baud); 293 294 cfsetospeed(&vnd_userial.termios, tcio_baud); 295 cfsetispeed(&vnd_userial.termios, tcio_baud); 296 tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 297} 298 299/******************************************************************************* 300** 301** Function userial_vendor_ioctl 302** 303** Description ioctl inteface 304** 305** Returns None 306** 307*******************************************************************************/ 308void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data) 309{ 310 switch (op) { 311#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 312 case USERIAL_OP_ASSERT_BT_WAKE: 313 VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); 314 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 315 break; 316 317 case USERIAL_OP_DEASSERT_BT_WAKE: 318 VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); 319 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 320 break; 321 322 case USERIAL_OP_GET_BT_WAKE_STATE: 323 ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); 324 break; 325#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 326 327 default: 328 break; 329 } 330} 331 332/******************************************************************************* 333** 334** Function userial_set_port 335** 336** Description Configure UART port name 337** 338** Returns 0 : Success 339** Otherwise : Fail 340** 341*******************************************************************************/ 342int userial_set_port(char *p_conf_name, char *p_conf_value, int param) 343{ 344 (void)strcpy_s(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, p_conf_value); 345 346 return 0; 347} 348