upload android base code part4

This commit is contained in:
August 2018-08-08 17:00:29 +08:00
parent b9e30e05b1
commit 78ea2404cd
23455 changed files with 5250148 additions and 0 deletions

View file

@ -0,0 +1,42 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
BDROID_DIR := $(TOP_DIR)system/bt
LOCAL_SRC_FILES := \
codec/msbc/sbc.c \
src/rtk_socket.c \
src/bt_vendor_rtk.c \
src/hardware.c \
src/userial_vendor.c \
src/upio.c \
src/bt_list.c \
src/bt_skbuff.c \
src/hci_h5.c \
src/rtk_parse.c \
src/rtk_btsnoop_net.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/codec/msbc \
$(BDROID_DIR)/hci/include
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog
ifeq ($(BOARD_HAVE_BLUETOOTH_NAME), rtl8723bs)
LOCAL_CFLAGS += -DRTL_8723BS_BT_USED
endif
ifeq ($(BOARD_HAVE_BLUETOOTH_NAME), rtl8723bs_vq0)
LOCAL_CFLAGS += -DRTL_8723BS_VQ0_BT_USED
endif
LOCAL_MODULE := libbt-vendor
LOCAL_MODULE_TAGS := optional
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_SHARED_LIBRARY)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __SBC_H
#define __SBC_H
#ifdef __cplusplus
extern "C" {
#endif
struct sbc_struct {
unsigned long flags;
unsigned short rate;
unsigned char channels;
unsigned char joint;
unsigned char blocks;
unsigned char subbands;
unsigned char bitpool;
void *data;
int size;
int len;
unsigned long duration;
void *priv;
};
typedef struct sbc_struct sbc_t;
int sbc_init(sbc_t *sbc, unsigned long flags);
int sbc_reinit(sbc_t *sbc, unsigned long flags);
int sbc_encode(sbc_t *sbc,
void *input,
int input_len,
void *output,
int output_len,
int *written);
int sbc_decode(sbc_t *sbc,
void *input,
int input_len,
void *output,
int output_len,
int *written);
void sbc_finish(sbc_t *sbc);
#ifdef __cplusplus
}
#endif
#endif /* __SBC_H */

View file

