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