10b966c5eSopenharmony_ci/****************************************************************************** 20b966c5eSopenharmony_ci * 30b966c5eSopenharmony_ci * Copyright (C) 2009-2012 Broadcom Corporation 40b966c5eSopenharmony_ci * 50b966c5eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 60b966c5eSopenharmony_ci * you may not use this file except in compliance with the License. 70b966c5eSopenharmony_ci * You may obtain a copy of the License at: 80b966c5eSopenharmony_ci * 90b966c5eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 100b966c5eSopenharmony_ci * 110b966c5eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 120b966c5eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 130b966c5eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140b966c5eSopenharmony_ci * See the License for the specific language governing permissions and 150b966c5eSopenharmony_ci * limitations under the License. 160b966c5eSopenharmony_ci * 170b966c5eSopenharmony_ci ******************************************************************************/ 180b966c5eSopenharmony_ci 190b966c5eSopenharmony_ci/****************************************************************************** 200b966c5eSopenharmony_ci * 210b966c5eSopenharmony_ci * Filename: userial_vendor.c 220b966c5eSopenharmony_ci * 230b966c5eSopenharmony_ci * Description: Contains vendor-specific userial functions 240b966c5eSopenharmony_ci * 250b966c5eSopenharmony_ci ******************************************************************************/ 260b966c5eSopenharmony_ci 270b966c5eSopenharmony_ci#define LOG_TAG "bt_userial_vendor" 280b966c5eSopenharmony_ci 290b966c5eSopenharmony_ci#include <termios.h> 300b966c5eSopenharmony_ci#include <fcntl.h> 310b966c5eSopenharmony_ci#include <errno.h> 320b966c5eSopenharmony_ci#include <stdio.h> 330b966c5eSopenharmony_ci#include <string.h> 340b966c5eSopenharmony_ci#include <unistd.h> 350b966c5eSopenharmony_ci#include <utils/Log.h> 360b966c5eSopenharmony_ci#include "bt_vendor_brcm.h" 370b966c5eSopenharmony_ci#include "userial.h" 380b966c5eSopenharmony_ci#include "userial_vendor.h" 390b966c5eSopenharmony_ci 400b966c5eSopenharmony_ci/****************************************************************************** 410b966c5eSopenharmony_ci** Constants & Macros 420b966c5eSopenharmony_ci******************************************************************************/ 430b966c5eSopenharmony_ci 440b966c5eSopenharmony_ci#ifndef VNDUSERIAL_DBG 450b966c5eSopenharmony_ci#define VNDUSERIAL_DBG FALSE 460b966c5eSopenharmony_ci#endif 470b966c5eSopenharmony_ci 480b966c5eSopenharmony_ci#if (VNDUSERIAL_DBG == TRUE) 490b966c5eSopenharmony_ci#define VNDUSERIALDBG(param, ...) \ 500b966c5eSopenharmony_ci{ \ 510b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 520b966c5eSopenharmony_ci} 530b966c5eSopenharmony_ci#else 540b966c5eSopenharmony_ci#define VNDUSERIALDBG(param, ...) \ 550b966c5eSopenharmony_ci{ \ 560b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 570b966c5eSopenharmony_ci} 580b966c5eSopenharmony_ci#endif 590b966c5eSopenharmony_ci 600b966c5eSopenharmony_ci#define VND_PORT_NAME_MAXLEN 256 610b966c5eSopenharmony_ci 620b966c5eSopenharmony_ci/****************************************************************************** 630b966c5eSopenharmony_ci** Local type definitions 640b966c5eSopenharmony_ci******************************************************************************/ 650b966c5eSopenharmony_ci 660b966c5eSopenharmony_ci/* vendor serial control block */ 670b966c5eSopenharmony_citypedef struct { 680b966c5eSopenharmony_ci int fd; /* fd to Bluetooth device */ 690b966c5eSopenharmony_ci struct termios termios; /* serial terminal of BT port */ 700b966c5eSopenharmony_ci char port_name[VND_PORT_NAME_MAXLEN]; 710b966c5eSopenharmony_ci} vnd_userial_cb_t; 720b966c5eSopenharmony_ci 730b966c5eSopenharmony_ci/****************************************************************************** 740b966c5eSopenharmony_ci** Static variables 750b966c5eSopenharmony_ci******************************************************************************/ 760b966c5eSopenharmony_ci 770b966c5eSopenharmony_cistatic vnd_userial_cb_t vnd_userial; 780b966c5eSopenharmony_ci 790b966c5eSopenharmony_ci/***************************************************************************** 800b966c5eSopenharmony_ci** Helper Functions 810b966c5eSopenharmony_ci*****************************************************************************/ 820b966c5eSopenharmony_ci 830b966c5eSopenharmony_ci/******************************************************************************* 840b966c5eSopenharmony_ci** 850b966c5eSopenharmony_ci** Function userial_to_tcio_baud 860b966c5eSopenharmony_ci** 870b966c5eSopenharmony_ci** Description helper function converts USERIAL baud rates into TCIO 880b966c5eSopenharmony_ci** conforming baud rates 890b966c5eSopenharmony_ci** 900b966c5eSopenharmony_ci** Returns TRUE/FALSE 910b966c5eSopenharmony_ci** 920b966c5eSopenharmony_ci*******************************************************************************/ 930b966c5eSopenharmony_ciuint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud) 940b966c5eSopenharmony_ci{ 950b966c5eSopenharmony_ci if (cfg_baud == USERIAL_BAUD_115200) 960b966c5eSopenharmony_ci *baud = B115200; 970b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_4M) 980b966c5eSopenharmony_ci *baud = B4000000; 990b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_3M) 1000b966c5eSopenharmony_ci *baud = B3000000; 1010b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_2M) 1020b966c5eSopenharmony_ci *baud = B2000000; 1030b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_1_5M) 1040b966c5eSopenharmony_ci *baud = B1500000; 1050b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_1M) 1060b966c5eSopenharmony_ci *baud = B1000000; 1070b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_921600) 1080b966c5eSopenharmony_ci *baud = B921600; 1090b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_460800) 1100b966c5eSopenharmony_ci *baud = B460800; 1110b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_230400) 1120b966c5eSopenharmony_ci *baud = B230400; 1130b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_57600) 1140b966c5eSopenharmony_ci *baud = B57600; 1150b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_19200) 1160b966c5eSopenharmony_ci *baud = B19200; 1170b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_9600) 1180b966c5eSopenharmony_ci *baud = B9600; 1190b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_1200) 1200b966c5eSopenharmony_ci *baud = B1200; 1210b966c5eSopenharmony_ci else if (cfg_baud == USERIAL_BAUD_600) 1220b966c5eSopenharmony_ci *baud = B600; 1230b966c5eSopenharmony_ci else { 1240b966c5eSopenharmony_ci HILOGE("userial vendor open: unsupported baud idx %i", cfg_baud); 1250b966c5eSopenharmony_ci *baud = B115200; 1260b966c5eSopenharmony_ci return FALSE; 1270b966c5eSopenharmony_ci } 1280b966c5eSopenharmony_ci 1290b966c5eSopenharmony_ci return TRUE; 1300b966c5eSopenharmony_ci} 1310b966c5eSopenharmony_ci 1320b966c5eSopenharmony_ci#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 1330b966c5eSopenharmony_ci/******************************************************************************* 1340b966c5eSopenharmony_ci** 1350b966c5eSopenharmony_ci** Function userial_ioctl_init_bt_wake 1360b966c5eSopenharmony_ci** 1370b966c5eSopenharmony_ci** Description helper function to set the open state of the bt_wake if ioctl 1380b966c5eSopenharmony_ci** is used. it should not hurt in the rfkill case but it might 1390b966c5eSopenharmony_ci** be better to compile it out. 1400b966c5eSopenharmony_ci** 1410b966c5eSopenharmony_ci** Returns none 1420b966c5eSopenharmony_ci** 1430b966c5eSopenharmony_ci*******************************************************************************/ 1440b966c5eSopenharmony_civoid userial_ioctl_init_bt_wake(int fd) 1450b966c5eSopenharmony_ci{ 1460b966c5eSopenharmony_ci uint32_t bt_wake_state; 1470b966c5eSopenharmony_ci 1480b966c5eSopenharmony_ci#if (BT_WAKE_USERIAL_LDISC == TRUE) 1490b966c5eSopenharmony_ci int ldisc = N_BRCM_HCI; /* brcm sleep mode support line discipline */ 1500b966c5eSopenharmony_ci 1510b966c5eSopenharmony_ci /* attempt to load enable discipline driver */ 1520b966c5eSopenharmony_ci if (ioctl(vnd_userial.fd, TIOCSETD, &ldisc) < 0) { 1530b966c5eSopenharmony_ci VNDUSERIALDBG("USERIAL_Open():fd %d, TIOCSETD failed: error %d for ldisc: %d", 1540b966c5eSopenharmony_ci fd, errno, ldisc); 1550b966c5eSopenharmony_ci } 1560b966c5eSopenharmony_ci#endif 1570b966c5eSopenharmony_ci 1580b966c5eSopenharmony_ci /* assert BT_WAKE through ioctl */ 1590b966c5eSopenharmony_ci ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 1600b966c5eSopenharmony_ci ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state); 1610b966c5eSopenharmony_ci VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", 1620b966c5eSopenharmony_ci bt_wake_state); 1630b966c5eSopenharmony_ci} 1640b966c5eSopenharmony_ci#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 1650b966c5eSopenharmony_ci 1660b966c5eSopenharmony_ci/***************************************************************************** 1670b966c5eSopenharmony_ci** Userial Vendor API Functions 1680b966c5eSopenharmony_ci*****************************************************************************/ 1690b966c5eSopenharmony_ci 1700b966c5eSopenharmony_ci/******************************************************************************* 1710b966c5eSopenharmony_ci** 1720b966c5eSopenharmony_ci** Function userial_vendor_init 1730b966c5eSopenharmony_ci** 1740b966c5eSopenharmony_ci** Description Initialize userial vendor-specific control block 1750b966c5eSopenharmony_ci** 1760b966c5eSopenharmony_ci** Returns None 1770b966c5eSopenharmony_ci** 1780b966c5eSopenharmony_ci*******************************************************************************/ 1790b966c5eSopenharmony_civoid userial_vendor_init(void) 1800b966c5eSopenharmony_ci{ 1810b966c5eSopenharmony_ci vnd_userial.fd = -1; 1820b966c5eSopenharmony_ci (void)snprintf_s(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, VND_PORT_NAME_MAXLEN, "%s", 1830b966c5eSopenharmony_ci BLUETOOTH_UART_DEVICE_PORT); 1840b966c5eSopenharmony_ci} 1850b966c5eSopenharmony_ci 1860b966c5eSopenharmony_ci/******************************************************************************* 1870b966c5eSopenharmony_ci** 1880b966c5eSopenharmony_ci** Function userial_vendor_open 1890b966c5eSopenharmony_ci** 1900b966c5eSopenharmony_ci** Description Open the serial port with the given configuration 1910b966c5eSopenharmony_ci** 1920b966c5eSopenharmony_ci** Returns device fd 1930b966c5eSopenharmony_ci** 1940b966c5eSopenharmony_ci*******************************************************************************/ 1950b966c5eSopenharmony_ciint userial_vendor_open(tUSERIAL_CFG *p_cfg) 1960b966c5eSopenharmony_ci{ 1970b966c5eSopenharmony_ci uint32_t baud; 1980b966c5eSopenharmony_ci uint8_t stop_bits; 1990b966c5eSopenharmony_ci 2000b966c5eSopenharmony_ci vnd_userial.fd = -1; 2010b966c5eSopenharmony_ci 2020b966c5eSopenharmony_ci if (!userial_to_tcio_baud(p_cfg->baud, &baud)) { 2030b966c5eSopenharmony_ci return -1; 2040b966c5eSopenharmony_ci } 2050b966c5eSopenharmony_ci 2060b966c5eSopenharmony_ci 2070b966c5eSopenharmony_ci if (p_cfg->fmt & USERIAL_STOPBITS_1) 2080b966c5eSopenharmony_ci stop_bits = 0; 2090b966c5eSopenharmony_ci else if (p_cfg->fmt & USERIAL_STOPBITS_2) 2100b966c5eSopenharmony_ci stop_bits = CSTOPB; 2110b966c5eSopenharmony_ci 2120b966c5eSopenharmony_ci HILOGI("userial vendor open: opening %s", vnd_userial.port_name); 2130b966c5eSopenharmony_ci 2140b966c5eSopenharmony_ci if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) { 2150b966c5eSopenharmony_ci return -1; 2160b966c5eSopenharmony_ci } 2170b966c5eSopenharmony_ci 2180b966c5eSopenharmony_ci tcflush(vnd_userial.fd, TCIOFLUSH); 2190b966c5eSopenharmony_ci 2200b966c5eSopenharmony_ci tcgetattr(vnd_userial.fd, &vnd_userial.termios); 2210b966c5eSopenharmony_ci cfmakeraw(&vnd_userial.termios); 2220b966c5eSopenharmony_ci vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits); 2230b966c5eSopenharmony_ci tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 2240b966c5eSopenharmony_ci tcflush(vnd_userial.fd, TCIOFLUSH); 2250b966c5eSopenharmony_ci 2260b966c5eSopenharmony_ci tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 2270b966c5eSopenharmony_ci tcflush(vnd_userial.fd, TCIOFLUSH); 2280b966c5eSopenharmony_ci tcflush(vnd_userial.fd, TCIOFLUSH); 2290b966c5eSopenharmony_ci 2300b966c5eSopenharmony_ci /* set input/output baudrate */ 2310b966c5eSopenharmony_ci cfsetospeed(&vnd_userial.termios, baud); 2320b966c5eSopenharmony_ci cfsetispeed(&vnd_userial.termios, baud); 2330b966c5eSopenharmony_ci tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 2340b966c5eSopenharmony_ci 2350b966c5eSopenharmony_ci#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 2360b966c5eSopenharmony_ci userial_ioctl_init_bt_wake(vnd_userial.fd); 2370b966c5eSopenharmony_ci#endif 2380b966c5eSopenharmony_ci 2390b966c5eSopenharmony_ci HILOGI("device fd = %d open", vnd_userial.fd); 2400b966c5eSopenharmony_ci return vnd_userial.fd; 2410b966c5eSopenharmony_ci} 2420b966c5eSopenharmony_ci 2430b966c5eSopenharmony_ci/******************************************************************************* 2440b966c5eSopenharmony_ci** 2450b966c5eSopenharmony_ci** Function userial_vendor_close 2460b966c5eSopenharmony_ci** 2470b966c5eSopenharmony_ci** Description Conduct vendor-specific close work 2480b966c5eSopenharmony_ci** 2490b966c5eSopenharmony_ci** Returns None 2500b966c5eSopenharmony_ci** 2510b966c5eSopenharmony_ci*******************************************************************************/ 2520b966c5eSopenharmony_civoid userial_vendor_close(void) 2530b966c5eSopenharmony_ci{ 2540b966c5eSopenharmony_ci int result; 2550b966c5eSopenharmony_ci 2560b966c5eSopenharmony_ci if (vnd_userial.fd == -1) { 2570b966c5eSopenharmony_ci return; 2580b966c5eSopenharmony_ci } 2590b966c5eSopenharmony_ci 2600b966c5eSopenharmony_ci#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 2610b966c5eSopenharmony_ci /* de-assert bt_wake BEFORE closing port */ 2620b966c5eSopenharmony_ci ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 2630b966c5eSopenharmony_ci#endif 2640b966c5eSopenharmony_ci 2650b966c5eSopenharmony_ci HILOGI("device fd = %d close", vnd_userial.fd); 2660b966c5eSopenharmony_ci // flush Tx before close to make sure no chars in buffer 2670b966c5eSopenharmony_ci tcflush(vnd_userial.fd, TCIOFLUSH); 2680b966c5eSopenharmony_ci if ((result = close(vnd_userial.fd)) < 0) { 2690b966c5eSopenharmony_ci HILOGE("close(fd:%d) FAILED result:%d", vnd_userial.fd, result); 2700b966c5eSopenharmony_ci } 2710b966c5eSopenharmony_ci 2720b966c5eSopenharmony_ci vnd_userial.fd = -1; 2730b966c5eSopenharmony_ci} 2740b966c5eSopenharmony_ci 2750b966c5eSopenharmony_ci/******************************************************************************* 2760b966c5eSopenharmony_ci** 2770b966c5eSopenharmony_ci** Function userial_vendor_set_baud 2780b966c5eSopenharmony_ci** 2790b966c5eSopenharmony_ci** Description Set new baud rate 2800b966c5eSopenharmony_ci** 2810b966c5eSopenharmony_ci** Returns None 2820b966c5eSopenharmony_ci** 2830b966c5eSopenharmony_ci*******************************************************************************/ 2840b966c5eSopenharmony_civoid userial_vendor_set_baud(uint8_t userial_baud) 2850b966c5eSopenharmony_ci{ 2860b966c5eSopenharmony_ci uint32_t tcio_baud; 2870b966c5eSopenharmony_ci 2880b966c5eSopenharmony_ci if (USERIAL_VENDOR_SET_BAUD_DELAY_US > 0) { 2890b966c5eSopenharmony_ci usleep(USERIAL_VENDOR_SET_BAUD_DELAY_US); 2900b966c5eSopenharmony_ci } 2910b966c5eSopenharmony_ci 2920b966c5eSopenharmony_ci userial_to_tcio_baud(userial_baud, &tcio_baud); 2930b966c5eSopenharmony_ci 2940b966c5eSopenharmony_ci cfsetospeed(&vnd_userial.termios, tcio_baud); 2950b966c5eSopenharmony_ci cfsetispeed(&vnd_userial.termios, tcio_baud); 2960b966c5eSopenharmony_ci tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); 2970b966c5eSopenharmony_ci} 2980b966c5eSopenharmony_ci 2990b966c5eSopenharmony_ci/******************************************************************************* 3000b966c5eSopenharmony_ci** 3010b966c5eSopenharmony_ci** Function userial_vendor_ioctl 3020b966c5eSopenharmony_ci** 3030b966c5eSopenharmony_ci** Description ioctl inteface 3040b966c5eSopenharmony_ci** 3050b966c5eSopenharmony_ci** Returns None 3060b966c5eSopenharmony_ci** 3070b966c5eSopenharmony_ci*******************************************************************************/ 3080b966c5eSopenharmony_civoid userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data) 3090b966c5eSopenharmony_ci{ 3100b966c5eSopenharmony_ci switch (op) { 3110b966c5eSopenharmony_ci#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 3120b966c5eSopenharmony_ci case USERIAL_OP_ASSERT_BT_WAKE: 3130b966c5eSopenharmony_ci VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); 3140b966c5eSopenharmony_ci ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); 3150b966c5eSopenharmony_ci break; 3160b966c5eSopenharmony_ci 3170b966c5eSopenharmony_ci case USERIAL_OP_DEASSERT_BT_WAKE: 3180b966c5eSopenharmony_ci VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); 3190b966c5eSopenharmony_ci ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); 3200b966c5eSopenharmony_ci break; 3210b966c5eSopenharmony_ci 3220b966c5eSopenharmony_ci case USERIAL_OP_GET_BT_WAKE_STATE: 3230b966c5eSopenharmony_ci ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); 3240b966c5eSopenharmony_ci break; 3250b966c5eSopenharmony_ci#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) 3260b966c5eSopenharmony_ci 3270b966c5eSopenharmony_ci default: 3280b966c5eSopenharmony_ci break; 3290b966c5eSopenharmony_ci } 3300b966c5eSopenharmony_ci} 3310b966c5eSopenharmony_ci 3320b966c5eSopenharmony_ci/******************************************************************************* 3330b966c5eSopenharmony_ci** 3340b966c5eSopenharmony_ci** Function userial_set_port 3350b966c5eSopenharmony_ci** 3360b966c5eSopenharmony_ci** Description Configure UART port name 3370b966c5eSopenharmony_ci** 3380b966c5eSopenharmony_ci** Returns 0 : Success 3390b966c5eSopenharmony_ci** Otherwise : Fail 3400b966c5eSopenharmony_ci** 3410b966c5eSopenharmony_ci*******************************************************************************/ 3420b966c5eSopenharmony_ciint userial_set_port(char *p_conf_name, char *p_conf_value, int param) 3430b966c5eSopenharmony_ci{ 3440b966c5eSopenharmony_ci (void)strcpy_s(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, p_conf_value); 3450b966c5eSopenharmony_ci 3460b966c5eSopenharmony_ci return 0; 3470b966c5eSopenharmony_ci} 348