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