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:      hci_h4.c
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Description:   Contains HCI transport send/receive functions
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define LOG_TAG "bt_h4"
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <utils/Log.h>
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <fcntl.h>
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_hci_bdroid.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hci.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "userial.h"
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "utils.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Constants & Macros
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef HCI_DBG
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_DBG FALSE
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (HCI_DBG == TRUE)
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCIDBG(param, ...) {LOGD(param, ## __VA_ARGS__);}
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCIDBG(param, ...) {}
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Preamble length for HCI Commands:
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      2-bytes for opcode and 1 byte for length
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_CMD_PREAMBLE_SIZE   3
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Preamble length for HCI Events:
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      1-byte for opcode and 1 byte for length
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_EVT_PREAMBLE_SIZE   2
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Preamble length for SCO Data:
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      2-byte for Handle and 1 byte for length
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_SCO_PREAMBLE_SIZE   3
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Preamble length for ACL Data:
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**      2-byte for Handle and 2 byte for length
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_ACL_PREAMBLE_SIZE   4
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Table of HCI preamble sizes for the different HCI message types */
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const uint8_t hci_preamble_table[] =
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCI_CMD_PREAMBLE_SIZE,
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCI_ACL_PREAMBLE_SIZE,
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCI_SCO_PREAMBLE_SIZE,
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCI_EVT_PREAMBLE_SIZE
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* HCI H4 message type definitions */
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define H4_TYPE_COMMAND         1
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define H4_TYPE_ACL_DATA        2
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define H4_TYPE_SCO_DATA        3
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define H4_TYPE_EVENT           4
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic const uint16_t msg_evt_table[] =
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    MSG_HC_TO_STACK_HCI_ERR,       /* H4_TYPE_COMMAND */
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    MSG_HC_TO_STACK_HCI_ACL,       /* H4_TYPE_ACL_DATA */
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    MSG_HC_TO_STACK_HCI_SCO,       /* H4_TYPE_SCO_DATA */
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    MSG_HC_TO_STACK_HCI_EVT        /* H4_TYPE_EVENT */
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define ACL_RX_PKT_START        2
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define ACL_RX_PKT_CONTINUE     1
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define L2CAP_HEADER_SIZE       4
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Maximum numbers of allowed internal
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** outstanding command packets at any time
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define INT_CMD_PKT_MAX_COUNT       8
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define INT_CMD_PKT_IDX_MASK        0x07
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_COMMAND_COMPLETE_EVT    0x0E
1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_COMMAND_STATUS_EVT      0x0F
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_READ_BUFFER_SIZE        0x1005
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define HCI_LE_READ_BUFFER_SIZE     0x2002
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Local type definitions
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* H4 Rx States */
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef enum {
1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    H4_RX_MSGTYPE_ST,
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    H4_RX_LEN_ST,
1175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    H4_RX_DATA_ST,
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    H4_RX_IGNORE_ST
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tHCI_H4_RCV_STATE;
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Callback function for the returned event of internal issued command */
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef void (*tINT_CMD_CBACK)(void *p_mem);
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef struct
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t opcode;        /* OPCODE of outstanding internal commands */
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tINT_CMD_CBACK cback;   /* Callback function when return of internal
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                             * command is received */
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tINT_CMD_Q;
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Control block for HCISU_H4 */
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttypedef struct
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR *p_rcv_msg;          /* Buffer to hold current rx HCI message */
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t rcv_len;               /* Size of current incoming message */
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t rcv_msg_type;           /* Current incoming message type */
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tHCI_H4_RCV_STATE rcv_state;    /* Receive state of current rx message */
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t hc_acl_data_size;      /* Controller's max ACL data length */
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t hc_ble_acl_data_size;  /* Controller's max BLE ACL data length */
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BUFFER_Q acl_rx_q;      /* Queue of base buffers for fragmented ACL pkts */
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t preload_count;          /* Count numbers of preload bytes */
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t preload_buffer[6];      /* HCI_ACL_PREAMBLE_SIZE + 2 */
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    int int_cmd_rsp_pending;        /* Num of internal cmds pending for ack */
1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t int_cmd_rd_idx;         /* Read index of int_cmd_opcode queue */
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t int_cmd_wrt_idx;        /* Write index of int_cmd_opcode queue */
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tINT_CMD_Q int_cmd[INT_CMD_PKT_MAX_COUNT]; /* FIFO queue */
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tHCI_H4_CB;
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Externs
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectextern BUFFER_Q tx_q;
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid btsnoop_init(void);
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid btsnoop_close(void);
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid btsnoop_cleanup (void);
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid btsnoop_capture(HC_BT_HDR *p_buf, uint8_t is_rcvd);
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint8_t hci_h4_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  tINT_CMD_CBACK p_cback);
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_wake_assert(void);
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid lpm_tx_done(uint8_t is_tx_done);
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Variables
1665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Num of allowed outstanding HCI CMD packets */
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvolatile int num_hci_cmd_pkts = 1;
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static variables
1735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic tHCI_H4_CB       h4_cb;
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  Static functions
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         get_acl_data_length_cback
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Callback function for HCI_READ_BUFFER_SIZE and
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  HCI_LE_READ_BUFFER_SIZE commands if they were sent because
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  of internal request.
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          None
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid get_acl_data_length_cback(void *p_mem)
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     *p, status;
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    opcode, len=0;
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR   *p_buf = (HC_BT_HDR *) p_mem;
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = (uint8_t *)(p_buf + 1) + 3;
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16(opcode, p)
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    status = *p++;
2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (status == 0) /* Success */
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16(len, p)
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (opcode == HCI_READ_BUFFER_SIZE)
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (status == 0)
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            h4_cb.hc_acl_data_size = len;
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* reuse the rx buffer for sending HCI_LE_READ_BUFFER_SIZE command */
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = 0;
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->layer_specific = 0;
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len = 3;
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = (uint8_t *) (p_buf + 1);
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM(p, HCI_LE_READ_BUFFER_SIZE);
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p = 0;
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((status = hci_h4_send_int_cmd(HCI_LE_READ_BUFFER_SIZE, p_buf, \
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                           get_acl_data_length_cback)) == FALSE)
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc((TRANSAC) p_buf, (char *) (p_buf + 1));
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->postload_cb(NULL, BT_HC_POSTLOAD_SUCCESS);
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (opcode == HCI_LE_READ_BUFFER_SIZE)
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (status == 0)
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            h4_cb.hc_ble_acl_data_size = (len) ? len : h4_cb.hc_acl_data_size;
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (bt_hc_cbacks)
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc((TRANSAC) p_buf, (char *) (p_buf + 1));
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGE("vendor lib postload completed");
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->postload_cb(NULL, BT_HC_POSTLOAD_SUCCESS);
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         internal_event_intercept
2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called to parse received HCI event and
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  - update the Num_HCI_Command_Packets
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  - intercept the event if it is the result of an early
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                    issued internal command.
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          TRUE : if the event had been intercepted for internal process
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  FALSE : send this event to core stack
2525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint8_t internal_event_intercept(void)
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     *p;
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     event_code;
2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    opcode, len;
2595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tHCI_H4_CB  *p_cb = &h4_cb;
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = (uint8_t *)(p_cb->p_rcv_msg + 1);
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    event_code = *p++;
2645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    len = *p++;
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (event_code == HCI_COMMAND_COMPLETE_EVT)
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        num_hci_cmd_pkts = *p++;
2695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_cb->int_cmd_rsp_pending > 0)
2715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16(opcode, p)
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (opcode == p_cb->int_cmd[p_cb->int_cmd_rd_idx].opcode)
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                HCIDBG( \
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                "Intercept CommandCompleteEvent for internal command (0x%04X)",\
2785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                          opcode);
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback != NULL)
2805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
2815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback(p_cb->p_rcv_msg);
2825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
2835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
2845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
2855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    // Missing cback function!
2865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    // Release the p_rcv_msg buffer.
2875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (bt_hc_cbacks)
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
2895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        bt_hc_cbacks->dealloc((TRANSAC) p_cb->p_rcv_msg, \
2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                              (char *) (p_cb->p_rcv_msg + 1));
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
2925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cb->int_cmd_rd_idx = ((p_cb->int_cmd_rd_idx+1) & \
2945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                        INT_CMD_PKT_IDX_MASK);
2955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cb->int_cmd_rsp_pending--;
2965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                return TRUE;
2975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (event_code == HCI_COMMAND_STATUS_EVT)
3015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        num_hci_cmd_pkts = *(++p);
3035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return FALSE;
3065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         acl_rx_frame_buffer_alloc
3115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called from the HCI transport when the
3135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  first 4 or 6 bytes of an HCI ACL packet have been received:
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  - Allocate a new buffer if it is a start pakcet of L2CAP
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                    message.
3165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  - Return the buffer address of the starting L2CAP message
3175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                    frame if the packet is the next segment of a fragmented
3185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                    L2CAP message.
3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          the address of the receive buffer H4 RX should use
3215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  (CR419: Modified to return NULL in case of error.)
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** NOTE             This assumes that the L2CAP MTU size is less than the size
3245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  of an HCI ACL buffer, so the maximum L2CAP message will fit
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  into one buffer.
3265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic HC_BT_HDR *acl_rx_frame_buffer_alloc (void)
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
3305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     *p;
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    handle;
3325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    hci_len;
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    total_len;
3345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     pkt_type;
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR  *p_return_buf = NULL;
3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tHCI_H4_CB  *p_cb = &h4_cb;
3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = p_cb->preload_buffer;
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (handle, p);
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (hci_len, p);
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (total_len, p);
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    pkt_type = (uint8_t)(((handle) >> 12) & 0x0003);
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    handle   = (uint16_t)((handle) & 0x0FFF);
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cb->acl_rx_q.count)
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        uint16_t save_handle;
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        HC_BT_HDR *p_hdr = p_cb->acl_rx_q.p_first;
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while (p_hdr != NULL)
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = (uint8_t *)(p_hdr + 1);
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16 (save_handle, p);
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            save_handle   = (uint16_t)((save_handle) & 0x0FFF);
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (save_handle == handle)
3595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
3605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_return_buf = p_hdr;
3615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
3625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_hdr = utils_getnext(p_hdr);
3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (pkt_type == ACL_RX_PKT_START)       /*** START PACKET ***/
3685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Might have read 2 bytes for the L2CAP payload length */
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cb->rcv_len = (hci_len) ? (hci_len - 2) : 0;
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Start of packet. If we were in the middle of receiving */
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* a packet on the same ACL handle, the original packet is incomplete.
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         * Drop it. */
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_return_buf)
3765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            ALOGW("H4 - dropping incomplete ACL frame");
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            utils_remove_from_queue(&(p_cb->acl_rx_q), p_return_buf);
3805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (bt_hc_cbacks)
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                bt_hc_cbacks->dealloc((TRANSAC) p_return_buf, \
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                          (char *) (p_return_buf + 1));
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf = NULL;
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Allocate a buffer for message */
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (bt_hc_cbacks)
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            int len = total_len + HCI_ACL_PREAMBLE_SIZE + L2CAP_HEADER_SIZE + \
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                      BT_HC_HDR_SIZE;
3945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf = (HC_BT_HDR *) bt_hc_cbacks->alloc(len);
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_return_buf)
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Initialize buffer with preloaded data */
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf->offset = 0;
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf->layer_specific = 0;
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf->event = MSG_HC_TO_STACK_HCI_ACL;
4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_return_buf->len = p_cb->preload_count;
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memcpy((uint8_t *)(p_return_buf + 1), p_cb->preload_buffer, \
4055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                   p_cb->preload_count);
4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (hci_len && ((total_len + L2CAP_HEADER_SIZE) > hci_len))
4085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Will expect to see fragmented ACL packets */
4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Keep the base buffer address in the watching queue */
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                utils_enqueue(&(p_cb->acl_rx_q), p_return_buf);
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else                                    /*** CONTINUATION PACKET ***/
4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cb->rcv_len = hci_len;
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (p_return_buf)
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Packet continuation and found the original rx buffer */
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            uint8_t *p_f = p = (uint8_t *)(p_return_buf + 1) + 2;
4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            STREAM_TO_UINT16 (total_len, p);
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Update HCI header of first segment (base buffer) with new len */
4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            total_len += hci_len;
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT16_TO_STREAM (p_f, total_len);
4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (p_return_buf);
4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         acl_rx_frame_end_chk
4385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called from the HCI transport when the last
4405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  byte of an HCI ACL packet has been received. It checks if
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  the L2CAP message is complete, i.e. no more continuation
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  packets are expected.
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          TRUE if message complete, FALSE if continuation expected
4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic uint8_t acl_rx_frame_end_chk (void)
4485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     *p;
4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    handle, hci_len, l2cap_len;
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR  *p_buf;
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tHCI_H4_CB  *p_cb = &h4_cb;
4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     frame_end=TRUE;
4545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf = p_cb->p_rcv_msg;
4565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = (uint8_t *)(p_buf + 1);
4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (handle, p);
4595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (hci_len, p);
4605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    STREAM_TO_UINT16 (l2cap_len, p);
4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (hci_len > 0)
4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (l2cap_len > (p_buf->len-(HCI_ACL_PREAMBLE_SIZE+L2CAP_HEADER_SIZE)) )
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If the L2CAP length has not been reached, tell H4 not to send
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             * this buffer to stack */
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            frame_end = FALSE;
4695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
4715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
4725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /*
4735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             * The current buffer coulb be in the watching list.
4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             * Remove it from the list if it is in.
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project             */
4765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->acl_rx_q.count)
4775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                utils_remove_from_queue(&(p_cb->acl_rx_q), p_buf);
4785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
4795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /****
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     ** Print snoop trace
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     ****/
4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_buf->offset)
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* CONTINUATION PACKET */
4875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* save original p_buf->len content */
4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        uint16_t tmp_u16 = p_buf->len;
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* borrow HCI_ACL_PREAMBLE_SIZE bytes from the payload section */
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = (uint8_t *)(p_buf + 1) + p_buf->offset - HCI_ACL_PREAMBLE_SIZE;
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* save contents */
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        memcpy(p_cb->preload_buffer, p, HCI_ACL_PREAMBLE_SIZE);
4965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Set packet boundary flags to "continuation packet" */
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        handle = (handle & 0xCFFF) | 0x1000;
4995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* write handl & length info */
5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, handle);
5025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM (p, (p_buf->len - p_buf->offset));
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* roll pointer back */
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = p - HCI_ACL_PREAMBLE_SIZE;
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* adjust `p_buf->offset` & `p_buf->len`
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         * before calling btsnoop_capture() */
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = p_buf->offset - HCI_ACL_PREAMBLE_SIZE;
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len = p_buf->len - p_buf->offset;
5115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        btsnoop_capture(p_buf, TRUE);
5135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* restore contents */
5155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        memcpy(p, p_cb->preload_buffer, HCI_ACL_PREAMBLE_SIZE);
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* restore p_buf->len */
5185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len = tmp_u16;
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
5215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* START PACKET */
5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        btsnoop_capture(p_buf, TRUE);
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (frame_end == TRUE)
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = 0;
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = p_buf->len; /* save current buffer-end position */
5305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return frame_end;
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
5355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**   HCI H4 INTERFACE FUNCTIONS
5365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*****************************************************************************/
5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_init
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Initialize H4 module
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
5455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid hci_h4_init(void)
5485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCIDBG("hci_h4_init");
5505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    memset(&h4_cb, 0, sizeof(tHCI_H4_CB));
5525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_queue_init(&(h4_cb.acl_rx_q));
5535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Per HCI spec., always starts with 1 */
5555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    num_hci_cmd_pkts = 1;
5565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Give an initial values of Host Controller's ACL data packet length
5585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     * Will update with an internal HCI(_LE)_Read_Buffer_Size request
5595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project     */
5605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.hc_acl_data_size = 1021;
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.hc_ble_acl_data_size = 27;
5625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btsnoop_init();
5645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_cleanup
5695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Clean H4 module
5715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
5735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid hci_h4_cleanup(void)
5765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HCIDBG("hci_h4_cleanup");
5785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btsnoop_close();
5805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btsnoop_cleanup();
5815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
5845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_send_msg
5865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Determine message type, set HCI H4 packet indicator, and
5885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 send message through USERIAL driver
5895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
5915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
5925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
5935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid hci_h4_send_msg(HC_BT_HDR *p_msg)
5945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
5955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t type = 0;
5965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t handle;
5975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t bytes_to_send, lay_spec;
5985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t *p = ((uint8_t *)(p_msg + 1)) + p_msg->offset;
5995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t event = p_msg->event & MSG_EVT_MASK;
6005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t sub_event = p_msg->event & MSG_SUB_EVT_MASK;
6015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t acl_pkt_size = 0, acl_data_size = 0;
6025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t bytes_sent;
6035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* wake up BT device if its in sleep mode */
6055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lpm_wake_assert();
6065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (event == MSG_STACK_TO_HC_HCI_ACL)
6085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        type = H4_TYPE_ACL_DATA;
6095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (event == MSG_STACK_TO_HC_HCI_SCO)
6105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        type = H4_TYPE_SCO_DATA;
6115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else if (event == MSG_STACK_TO_HC_HCI_CMD)
6125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        type = H4_TYPE_COMMAND;
6135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (sub_event == LOCAL_BR_EDR_CONTROLLER_ID)
6155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        acl_data_size = h4_cb.hc_acl_data_size;
6175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        acl_pkt_size = h4_cb.hc_acl_data_size + HCI_ACL_PREAMBLE_SIZE;
6185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
6205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        acl_data_size = h4_cb.hc_ble_acl_data_size;
6225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        acl_pkt_size = h4_cb.hc_ble_acl_data_size + HCI_ACL_PREAMBLE_SIZE;
6235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check if sending ACL data that needs fragmenting */
6265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if ((event == MSG_STACK_TO_HC_HCI_ACL) && (p_msg->len > acl_pkt_size))
6275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
6285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Get the handle from the packet */
6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16 (handle, p);
6305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Set packet boundary flags to "continuation packet" */
6325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        handle = (handle & 0xCFFF) | 0x1000;
6335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Do all the first chunks */
6355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        while (p_msg->len > acl_pkt_size)
6365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
6375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* remember layer_specific because uart borrow
6385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project               one byte from layer_specific for packet type */
6395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            lay_spec = p_msg->layer_specific;
6405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((uint8_t *)(p_msg + 1)) + p_msg->offset - 1;
6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            *p = type;
6435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bytes_to_send = acl_pkt_size + 1; /* packet_size + message type */
6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bytes_sent = userial_write(event,(uint8_t *) p,bytes_to_send);
6465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* generate snoop trace message */
6485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            btsnoop_capture(p_msg, FALSE);
6495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_msg->layer_specific = lay_spec;
6515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Adjust offset and length for what we just sent */
6525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_msg->offset += acl_data_size;
6535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_msg->len    -= acl_data_size;
6545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p = ((uint8_t *)(p_msg + 1)) + p_msg->offset;
6565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            UINT16_TO_STREAM (p, handle);
6585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_msg->len > acl_pkt_size)
6605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
6615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                UINT16_TO_STREAM (p, acl_data_size);
6625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
6635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            else
6645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
6655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                UINT16_TO_STREAM (p, p_msg->len - HCI_ACL_PREAMBLE_SIZE);
6665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
6675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* If we were only to send partial buffer, stop when done.    */
6695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Send the buffer back to L2CAP to send the rest of it later */
6705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_msg->layer_specific)
6715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (--p_msg->layer_specific == 0)
6735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
6745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_msg->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
6755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (bt_hc_cbacks)
6775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
6785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        bt_hc_cbacks->tx_result((TRANSAC) p_msg, \
6795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                    (char *) (p_msg + 1), \
6805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                    BT_HC_TX_FRAGMENT);
6815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
6825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    return;
6845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
6855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
6865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
6875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
6885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* remember layer_specific because uart borrow
6915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project       one byte from layer_specific for packet type */
6925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lay_spec = p_msg->layer_specific;
6935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Put the HCI Transport packet type 1 byte before the message */
6955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p = ((uint8_t *)(p_msg + 1)) + p_msg->offset - 1;
6965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    *p = type;
6975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    bytes_to_send = p_msg->len + 1;     /* message_size + message type */
6985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    bytes_sent = userial_write(event,(uint8_t *) p, bytes_to_send);
7005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_msg->layer_specific = lay_spec;
7025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (event == MSG_STACK_TO_HC_HCI_CMD)
7045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        num_hci_cmd_pkts--;
7065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If this is an internal Cmd packet, the layer_specific field would
7085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         * have stored with the opcode of HCI command.
7095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         * Retrieve the opcode from the Cmd packet.
7105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         */
7115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project         p++;
7125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        STREAM_TO_UINT16(lay_spec, p);
7135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* generate snoop trace message */
7165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btsnoop_capture(p_msg, FALSE);
7175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_hc_cbacks)
7195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((event == MSG_STACK_TO_HC_HCI_CMD) && \
7215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            (h4_cb.int_cmd_rsp_pending > 0) && \
7225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            (p_msg->layer_specific == lay_spec))
7235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
7245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* dealloc buffer of internal command */
7255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc((TRANSAC) p_msg, (char *) (p_msg + 1));
7265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
7285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->tx_result((TRANSAC) p_msg, (char *) (p_msg + 1), \
7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                        BT_HC_TX_SUCCESS);
7315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    lpm_tx_done(TRUE);
7355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return;
7375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
7415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
7425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_receive_msg
7435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
7445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Construct HCI EVENT/ACL packets and send them to stack once
7455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 complete packet has been received.
7465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
7475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         Number of read bytes
7485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
7505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint16_t hci_h4_receive_msg(void)
7515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    bytes_read = 0;
7535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     byte;
7545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint16_t    msg_len, len;
7555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     msg_received;
7565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tHCI_H4_CB  *p_cb=&h4_cb;
7575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while (TRUE)
7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
7605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Read one byte to see if there is anything waiting to be read */
7615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (userial_read(0 /*dummy*/, &byte, 1) == 0)
7625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
7635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
7645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        bytes_read++;
7675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        msg_received = FALSE;
7685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        switch (p_cb->rcv_state)
7705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
7715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case H4_RX_MSGTYPE_ST:
7725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Start of new message */
7735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((byte < H4_TYPE_ACL_DATA) || (byte > H4_TYPE_EVENT))
7745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
7755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Unknown HCI message type */
7765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Drop this byte */
7775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                ALOGE("[h4] Unknown HCI message type drop this byte 0x%x", byte);
7785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                break;
7795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Initialize rx parameters */
7825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_msg_type = byte;
7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_len = hci_preamble_table[byte-1];
7845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            memset(p_cb->preload_buffer, 0 , 6);
7855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->preload_count = 0;
7865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            // p_cb->p_rcv_msg = NULL;
7875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_state = H4_RX_LEN_ST; /* Next, wait for length to come */
7885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
7895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case H4_RX_LEN_ST:
7915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Receiving preamble */
7925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->preload_buffer[p_cb->preload_count++] = byte;
7935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_len--;
7945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Check if we received entire preamble yet */
7965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->rcv_len == 0)
7975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
7985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (p_cb->rcv_msg_type == H4_TYPE_ACL_DATA)
7995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
8005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* ACL data lengths are 16-bits */
8015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    msg_len = p_cb->preload_buffer[3];
8025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    msg_len = (msg_len << 8) + p_cb->preload_buffer[2];
8035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (msg_len && (p_cb->preload_count == 4))
8055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
8065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        /* Check if this is a start packet */
8075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        byte = ((p_cb->preload_buffer[1] >> 4) & 0x03);
8085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        if (byte == ACL_RX_PKT_START)
8105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        {
8115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                           /*
8125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            * A start packet & with non-zero data payload length.
8135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            * We want to read 2 more bytes to get L2CAP payload
8145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            * length.
8155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            */
8165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            p_cb->rcv_len = 2;
8175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            break;
8195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        }
8205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
8215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /*
8235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     * Check for segmented packets. If this is a continuation
8245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     * packet, then we will continue appending data to the
8255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     * original rcv buffer.
8265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     */
8275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->p_rcv_msg = acl_rx_frame_buffer_alloc();
8285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
8295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
8305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
8315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Received entire preamble.
8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     * Length is in the last received byte */
8335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    msg_len = byte;
8345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->rcv_len = msg_len;
8355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Allocate a buffer for message */
8375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (bt_hc_cbacks)
8385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
8395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        len = msg_len + p_cb->preload_count + BT_HC_HDR_SIZE;
8405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->p_rcv_msg = \
8415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            (HC_BT_HDR *) bt_hc_cbacks->alloc(len);
8425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
8435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (p_cb->p_rcv_msg)
8455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        /* Initialize buffer with preloaded data */
8475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->p_rcv_msg->offset = 0;
8485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->p_rcv_msg->layer_specific = 0;
8495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->p_rcv_msg->event = \
8505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            msg_evt_table[p_cb->rcv_msg_type-1];
8515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->p_rcv_msg->len = p_cb->preload_count;
8525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        memcpy((uint8_t *)(p_cb->p_rcv_msg + 1), \
8535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                               p_cb->preload_buffer, p_cb->preload_count);
8545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
8555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
8565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (p_cb->p_rcv_msg == NULL)
8585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
8595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Unable to acquire message buffer. */
8605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    ALOGE( \
8615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     "H4: Unable to acquire buffer for incoming HCI message." \
8625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    );
8635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (msg_len == 0)
8655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
8665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        /* Wait for next message */
8675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->rcv_state = H4_RX_MSGTYPE_ST;
8685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
8695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    else
8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    {
8715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        /* Ignore rest of the packet */
8725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        p_cb->rcv_state = H4_RX_IGNORE_ST;
8735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    }
8745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    break;
8765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
8775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Message length is valid */
8795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if (msg_len)
8805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
8815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Read rest of message */
8825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->rcv_state = H4_RX_DATA_ST;
8835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
8845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
8865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Message has no additional parameters.
8875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                     * (Entire message has been received) */
8885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    if (p_cb->rcv_msg_type == H4_TYPE_ACL_DATA)
8895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                        acl_rx_frame_end_chk(); /* to print snoop trace */
8905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    msg_received = TRUE;
8925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Next, wait for next message */
8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->rcv_state = H4_RX_MSGTYPE_ST;
8955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
8975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
8985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case H4_RX_DATA_ST:
9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            *((uint8_t *)(p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->len++) = byte;
9015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_len--;
9025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->rcv_len > 0)
9045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
9055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Read in the rest of the message */
9065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                len = userial_read(0 /*dummy*/, \
9075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                      ((uint8_t *)(p_cb->p_rcv_msg+1) + p_cb->p_rcv_msg->len), \
9085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                      p_cb->rcv_len);
9095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cb->p_rcv_msg->len += len;
9105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cb->rcv_len -= len;
9115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                bytes_read += len;
9125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
9135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Check if we read in entire message yet */
9155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->rcv_len == 0)
9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Received entire packet. */
9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Check for segmented l2cap packets */
9195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                if ((p_cb->rcv_msg_type == H4_TYPE_ACL_DATA) &&
9205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    !acl_rx_frame_end_chk())
9215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
9225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Not the end of packet yet. */
9235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Next, wait for next message */
9245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->rcv_state = H4_RX_MSGTYPE_ST;
9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
9265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                else
9275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                {
9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    msg_received = TRUE;
9295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    /* Next, wait for next message */
9305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    p_cb->rcv_state = H4_RX_MSGTYPE_ST;
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                }
9325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
9345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        case H4_RX_IGNORE_ST:
9375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Ignore reset of packet */
9385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->rcv_len--;
9395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* Check if we read in entire message yet */
9415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->rcv_len == 0)
9425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
9435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                /* Next, wait for next message */
9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_cb->rcv_state = H4_RX_MSGTYPE_ST;
9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
9465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            break;
9475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* If we received entire message, then send it to the task */
9515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if (msg_received)
9525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            uint8_t intercepted = FALSE;
9545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* generate snoop trace message */
9565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            /* ACL packet tracing had done in acl_rx_frame_end_chk() */
9575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->p_rcv_msg->event != MSG_HC_TO_STACK_HCI_ACL)
9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                btsnoop_capture(p_cb->p_rcv_msg, TRUE);
9595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if (p_cb->p_rcv_msg->event == MSG_HC_TO_STACK_HCI_EVT)
9615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                intercepted = internal_event_intercept();
9625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((bt_hc_cbacks) && (intercepted == FALSE))
9645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
9655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                bt_hc_cbacks->data_ind((TRANSAC) p_cb->p_rcv_msg, \
9665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                       (char *) (p_cb->p_rcv_msg + 1), \
9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                       p_cb->p_rcv_msg->len + BT_HC_HDR_SIZE);
9685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            p_cb->p_rcv_msg = NULL;
9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return (bytes_read);
9745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
9785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_send_int_cmd
9805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Place the internal commands (issued internally by vendor lib)
9825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 in the tx_q.
9835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         TRUE/FALSE
9855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
9865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
9875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectuint8_t hci_h4_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
9885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                  tINT_CMD_CBACK p_cback)
9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
9905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (h4_cb.int_cmd_rsp_pending > INT_CMD_PKT_MAX_COUNT)
9915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
9925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE( \
9935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        "Allow only %d outstanding internal commands at a time [Reject 0x%04X]"\
9945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        , INT_CMD_PKT_MAX_COUNT, opcode);
9955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return FALSE;
9965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.int_cmd_rsp_pending++;
9995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.int_cmd[h4_cb.int_cmd_wrt_idx].opcode = opcode;
10005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.int_cmd[h4_cb.int_cmd_wrt_idx].cback = p_cback;
10015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    h4_cb.int_cmd_wrt_idx = ((h4_cb.int_cmd_wrt_idx+1) & INT_CMD_PKT_IDX_MASK);
10025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* stamp signature to indicate an internal command */
10045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_buf->layer_specific = opcode;
10055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    utils_enqueue(&tx_q, (void *) p_buf);
10075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    bthc_signal_event(HC_EVENT_TX);
10085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return TRUE;
10105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
10145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function        hci_h4_get_acl_data_length
10165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description     Issue HCI_READ_BUFFER_SIZE command to retrieve Controller's
10185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                 ACL data length setting
10195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns         None
10215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
10225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
10235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid hci_h4_get_acl_data_length(void)
10245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    HC_BT_HDR  *p_buf = NULL;
10265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    uint8_t     *p, ret;
10275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_hc_cbacks)
10295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf = (HC_BT_HDR *) bt_hc_cbacks->alloc(BT_HC_HDR_SIZE + \
10315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                       HCI_CMD_PREAMBLE_SIZE);
10325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_buf)
10355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
10375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->offset = 0;
10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->layer_specific = 0;
10395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p = (uint8_t *) (p_buf + 1);
10425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        UINT16_TO_STREAM(p, HCI_READ_BUFFER_SIZE);
10435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p = 0;
10445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if ((ret = hci_h4_send_int_cmd(HCI_READ_BUFFER_SIZE, p_buf, \
10465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                       get_acl_data_length_cback)) == FALSE)
10475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            bt_hc_cbacks->dealloc((TRANSAC) p_buf, (char *) (p_buf + 1));
10495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
10505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else
10515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            return;
10525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (bt_hc_cbacks)
10555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
10565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        ALOGE("vendor lib postload aborted");
10575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        bt_hc_cbacks->postload_cb(NULL, BT_HC_POSTLOAD_FAIL);
10585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**  HCI H4 Services interface table
10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
10655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectconst tHCI_IF hci_h4_func_table =
10675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
10685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_init,
10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_cleanup,
10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_send_msg,
10715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_send_int_cmd,
10725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_get_acl_data_length,
10735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    hci_h4_receive_msg
10745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
10755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1076