15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2009-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Filename:      userial.c
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Description:   Contains open/read/write/close functions on serial port
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define LOG_TAG "bt_userial"
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <utils/Log.h>
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <pthread.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <fcntl.h>
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <errno.h>
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdio.h>
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/socket.h>
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_hci_bdroid.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "userial.h"
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "utils.h"
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_vendor_lib.h"
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <sys/prctl.h>
40690401a234619e7a836859f6e4458aabdfb7c9e0Zhihai Xu#include "bt_utils.h"
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Constants & Macros
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef USERIAL_DBG
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define USERIAL_DBG FALSE
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (USERIAL_DBG == TRUE)
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define USERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define USERIALDBG(param, ...) {}
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
56ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#ifndef ENABLE_USERIAL_TIMING_LOGS
57ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#define ENABLE_USERIAL_TIMING_LOGS FALSE
58ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#endif
59ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define MAX_SERIAL_PORT (USERIAL_PORT_3 + 1)
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define READ_LIMIT (BTHC_USERIAL_READ_MEM_SIZE - BT_HC_HDR_SIZE)
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectenum {
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIAL_RX_EXIT,
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIAL_RX_FLOW_OFF,
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIAL_RX_FLOW_ON
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Externs
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectextern bt_vendor_interface_t *bt_vnd_if;
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Local type definitions
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef struct
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int             fd;
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t         port;
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_t       read_thread;
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BUFFER_Q        rx_q;
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR      *p_rx_hdr;
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tUSERIAL_CB;
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static variables
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic tUSERIAL_CB userial_cb;
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic volatile uint8_t userial_running = 0;
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static functions
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
99ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
100ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
101ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Battastatic void log_userial_tx_timing(int len)
102ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta{
103ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    #define USEC_PER_SEC 1000000L
104ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    static struct timespec prev = {0, 0};
105ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    struct timespec now, diff;
106ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    unsigned int diff_us = 0;
107ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    unsigned int now_us = 0;
108ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
109ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    clock_gettime(CLOCK_MONOTONIC, &now);
110ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
111ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
112ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
113ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    ALOGW("[userial] ts %08d diff : %08d len %d", now_us, diff_us,
114ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta                len);
115ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
116ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    prev = now;
117ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
118ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
119ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#endif
120ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
121ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   Socket signal functions to wake up userial_read_thread for termination
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   creating an unnamed pair of connected sockets
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      - signal_fds[0]: join fd_set in select call of userial_read_thread
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      - signal_fds[1]: trigger from userial_close
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int signal_fds[2]={0,1};
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint8_t rx_flow_on = TRUE;
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic inline int create_signal_fds(fd_set* set)
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if(signal_fds[0]==0 && socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fds)<0)
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("create_signal_sockets:socketpair failed, errno: %d", errno);
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return -1;
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    FD_SET(signal_fds[0], set);
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return signal_fds[0];
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic inline int send_wakeup_signal(char sig_cmd)
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return send(signal_fds[1], &sig_cmd, sizeof(sig_cmd), 0);
1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic inline char reset_signal()
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    char sig_recv = -1;
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    recv(signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return sig_recv;
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic inline int is_signaled(fd_set* set)
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return FD_ISSET(signal_fds[0], set);
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
156ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        select_read
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     check if fd is ready for reading and listen for termination
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  signal. need to use select in order to avoid collision
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  between read and close on the same fd
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         -1: termination
1665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 >=0: numbers of bytes read back from fd
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic int select_read(int fd, uint8_t *pbuf, int len)
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    fd_set input;
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int n = 0, ret = -1;
1735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    char reason = 0;
1745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (userial_running)
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Initialize the input fd set */
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        FD_ZERO(&input);
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (rx_flow_on == TRUE)
1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            FD_SET(fd, &input);
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        int fd_max = create_signal_fds(&input);
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        fd_max = fd_max > fd ? fd_max : fd;
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Do the select */
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        n = select(fd_max+1, &input, NULL, NULL, NULL);
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if(is_signaled(&input))
1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            reason = reset_signal();
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (reason == USERIAL_RX_EXIT)
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                USERIALDBG("RX termination");
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return -1;
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (reason == USERIAL_RX_FLOW_OFF)
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                USERIALDBG("RX flow OFF");
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                rx_flow_on = FALSE;
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else if (reason == USERIAL_RX_FLOW_ON)
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                USERIALDBG("RX flow ON");
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                rx_flow_on = TRUE;
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (n > 0)
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* We might have input */
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (FD_ISSET(fd, &input))
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                ret = read(fd, pbuf, (size_t)len);
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (0 == ret)
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    ALOGW( "read() returned 0!" );
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return ret;
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if (n < 0)
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW( "select() Failed");
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if (n == 0)
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW( "Got a select() TIMEOUT");
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return ret;
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_read_thread
2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         void *
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void *userial_read_thread(void *arg)
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int rx_length = 0;
2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR *p_buf = NULL;
2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t *p;
2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG("Entering userial_read_thread()");
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    prctl(PR_SET_NAME, (unsigned long)"userial_read", 0, 0, 0);
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    rx_flow_on = TRUE;
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_running = 1;
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
251690401a234619e7a836859f6e4458aabdfb7c9e0Zhihai Xu    raise_priority_a2dp(TASK_HIGH_USERIAL_READ);
252690401a234619e7a836859f6e4458aabdfb7c9e0Zhihai Xu
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (userial_running)
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (bt_hc_cbacks)
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf = (HC_BT_HDR *) bt_hc_cbacks->alloc( \
2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                BTHC_USERIAL_READ_MEM_SIZE);
2595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf = NULL;
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_buf != NULL)
2645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->offset = 0;
2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->layer_specific = 0;
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = (uint8_t *) (p_buf + 1);
2695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            rx_length = select_read(userial_cb.fd, p, READ_LIMIT);
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            rx_length = 0;
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            utils_delay(100);
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW("userial_read_thread() failed to gain buffers");
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            continue;
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (rx_length > 0)
2815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_buf->len = (uint16_t)rx_length;
2835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            utils_enqueue(&(userial_cb.rx_q), p_buf);
2845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bthc_signal_event(HC_EVENT_RX);
2855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else /* either 0 or < 0 */
2875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW("select_read return size <=0:%d, exiting userial_read_thread",\
2895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                 rx_length);
2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* if we get here, we should have a buffer */
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc((TRANSAC) p_buf, (char *) (p_buf + 1));
2925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* negative value means exit thread */
2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
2945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    } /* for */
2965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_running = 0;
2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG("Leaving userial_read_thread()");
2995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_exit(NULL);
3005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return NULL;    // Compiler friendly
3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
3065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   Userial API Functions
3075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_init
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Initializes the userial driver
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         TRUE/FALSE
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint8_t userial_init(void)
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG("userial_init");
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset(&userial_cb, 0, sizeof(tUSERIAL_CB));
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_cb.fd = -1;
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_queue_init(&(userial_cb.rx_q));
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return TRUE;
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_open
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Open Bluetooth device with the port ID
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         TRUE/FALSE
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint8_t userial_open(uint8_t port)
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    struct sched_param param;
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int policy, result;
3415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_attr_t thread_attr;
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int fd_array[CH_MAX];
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG("userial_open(port:%d)", port);
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (userial_running)
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Userial is open; close it first */
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        userial_close();
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        utils_delay(50);
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (port >= MAX_SERIAL_PORT)
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("Port > MAX_SERIAL_PORT");
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Calling vendor-specific part */
3605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_vnd_if)
3615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array);
3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (result != 1)
3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGE("userial_open: wrong numbers of open fd in vendor lib [%d]!",
3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    result);
3685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGE("userial_open: HCI UART expects only one open fd");
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL);
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return FALSE;
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        userial_cb.fd = fd_array[0];
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("userial_open: missing vendor lib interface !!!");
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("userial_open: unable to open UART port");
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
3805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (userial_cb.fd == -1)
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("userial_open: failed to open UART port");
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG( "fd = %d", userial_cb.fd);
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_cb.port = port;
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pthread_attr_init(&thread_attr);
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (pthread_create(&(userial_cb.read_thread), &thread_attr, \
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                       userial_read_thread, NULL) != 0 )
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("pthread_create failed!");
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if(pthread_getschedparam(userial_cb.read_thread, &policy, &param)==0)
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        policy = BTHC_LINUX_BASE_POLICY;
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (BTHC_LINUX_BASE_POLICY!=SCHED_NORMAL)
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        param.sched_priority = BTHC_USERIAL_READ_THREAD_PRIORITY;
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        result = pthread_setschedparam(userial_cb.read_thread, policy, &param);
4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (result != 0)
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW("userial_open: pthread_setschedparam failed (%s)", \
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                  strerror(result));
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return TRUE;
4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_read
4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Read data from the userial port
4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         Number of bytes actually read from the userial port and
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 copied into p_data.  This may be less than len.
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint16_t  userial_read(uint16_t msg_id, uint8_t *p_buffer, uint16_t len)
4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t total_len = 0;
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t copy_len = 0;
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t *p_data = NULL;
4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    do
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if(userial_cb.p_rx_hdr != NULL)
4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_data = ((uint8_t *)(userial_cb.p_rx_hdr + 1)) + \
4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     (userial_cb.p_rx_hdr->offset);
4405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if((userial_cb.p_rx_hdr->len) <= (len - total_len))
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                copy_len = userial_cb.p_rx_hdr->len;
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                copy_len = (len - total_len);
4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memcpy((p_buffer + total_len), p_data, copy_len);
4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            total_len += copy_len;
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            userial_cb.p_rx_hdr->offset += copy_len;
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            userial_cb.p_rx_hdr->len -= copy_len;
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if(userial_cb.p_rx_hdr->len == 0)
4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
4555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (bt_hc_cbacks)
4565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    bt_hc_cbacks->dealloc((TRANSAC) userial_cb.p_rx_hdr, \
4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                              (char *) (userial_cb.p_rx_hdr+1));
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                userial_cb.p_rx_hdr = NULL;
4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if(userial_cb.p_rx_hdr == NULL)
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            userial_cb.p_rx_hdr=(HC_BT_HDR *)utils_dequeue(&(userial_cb.rx_q));
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    } while ((userial_cb.p_rx_hdr != NULL) && (total_len < len));
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return total_len;
4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_write
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Write data to the userial port
4775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         Number of bytes actually written to the userial port. This
4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 may be less than len.
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint16_t userial_write(uint16_t msg_id, uint8_t *p_data, uint16_t len)
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int ret, total = 0;
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while(len != 0)
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
488ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
489ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta        log_userial_tx_timing(len);
490ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#endif
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ret = write(userial_cb.fd, p_data+total, len);
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        total += ret;
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        len -= ret;
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return ((uint16_t)total);
4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_close
5025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Close the userial port
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid userial_close(void)
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int result;
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    TRANSAC p_buf;
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    USERIALDBG("userial_close(fd:%d)", userial_cb.fd);
5145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (userial_running)
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        send_wakeup_signal(USERIAL_RX_EXIT);
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((result=pthread_join(userial_cb.read_thread, NULL)) < 0)
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE( "pthread_join() FAILED result:%d", result);
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Calling vendor-specific part */
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_vnd_if)
5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL);
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    userial_cb.fd = -1;
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_hc_cbacks)
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while ((p_buf = utils_dequeue (&(userial_cb.rx_q))) != NULL)
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc(p_buf, (char *) ((HC_BT_HDR *)p_buf+1));
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
5335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        userial_ioctl
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     ioctl inteface
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid userial_ioctl(userial_ioctl_op_t op, void *p_data)
5465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    switch(op)
5485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case USERIAL_OP_RXFLOW_ON:
5505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (userial_running)
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                send_wakeup_signal(USERIAL_RX_FLOW_ON);
5525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case USERIAL_OP_RXFLOW_OFF:
5555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (userial_running)
5565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                send_wakeup_signal(USERIAL_RX_FLOW_OFF);
5575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case USERIAL_OP_INIT:
5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        default:
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
5625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
565