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