@ -0,0 +1,70 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#define fabs(x) ((x) < 0 ? -(x) : (x))
/* C does not provide an explicit arithmetic shift right but this will
always be correct and every compiler *should* generate optimal code */
#define ASR(val, bits) ((-2 >> 1 == -1) ? \
((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
#define ASR_64(val, bits) ((-2 >> 1 == -1) ? \
((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits)))
#define SCALE_PROTO4_TBL 15
#define SCALE_ANA4_TBL 16
#define SCALE_PROTO8_TBL 15
#define SCALE_ANA8_TBL 16
#define SCALE_SPROTO4_TBL 16
#define SCALE_SPROTO8_TBL 16
#define SCALE_NPROTO4_TBL 10
#define SCALE_NPROTO8_TBL 12
#define SCALE_SAMPLES 14
#define SCALE4_STAGE1_BITS 10
#define SCALE4_STAGE2_BITS 21
#define SCALE4_STAGED1_BITS 18
#define SCALE4_STAGED2_BITS 23
#define SCALE8_STAGE1_BITS 8
#define SCALE8_STAGE2_BITS 24
#define SCALE8_STAGED1_BITS 18
#define SCALE8_STAGED2_BITS 23
typedef int int32_t;
typedef int32_t sbc_fixed_t;
typedef long long sbc_extended_t;
#define SCALE4_STAGE1(src) ASR_64(src, SCALE4_STAGE1_BITS)
#define SCALE4_STAGE2(src) ASR_64(src, SCALE4_STAGE2_BITS)
#define SCALE4_STAGED1(src) ASR_64(src, SCALE4_STAGED1_BITS)
#define SCALE4_STAGED2(src) ASR_64(src, SCALE4_STAGED2_BITS)
#define SCALE8_STAGE1(src) ASR_64(src, SCALE8_STAGE1_BITS)
#define SCALE8_STAGE2(src) ASR_64(src, SCALE8_STAGE2_BITS)
#define SCALE8_STAGED1(src) ASR_64(src, SCALE8_STAGED1_BITS)
#define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS)
#define SBC_FIXED_0(val) { val = 0; }
#define ADD(dst, src) { dst += src; }
#define SUB(dst, src) { dst -= src; }
#define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); }
#define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); }
#define DIV2(dst, src) { dst = ASR(src, 1); }

View file

@ -0,0 +1,169 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "sbc_math.h"
/* A2DP specification: Appendix B, page 69 */
static const int sbc_offset4[4][4] = {
{ -1, 0, 0, 0 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 }
};
/* A2DP specification: Appendix B, page 69 */
static const int sbc_offset8[4][8] = {
{ -2, 0, 0, 0, 0, 0, 0, 1 },
{ -3, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 }
};
#define SP4(val) ASR(val, SCALE_PROTO4_TBL)
#define SA4(val) ASR(val, SCALE_ANA4_TBL)
#define SP8(val) ASR(val, SCALE_PROTO8_TBL)
#define SA8(val) ASR(val, SCALE_ANA8_TBL)
#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
#define SN4(val) ASR(val, SCALE_NPROTO4_TBL)
#define SN8(val) ASR(val, SCALE_NPROTO8_TBL)
static const int32_t _sbc_proto_4[20] = {
SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548),
SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7),
SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737),
SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578),
SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000)
};
static const int32_t _anamatrix4[4] = {
SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0)
};
static const int32_t _sbc_proto_8[40] = {
SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930),
SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28),
SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc),
SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c),
SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0),
SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00),
SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950),
SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f),
SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20),
SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48)
};
static const int32_t sbc_proto_4_40m0[] = {
SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
};
static const int32_t sbc_proto_4_40m1[] = {
SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
};
static const int32_t sbc_proto_8_80m0[] = {
SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
};
static const int32_t sbc_proto_8_80m1[] = {
SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
};
static const int32_t _anamatrix8[8] = {
SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40),
SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000)
};
static const int32_t synmatrix4[8][4] = {
{ SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
{ SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
{ SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
{ SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
{ SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
{ SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
};
static const int32_t synmatrix8[16][8] = {
{ SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
{ SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
{ SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
{ SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
{ SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
{ SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
{ SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
{ SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
{ SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
{ SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
};

View file

@ -0,0 +1,168 @@
/******************************************************************************
*
* Copyright (C) 2016 Realtek Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Module Name:
* bt_list.h
*
* Abstract:
* To implement list data structure
*
* Major Change History:
* When Who What
* --------------------------------------------------------------
* 2010-06-04 W.Bi Created
*
* Notes:
*
******************************************************************************/
#ifndef BT_LIST_H
#define BT_LIST_H
/**
\file bt_list.h
\brief Implement bluetooth list data structure. Has referred to Linux list implementation
You could add your new list manipulation here.
*/
/**
List entry structure, could be header or node.
Prev<-----Header---->Next
Every List has an additional header, and list tail will be list header's previous node.
You can use list to form a queue or a stack data structure
queue:
ListAddToTail----->LIST_FOR_EACH iterate--->manipulate on the list entry
Stack:
ListAddToHead--- >LIST_FOR_EACH iterate--->manipulate on the list entry
*/
///RT list structure definition
typedef struct _RT_LIST_ENTRY {
struct _RT_LIST_ENTRY *Next; ///< Entry's next element
struct _RT_LIST_ENTRY *Prev; ///< Entry's previous element
} RT_LIST_ENTRY, *PRT_LIST_ENTRY;
///List head would be another name of list entry, and it points to the list header
typedef RT_LIST_ENTRY RT_LIST_HEAD, *PRT_LIST_HEAD;
/*----------------------------------------------------------------------------------
EXTERNAL FUNCTION
----------------------------------------------------------------------------------*/
///Initialize a list with its header
void ListInitializeHeader(PRT_LIST_HEAD ListHead);
/**
Add a new entry to the list.
Insert a new entry after the specified head. This is good for implementing stacks.
\param [IN] ListNew <RT_LIST_ENTRY> : new entry to be added
\param [IN OUT] ListHead <RT_LIST_ENTRY> : List header after which to add new entry
*/
void ListAddToHead(PRT_LIST_ENTRY ListNew, PRT_LIST_HEAD ListHead);
/**
Add a new entry to the list.
Insert a new entry before the specified head. This is good for implementing queues.
\param [IN] ListNew <RT_LIST_ENTRY> : new entry to be added
\param [IN OUT] ListHead <RT_LIST_ENTRY> : List header before which to add new entry
*/
void ListAddToTail(PRT_LIST_ENTRY ListNew, PRT_LIST_HEAD ListHead);
/**
Get entry in the head of the list
\param [IN ] ListHead <RT_LIST_ENTRY> : List header
\return entry in the head , otherwise NULL
*/
RT_LIST_ENTRY* ListGetTop(PRT_LIST_HEAD ListHead);
/**
Get entry in the tail of the list
\param [IN ] ListHead <RT_LIST_ENTRY> : List header
\return entry in the tail , otherwise NULL
*/
RT_LIST_ENTRY*
ListGetTail(
PRT_LIST_HEAD ListHead
);
/**
Delete entry from the list
Note: ListIsEmpty() on this list entry would not return true, since its state is undefined
\param [IN] ListToDelete <RT_LIST_ENTRY> : list entry to be deleted
*/
void ListDeleteNode(PRT_LIST_ENTRY ListToDelete);
/**
Tell whether the list is empty
\param [IN] ListHead <RT_LIST_ENTRY> : List header of which to be test
*/
unsigned char ListIsEmpty(PRT_LIST_HEAD ListHead);
//EXTERN void ListEmpty(PRT_LIST_HEAD ListHead);
void
ListAdd(
PRT_LIST_ENTRY New,
PRT_LIST_ENTRY Prev,
PRT_LIST_ENTRY Next
);
/*----------------------------------------------------------------------------------
MACRO
----------------------------------------------------------------------------------*/
/**
Macros to iterate over the list.
\param _Iter : struct PRT_LIST_ENTRY type iterator to use as a loop cursor
\param _ListHead : List head of which to be iterated
*/
#define LIST_FOR_EACH(_Iter, _ListHead) \
for ((_Iter) = (_ListHead)->Next; (_Iter) != (_ListHead); (_Iter) = (_Iter)->Next)
/**
Macros to iterate over the list safely against removal of list entry.
If you would delete any list entry from the list while iterating the list, should use this macro
\param _Iter : Struct PRT_LIST_ENTRY type iterator to use as a loop cursor
\param _Temp : Another Struct PRT_LIST_ENTRY type to use as a temporary storage
\param _ListHead : List head of which to be iterated
*/
#define LIST_FOR_EACH_SAFELY(_Iter, _Temp, _ListHead) \
for ((_Iter) = (_ListHead)->Next, (_Temp) = (_Iter)->Next; (_Iter) != (_ListHead); \
(_Iter) = (_Temp), (_Temp) = (_Iter)->Next)
/**
Macros to get the struct pointer of this list entry
You could make every RT_LIST_ENTRY at the first place of your structure to avoid the macro, which will be dangerouse.
Copy from winnt.h.
BUG:if offset of field in type larger than 32 bit interger, which is not likely to happen, it will error
\param _Ptr : Struct RT_LIST_ENTRY type pointer
\param _Type : The type of structure in which the RT_LIST_ENTRY embedded in
\param _Field : the name of the RT_LIST_ENTRY within the struct
*/
#define LIST_ENTRY(_Ptr, _Type, _Field) ((_Type *)((char *)(_Ptr)-(unsigned long)(&((_Type *)0)->_Field)))
#endif /*BT_LIST_H*/

View file

@ -0,0 +1,362 @@
/******************************************************************************
*
* Copyright (C) 2016 Realtek Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Module Name:
* bt_skbuff.h
*
* Abstract:
* Data buffer managerment through whole bluetooth stack.
*
* Major Change History:
* When Who What
* --------------------------------------------------------------
* 2010-06-11 W.Bi Created.
*
* Notes:
* To reduce memory copy when pass data buffer to other layers,
* RTK_BUFFER is designed referring to linux socket buffer.
* But I still wonder its effect, since RTK_BUFFER is much bigger
* than original data buffer.RTK_BUFFER will reduce its member if
* it would not reach what i had expected.
*
******************************************************************************/
#ifndef BT_SKBUFF_H
#define BT_SKBUFF_H
#include "bt_list.h"
#include <stdbool.h>
#ifndef EXTERN
#define EXTERN
#endif
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
/*----------------------------------------------------------------------------------
CONSTANT DEFINITION
----------------------------------------------------------------------------------*/
#define RTK_CONTEXT_SIZE 12
#define RTB_QUEUE_ID_LENGTH 64
/*----------------------------------------------------------------------------------
STRUCTURE DEFINITION
----------------------------------------------------------------------------------*/
/**
Rtk buffer definition
Head -->|<---Data--->|<-----Length------>| <---End
_________________________________
|_____________|___________________|
|<-headroom->|<--RealDataBuffer-->|
Compared to socket buffer, there exists no tail and end pointer and tailroom as tail is rarely used in bluetooth stack
\param List : List structure used to list same type rtk buffer and manipulate rtk buffer like list.
\param Head : Pointer to truely allocated data buffer. It point to the headroom
\param Data : Pointer to real data buffer.
\param Length : currently data length
\param HeadRoom : Record initialize headroom size.
\param RefCount : Reference count. zero means able to be freed, otherwise somebody is handling it.
\param Priv : Reserved for multi-device support. Record Hci pointer which will handles this packet
\param Contest : Control buffer, put private variables here.
*/
typedef struct _RTK_BUFFER
{
RT_LIST_ENTRY List;
uint8_t *Head;
uint8_t *Data;
uint8_t *Tail;
uint8_t *End;
uint32_t Length;
uint32_t HeadRoom;
// RT_U16 TailRoom;
signed char RefCount;
void* Priv;
uint8_t Context[RTK_CONTEXT_SIZE];
}RTK_BUFFER, *PRTK_BUFFER;
/**
RTK_BUFFER Control Buffer Context
\param PacketType : HCI data types, Command/Acl/...
\param LastFrag : Is Current Acl buffer the last fragment.(0 for no, 1 for yes)
\param TxSeq : Current packet tx sequence
\param Retries : Current packet retransmission times
\param Sar : L2cap control field segmentation and reassembly bits
*/
struct BT_RTB_CONTEXT{
uint8_t PacketType;
uint16_t Handle;
};
///definition to get rtk_buffer's control buffer context pointer
#define BT_CONTEXT(_Rtb) ((struct BT_RTB_CONTEXT *)((_Rtb)->Context))
/**
Since RTBs are always used into/from list, so abstract this struct and provide APIs to easy process on RTBs
*/
typedef struct _RTB_QUEUE_HEAD RTB_QUEUE_HEAD;
/*----------------------------------------------------------------------------------
EXTERNAL FUNCTION
----------------------------------------------------------------------------------*/
/**
Allocate a RTK_BUFFER with specified data length and reserved headroom.
If caller does not know actual headroom to reserve for further usage, specify it to zero to use default value.
\param [IN] Length <uint32_t> : current data buffer length to allcated
\param [IN] HeadRoom <uint32_t> : if caller knows reserved head space, set it; otherwise set 0 to use default value
\return pointer to RTK_BUFFER if succeed, null otherwise
*/
RTK_BUFFER*
RtbAllocate(
IN uint32_t Length,
IN uint32_t HeadRoom
);
/**
Free specified Rtk_buffer
\param [IN] RtkBuffer <RTK_BUFFER*> : buffer to free
*/
void
RtbFree(
IN RTK_BUFFER* RtkBuffer
);
/**
increament reference count
*/
void
RtbIncreaseRefCount(
IN RTK_BUFFER* RtkBuffer
);
/**
Recycle a rtk_buffer after its usage if specified rtb could
if rtb total length is not smaller than specified rtbsize to be recycled for, it will succeeded recycling
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : buffer to recycle
\param [IN] RtbSize <uint32_t> : size of buffer to be recycled for
*/
/*
BOOLEAN
RtbCheckRecycle(
IN OUT RTK_BUFFER* RtkBuffer,
IN uint32_t RtbSize
);
*/
/**
Add a specified length protocal header to the start of data buffer hold by specified rtk_buffer.
This function extends used data area of the buffer at the buffer start.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
\param [IN] Length <uint32_t> : header length
\return Pointer to the first byte of the extra data is returned
*/
uint8_t*
RtbAddHead(
IN OUT RTK_BUFFER* RtkBuffer,
IN uint32_t Length
);
/**
Remove a specified length data from the start of data buffer hold by specified rtk_buffer.
This function returns the memory to the headroom.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to remove
\param [IN] Length <uint32_t> : header length
\return Pointer to the next data in the buffer is returned, usually useless
*/
unsigned char
RtbRemoveHead(
IN OUT RTK_BUFFER* RtkBuffer,
IN uint32_t Length
);
/**
Add a specified length protocal header to the end of data buffer hold by specified rtk_buffer.
This function extends used data area of the buffer at the buffer end.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
\param [IN] Length <uint32_t> : header length
\return Pointer to the first byte of the extra data is returned
*/
EXTERN uint8_t*
RtbAddTail(
IN OUT RTK_BUFFER* RtkBuffer,
IN uint32_t Length
);
/**
Remove a specified length data from the end of data buffer hold by specified rtk_buffer.
*/
EXTERN unsigned char
RtbRemoveTail(
IN OUT RTK_BUFFER * RtkBuffer,
IN uint32_t Length
);
/**
Initialize a rtb queue.
\return Initilized rtb queue if succeed, otherwise NULL
*/
EXTERN RTB_QUEUE_HEAD*
RtbQueueInit(
);
/**
Free a rtb queue.
\param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
*/
EXTERN void
RtbQueueFree(
RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Queue specified RtkBuffer into a RtkQueue at list tail.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
EXTERN void
RtbQueueTail(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
);
/**
Queue specified RtkBuffer into a RtkQueue at list Head.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
EXTERN void
RtbQueueHead(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
);
/**
Remove a RtkBuffer from specified rtkqueue at list tail.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return removed rtkbuffer if succeed, otherwise NULL
*/
EXTERN RTK_BUFFER*
RtbDequeueTail(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Remove a RtkBuffer from specified rtkqueue at list head.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return removed rtkbuffer if succeed, otherwise NULL
*/
EXTERN RTK_BUFFER*
RtbDequeueHead(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Get current rtb queue's length.
\param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return current queue's length
*/
EXTERN signed long
RtbGetQueueLen(
IN RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Empty the rtkqueue.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
*/
EXTERN void
RtbEmptyQueue(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Get the RtkBuffer which is the head of a RtkQueue
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return head of the RtkQueue , otherwise NULL
*/
EXTERN RTK_BUFFER*
RtbTopQueue(
IN RTB_QUEUE_HEAD* RtkQueueHead
);
/**
Insert new Rtkbuffer in the old buffer
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] OldRtkBuffer <RTK_BUFFER*> : old rtk buffer
\param [IN] NewRtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
EXTERN void
RtbInsertBefore(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pOldRtkBuffer,
IN RTK_BUFFER* pNewRtkBuffer
);
/**
check whether the buffer is the last node in the queue
*/
EXTERN unsigned char
RtbNodeIsLast(
IN RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pRtkBuffer
);
/**
get the next buffer node after the specified buffer in the queue
if the specified buffer is the last node in the queue , return NULL
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer
\return node after the specified buffer
*/
EXTERN RTK_BUFFER*
RtbQueueNextNode(
IN RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pRtkBuffer
);
/**
check whether queue is empty
*/
EXTERN bool
RtbQueueIsEmpty(
IN RTB_QUEUE_HEAD* RtkQueueHead
);
//annie_tmp
EXTERN unsigned char
RtbCheckQueueLen(
IN RTB_QUEUE_HEAD* RtkQueueHead,
IN uint8_t Len
);
EXTERN void
RtbRemoveNode(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
);
EXTERN RTK_BUFFER*
RtbCloneBuffer(
IN RTK_BUFFER* pDataBuffer
);
#endif /*BT_SKBUFF_H*/

View file

@ -0,0 +1,245 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: bt_vendor_rtk.h
*
* Description: A wrapper header file of bt_vendor_lib.h
*
* Contains definitions specific for interfacing with Realtek
* Bluetooth chipsets
*
******************************************************************************/
#ifndef BT_VENDOR_RTK_H
#define BT_VENDOR_RTK_H
#include "bt_vendor_lib.h"
#include "vnd_buildcfg.h"
#include "rtk_btsnoop_net.h"
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include <ctype.h>
#include <cutils/properties.h>
/******************************************************************************
** Constants & Macros
******************************************************************************/
#define RTKBT_TRANS_H4 0x20
#define RTKBT_TRANS_H5 0x10
#define RTKBT_TRANS_UART 0x01
#define RTKBT_TRANS_USB 0x20
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#ifndef BTVND_DBG
#define BTVND_DBG TRUE
#endif
#if (BTVND_DBG == TRUE)
#define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
#else
#define BTVNDDBG(param, ...) {}
#endif
#define DOWN_FW_CFG _IOW('H', 201, int)
#define SET_ISO_CFG _IOW('H', 202, int)
/* Device port name where Bluetooth controller attached */
#ifndef BLUETOOTH_UART_DEVICE_PORT
#define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyO1" /* maguro */
#endif
/* Location of firmware patch files */
#ifndef FW_PATCHFILE_LOCATION
#define FW_PATCHFILE_LOCATION "/vendor/firmware/" /* maguro */
#endif
#ifndef UART_TARGET_BAUD_RATE
#define UART_TARGET_BAUD_RATE 3000000
#endif
/* The Bluetooth Device Aaddress source switch:
*
* -FALSE- (default value)
* Get the factory BDADDR from device's file system. Normally the BDADDR is
* stored in the location pointed by the PROPERTY_BT_BDADDR_PATH (defined in
* btif_common.h file) property.
*
* -TRUE-
* If the Bluetooth Controller has equipped with a non-volatile memory (such
* as BCM4330's OTP memory), the factory BDADDR can be stored in there and
* retrieved by the stack while enabling BT.
* !!! WARNING !!! Make sure that the OTP feature has been enabled in the
* firmware patchram (.hcd) file.
*/
#ifndef USE_CONTROLLER_BDADDR
#define USE_CONTROLLER_BDADDR TRUE //FALSE
#endif
/* sleep mode
0: disable
1: UART with Host wake/BT wake out of band signals
*/
#ifndef LPM_SLEEP_MODE
#define LPM_SLEEP_MODE 1
#endif
/* Host Stack Idle Threshold in 300ms or 25ms
In sleep mode 1, this is the number of firmware loops executed with no
activity before the Host wake line is deasserted. Activity includes HCI
traffic excluding certain sleep mode commands and the presence of SCO
connections if the "Allow Host Sleep During SCO" flag is not set to 1.
Each count of this parameter is roughly equivalent to 300ms or 25ms.
*/
#ifndef LPM_IDLE_THRESHOLD
#define LPM_IDLE_THRESHOLD 1
#endif
/* Host Controller Idle Threshold in 300ms or 25ms
This is the number of firmware loops executed with no activity before the
HC is considered idle. Depending on the mode, HC may then attempt to sleep.
Activity includes HCI traffic excluding certain sleep mode commands and
the presence of ACL/SCO connections.
*/
#ifndef LPM_HC_IDLE_THRESHOLD
#define LPM_HC_IDLE_THRESHOLD 1
#endif
/* BT_WAKE Polarity - 0=Active Low, 1= Active High */
#ifndef LPM_BT_WAKE_POLARITY
#define LPM_BT_WAKE_POLARITY 1 /* maguro */
#endif
/* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
#ifndef LPM_HOST_WAKE_POLARITY
#define LPM_HOST_WAKE_POLARITY 1 /* maguro */
#endif
/* LPM_ALLOW_HOST_SLEEP_DURING_SCO
When this flag is set to 0, the host is not allowed to sleep while
an SCO is active. In sleep mode 1, the device will keep the host
wake line asserted while an SCO is active.
When this flag is set to 1, the host can sleep while an SCO is active.
This flag should only be set to 1 if SCO traffic is directed to the PCM
interface.
*/
#ifndef LPM_ALLOW_HOST_SLEEP_DURING_SCO
#define LPM_ALLOW_HOST_SLEEP_DURING_SCO 1
#endif
/* LPM_COMBINE_SLEEP_MODE_AND_LPM
In Mode 0, always set byte 7 to 0. In sleep mode 1, device always
requires permission to sleep between scans / periodic inquiries regardless
of the setting of this byte. In sleep mode 1, if byte is set, device must
have "permission" to sleep during the low power modes of sniff, hold, and
park. If byte is not set, device can sleep without permission during these
modes. Permission to sleep in Mode 1 is obtained if the BT_WAKE signal is
not asserted.
*/
#ifndef LPM_COMBINE_SLEEP_MODE_AND_LPM
#define LPM_COMBINE_SLEEP_MODE_AND_LPM 1
#endif
/* LPM_ENABLE_UART_TXD_TRI_STATE
When set to 0, the device will not tristate its UART TX line before going
to sleep.
When set to 1, the device will tristate its UART TX line before going to
sleep.
*/
#ifndef LPM_ENABLE_UART_TXD_TRI_STATE
#define LPM_ENABLE_UART_TXD_TRI_STATE 0
#endif
/* LPM_PULSED_HOST_WAKE
*/
#ifndef LPM_PULSED_HOST_WAKE
#define LPM_PULSED_HOST_WAKE 0
#endif
/* LPM_IDLE_TIMEOUT_MULTIPLE
The multiple factor of host stack idle threshold in 300ms/25ms
*/
#ifndef LPM_IDLE_TIMEOUT_MULTIPLE
#define LPM_IDLE_TIMEOUT_MULTIPLE 10
#endif
/* BT_WAKE_VIA_USERIAL_IOCTL
Use userial ioctl function to control BT_WAKE signal
*/
#ifndef BT_WAKE_VIA_USERIAL_IOCTL
#define BT_WAKE_VIA_USERIAL_IOCTL FALSE
#endif
/* BT_WAKE_VIA_PROC
LPM & BT_WAKE control through PROC nodes
*/
#ifndef BT_WAKE_VIA_PROC
#define BT_WAKE_VIA_PROC FALSE
#endif
/* HW_END_WITH_HCI_RESET
Sample code implementation of sending a HCI_RESET command during the epilog
process. It calls back to the callers after command complete of HCI_RESET
is received.
*/
#ifndef HW_END_WITH_HCI_RESET
#define HW_END_WITH_HCI_RESET FALSE
#endif
/******************************************************************************
** Extern variables and functions
******************************************************************************/
extern bt_vendor_callbacks_t *bt_vendor_cbacks;
#endif /* BT_VENDOR_RTK_H */

View file

@ -0,0 +1,82 @@
/******************************************************************************
*
* Copyright (C) 2014 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#ifndef RTK_HCI_H5_INT_H
#define RTK_HCI_H5_INT_H
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "bt_hci_bdroid.h"
#include "bt_vendor_lib.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "rtk_hcidefs.h"
//HCI Command opcodes
#define HCI_LE_READ_BUFFER_SIZE 0x2002
#define DATA_TYPE_H5 0x05
//HCI VENDOR Command opcode
#define HCI_VSC_H5_INIT 0xFCEE
#define HCI_VSC_UPDATE_BAUDRATE 0xFC17
#define HCI_VSC_DOWNLOAD_FW_PATCH 0xFC20
#define HCI_VSC_READ_ROM_VERSION 0xFC6D
#define HCI_VSC_READ_CHIP_TYPE 0xFC61
#define HCI_VSC_SET_WAKE_UP_DEVICE 0xFC7B
#define HCI_VSC_BT_OFF 0xFC28
#define HCI_READ_LMP_VERSION 0x1001
#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
#define STREAM_TO_UINT32(u32, p) {u32 = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); (p) += 4;}
#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);}
void ms_delay (uint32_t timeout);
typedef enum {
DATA_TYPE_COMMAND = 1,
DATA_TYPE_ACL = 2,
DATA_TYPE_SCO = 3,
DATA_TYPE_EVENT = 4
} serial_data_type_t;
typedef struct hci_h5_callbacks_t{
uint16_t (*h5_int_transmit_data_cb)(serial_data_type_t type, uint8_t *data, uint16_t length);
void (*h5_data_ready_cb)(serial_data_type_t type, unsigned int total_length);
} hci_h5_callbacks_t;
typedef struct hci_h5_t {
void (*h5_int_init)(hci_h5_callbacks_t *h5_callbacks);
void (*h5_int_cleanup)(void);
uint16_t (*h5_send_cmd)(serial_data_type_t type, uint8_t *data, uint16_t length);
uint8_t (*h5_send_sync_cmd)(uint16_t opcode, uint8_t *data, uint16_t length);
uint16_t (*h5_send_acl_data)(serial_data_type_t type, uint8_t *data, uint16_t length);
uint16_t (*h5_send_sco_data)(serial_data_type_t type, uint8_t *data, uint16_t length);
bool (*h5_recv_msg)(uint8_t *byte, uint16_t length);
size_t (*h5_int_read_data)(uint8_t *data_buffer, size_t max_size);
} hci_h5_t;
const hci_h5_t *hci_get_h5_int_interface(void);
#endif

View file

@ -0,0 +1,58 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: rtk_btsnoop_net.h
*
* Description: A wrapper header file of bt_vendor_lib.h
*
* Contains definitions specific for interfacing with Realtek
* Bluetooth chipsets
*
******************************************************************************/
#ifndef RTK_BTSNOOP_NET_H
#define RTK_BTSNOOP_NET_H
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include "hci_h5_int.h"
#include <utils/Log.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
void rtk_btsnoop_open(void);
void rtk_btsnoop_close(void);
void rtk_btsnoop_capture(const HC_BT_HDR *p_buf, bool is_rcvd);
void rtk_btsnoop_net_open();
void rtk_btsnoop_net_close();
void rtk_btsnoop_net_write(serial_data_type_t type, uint8_t *data, bool is_received);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,152 @@
/******************************************************************************
*
* Copyright (C) 2016 Realtek Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Module Name:
* rtk_parse.h
*
* Abstract:
* Contains wifi-bt coex functions implemented by bluedroid stack
*
* Major Change History:
* When Who What
* ---------------------------------------------------------------
* 2015-12-15 lamparten modified
* 2014-10-23 kyle_xu modified
*
* Notes:
* This is designed for wifi-bt Coex in Android 6.0.
*
******************************************************************************/
#ifndef RTK_PARSE_H
#define RTK_PARSE_H
#pragma once
#include <stdlib.h>
#include <strings.h>
#include "bt_vendor_rtk.h"
#include "userial_vendor.h"
/******************************************************************************
** Constants & Macros
******************************************************************************/
#define HOST_PROFILE_INFO
/******************************************************************************
** Type definitions
******************************************************************************/
typedef unsigned char UINT8;
#define BD_ADDR_LEN 6 /* Device address length */
typedef UINT8 BD_ADDR[BD_ADDR_LEN]; /* Device address */
typedef void* TRANSAC;
/******************************************************************************
** Extern variables and functions
******************************************************************************/
extern uint8_t coex_log_enable;
/******************************************************************************
** Functions
******************************************************************************/
typedef struct rtk_parse_manager_t {
void (*rtk_parse_internal_event_intercept)(uint8_t *p);
void (*rtk_parse_l2cap_data)(uint8_t *p, uint8_t direction);
void (*rtk_parse_init)(void);
void (*rtk_parse_cleanup)(void);
void (*rtk_parse_command)(uint8_t *p);
void (*rtk_add_le_profile)(BD_ADDR bdaddr, uint16_t handle, uint8_t profile_map);
void (*rtk_delete_le_profile)(BD_ADDR bdaddr, uint16_t handle, uint8_t profile_map);
void (*rtk_add_le_data_count)(uint8_t data_type);
}rtk_parse_manager_t;
const rtk_parse_manager_t *rtk_parse_manager_get_interface();
#ifdef __LITTLE_ENDIAN
struct sbc_frame_hdr {
uint8_t syncword:8; /* Sync word */
uint8_t subbands:1; /* Subbands */
uint8_t allocation_method:1; /* Allocation method */
uint8_t channel_mode:2; /* Channel mode */
uint8_t blocks:2; /* Blocks */
uint8_t sampling_frequency:2; /* Sampling frequency */
uint8_t bitpool:8; /* Bitpool */
uint8_t crc_check:8; /* CRC check */
} __attribute__ ((packed));
/* NOTE: The code is copied from pa.
* only the bit field in 8-bit is affected by endian, not the 16-bit or 32-bit.
* why?
*/
struct rtp_header {
unsigned cc:4;
unsigned x:1;
unsigned p:1;
unsigned v:2;
unsigned pt:7;
unsigned m:1;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
#else
/* big endian */
struct sbc_frame_hdr {
uint8_t syncword:8; /* Sync word */
uint8_t sampling_frequency:2; /* Sampling frequency */
uint8_t blocks:2; /* Blocks */
uint8_t channel_mode:2; /* Channel mode */
uint8_t allocation_method:1; /* Allocation method */
uint8_t subbands:1; /* Subbands */
uint8_t bitpool:8; /* Bitpool */
uint8_t crc_check:8; /* CRC check */
} __attribute__ ((packed));
struct rtp_header {
unsigned v:2;
unsigned p:1;
unsigned x:1;
unsigned cc:4;
unsigned m:1;
unsigned pt:7;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
#endif /* __LITTLE_ENDIAN */
#endif /*RTK_PARSE_H*/

View file

@ -0,0 +1,73 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: userial_vendor.h
*
* Description: Contains vendor-specific definitions used in serial port
* controls
*
******************************************************************************/
#ifndef RTK_SOCKET_H
#define RTK_SOCKET_H
#include "bt_vendor_rtk.h"
#include "userial.h"
#include <sys/poll.h>
#include <assert.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/prctl.h>
#include <sys/un.h>
#ifdef CONFIG_SCO_OVER_HCI
#define SCO_CTRL_PATH "/data/misc/bluedroid/.sco_ctrl"
#define SCO_DATA_PATH "/data/misc/bluedroid/.sco_data"
typedef enum {
SCO_CTRL_CMD_NONE,
SCO_CTRL_CMD_CHECK_READY,
SCO_CTRL_CMD_OUT_START,
SCO_CTRL_CMD_IN_START,
SCO_CTRL_CMD_OUT_STOP,
SCO_CTRL_CMD_IN_STOP,
SCO_CTRL_CMD_SUSPEND,
SCO_CTRL_GET_AUDIO_CONFIG,
SCO_CTRL_CMD_OFFLOAD_START,
} tSCO_CTRL_CMD;
#define SCO_SAMPLE_RATE_8K 1
#define SCO_SAMPLE_RATE_16K 2
#endif
#define MAX(a,b) ((a)>(b)?(a):(b))
/******************************************************************************
** Constants & Macros
******************************************************************************/
uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len);
int Skt_Read_noblock(int fd, uint8_t *p_buf, uint32_t len);
bool Skt_Send(int fd, uint8_t *p_buf, uint16_t msglen);
int Skt_Send_noblock(int fd, uint8_t *p_buf, uint16_t msglen);
#endif

View file

@ -0,0 +1,118 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: upio.h
*
* Description: Contains definitions used for I/O controls
*
******************************************************************************/
#ifndef UPIO_H
#define UPIO_H
/******************************************************************************
** Constants & Macros
******************************************************************************/
#define UPIO_BT_POWER_OFF 0
#define UPIO_BT_POWER_ON 1
/* UPIO signals */
enum {
UPIO_BT_WAKE = 0,
UPIO_HOST_WAKE,
UPIO_LPM_MODE,
UPIO_MAX_COUNT
};
/* UPIO assertion/deassertion */
enum {
UPIO_UNKNOWN = 0,
UPIO_DEASSERT,
UPIO_ASSERT
};
/******************************************************************************
** Extern variables and functions
******************************************************************************/
/******************************************************************************
** Functions
******************************************************************************/
/*******************************************************************************
**
** Function upio_init
**
** Description Initialization
**
** Returns None
**
*******************************************************************************/
void upio_init(void);
/*******************************************************************************
**
** Function upio_cleanup
**
** Description Clean up
**
** Returns None
**
*******************************************************************************/
void upio_cleanup(void);
/*******************************************************************************
**
** Function upio_set_bluetooth_power
**
** Description Interact with low layer driver to set Bluetooth power
** on/off.
**
** Returns 0 : SUCCESS or Not-Applicable
** <0 : ERROR
**
*******************************************************************************/
int upio_set_bluetooth_power(int on);
/*******************************************************************************
**
** Function upio_set
**
** Description Set i/o based on polarity
**
** Returns None
**
*******************************************************************************/
void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
/*******************************************************************************
**
** Function bt_wake_up_host_mode_set
**
** Description To enable/disable bt_wake_up_host mode.
**
** Returns 0 : SUCCESS or Not-Applicable
** <0 : ERROR
**
*******************************************************************************/
int bt_wake_up_host_mode_set(uint8_t mode);
#endif /* UPIO_H */

View file

@ -0,0 +1,221 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: userial_vendor.h
*
* Description: Contains vendor-specific definitions used in serial port
* controls
*
******************************************************************************/
#ifndef USERIAL_VENDOR_H
#define USERIAL_VENDOR_H
#include "bt_vendor_rtk.h"
#include "userial.h"
#include "hci_h5_int.h"
#include <sys/poll.h>
#include <assert.h>
#include "rtk_parse.h"
#include "bt_skbuff.h"
/******************************************************************************
** Constants & Macros
******************************************************************************/
#define RTK_NO_INTR(fn) do {} while ((fn) == -1 && errno == EINTR)
#define RTK_GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
#define RTK_START_PACKET_BOUNDARY 2
/**** baud rates ****/
#define USERIAL_BAUD_300 0
#define USERIAL_BAUD_600 1
#define USERIAL_BAUD_1200 2
#define USERIAL_BAUD_2400 3
#define USERIAL_BAUD_9600 4
#define USERIAL_BAUD_19200 5
#define USERIAL_BAUD_57600 6
#define USERIAL_BAUD_115200 7
#define USERIAL_BAUD_230400 8
#define USERIAL_BAUD_460800 9
#define USERIAL_BAUD_921600 10
#define USERIAL_BAUD_1M 11
#define USERIAL_BAUD_1_5M 12
#define USERIAL_BAUD_2M 13
#define USERIAL_BAUD_3M 14
#define USERIAL_BAUD_4M 15
#define USERIAL_BAUD_AUTO 16
/**** Data Format ****/
/* Stop Bits */
#define USERIAL_STOPBITS_1 1
#define USERIAL_STOPBITS_1_5 (1<<1)
#define USERIAL_STOPBITS_2 (1<<2)
/* Parity Bits */
#define USERIAL_PARITY_NONE (1<<3)
#define USERIAL_PARITY_EVEN (1<<4)
#define USERIAL_PARITY_ODD (1<<5)
/* Data Bits */
#define USERIAL_DATABITS_5 (1<<6)
#define USERIAL_DATABITS_6 (1<<7)
#define USERIAL_DATABITS_7 (1<<8)
#define USERIAL_DATABITS_8 (1<<9)
#define USERIAL_HW_FLOW_CTRL_OFF 0
#define USERIAL_HW_FLOW_CTRL_ON 1
#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
/* These are the ioctl values used for bt_wake ioctl via UART driver. you may
* need to redefine them on you platform!
* Logically they need to be unique and not colide with existing uart ioctl's.
*/
#ifndef USERIAL_IOCTL_BT_WAKE_ASSERT
#define USERIAL_IOCTL_BT_WAKE_ASSERT 0x8003
#endif
#ifndef USERIAL_IOCTL_BT_WAKE_DEASSERT
#define USERIAL_IOCTL_BT_WAKE_DEASSERT 0x8004
#endif
#ifndef USERIAL_IOCTL_BT_WAKE_GET_ST
#define USERIAL_IOCTL_BT_WAKE_GET_ST 0x8005
#endif
#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
/******************************************************************************
** Type definitions
******************************************************************************/
// 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
#define COMMAND_PREAMBLE_SIZE 3
// 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
#define ACL_PREAMBLE_SIZE 4
// 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
#define SCO_PREAMBLE_SIZE 3
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
#define EVENT_PREAMBLE_SIZE 2
#define HCI_PACKET_TYPE_TO_INDEX(type) ((type) - 1)
#define COMMON_DATA_LENGTH_INDEX 3
#define EVENT_DATA_LENGTH_INDEX 2
/* Structure used to configure serial port during open */
typedef struct
{
uint16_t fmt; /* Data format */
uint8_t baud; /* Baud rate */
uint8_t hw_fctrl; /*hardware flowcontrol*/
} tUSERIAL_CFG;
typedef enum {
#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
USERIAL_OP_ASSERT_BT_WAKE,
USERIAL_OP_DEASSERT_BT_WAKE,
USERIAL_OP_GET_BT_WAKE_STATE,
#endif
USERIAL_OP_NOP,
} userial_vendor_ioctl_op_t;
enum {
RTKBT_PACKET_IDLE,
RTKBT_PACKET_TYPE,
RTKBT_PACKET_HEADER,
RTKBT_PACKET_CONTENT,
RTKBT_PACKET_END
};
/******************************************************************************
** Extern variables and functions
******************************************************************************/
/******************************************************************************
** Functions
******************************************************************************/
/*******************************************************************************
**
** Function userial_vendor_init
**
** Description Initialize userial vendor-specific control block
**
** Returns None
**
*******************************************************************************/
void userial_vendor_init(char *bt_device_node);
/*******************************************************************************
**
** Function userial_vendor_open
**
** Description Open the serial port with the given configuration
**
** Returns device fd
**
*******************************************************************************/
int userial_vendor_open(tUSERIAL_CFG *p_cfg);
/*******************************************************************************
**
** Function userial_vendor_close
**
** Description Conduct vendor-specific close work
**
** Returns None
**
*******************************************************************************/
void userial_vendor_close(void);
/*******************************************************************************
**
** Function userial_vendor_set_baud
**
** Description Set new baud rate
**
** Returns None
**
*******************************************************************************/
void userial_vendor_set_baud(uint8_t userial_baud);
/*******************************************************************************
**
** Function userial_vendor_ioctl
**
** Description ioctl inteface
**
** Returns None
**
*******************************************************************************/
void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data);
void userial_vendor_set_hw_fctrl(uint8_t hw_fctrl);
int userial_socket_open(void);
int userial_vendor_usb_ioctl(int operation, void* param);
int userial_vendor_usb_open(void);
#define RTK_HANDLE_EVENT
#define RTK_HANDLE_CMD
//#define CONFIG_SCO_OVER_HCI
#endif /* USERIAL_VENDOR_H */

View file

@ -0,0 +1,11 @@
#ifndef _VND_BUILDCFG_H
#define _VND_BUILDCFG_H
#define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyS1"
#define FW_PATCHFILE_LOCATION "/etc/firmware/"
#define LPM_IDLE_TIMEOUT_MULTIPLE 5
#define SCO_USE_I2S_INTERFACE TRUE
#define BTVND_DBG TRUE
#define BTHW_DBG TRUE
#define VNDUSERIAL_DBG TRUE
#define UPIO_DBG TRUE
#endif

View file

@ -0,0 +1,144 @@
/******************************************************************************
*
* Copyright (C) 2016 Realtek Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Module Name:
* bt_list.c
*
* Abstract:
* To implement list data structure
*
* Major Change History:
* When Who What
* --------------------------------------------------------------
* 2010-06-04 W.Bi Created
*
* Notes:
*
******************************************************************************/
#include "bt_list.h"
//****************************************************************************
// Structure
//****************************************************************************
//****************************************************************************
// FUNCTION
//****************************************************************************
//Initialize a list with its header
void ListInitializeHeader(PRT_LIST_HEAD ListHead)
{
ListHead->Next = ListHead;
ListHead->Prev = ListHead;
}
/**
Tell whether the list is empty
\param [IN] ListHead <RT_LIST_ENTRY> : List header of which to be test
*/
unsigned char ListIsEmpty(PRT_LIST_HEAD ListHead)
{
return ListHead->Next == ListHead;
}
/*
Insert a new entry between two known consecutive entries.
This is only for internal list manipulation where we know the prev&next entries already
@New : New element to be added
@Prev: previous element in the list
@Next: Next element in the list
*/
void
ListAdd(
PRT_LIST_ENTRY New,
PRT_LIST_ENTRY Prev,
PRT_LIST_ENTRY Next
)
{
Next->Prev = New;
New->Next = Next;
New->Prev = Prev;
Prev->Next = New;
}
/**
Add a new entry to the list.
Insert a new entry after the specified head. This is good for implementing stacks.
\param [IN] ListNew <RT_LIST_ENTRY> : new entry to be added
\param [IN OUT] ListHead <RT_LIST_ENTRY> : List header after which to add new entry
*/
void
ListAddToHead(
PRT_LIST_ENTRY ListNew,
PRT_LIST_HEAD ListHead
)
{
ListAdd(ListNew, ListHead, ListHead->Next);
}
/**
Add a new entry to the list.
Insert a new entry before the specified head. This is good for implementing queues.
\param [IN] ListNew <RT_LIST_ENTRY> : new entry to be added
\param [IN OUT] ListHead <RT_LIST_ENTRY> : List header before which to add new entry
*/
void
ListAddToTail(
PRT_LIST_ENTRY ListNew,
PRT_LIST_HEAD ListHead
)
{
ListAdd(ListNew, ListHead->Prev, ListHead);
}
RT_LIST_ENTRY*
ListGetTop(
PRT_LIST_HEAD ListHead
)
{
if (ListIsEmpty(ListHead))
return 0;
return ListHead->Next;
}
RT_LIST_ENTRY*
ListGetTail(
PRT_LIST_HEAD ListHead
)
{
if (ListIsEmpty(ListHead))
return 0;
return ListHead->Prev;
}
/**
Delete entry from the list
Note: ListIsEmpty() on this list entry would not return true, since its state is undefined
\param [IN] ListToDelete <RT_LIST_ENTRY> : list entry to be deleted
*/
void ListDeleteNode(PRT_LIST_ENTRY ListToDelete)
{
// if (ListToDelete->Next != NULL && ListToDelete->Prev != NULL)
{
ListToDelete->Next->Prev = ListToDelete->Prev;
ListToDelete->Prev->Next = ListToDelete->Next;
ListToDelete->Next = ListToDelete->Prev = ListToDelete;
}
}

View file

@ -0,0 +1,573 @@
/******************************************************************************
*
* Copyright (C) 2016 Realtek Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Module Name:
* bt_skbuff.c
*
* Abstract:
* Data buffer managerment through whole bluetooth stack.
*
* Major Change History:
* When Who What
* --------------------------------------------------------------
* 2010-06-11 W.Bi Created.
*
* Notes:
* To reduce memory copy when pass data buffer to other layers,
* RTK_BUFFER is designed referring to linux socket buffer.
* But I still wonder its effect, since RTK_BUFFER is much bigger
* than original data buffer.RTK_BUFFER will reduce its member if
* it would not reach what i had expected.
*
******************************************************************************/
#define LOG_TAG "bt_h5"
#undef NDEBUG
#include <utils/Log.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <pthread.h>
#include "bt_list.h"
#include "bt_skbuff.h"
#include "string.h"
#include "hci_h5_int.h"
#define IN
#define OUT
//****************************************************************************
// CONSTANT DEFINITION
//****************************************************************************
///default header size
///l2cap header(8)+hci acl(4)
#define DEFAULT_HEADER_SIZE (8+4)
//RTK_BUFFER data buffer alignment
#define RTB_ALIGN 4
//do alignment with RTB_ALIGN
#define RTB_DATA_ALIGN(_Length) ((_Length + (RTB_ALIGN - 1)) & (~(RTB_ALIGN - 1)))
//****************************************************************************
// STRUCTURE DEFINITION
//****************************************************************************
typedef struct _RTB_QUEUE_HEAD{
RT_LIST_HEAD List;
uint32_t QueueLen;
pthread_mutex_t Lock;
uint8_t Id[RTB_QUEUE_ID_LENGTH];
}RTB_QUEUE_HEAD, *PRTB_QUEUE_HEAD;
//****************************************************************************
// FUNCTION
//****************************************************************************
/**
check whether queue is empty
\return : FALSE Queue is not empty
TRU Queue is empty
*/
bool
RtbQueueIsEmpty(
IN RTB_QUEUE_HEAD* RtkQueueHead
)
{
//return ListIsEmpty(&RtkQueueHead->List);
return RtkQueueHead->QueueLen > 0 ? false : true;
}
/**
Allocate a RTK_BUFFER with specified data length and reserved headroom.
If caller does not know actual headroom to reserve for further usage, specify it to zero to use default value.
\param [IN] Length <uint32_t> : current data buffer length to allcated
\param [IN] HeadRoom <uint32_t> : if caller knows reserved head space, set it; otherwise set 0 to use default value
\return pointer to RTK_BUFFER if succeed, null otherwise
*/
RTK_BUFFER*
RtbAllocate(
uint32_t Length,
uint32_t HeadRoom
)
{
RTK_BUFFER* Rtb = NULL;
///Rtb buffer length:
/// RTK_BUFFER 48
/// HeadRoom HeadRomm or 12
/// Length
///memory size: 48 + Length + 12(default) + 8*2(header for each memory) ---> a multiple of 8
///example: (48 + 8)+ (300 + 12 + 8) = 372
Rtb = malloc( sizeof(RTK_BUFFER) );
if(Rtb)
{
uint32_t BufferLen = HeadRoom ? (Length + HeadRoom) : (Length + DEFAULT_HEADER_SIZE);
BufferLen = RTB_DATA_ALIGN(BufferLen);
Rtb->Head = malloc(BufferLen);
if(Rtb->Head)
{
Rtb->HeadRoom = HeadRoom ? HeadRoom : DEFAULT_HEADER_SIZE;
Rtb->Data = Rtb->Head + Rtb->HeadRoom;
Rtb->End = Rtb->Data;
Rtb->Tail = Rtb->End + Length;
Rtb->Length = 0;
ListInitializeHeader(&Rtb->List);
Rtb->RefCount = 1;
return Rtb;
}
}
if (Rtb)
{
if (Rtb->Head)
{
free(Rtb->Head);
}
free(Rtb);
}
return NULL;
}
/**
Free specified Rtk_buffer
\param [IN] RtkBuffer <RTK_BUFFER*> : buffer to free
*/
void
RtbFree(
RTK_BUFFER* RtkBuffer
)
{
if(RtkBuffer)
{
free(RtkBuffer->Head);
free(RtkBuffer);
}
return;
}
/**
Add a specified length protocal header to the start of data buffer hold by specified rtk_buffer.
This function extends used data area of the buffer at the buffer start.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
\param [IN] Length <uint32_t> : header length
\return Pointer to the first byte of the extra data is returned
*/
uint8_t*
RtbAddHead(
RTK_BUFFER* RtkBuffer,
uint32_t Length
)
{
if ((uint32_t)(RtkBuffer->Data - RtkBuffer->Head) >= Length)
{
RtkBuffer->Data -= Length;
RtkBuffer->Length += Length;
RtkBuffer->HeadRoom -= Length;
return RtkBuffer->Data;
}
return NULL;
}
/**
Remove a specified length data from the start of data buffer hold by specified rtk_buffer.
This function returns the memory to the headroom.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to remove
\param [IN] Length <uint32_t> : header length
\return Pointer to the next data in the buffer is returned, usually useless
*/
unsigned char
RtbRemoveHead(
RTK_BUFFER* RtkBuffer,
uint32_t Length
)
{
if (RtkBuffer->Length >= Length)
{
RtkBuffer->Data += Length;
RtkBuffer->Length -= Length;
RtkBuffer->HeadRoom += Length;
return true;
}
return false;
}
/**
Add a specified length protocal header to the end of data buffer hold by specified rtk_buffer.
This function extends used data area of the buffer at the buffer end.
\param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
\param [IN] Length <uint32_t> : header length
\return Pointer to the first byte of the extra data is returned
*/
uint8_t*
RtbAddTail(
RTK_BUFFER* RtkBuffer,
uint32_t Length
)
{
if ((uint32_t)(RtkBuffer->Tail - RtkBuffer->End) >= Length)
{
uint8_t* Tmp = RtkBuffer->End;
RtkBuffer->End += Length;
RtkBuffer->Length += Length;
return Tmp;
}
return NULL;
}
unsigned char
RtbRemoveTail(
IN OUT RTK_BUFFER * RtkBuffer,
IN uint32_t Length
)
{
if ((uint32_t)(RtkBuffer->End - RtkBuffer->Data) >= Length)
{
RtkBuffer->End -= Length;
RtkBuffer->Length -= Length;
return true;
}
return false;
}
//****************************************************************************
// RTB list manipulation
//****************************************************************************
/**
Initialize a rtb queue.
\return Initilized rtb queue if succeed, otherwise NULL
*/
RTB_QUEUE_HEAD*
RtbQueueInit(
)
{
RTB_QUEUE_HEAD* RtbQueue = NULL;
RtbQueue = malloc(sizeof(RTB_QUEUE_HEAD));
if(RtbQueue)
{
pthread_mutex_init(&RtbQueue->Lock, NULL);
ListInitializeHeader(&RtbQueue->List);
RtbQueue->QueueLen = 0;
return RtbQueue;
}
//error code comes here
if (RtbQueue)
{
free(RtbQueue);
}
return NULL;
}
/**
Free a rtb queue.
\param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
*/
void
RtbQueueFree(
RTB_QUEUE_HEAD* RtkQueueHead
)
{
if (RtkQueueHead)
{
RtbEmptyQueue(RtkQueueHead);
pthread_mutex_destroy(&RtkQueueHead->Lock);
free(RtkQueueHead);
}
}
/**
Queue specified RtkBuffer into a RtkQueue at list tail.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
void
RtbQueueTail(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
)
{
pthread_mutex_lock(&RtkQueueHead->Lock);
ListAddToTail(&RtkBuffer->List, &RtkQueueHead->List);
RtkQueueHead->QueueLen++;
pthread_mutex_unlock(&RtkQueueHead->Lock);
}
/**
Queue specified RtkBuffer into a RtkQueue at list Head.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
void
RtbQueueHead(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
)
{
pthread_mutex_lock(&RtkQueueHead->Lock);
ListAddToHead(&RtkBuffer->List, &RtkQueueHead->List);
RtkQueueHead->QueueLen++;
pthread_mutex_unlock(&RtkQueueHead->Lock);
}
/**
Insert new Rtkbuffer in the old buffer
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] OldRtkBuffer <RTK_BUFFER*> : old rtk buffer
\param [IN] NewRtkBuffer <RTK_BUFFER*> : Rtk buffer to add
*/
void
RtbInsertBefore(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pOldRtkBuffer,
IN RTK_BUFFER* pNewRtkBuffer
)
{
pthread_mutex_lock(&RtkQueueHead->Lock);
ListAdd(&pNewRtkBuffer->List, pOldRtkBuffer->List.Prev, &pOldRtkBuffer->List);
RtkQueueHead->QueueLen++;
pthread_mutex_unlock(&RtkQueueHead->Lock);
}
/**
check whether the buffer is the last node in the queue
*/
unsigned char
RtbNodeIsLast(
IN RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pRtkBuffer
)
{
RTK_BUFFER* pBuf;
pthread_mutex_lock(&RtkQueueHead->Lock);
pBuf = (RTK_BUFFER*)RtkQueueHead->List.Prev;
if(pBuf == pRtkBuffer)
{
pthread_mutex_unlock(&RtkQueueHead->Lock);
return true;
}
pthread_mutex_unlock(&RtkQueueHead->Lock);
return false;
}
/**
get the next buffer node after the specified buffer in the queue
if the specified buffer is the last node in the queue , return NULL
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer
\return node after the specified buffer
*/
RTK_BUFFER*
RtbQueueNextNode(
IN RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* pRtkBuffer
)
{
RTK_BUFFER* pBuf;
pthread_mutex_lock(&RtkQueueHead->Lock);
pBuf = (RTK_BUFFER*)RtkQueueHead->List.Prev;
if(pBuf == pRtkBuffer)
{
pthread_mutex_unlock(&RtkQueueHead->Lock);
return NULL; ///< if it is already the last node in the queue , return NULL
}
pBuf = (RTK_BUFFER*)pRtkBuffer->List.Next;
pthread_mutex_unlock(&RtkQueueHead->Lock);
return pBuf; ///< return next node after this node
}
/**
Delete specified RtkBuffer from a RtkQueue.
It don't hold spinlock itself, so caller must hold it at someplace.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to Remove
*/
void
RtbRemoveNode(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead,
IN RTK_BUFFER* RtkBuffer
)
{
RtkQueueHead->QueueLen--;
ListDeleteNode(&RtkBuffer->List);
}
/**
Get the RtkBuffer which is the head of a RtkQueue
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return head of the RtkQueue , otherwise NULL
*/
RTK_BUFFER*
RtbTopQueue(
IN RTB_QUEUE_HEAD* RtkQueueHead
)
{
RTK_BUFFER* Rtb = NULL;
pthread_mutex_lock(&RtkQueueHead->Lock);
if (RtbQueueIsEmpty(RtkQueueHead))
{
pthread_mutex_unlock(&RtkQueueHead->Lock);
return NULL;
}
Rtb = (RTK_BUFFER*)RtkQueueHead->List.Next;
pthread_mutex_unlock(&RtkQueueHead->Lock);
return Rtb;
}
/**
Remove a RtkBuffer from specified rtkqueue at list tail.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return removed rtkbuffer if succeed, otherwise NULL
*/
RTK_BUFFER*
RtbDequeueTail(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
)
{
RTK_BUFFER* Rtb = NULL;
pthread_mutex_lock(&RtkQueueHead->Lock);
if (RtbQueueIsEmpty(RtkQueueHead))
{
pthread_mutex_unlock(&RtkQueueHead->Lock);
return NULL;
}
Rtb = (RTK_BUFFER*)RtkQueueHead->List.Prev;
RtbRemoveNode(RtkQueueHead, Rtb);
pthread_mutex_unlock(&RtkQueueHead->Lock);
return Rtb;
}
/**
Remove a RtkBuffer from specified rtkqueue at list head.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return removed rtkbuffer if succeed, otherwise NULL
*/
RTK_BUFFER*
RtbDequeueHead(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
)
{
RTK_BUFFER* Rtb = NULL;
pthread_mutex_lock(&RtkQueueHead->Lock);
if (RtbQueueIsEmpty(RtkQueueHead))
{
pthread_mutex_unlock(&RtkQueueHead->Lock);
return NULL;
}
Rtb = (RTK_BUFFER*)RtkQueueHead->List.Next;
RtbRemoveNode(RtkQueueHead, Rtb);
pthread_mutex_unlock(&RtkQueueHead->Lock);
return Rtb;
}
/**
Get current rtb queue's length.
\param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
\return current queue's length
*/
signed long RtbGetQueueLen(
IN RTB_QUEUE_HEAD* RtkQueueHead
)
{
return RtkQueueHead->QueueLen;
}
/**
Empty the rtkqueue.
\param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
*/
void
RtbEmptyQueue(
IN OUT RTB_QUEUE_HEAD* RtkQueueHead
)
{
RTK_BUFFER* Rtb = NULL;
pthread_mutex_lock(&RtkQueueHead->Lock);
while( !RtbQueueIsEmpty(RtkQueueHead))
{
Rtb = (RTK_BUFFER*)RtkQueueHead->List.Next;
RtbRemoveNode(RtkQueueHead, Rtb);
RtbFree(Rtb);
}
pthread_mutex_unlock(&RtkQueueHead->Lock);
return;
}
///Annie_tmp
unsigned char
RtbCheckQueueLen(IN RTB_QUEUE_HEAD* RtkQueueHead, IN uint8_t Len)
{
return RtkQueueHead->QueueLen < Len ? true : false;
}
/**
clone buffer for upper or lower layer, because original buffer should be stored in l2cap
\param <RTK_BUFFER* pDataBuffer: original buffer
\return cloned buffer
*/
RTK_BUFFER*
RtbCloneBuffer(
IN RTK_BUFFER* pDataBuffer
)
{
RTK_BUFFER* pNewBuffer = NULL;
if(pDataBuffer)
{
pNewBuffer = RtbAllocate(pDataBuffer->Length,0);
if(!pNewBuffer)
{
return NULL;
}
if(pDataBuffer->Data)
memcpy(pNewBuffer->Data, pDataBuffer->Data, pDataBuffer->Length);
else
{
RtbFree(pNewBuffer);
return NULL;
}
pNewBuffer->Length = pDataBuffer->Length;
}
return pNewBuffer;
}

View file

@ -0,0 +1,570 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: bt_vendor_rtk.c
*
* Description: Realtek vendor specific library implementation
*
******************************************************************************/
#undef NDEBUG
#define LOG_TAG "libbt_vendor"
#define RTKBT_RELEASE_NAME "20180321_BT_ANDROID_8.x"
#include <utils/Log.h>
#include "bt_vendor_rtk.h"
#include "upio.h"
#include "userial_vendor.h"
/******************************************************************************
** Externs
******************************************************************************/
extern unsigned int rtkbt_h5logfilter;
extern unsigned int h5_log_enable;
extern bool rtk_btsnoop_dump;
extern bool rtk_btsnoop_net_dump;
extern bool rtk_btsnoop_save_log;
extern char rtk_btsnoop_path[];
extern uint8_t coex_log_enable;
extern void hw_config_start(char transtype);
#if (HW_END_WITH_HCI_RESET == TRUE)
void hw_epilog_process(void);
#endif
/******************************************************************************
** Variables
******************************************************************************/
bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bool rtkbt_auto_restart = false;
/******************************************************************************
** Local type definitions
******************************************************************************/
#define DEVICE_NODE_MAX_LEN 512
#define RTKBT_CONF_FILE "/vendor/etc/bluetooth/rtkbt.conf"
#define USB_DEVICE_DIR "/sys/bus/usb/devices"
#define DEBUG_SCAN_USB FALSE
/******************************************************************************
** Static Variables
******************************************************************************/
//transfer_type(4 bit) | transfer_interface(4 bit)
char rtkbt_transtype = 0;
static char rtkbt_device_node[DEVICE_NODE_MAX_LEN] = {0};
static const tUSERIAL_CFG userial_H5_cfg =
{
(USERIAL_DATABITS_8 | USERIAL_PARITY_EVEN | USERIAL_STOPBITS_1),
USERIAL_BAUD_115200,
USERIAL_HW_FLOW_CTRL_OFF
};
static const tUSERIAL_CFG userial_H4_cfg =
{
(USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
USERIAL_BAUD_115200,
USERIAL_HW_FLOW_CTRL_OFF
};
/******************************************************************************
** Functions
******************************************************************************/
static int Check_Key_Value(char* path,char* key,int value){
FILE *fp;
char newpath[100];
char string_get[6];
int value_int = 0;
memset(newpath,0,100);
sprintf(newpath,"%s/%s",path,key);
if((fp = fopen(newpath, "r")) != NULL){
memset(string_get,0,6);
if(fgets(string_get, 5, fp) != NULL)
if(DEBUG_SCAN_USB)
ALOGE("string_get %s =%s\n",key,string_get);
fclose(fp);
value_int = strtol(string_get,NULL,16);
if(value_int == value)
return 1;
}
return 0;
}
static int Scan_Usb_Devices_For_RTK(char* path){
char newpath[100];
char subpath[100];
DIR * pdir;
DIR * newpdir;
struct dirent * ptr;
struct dirent * newptr;
struct stat filestat;
struct stat subfilestat;
if(stat(path, &filestat) != 0){
ALOGE("The file or path(%s) can not be get stat!\n", newpath);
return -1;
}
if((filestat.st_mode & S_IFDIR) != S_IFDIR){
ALOGE("(%s) is not be a path!\n", path);
return -1;
}
pdir =opendir(path);
/*enter sub direc*/
while((ptr = readdir(pdir))!=NULL){
if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
continue;
memset(newpath,0,100);
sprintf(newpath,"%s/%s", path,ptr->d_name);
if(DEBUG_SCAN_USB)
ALOGE("The file or path(%s)\n", newpath);
if(stat(newpath, &filestat) != 0){
ALOGE("The file or path(%s) can not be get stat!\n", newpath);
continue;
}
/* Check if it is path. */
if((filestat.st_mode & S_IFDIR) == S_IFDIR){
if(!Check_Key_Value(newpath,"idVendor",0x0bda))
continue;
newpdir =opendir(newpath);
/*read sub directory*/
while((newptr = readdir(newpdir))!=NULL){
if(strcmp(newptr->d_name, ".") == 0 || strcmp(newptr->d_name, "..") == 0)
continue;
memset(subpath,0,100);
sprintf(subpath,"%s/%s", newpath,newptr->d_name);
if(DEBUG_SCAN_USB)
ALOGE("The file or path(%s)\n", subpath);
if(stat(subpath, &subfilestat) != 0){
ALOGE("The file or path(%s) can not be get stat!\n", newpath);
continue;
}
/* Check if it is path. */
if((subfilestat.st_mode & S_IFDIR) == S_IFDIR){
if(Check_Key_Value(subpath,"bInterfaceClass",0xe0) && \
Check_Key_Value(subpath,"bInterfaceSubClass",0x01) && \
Check_Key_Value(subpath,"bInterfaceProtocol",0x01)){
closedir(newpdir);
closedir(pdir);
return 1;
}
}
}
closedir(newpdir);
}
}
closedir(pdir);
return 0;
}
static char *rtk_trim(char *str) {
while (isspace(*str))
++str;
if (!*str)
return str;
char *end_str = str + strlen(str) - 1;
while (end_str > str && isspace(*end_str))
--end_str;
end_str[1] = '\0';
return str;
}
static void load_rtkbt_stack_conf()
{
char *split;
FILE *fp = fopen(RTKBT_CONF_FILE, "rt");
if (!fp) {
ALOGE("%s unable to open file '%s': %s", __func__, RTKBT_CONF_FILE, strerror(errno));
return;
}
int line_num = 0;
char line[1024];
char value[1024];
while (fgets(line, sizeof(line), fp)) {
char *line_ptr = rtk_trim(line);
++line_num;
// Skip blank and comment lines.
if (*line_ptr == '\0' || *line_ptr == '#' || *line_ptr == '[')
continue;
split = strchr(line_ptr, '=');
if (!split) {
ALOGE("%s no key/value separator found on line %d.", __func__, line_num);
continue;
}
*split = '\0';
char *endptr;
if(!strcmp(rtk_trim(line_ptr), "RtkbtLogFilter")) {
rtkbt_h5logfilter = strtol(rtk_trim(split+1), &endptr, 0);
}
else if(!strcmp(rtk_trim(line_ptr), "H5LogOutput")) {
h5_log_enable = strtol(rtk_trim(split+1), &endptr, 0);
}
else if(!strcmp(rtk_trim(line_ptr), "RtkBtsnoopDump")) {
if(!strcmp(rtk_trim(split+1), "true"))
rtk_btsnoop_dump = true;
}
else if(!strcmp(rtk_trim(line_ptr), "RtkBtsnoopNetDump")) {
if(!strcmp(rtk_trim(split+1), "true"))
rtk_btsnoop_net_dump = true;
}
else if(!strcmp(rtk_trim(line_ptr), "BtSnoopFileName")) {
sprintf(rtk_btsnoop_path, "%s_rtk", rtk_trim(split+1));
}
else if(!strcmp(rtk_trim(line_ptr), "BtSnoopSaveLog")) {
if(!strcmp(rtk_trim(split+1), "true"))
rtk_btsnoop_save_log = true;
}
else if(!strcmp(rtk_trim(line_ptr), "BtCoexLogOutput")) {
coex_log_enable = strtol(rtk_trim(split+1), &endptr, 0);
}
else if(!strcmp(rtk_trim(line_ptr), "RtkBtAutoRestart")) {
if(!strcmp(rtk_trim(split+1), "true"))
rtkbt_auto_restart = true;
}
}
fclose(fp);
}
static void rtkbt_stack_conf_cleanup()
{
rtkbt_h5logfilter = 0;
h5_log_enable = 0;
rtk_btsnoop_dump = false;
rtk_btsnoop_net_dump = false;
}
static void load_rtkbt_conf()
{
char *split;
memset(rtkbt_device_node, 0, sizeof(rtkbt_device_node));
FILE *fp = fopen(RTKBT_CONF_FILE, "rt");
if (!fp) {
ALOGE("%s unable to open file '%s': %s", __func__, RTKBT_CONF_FILE, strerror(errno));
strcpy(rtkbt_device_node,"/dev/rtk_btusb");
return;
}
int line_num = 0;
char line[1024];
while (fgets(line, sizeof(line), fp)) {
char *line_ptr = rtk_trim(line);
++line_num;
// Skip blank and comment lines.
if (*line_ptr == '\0' || *line_ptr == '#' || *line_ptr == '[')
continue;
split = strchr(line_ptr, '=');
if (!split) {
ALOGE("%s no key/value separator found on line %d.", __func__, line_num);
strcpy(rtkbt_device_node,"/dev/rtk_btusb");
fclose(fp);
return;
}
*split = '\0';
if(!strcmp(rtk_trim(line_ptr), "BtDeviceNode")) {
strcpy(rtkbt_device_node, rtk_trim(split + 1));
}
}
fclose(fp);
rtkbt_transtype = 0;
if(rtkbt_device_node[0]=='?'){
/*1.Scan_Usb_Device*/
if(Scan_Usb_Devices_For_RTK(USB_DEVICE_DIR) == 0x01) {
strcpy(rtkbt_device_node,"/dev/rtk_btusb");
}
else{
int i = 0;
while(rtkbt_device_node[i] != '\0'){
rtkbt_device_node[i] = rtkbt_device_node[i+1];
i++;
}
}
}
if(split = strchr(rtkbt_device_node, ':')) {
*split = '\0';
if(!strcmp(rtk_trim(split + 1), "H5")) {
rtkbt_transtype |= RTKBT_TRANS_H5;
}
else if(!strcmp(rtk_trim(split + 1), "H4")) {
rtkbt_transtype |= RTKBT_TRANS_H4;
}
}
else if(strcmp(rtkbt_device_node, "/dev/rtk_btusb")) {
//default use h5
rtkbt_transtype |= RTKBT_TRANS_H5;
}
if(strcmp(rtkbt_device_node, "/dev/rtk_btusb")) {
rtkbt_transtype |= RTKBT_TRANS_UART;
}
else {
rtkbt_transtype |= RTKBT_TRANS_USB;
}
}
/*****************************************************************************
**
** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
**
*****************************************************************************/
static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
{
ALOGI("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
ALOGI("init");
load_rtkbt_conf();
load_rtkbt_stack_conf();
if (p_cb == NULL)
{
ALOGE("init failed with no user callbacks!");
return -1;
}
userial_vendor_init(rtkbt_device_node);
if(rtkbt_transtype & RTKBT_TRANS_UART) {
upio_init();
ALOGE("bt_wake_up_host_mode_set(1)");
bt_wake_up_host_mode_set(1);
}
/* store reference to user callbacks */
bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;
/* This is handed over from the stack */
memcpy(vnd_local_bd_addr, local_bdaddr, 6);
if(rtk_btsnoop_dump)
rtk_btsnoop_open();
if(rtk_btsnoop_net_dump)
rtk_btsnoop_net_open();
return 0;
}
/** Requested operations */
static int op(bt_vendor_opcode_t opcode, void *param)
{
int retval = 0;
//BTVNDDBG("op for %d", opcode);
switch(opcode)
{
case BT_VND_OP_POWER_CTRL:
{
if(rtkbt_transtype & RTKBT_TRANS_UART) {
int *state = (int *) param;
if (*state == BT_VND_PWR_OFF)
{
upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
usleep(200000);
BTVNDDBG("set power off and delay 200ms");
}
else if (*state == BT_VND_PWR_ON)
{
upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
usleep(200000);
BTVNDDBG("set power off and delay 200ms");
upio_set_bluetooth_power(UPIO_BT_POWER_ON);
usleep(200000);
BTVNDDBG("set power on and delay 200ms");
}
}
}
break;
case BT_VND_OP_FW_CFG:
{
if(rtkbt_transtype & RTKBT_TRANS_UART) {
hw_config_start(rtkbt_transtype);
}
else {
BTVNDDBG("usb op for %d", opcode);
ALOGE("Bt_vendor_rtk Op for BT_VND_OP_FW_CFG");
retval = userial_vendor_usb_ioctl(DOWN_FW_CFG, NULL);
if(retval>0){
ALOGE("Bt_vendor_rtk Download Fw Success");
bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
}else{
ALOGE("Bt_vendor_rtk Download Fw failed: %s(%d)", strerror(errno), errno);
if(rtkbt_auto_restart) {
bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
kill(getpid(), SIGKILL);
}
}
}
}
break;
case BT_VND_OP_SCO_CFG:
{
retval = -1;
}
break;
case BT_VND_OP_USERIAL_OPEN:
{
if((rtkbt_transtype & RTKBT_TRANS_UART) && (rtkbt_transtype & RTKBT_TRANS_H5)) {
int fd, idx;
int (*fd_array)[] = (int (*)[]) param;
if(userial_vendor_open((tUSERIAL_CFG *) &userial_H5_cfg) != -1){
retval = 1;
}
fd = userial_socket_open();
if (fd != -1)
{
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
}
else
retval = 0;
/* retval contains numbers of open fd of HCI channels */
}
else if((rtkbt_transtype & RTKBT_TRANS_UART) && (rtkbt_transtype & RTKBT_TRANS_H4)) {
int (*fd_array)[] = (int (*)[]) param;
int fd, idx;
if(userial_vendor_open((tUSERIAL_CFG *) &userial_H4_cfg) != -1) {
retval = 1;
}
fd = userial_socket_open();
if (fd != -1)
{
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
}
else
retval = 0;
/* retval contains numbers of open fd of HCI channels */
}
else {
BTVNDDBG("USB op for %d", opcode);
int fd, idx = 0;
int (*fd_array)[] = (int (*)[]) param;
for(idx = 0; idx < 10; idx++) {
if(userial_vendor_usb_open() != -1){
retval = 1;
break;
}
}
fd = userial_socket_open();
if (fd != -1)
{
for (idx = 0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
}
else
retval = 0;
}
}
break;
case BT_VND_OP_USERIAL_CLOSE:
{
userial_vendor_close();
}
break;
case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
{
}
break;
case BT_VND_OP_LPM_SET_MODE:
{
}
break;
case BT_VND_OP_LPM_WAKE_SET_STATE:
{
}
break;
case BT_VND_OP_EPILOG:
{
if(rtkbt_transtype & RTKBT_TRANS_USB) {
if (bt_vendor_cbacks)
{
bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
}
}
else {
#if (HW_END_WITH_HCI_RESET == FALSE)
if (bt_vendor_cbacks)
{
bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
}
#else
hw_epilog_process();
#endif
}
}
break;
default:
break;
}
return retval;
}
/** Closes the interface */
static void cleanup( void )
{
BTVNDDBG("cleanup");
if(rtkbt_transtype & RTKBT_TRANS_UART) {
upio_cleanup();
bt_wake_up_host_mode_set(0);
}
bt_vendor_cbacks = NULL;
if(rtk_btsnoop_dump)
rtk_btsnoop_close();
if(rtk_btsnoop_net_dump)
rtk_btsnoop_net_close();
rtkbt_stack_conf_cleanup();
}
// Entry point of DLib
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
sizeof(bt_vendor_interface_t),
init,
op,
cleanup
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,392 @@
/******************************************************************************
*
* Copyright (C) 2013 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#define LOG_TAG "rtk_btsnoop_net"
#include "rtk_btsnoop_net.h"
#include <pthread.h>
#include <unistd.h>
#define DATA_DIRECT_2_ELLISY 1
#define HCI_COMMAND 0x01
#define HCI_ACL_DATA_H2C 0x02
#define HCI_ACL_DATA_C2H 0x82
#define HCI_SCO_DATA_H2C 0x03
#define HCI_SCO_DATA_C2H 0x83
#define HCI_EVENT 0x84
#define HCI_COMMAND_PKT 0x01
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
unsigned int rtkbt_h5logfilter = 0x01;
bool rtk_btsnoop_dump = false;
bool rtk_btsnoop_net_dump = false;
bool rtk_btsnoop_save_log = false;
char rtk_btsnoop_path[1024] = {'\0'};
static pthread_mutex_t btsnoop_log_lock;
static void rtk_safe_close_(int *fd);
static void *rtk_listen_fn_(void *context);
static const char *RTK_LISTEN_THREAD_NAME_ = "rtk_btsnoop_net";
static const int RTK_LOCALHOST_ = 0xC0A80AE2; // 192.168.10.226
static const int RTK_LISTEN_PORT_ = 8872;
static const int RTK_REMOTEHOST_ = 0xC0A80A03; // 192.168.10.21
static const int RTK_REMOTE_PORT_ = 24352;
static pthread_t rtk_listen_thread_;
static bool rtk_listen_thread_valid_ = false;
static pthread_mutex_t rtk_client_socket_lock_ = PTHREAD_MUTEX_INITIALIZER;
static int rtk_listen_socket_ = -1;
// File descriptor for btsnoop file.
static int hci_btsnoop_fd = -1;
// Epoch in microseconds since 01/01/0000.
static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
static uint64_t rtk_btsnoop_timestamp(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
// Timestamp is in microseconds.
uint64_t timestamp = tv.tv_sec * 1000LL * 1000LL;
timestamp += tv.tv_usec;
timestamp += BTSNOOP_EPOCH_DELTA;
return timestamp;
}
void rtk_btsnoop_open()
{
pthread_mutex_init(&btsnoop_log_lock, NULL);
char last_log_path[PATH_MAX];
uint64_t timestamp;
uint32_t usec;
uint8_t sec,hour, minus,day;
if (hci_btsnoop_fd != -1) {
ALOGE("%s btsnoop log file is already open.", __func__);
return;
}
if(rtk_btsnoop_save_log) {
timestamp = rtk_btsnoop_timestamp() - BTSNOOP_EPOCH_DELTA;
usec = (uint32_t)(timestamp % 1000000LL);
timestamp /= 1000000LL;
sec = (uint8_t)(timestamp % 60LL);
timestamp /= 60LL;
minus = (uint8_t)(timestamp % 60LL);
timestamp /= 60LL;
hour = (uint8_t)(timestamp % 24LL);
timestamp /= 24LL;
day = (uint8_t)(timestamp % 30LL);
timestamp /= 30LL;
//snprintf(last_log_path, PATH_MAX, "%s.%llu", rtk_btsnoop_path, rtk_btsnoop_timestamp());
snprintf(last_log_path, PATH_MAX, "%s.%uY-%dD-%dH-%dM-%dS-%dUS", rtk_btsnoop_path,
(uint32_t)timestamp, day, hour, minus, sec, usec);
if (!rename(rtk_btsnoop_path, last_log_path) && errno != ENOENT)
ALOGE("%s unable to rename '%s' to '%s': %s", __func__, rtk_btsnoop_path, last_log_path, strerror(errno));
}
else {
snprintf(last_log_path, PATH_MAX, "%s.last", rtk_btsnoop_path);
if (!rename(rtk_btsnoop_path, last_log_path) && errno != ENOENT)
ALOGE("%s unable to rename '%s' to '%s': %s", __func__, rtk_btsnoop_path, last_log_path, strerror(errno));
}
hci_btsnoop_fd = open(rtk_btsnoop_path,
O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
if (hci_btsnoop_fd == -1) {
ALOGE("%s unable to open '%s': %s", __func__, rtk_btsnoop_path, strerror(errno));
return;
}
write(hci_btsnoop_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16);
}
void rtk_btsnoop_close(void) {
pthread_mutex_destroy(&btsnoop_log_lock);
if (hci_btsnoop_fd != -1)
close(hci_btsnoop_fd);
hci_btsnoop_fd = -1;
}
static void rtk_btsnoop_write(const void *data, size_t length) {
if (hci_btsnoop_fd != -1)
write(hci_btsnoop_fd, data, length);
}
static void rtk_btsnoop_write_packet(serial_data_type_t type, const uint8_t *packet, bool is_received) {
int length_he = 0;
int length;
int flags;
int drops = 0;
pthread_mutex_lock(&btsnoop_log_lock);
switch (type) {
case HCI_COMMAND_PKT:
length_he = packet[2] + 4;
flags = 2;
break;
case HCI_ACLDATA_PKT:
length_he = (packet[3] << 8) + packet[2] + 5;
flags = is_received;
break;
case HCI_SCODATA_PKT:
length_he = packet[2] + 4;
flags = is_received;
break;
case HCI_EVENT_PKT:
length_he = packet[1] + 3;
flags = 3;
break;
default:
break;
}
uint64_t timestamp = rtk_btsnoop_timestamp();
uint32_t time_hi = timestamp >> 32;
uint32_t time_lo = timestamp & 0xFFFFFFFF;
length = htonl(length_he);
flags = htonl(flags);
drops = htonl(drops);
time_hi = htonl(time_hi);
time_lo = htonl(time_lo);
rtk_btsnoop_write(&length, 4);
rtk_btsnoop_write(&length, 4);
rtk_btsnoop_write(&flags, 4);
rtk_btsnoop_write(&drops, 4);
rtk_btsnoop_write(&time_hi, 4);
rtk_btsnoop_write(&time_lo, 4);
rtk_btsnoop_write(&type, 1);
rtk_btsnoop_write(packet, length_he - 1);
pthread_mutex_unlock(&btsnoop_log_lock);
}
void rtk_btsnoop_capture(const HC_BT_HDR *p_buf, bool is_rcvd) {
const uint8_t *p = (const uint8_t *)(p_buf + 1) + p_buf->offset;
if (hci_btsnoop_fd == -1)
return;
switch (p_buf->event & MSG_EVT_MASK) {
case MSG_HC_TO_STACK_HCI_EVT:
if((*(p + 3) == 0x94) && (*(p + 4) == 0xfc) && (*(p + 5) == 0x00)&&(rtkbt_h5logfilter&1)){}
else
rtk_btsnoop_write_packet(HCI_EVENT_PKT, p, false);
break;
case MSG_HC_TO_STACK_HCI_ACL:
case MSG_STACK_TO_HC_HCI_ACL:
rtk_btsnoop_write_packet(HCI_ACLDATA_PKT, p, is_rcvd);
break;
case MSG_HC_TO_STACK_HCI_SCO:
case MSG_STACK_TO_HC_HCI_SCO:
rtk_btsnoop_write_packet(HCI_SCODATA_PKT, p, is_rcvd);
break;
case MSG_STACK_TO_HC_HCI_CMD:
if(((rtkbt_h5logfilter & 1) == 0) || (*p != 0x94) || (*(p + 1) != 0xfc))
rtk_btsnoop_write_packet(HCI_COMMAND_PKT, p, true);
break;
}
}
void rtk_btsnoop_net_open() {
rtk_listen_thread_valid_ = (pthread_create(&rtk_listen_thread_, NULL, rtk_listen_fn_, NULL) == 0);
if (!rtk_listen_thread_valid_) {
ALOGE("%s pthread_create failed: %s", __func__, strerror(errno));
} else {
ALOGD("initialized");
}
}
void rtk_btsnoop_net_close() {
if (rtk_listen_thread_valid_) {
shutdown(rtk_listen_socket_, SHUT_RDWR);
pthread_join(rtk_listen_thread_, NULL);
rtk_listen_thread_valid_ = false;
}
}
void rtk_btsnoop_net_write(serial_data_type_t type, uint8_t *data, bool is_received) {
if (rtk_listen_socket_ == -1) {
return;
}
int length = 0;
uint8_t *p = data;
switch (type) {
case HCI_COMMAND_PKT:
if(((rtkbt_h5logfilter & 1) == 0) || (*p != 0x94) || (*(p + 1) != 0xfc))
length = data[2] + 3;
else
return;
break;
case HCI_ACLDATA_PKT:
length = (data[3] << 8) + data[2] + 4;
break;
case HCI_SCODATA_PKT:
length = data[2] + 3;
break;
case HCI_EVENT_PKT:
if((*(p + 3) == 0x94) && (*(p + 4) == 0xfc) && (*(p + 5) == 0x00)&&(rtkbt_h5logfilter&1)){return;}
else
length = data[1] + 2;
break;
default:
break;
}
uint8_t buffer[4126] = {0};
//uint8_t test_buffer[] = {0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00};
//uint8_t test_buffer2[] = {0x01, 0x10, 0x00};
struct sockaddr_in client_addr;
int i = 0;
#if DATA_DIRECT_2_ELLISY
uint8_t bit_rate[4] = {0x00, 0x1b, 0x37, 0x4b};
struct tm *t;
time_t tt;
time(&tt);
t = localtime(&tt);
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t nano_time = (t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec) * 1000 * 1000LL * 1000 + tv.tv_usec * 1000;
uint16_t year = (t->tm_year + 1900) & 0xFFFF;
uint8_t month = (t->tm_mon+1) & 0xFF;
uint8_t day =
buffer[0] = 0x02;
buffer[1] = 0x00;
buffer[2] = 0x01;
buffer[3] = 0x02;
//time
memcpy(&buffer[4], &year, 2);
buffer[6] = month;
buffer[7] = day;
memcpy(&buffer[8], &nano_time, 6);
//bit rate
buffer[14] = 0x80;
memcpy(&buffer[15], bit_rate, 4);
//type
buffer[19] = 0x81;
i = 20;
#else
memcpy(&buffer[i], &length, sizeof(int));
i = 4;
#endif
switch (type) {
case HCI_COMMAND_PKT:
buffer[i] = HCI_COMMAND;
break;
case HCI_ACLDATA_PKT:
if(is_received) {
buffer[i] = HCI_ACL_DATA_C2H;
}
else {
buffer[i] = HCI_ACL_DATA_H2C;
}
break;
case HCI_SCODATA_PKT:
if(is_received) {
buffer[i] = HCI_SCO_DATA_C2H;
}
else {
buffer[i] = HCI_SCO_DATA_H2C;
}
break;
case HCI_EVENT_PKT:
buffer[i] = HCI_EVENT;
break;
default:
buffer[i] = 0;
break;
}
#if DATA_DIRECT_2_ELLISY
//buffer[i] = HCI_COMMAND;
buffer[21] = 0x82;
i = 22;
#else
i = 5;
#endif
memcpy(&buffer[i], data, length);
//memcpy(&buffer[i], test_buffer2, 3);
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(RTK_REMOTEHOST_);
client_addr.sin_port = htons(RTK_REMOTE_PORT_);
pthread_mutex_lock(&rtk_client_socket_lock_);
sendto(rtk_listen_socket_, buffer, (length+i), 0,(struct sockaddr*)&client_addr, sizeof(struct sockaddr_in));
//sendto(rtk_listen_socket_, buffer, 25, 0,(struct sockaddr*)&client_addr, sizeof(struct sockaddr_in));
pthread_mutex_unlock(&rtk_client_socket_lock_);
}
static void *rtk_listen_fn_(void *context) {
prctl(PR_SET_NAME, (unsigned long)RTK_LISTEN_THREAD_NAME_, 0, 0, 0);
rtk_listen_socket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (rtk_listen_socket_ == -1) {
ALOGE("%s socket creation failed: %s", __func__, strerror(errno));
goto cleanup;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(RTK_LOCALHOST_);
addr.sin_port = htons(RTK_LISTEN_PORT_);
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(RTK_REMOTEHOST_);
client_addr.sin_port = htons(RTK_REMOTE_PORT_);
if (bind(rtk_listen_socket_, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
ALOGE("%s unable to bind listen socket: %s", __func__, strerror(errno));
goto cleanup;
}
return NULL;
cleanup:
rtk_safe_close_(&rtk_listen_socket_);
return NULL;
}
static void rtk_safe_close_(int *fd) {
assert(fd != NULL);
if (*fd != -1) {
close(*fd);
*fd = -1;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,191 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: userial_vendor.c
*
* Description: Contains vendor-specific userial functions
*
******************************************************************************/
#undef NDEBUG
#define LOG_TAG "rtk_socket"
#include <utils/Log.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <sys/eventfd.h>
#include "userial.h"
#include "userial_vendor.h"
#include "rtk_socket.h"
/******************************************************************************
** Constants & Macros
******************************************************************************/
/******************************************************************************
** Extern functions
******************************************************************************/
/******************************************************************************
** Local type definitions
******************************************************************************/
/******************************************************************************
** Static functions
******************************************************************************/
/******************************************************************************
** functions
******************************************************************************/
uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len)
{
int n_read = 0;
struct pollfd pfd;
if (fd == -1)
{
return 0;
}
while (n_read < (int)len)
{
pfd.fd = fd;
pfd.events = POLLIN|POLLHUP;
/* make sure there is data prior to attempting read to avoid blocking
a read for more than poll timeout */
int poll_ret;
RTK_NO_INTR(poll_ret = poll(&pfd, 1, 100));
if (poll_ret == 0)
{
continue;
}
if (poll_ret < 0) {
ALOGE("%s(): poll() failed: return %d errno %d (%s)",
__func__, poll_ret, errno, strerror(errno));
break;
}
if (pfd.revents & (POLLHUP|POLLNVAL) )
{
return 0;
}
ssize_t n;
RTK_NO_INTR(n = recv(fd, p_buf + n_read, len - n_read, 0));
if (n == 0)
{
ALOGE("Skt_Read : channel detached remotely");
return 0;
}
if (n < 0)
{
ALOGE("Skt_Read : read failed (%s)", strerror(errno));
return 0;
}
n_read += n;
}
return n_read;
}
int Skt_Read_noblock(int fd, uint8_t *p_buf, uint32_t len)
{
int n_read = 0;
struct pollfd pfd;
if (fd == -1)
{
ALOGE("UIPC_Read_noblock closed");
return 0;
}
pfd.fd = fd;
pfd.events = POLLIN|POLLHUP;
if (poll(&pfd, 1, 0) == 0)
{
return 0;
}
if (pfd.revents & (POLLHUP|POLLNVAL) )
{
return 0;
}
n_read = recv(fd, p_buf, len, MSG_DONTWAIT|MSG_NOSIGNAL);
return n_read;
}
bool Skt_Send(int fd, uint8_t *p_buf, uint16_t msglen)
{
ssize_t ret;
RTK_NO_INTR(ret = write(fd, p_buf, msglen));
if (ret < 0) {
ALOGE("failed to write (%s)", strerror(errno));
}
return false;
}
int Skt_Send_noblock(int fd, uint8_t *p_buf, uint16_t msglen)
{
int res = 0;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT|POLLHUP;
if (poll(&pfd, 1, 0) == 0)
{
return 0;
}
if (pfd.revents & (POLLHUP|POLLNVAL) )
{
ALOGE("poll : channel detached remotely");
return 0;
}
res = send(fd, p_buf, msglen, MSG_DONTWAIT);
if (res < 0)
{
ALOGE("failed to write (%s)", strerror(errno));
}
return res;
}
/******************************************************************************
** Static variables
******************************************************************************/
/*****************************************************************************
** Helper Functions
*****************************************************************************/

View file

@ -0,0 +1,532 @@
/******************************************************************************
*
* Copyright (C) 2009-2012 Realtek Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Filename: upio.c
*
* Description: Contains I/O functions, like
* rfkill control
* BT_WAKE/HOST_WAKE control
*
******************************************************************************/
#define LOG_TAG "bt_upio"
#include <utils/Log.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/properties.h>
#include "bt_vendor_rtk.h"
#include "upio.h"
#include "userial_vendor.h"
/******************************************************************************
** Constants & Macros
******************************************************************************/
#ifndef UPIO_DBG
#define UPIO_DBG FALSE
#endif
#if (UPIO_DBG == TRUE)
#define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
#else
#define UPIODBG(param, ...) {}
#endif
/******************************************************************************
** Local type definitions
******************************************************************************/
#if (BT_WAKE_VIA_PROC == TRUE)
/* proc fs node for enable/disable lpm mode */
#ifndef VENDOR_LPM_PROC_NODE
#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
#endif
/* proc fs node for notifying write request */
#ifndef VENDOR_BTWRITE_PROC_NODE
#define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
#endif
/*
* Maximum btwrite assertion holding time without consecutive btwrite kicking.
* This value is correlative(shorter) to the in-activity timeout period set in
* the bluesleep LPM code. The current value used in bluesleep is 10sec.
*/
#ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS
#define PROC_BTWRITE_TIMER_TIMEOUT_MS 8000
#endif
/* lpm proc control block */
typedef struct
{
uint8_t btwrite_active;
uint8_t timer_created;
timer_t timer_id;
uint32_t timeout_ms;
} vnd_lpm_proc_cb_t;
static vnd_lpm_proc_cb_t lpm_proc_cb;
#endif
/******************************************************************************
** Static variables
******************************************************************************/
static uint8_t upio_state[UPIO_MAX_COUNT];
static int rfkill_id = -1;
static int bt_emul_enable = 0;
static char *rfkill_state_path = NULL;
/******************************************************************************
** Static functions
******************************************************************************/
/* for friendly debugging outpout string */
static char *lpm_mode[] = {
"UNKNOWN",
"disabled",
"enabled"
};
static char *lpm_state[] = {
"UNKNOWN",
"de-asserted",
"asserted"
};
/*****************************************************************************
** Bluetooth On/Off Static Functions
*****************************************************************************/
static int is_emulator_context(void)
{
char value[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", value, "0");
UPIODBG("is_emulator_context : %s", value);
if (strcmp(value, "1") == 0) {
return 1;
}
return 0;
}
static int is_rfkill_disabled(void)
{
char value[PROPERTY_VALUE_MAX];
property_get("ro.rfkilldisabled", value, "0");
UPIODBG("is_rfkill_disabled ? [%s]", value);
if (strcmp(value, "1") == 0) {
return UPIO_BT_POWER_ON;
}
return UPIO_BT_POWER_OFF;
}
static int init_rfkill()
{
char path[64];
char buf[16];
int fd, sz, id;
if (is_rfkill_disabled())
return -1;
for (id = 0; ; id++)
{
snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
fd = open(path, O_RDONLY);
if (fd < 0)
{
ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \
path, strerror(errno), errno);
return -1;
}
sz = read(fd, &buf, sizeof(buf));
close(fd);
if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0)
{
rfkill_id = id;
break;
}
}
asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
return 0;
}
int bt_wake_up_host_mode_set(uint8_t mode)
{
char path[64];
char buffer = '0';
int sz;
int fd = -1;
int ret = -1;
ALOGE("bt_wake_up_host_mode_set");
snprintf(path, sizeof(path), "/proc/bluetooth/sleep/lpm");
ALOGE("bt_wake_up_host_mode_set path:%s", path);
fd = open(path, O_WRONLY);
if (fd < 0)
{
ALOGE("bt_wake_up_host_mode_set fd:%d = open(path, O_RDWR): open(%s) failed: %s (%d)\n", \
fd, path, strerror(errno), errno);
return -1;
}
ALOGE("bt_wake_up_host_mode_set fd:%d = open(path, O_RDWR): open(%s) success\n", \
fd, path);
if(mode == 1)
{
buffer = '1';
} else {
buffer = '0';
}
ALOGE("bt_wake_up_host_mode_set buffer:%d", buffer);
sz = write(fd, &buffer, 1);
if (sz < 0) {
ALOGE("bt_wake_up_host_mode_set : write(%s) failed: %s (%d)",
rfkill_state_path, strerror(errno),errno);
}
else
ret = 0;
if (fd >= 0)
close(fd);
return ret;
}
/*****************************************************************************
** LPM Static Functions
*****************************************************************************/
#if (BT_WAKE_VIA_PROC == TRUE)
/*******************************************************************************
**
** Function proc_btwrite_timeout
**
** Description Timeout thread of proc/.../btwrite assertion holding timer
**
** Returns None
**
*******************************************************************************/
static void proc_btwrite_timeout(union sigval arg)
{
UPIODBG("..%s..", __FUNCTION__);
lpm_proc_cb.btwrite_active = FALSE;
}
#endif
/*****************************************************************************
** UPIO Interface Functions
*****************************************************************************/
/*******************************************************************************
**
** Function upio_init
**
** Description Initialization
**
** Returns None
**
*******************************************************************************/
void upio_init(void)
{
memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
#if (BT_WAKE_VIA_PROC == TRUE)
memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
#endif
}
/*******************************************************************************
**
** Function upio_cleanup
**
** Description Clean up
**
** Returns None
**
*******************************************************************************/
void upio_cleanup(void)
{
#if (BT_WAKE_VIA_PROC == TRUE)
if (lpm_proc_cb.timer_created == TRUE)
timer_delete(lpm_proc_cb.timer_id);
lpm_proc_cb.timer_created = FALSE;
#endif
}
/*******************************************************************************
**
** Function upio_set_bluetooth_power
**
** Description Interact with low layer driver to set Bluetooth power
** on/off.
**
** Returns 0 : SUCCESS or Not-Applicable
** <0 : ERROR
**
*******************************************************************************/
int upio_set_bluetooth_power(int on)
{
int sz;
int fd = -1;
int ret = -1;
char buffer = '0';
switch(on)
{
case UPIO_BT_POWER_OFF:
buffer = '0';
break;
case UPIO_BT_POWER_ON:
buffer = '1';
break;
}
if (is_emulator_context())
{
/* if new value is same as current, return -1 */
if (bt_emul_enable == on)
return ret;
UPIODBG("set_bluetooth_power [emul] %d", on);
bt_emul_enable = on;
return 0;
}
/* check if we have rfkill interface */
if (is_rfkill_disabled())
return 0;
if (rfkill_id == -1)
{
if (init_rfkill())
return ret;
}
fd = open(rfkill_state_path, O_WRONLY);
if (fd < 0)
{
ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)",
rfkill_state_path, strerror(errno), errno);
return ret;
}
sz = write(fd, &buffer, 1);
if (sz < 0) {
ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)",
rfkill_state_path, strerror(errno),errno);
}
else
ret = 0;
if (fd >= 0)
close(fd);
return ret;
}
/*******************************************************************************
**
** Function upio_set
**
** Description Set i/o based on polarity
**
** Returns None
**
*******************************************************************************/
void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
{
int rc;
#if (BT_WAKE_VIA_PROC == TRUE)
int fd = -1;
char buffer;
#endif
switch (pio)
{
case UPIO_LPM_MODE:
if (upio_state[UPIO_LPM_MODE] == action)
{
UPIODBG("LPM is %s already", lpm_mode[action]);
return;
}
upio_state[UPIO_LPM_MODE] = action;
#if (BT_WAKE_VIA_PROC == TRUE)
fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY);
if (fd < 0)
{
ALOGE("upio_set : open(%s) for write failed: %s (%d)",
VENDOR_LPM_PROC_NODE, strerror(errno), errno);
return;
}
if (action == UPIO_ASSERT)
{
buffer = '1';
}
else
{
buffer = '0';
// delete btwrite assertion holding timer
if (lpm_proc_cb.timer_created == TRUE)
{
timer_delete(lpm_proc_cb.timer_id);
lpm_proc_cb.timer_created = FALSE;
}
}
if (write(fd, &buffer, 1) < 0)
{
ALOGE("upio_set : write(%s) failed: %s (%d)",
VENDOR_LPM_PROC_NODE, strerror(errno),errno);
}
else
{
if (action == UPIO_ASSERT)
{
// create btwrite assertion holding timer
if (lpm_proc_cb.timer_created == FALSE)
{
int status;
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
se.sigev_notify_function = proc_btwrite_timeout;
se.sigev_notify_attributes = NULL;
status = timer_create(CLOCK_MONOTONIC, &se,
&lpm_proc_cb.timer_id);
if (status == 0)
lpm_proc_cb.timer_created = TRUE;
}
}
}
if (fd >= 0)
close(fd);
#endif
break;
case UPIO_BT_WAKE:
if (upio_state[UPIO_BT_WAKE] == action)
{
UPIODBG("BT_WAKE is %s already", lpm_state[action]);
#if (BT_WAKE_VIA_PROC == TRUE)
if (lpm_proc_cb.btwrite_active == TRUE)
/*
* The proc btwrite node could have not been updated for
* certain time already due to heavy downstream path flow.
* In this case, we want to explicity touch proc btwrite
* node to keep the bt_wake assertion in the LPM kernel
* driver. The current kernel bluesleep LPM code starts
* a 10sec internal in-activity timeout timer before it
* attempts to deassert BT_WAKE line.
*/
#endif
return;
}
upio_state[UPIO_BT_WAKE] = action;
#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
NULL);
#elif (BT_WAKE_VIA_PROC == TRUE)
/*
* Kick proc btwrite node only at UPIO_ASSERT
*/
if (action == UPIO_DEASSERT)
return;
fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY);
if (fd < 0)
{
ALOGE("upio_set : open(%s) for write failed: %s (%d)",
VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno);
return;
}
buffer = '1';
if (write(fd, &buffer, 1) < 0)
{
ALOGE("upio_set : write(%s) failed: %s (%d)",
VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
}
else
{
lpm_proc_cb.btwrite_active = TRUE;
if (lpm_proc_cb.timer_created == TRUE)
{
struct itimerspec ts;
ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000;
ts.it_value.tv_nsec = 1000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000);
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0);
}
}
UPIODBG("proc btwrite assertion");
if (fd >= 0)
close(fd);
#endif
break;
case UPIO_HOST_WAKE:
UPIODBG("upio_set: UPIO_HOST_WAKE");
break;
}
}

File diff suppressed because it is too large Load diff