mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-25 21:48:54 +00:00
822 lines
28 KiB
C
822 lines
28 KiB
C
|
|
/**
|
|||
|
|
******************************************************************************
|
|||
|
|
* @file hgics_blenc.c
|
|||
|
|
* @author HUGE-IC Application Team
|
|||
|
|
* @version V1.0.0
|
|||
|
|
* @date 2022-05-18
|
|||
|
|
* @brief hgic BLE network configure lib
|
|||
|
|
******************************************************************************
|
|||
|
|
* @attention
|
|||
|
|
*
|
|||
|
|
* <h2><center>© COPYRIGHT 2022 HUGE-IC</center></h2>
|
|||
|
|
*
|
|||
|
|
******************************************************************************
|
|||
|
|
*/
|
|||
|
|
#ifndef __RTOS__
|
|||
|
|
#include <error.h>
|
|||
|
|
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
#include <stdarg.h>
|
|||
|
|
#include <errno.h>
|
|||
|
|
#include <time.h>
|
|||
|
|
#include <unistd.h>
|
|||
|
|
#include <sys/types.h>
|
|||
|
|
#include <sys/stat.h>
|
|||
|
|
#include <fcntl.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
#include <sys/time.h>
|
|||
|
|
#include <sys/socket.h>
|
|||
|
|
#include <sys/types.h>
|
|||
|
|
#include <netinet/in.h>
|
|||
|
|
#include <netinet/tcp.h>
|
|||
|
|
#include <arpa/inet.h>
|
|||
|
|
#include <netdb.h>
|
|||
|
|
#include <poll.h>
|
|||
|
|
#else
|
|||
|
|
#include <linux/defs.h>
|
|||
|
|
#include <linux/types.h>
|
|||
|
|
#endif
|
|||
|
|
#include "hgic.h"
|
|||
|
|
|
|||
|
|
#define ATT_MTU (512)
|
|||
|
|
|
|||
|
|
#define BT_L2CAP_HDR_SIZE (4)
|
|||
|
|
#define HCI_CONN_HANDLE (1)
|
|||
|
|
#define HCI_ACL_HDR_SIZE (4)
|
|||
|
|
#define HCI_ACL_DATA_PACKET (2)
|
|||
|
|
#define HGICS_GATT_CHARAC_Broadcast (0x01)
|
|||
|
|
#define HGICS_GATT_CHARAC_Read (0x02)
|
|||
|
|
#define HGICS_GATT_CHARAC_Write_Without_Response (0x04)
|
|||
|
|
#define HGICS_GATT_CHARAC_Write (0x08)
|
|||
|
|
#define HGICS_GATT_CHARAC_Notify (0x10)
|
|||
|
|
#define HGICS_GATT_CHARAC_Indicate (0x20)
|
|||
|
|
#define HGICS_GATT_CHARAC_Authenticated_Signed_Writes (0x40)
|
|||
|
|
#define HGICS_GATT_CHARAC_Extended_Properties (0x80)
|
|||
|
|
|
|||
|
|
#define BLENC_STR_CUTDOWN_BUFFER_LEN (1024)
|
|||
|
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|||
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|||
|
|
int hgic_gatt_notify(uint16_t att_hdl, char *data, int len);
|
|||
|
|
|
|||
|
|
typedef int (*hgic_gatt_valhdl)(int hdl, int offset, char *data, int len);
|
|||
|
|
struct hgic_gatt_hdr {
|
|||
|
|
uint16_t att_hdl;
|
|||
|
|
union {
|
|||
|
|
uint8_t att_type_128[16];
|
|||
|
|
uint16_t att_type;
|
|||
|
|
};
|
|||
|
|
uint16_t priv_type;
|
|||
|
|
};
|
|||
|
|
struct hgic_gatt_primary_service {
|
|||
|
|
struct hgic_gatt_hdr hdr;
|
|||
|
|
union {
|
|||
|
|
uint8_t att_type_128[16];
|
|||
|
|
uint16_t att_type;
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
struct hgic_gatt_characteristic {
|
|||
|
|
struct hgic_gatt_hdr hdr;
|
|||
|
|
uint8_t properties;
|
|||
|
|
uint16_t value_hdl;
|
|||
|
|
union {
|
|||
|
|
uint8_t value_type_128[16];
|
|||
|
|
uint16_t value_type;
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
struct hgic_gatt_characteristic_value {
|
|||
|
|
struct hgic_gatt_hdr hdr;
|
|||
|
|
hgic_gatt_valhdl read_cb;
|
|||
|
|
hgic_gatt_valhdl write_cb;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_PRIMARY_SVR(hdl, type) struct hgic_gatt_primary_service att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = (hdl), \
|
|||
|
|
.att_type = 0x2800,\
|
|||
|
|
.priv_type = 1,\
|
|||
|
|
}, \
|
|||
|
|
.att_type = (type),\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_PRIMARY_SVR_128(hdl, type_128) struct hgic_gatt_primary_service att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = (hdl), \
|
|||
|
|
.att_type = 0x2800,\
|
|||
|
|
.priv_type = 11,\
|
|||
|
|
}, \
|
|||
|
|
.att_type_128 = type_128,\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_CHARACTER(hdl, flag, v_hdl, v_type) struct hgic_gatt_characteristic att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = (hdl), \
|
|||
|
|
.att_type = 0x2803,\
|
|||
|
|
.priv_type = 2,\
|
|||
|
|
}, \
|
|||
|
|
.properties = (flag),\
|
|||
|
|
.value_hdl = (v_hdl),\
|
|||
|
|
.value_type = (v_type),\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_CHARACTER_128(hdl, flag, v_hdl, v_type_128) struct hgic_gatt_characteristic att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = hdl, \
|
|||
|
|
.att_type = 0x2803,\
|
|||
|
|
.priv_type = 21,\
|
|||
|
|
}, \
|
|||
|
|
.properties = flag,\
|
|||
|
|
.value_hdl = v_hdl,\
|
|||
|
|
.value_type_128 = v_type_128,\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_CHARACTER_VALUE(hdl, type, read, write) struct hgic_gatt_characteristic_value att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = (hdl), \
|
|||
|
|
.att_type = (type),\
|
|||
|
|
.priv_type = 4,\
|
|||
|
|
}, \
|
|||
|
|
.read_cb = (read),\
|
|||
|
|
.write_cb = (write),\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_CHARACTER_VALUE_128(hdl, type_128, read, write) struct hgic_gatt_characteristic_value att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = hdl, \
|
|||
|
|
.att_type_128 = type_128,\
|
|||
|
|
.priv_type = 41,\
|
|||
|
|
}, \
|
|||
|
|
.read_cb = read,\
|
|||
|
|
.write_cb = write,\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#define HGICS_GATT_CHARACTER_CCCD(hdl, read, write) struct hgic_gatt_characteristic_value att##hdl = {\
|
|||
|
|
.hdr = { \
|
|||
|
|
.att_hdl = (hdl), \
|
|||
|
|
.att_type = (0x2902),\
|
|||
|
|
.priv_type = 4,\
|
|||
|
|
}, \
|
|||
|
|
.read_cb = (read),\
|
|||
|
|
.write_cb = (write),\
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
static inline void put_unaligned_le16(unsigned short val, unsigned char *p)
|
|||
|
|
{
|
|||
|
|
*p++ = val;
|
|||
|
|
*p++ = val >> 8;
|
|||
|
|
}
|
|||
|
|
static inline unsigned short get_unaligned_le16(const unsigned char *p)
|
|||
|
|
{
|
|||
|
|
return p[0] | p[1] << 8;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
int ble_connected = 0;
|
|||
|
|
int att_mtu = 23;
|
|||
|
|
int mtu_exchanged = 0;
|
|||
|
|
int ble_ll_length = 27;
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
/* Define GATT Service --- Demo Service */
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////
|
|||
|
|
extern int demo_app_recv_attdata(int hdl, int offset, char *data, int len);
|
|||
|
|
extern int demo_app_read_attdata(int hdl, int offset, char *data, int len);
|
|||
|
|
|
|||
|
|
/* ͨ<><CDA8>UUID<49>Ķ<EFBFBD><C4B6>壬<EFBFBD>ο<EFBFBD><CEBF>ĵ<EFBFBD><C4B5><EFBFBD>BLE_Assigned_Numbers.pdf<64><66>, section 3: 16-bit UUIDs*/
|
|||
|
|
|
|||
|
|
/* Primary Service 1 */
|
|||
|
|
HGICS_GATT_PRIMARY_SVR(1, 0x1800);
|
|||
|
|
HGICS_GATT_CHARACTER(2, HGICS_GATT_CHARAC_Read, 3, 0x2a00);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE(3, 0x2a00, demo_app_read_attdata, NULL);
|
|||
|
|
HGICS_GATT_CHARACTER(4, HGICS_GATT_CHARAC_Read, 5, 0x2a01);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE(5, 0x2a01, demo_app_read_attdata, NULL);
|
|||
|
|
|
|||
|
|
/* Primary Service 2 */
|
|||
|
|
#if 0 //demo1, UUID 128
|
|||
|
|
#define server_uuid {0x00,0x00,0x18,0x2c,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0x80,0x5f,0x9b,0x34,0xfb}
|
|||
|
|
#define data_uuid {0x00,0x00,0x2A,0x7A,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0x80,0x5f,0x9b,0x34,0xfb}
|
|||
|
|
#define notity_uuid {0x00,0x00,0x2A,0x80,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0x80,0x5f,0x9b,0x34,0xfb}
|
|||
|
|
HGICS_GATT_PRIMARY_SVR_128(6, server_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_128(7, HGICS_GATT_CHARAC_Write_Without_Response, 8, data_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE_128(8, data_uuid, demo_app_read_attdata, demo_app_recv_attdata);
|
|||
|
|
HGICS_GATT_CHARACTER_128(9, HGICS_GATT_CHARAC_Notify, 10, notity_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE_128(10, notity_uuid, NULL, NULL);
|
|||
|
|
HGICS_GATT_CHARACTER_CCCD(11, NULL, NULL);
|
|||
|
|
#endif
|
|||
|
|
#if 0 //demo2, UUID 128
|
|||
|
|
#define server_uuid {0x06,0x05,0x04,0x03,0x02,0x01,0x03,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x36}
|
|||
|
|
#define data_uuid {0x06,0x05,0x04,0x03,0x02,0x01,0x03,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x36}
|
|||
|
|
#define notity_uuid {0x06,0x05,0x04,0x03,0x02,0x01,0x03,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0x00,0x36}
|
|||
|
|
HGICS_GATT_PRIMARY_SVR_128(6, server_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_128(7, HGICS_GATT_CHARAC_Write_Without_Response, 8, data_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE_128(8, data_uuid, demo_app_read_attdata, demo_app_recv_attdata);
|
|||
|
|
HGICS_GATT_CHARACTER_128(9, HGICS_GATT_CHARAC_Notify, 10, notity_uuid);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE_128(10, notity_uuid, NULL, NULL);
|
|||
|
|
HGICS_GATT_CHARACTER_CCCD(11, NULL, NULL);
|
|||
|
|
#endif
|
|||
|
|
#if 0 //demo 3: UUID 128
|
|||
|
|
HGICS_GATT_PRIMARY_SVR(6, 0x1912);
|
|||
|
|
HGICS_GATT_CHARACTER(7, HGICS_GATT_CHARAC_Read|HGICS_GATT_CHARAC_Write, 8, 0x2b13);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE(8, 0x2b13, demo_app_read_attdata, demo_app_recv_attdata);
|
|||
|
|
#define UUID1 {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}
|
|||
|
|
HGICS_GATT_CHARACTER_128(7, HGICS_GATT_CHARAC_Write_Without_Response, 8, UUID1);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE_128(8, UUID1, demo_app_read_attdata, demo_app_recv_attdata);
|
|||
|
|
#endif
|
|||
|
|
#if 1 //default demo: UUID 16
|
|||
|
|
HGICS_GATT_PRIMARY_SVR(6, 0x1912);
|
|||
|
|
HGICS_GATT_CHARACTER(7, HGICS_GATT_CHARAC_Read|HGICS_GATT_CHARAC_Write, 8, 0x2b13);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE(8, 0x2b13, demo_app_read_attdata, demo_app_recv_attdata);
|
|||
|
|
HGICS_GATT_CHARACTER(9, HGICS_GATT_CHARAC_Notify, 10, 0x2b10);
|
|||
|
|
HGICS_GATT_CHARACTER_VALUE(10, 0x2b10, NULL, NULL);
|
|||
|
|
HGICS_GATT_CHARACTER_CCCD(11, NULL, NULL);
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
static struct hgic_gatt_hdr *att_table[] = { (struct hgic_gatt_hdr *)&att1,
|
|||
|
|
(struct hgic_gatt_hdr *)&att2,
|
|||
|
|
(struct hgic_gatt_hdr *)&att3,
|
|||
|
|
(struct hgic_gatt_hdr *)&att4,
|
|||
|
|
(struct hgic_gatt_hdr *)&att5,
|
|||
|
|
(struct hgic_gatt_hdr *)&att6,
|
|||
|
|
(struct hgic_gatt_hdr *)&att7,
|
|||
|
|
(struct hgic_gatt_hdr *)&att8,
|
|||
|
|
(struct hgic_gatt_hdr *)&att9,
|
|||
|
|
(struct hgic_gatt_hdr *)&att10,
|
|||
|
|
(struct hgic_gatt_hdr *)&att11
|
|||
|
|
};
|
|||
|
|
static char test_read_data[ATT_MTU]={0};
|
|||
|
|
int demo_app_read_attdata(int hdl, int offset, char *data, int len)
|
|||
|
|
{
|
|||
|
|
//setup test data.
|
|||
|
|
if(test_read_data[0] == 0){
|
|||
|
|
int i = 0;
|
|||
|
|
for(i=0; i<ATT_MTU; i++){
|
|||
|
|
test_read_data[i] = 0x41+(i/10);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int ret = 0;
|
|||
|
|
switch (hdl) {
|
|||
|
|
case 8:
|
|||
|
|
ret = (ATT_MTU-offset) < len ? (ATT_MTU-offset) : len;
|
|||
|
|
if(ret > 0){
|
|||
|
|
memcpy(data, test_read_data+offset, ret);
|
|||
|
|
}
|
|||
|
|
printf("hdl 8 read, offset=%d, len=%d\r\n", offset, ret);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
sprintf(data, "hdl %d NULL Value", hdl);
|
|||
|
|
ret = strlen(data);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int demo_app_recv_attdata(int hdl, int offset, char *data, int len)
|
|||
|
|
{
|
|||
|
|
#if 1 //sample code
|
|||
|
|
char *ssid, *psk, *keymgmt;
|
|||
|
|
uint8_t cmd[64];
|
|||
|
|
//char out[128];
|
|||
|
|
extern char *HGIC;
|
|||
|
|
|
|||
|
|
printf("hdl %d recv data, len = %d, offset=%d\r\n", hdl, len, offset);
|
|||
|
|
if (hdl == 8 && data[0] == ':') {
|
|||
|
|
ssid = data + 1;
|
|||
|
|
psk = strchr(ssid, ',');
|
|||
|
|
if(psk == NULL) return -1;
|
|||
|
|
*psk++ = 0;
|
|||
|
|
keymgmt = strchr(psk, ',');
|
|||
|
|
if(keymgmt == NULL) return -1;
|
|||
|
|
*keymgmt++ = 0;
|
|||
|
|
|
|||
|
|
printf("SET ssid:%s\r\n", ssid);
|
|||
|
|
hgics_wpacli_set_ssid("hg0", ssid);
|
|||
|
|
|
|||
|
|
printf("SET passwd:%s\r\n", psk);
|
|||
|
|
hgics_wpacli_set_psk("hg0", psk);
|
|||
|
|
|
|||
|
|
printf("SET keymgmt:%s\r\n", keymgmt[0] == '1' ? "WPA-PSK" : "NONE");
|
|||
|
|
hgics_wpacli_set_keymgmt("hg0", keymgmt[0] ? "WPA-PSK" : "NONE");
|
|||
|
|
|
|||
|
|
hgic_blenc_release();
|
|||
|
|
|
|||
|
|
hgic_iwpriv_blenc_start("hg0", 0, 38);
|
|||
|
|
|
|||
|
|
hgics_wpacli_disable_network(
"hg0");
|
|||
|
|
hgics_wpacli_enable_network("hg0");
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_notify_test()
|
|||
|
|
{
|
|||
|
|
static int __loop__ = 0;
|
|||
|
|
static int __value__ = 0;
|
|||
|
|
|
|||
|
|
int notify_hdl = 10;
|
|||
|
|
char notify_data[ATT_MTU];
|
|||
|
|
|
|||
|
|
__loop__++;
|
|||
|
|
if(ble_connected && __loop__ > 50){
|
|||
|
|
__loop__ = 0;
|
|||
|
|
memset(notify_data, 'A'+__value__, att_mtu-3);
|
|||
|
|
__value__ = (__value__ >= 26 ? 0 : __value__+1);
|
|||
|
|
hgic_gatt_notify(notify_hdl, notify_data, att_mtu-3);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
int hgic_gatt_send_frag(char *att_data, int len, int tot_len, int first)
|
|||
|
|
{
|
|||
|
|
int off = 0;
|
|||
|
|
int bc = 0;
|
|||
|
|
int pb = first ? 0 : 1;
|
|||
|
|
int ret = -ENOMEM;
|
|||
|
|
char *data = malloc(ble_ll_length+HCI_ACL_HDR_SIZE+4);
|
|||
|
|
if(data == NULL){
|
|||
|
|
printf("malloc fail, ble_ll_length=%d\r\n", ble_ll_length);
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 0 - Connection handle
|
|||
|
|
put_unaligned_le16(HCI_CONN_HANDLE|(pb<<12)|(bc<<14), data+off); off += 2;
|
|||
|
|
// 2 - ACL length
|
|||
|
|
put_unaligned_le16(len + 4u, data+off); off += 2;
|
|||
|
|
|
|||
|
|
if(first){
|
|||
|
|
// 4 - L2CAP packet length: tot_len
|
|||
|
|
put_unaligned_le16(tot_len, data+off); off += 2;
|
|||
|
|
// 6 - L2CAP CID
|
|||
|
|
put_unaligned_le16(0x04, data+off); off += 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
memcpy(data+off, att_data, len); off += len;
|
|||
|
|
ret = hgic_iwpriv_blenc_send_hcidata("hg0", HCI_ACL_DATA_PACKET, data, off);
|
|||
|
|
//printf(" -->send ble frag, len=%d\r\n", len);
|
|||
|
|
|
|||
|
|
free(data);
|
|||
|
|
return ret >= 0 ? len : 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int hgic_gatt_send_data(char *att_data, int tot_len)
|
|||
|
|
{
|
|||
|
|
int flen;
|
|||
|
|
int off = 0;
|
|||
|
|
|
|||
|
|
//hgic_dump_hex("\r\nSEND:\r\n", att_data, tot_len, 1);
|
|||
|
|
while(off < tot_len){
|
|||
|
|
flen = ((off==0)?(ble_ll_length-4):ble_ll_length);
|
|||
|
|
flen = (tot_len-off)>flen?flen:(tot_len-off);
|
|||
|
|
flen = hgic_gatt_send_frag(att_data+off, flen, tot_len, (off==0));
|
|||
|
|
if(flen <= 0) break;
|
|||
|
|
off += flen;
|
|||
|
|
}
|
|||
|
|
return off;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// att_hdl: the CHARACTER_VALUE's handle that has Notify properties.
|
|||
|
|
int hgic_gatt_notify(uint16_t att_hdl, char *data, int len)
|
|||
|
|
{
|
|||
|
|
int ret = -ENOMEM;
|
|||
|
|
char buff[ATT_MTU];
|
|||
|
|
|
|||
|
|
if(len > att_mtu - 3){
|
|||
|
|
printf("BLE: data len exceed MTU size! MTU is %d\r\n", att_mtu);
|
|||
|
|
return -E2BIG;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
buff[0] = 0x1B;
|
|||
|
|
put_unaligned_le16(att_hdl, buff + 1);
|
|||
|
|
memcpy(buff + 3, data, len);
|
|||
|
|
printf("att hdl %d notify data, len:%d.\r\n", att_hdl, len);
|
|||
|
|
return hgic_gatt_send_data(buff, 3 + len);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_send_ATT_ERROR(uint8_t opcode, uint16_t atthandle, uint8_t err_code)
|
|||
|
|
{
|
|||
|
|
uint8_t buff[5];
|
|||
|
|
buff[0] = 0x01;
|
|||
|
|
buff[1] = opcode;
|
|||
|
|
put_unaligned_le16(atthandle, buff + 2);
|
|||
|
|
buff[4] = err_code;
|
|||
|
|
hgic_gatt_send_data( buff, 5);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_send_PREPARE_WRITE_RESP(uint8_t *req, uint16_t len)
|
|||
|
|
{
|
|||
|
|
req[0] = 0x17;
|
|||
|
|
hgic_gatt_send_data(req, len);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_EXCUTE_WRITE(uint8_t req)
|
|||
|
|
{
|
|||
|
|
uint8_t opcode = 0x19;
|
|||
|
|
hgic_gatt_send_data(&opcode, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_send_EXCHANGE_MTU(uint8_t opcode)
|
|||
|
|
{
|
|||
|
|
uint8_t buff[5];
|
|||
|
|
buff[0] = opcode;
|
|||
|
|
put_unaligned_le16(ATT_MTU, buff + 1);
|
|||
|
|
hgic_gatt_send_data(buff, 3);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_EXCHANGE_MTU(uint32_t mtu, uint8_t req)
|
|||
|
|
{
|
|||
|
|
if(mtu < 23) mtu = 23;
|
|||
|
|
att_mtu = MIN(mtu, ATT_MTU);
|
|||
|
|
mtu_exchanged = 1;
|
|||
|
|
printf("new ATT MTU %d\r\n", att_mtu);
|
|||
|
|
if(req){
|
|||
|
|
hgic_gatt_send_EXCHANGE_MTU(0x03);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_READ_REQ(uint16_t att_hdl, uint32_t offset, uint8_t opcode)
|
|||
|
|
{
|
|||
|
|
int i = 0;
|
|||
|
|
int len = -1;
|
|||
|
|
char resp[ATT_MTU];
|
|||
|
|
struct hgic_gatt_characteristic_value *v;
|
|||
|
|
|
|||
|
|
resp[0] = opcode + 1;
|
|||
|
|
for (i = 0; i < ARRAY_SIZE(att_table); i++) {
|
|||
|
|
if (att_table[i]->att_hdl == att_hdl && (att_table[i]->priv_type == 4 || att_table[i]->priv_type == 41)) {
|
|||
|
|
v = (struct hgic_gatt_characteristic_value *)att_table[i];
|
|||
|
|
if (v->read_cb) {
|
|||
|
|
len = v->read_cb(att_table[i]->att_hdl, offset, resp + 1, att_mtu-1);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (len >= 0) {
|
|||
|
|
hgic_gatt_send_data(resp, 1 + len);
|
|||
|
|
} else {
|
|||
|
|
printf("==>ATT_NOT_FOUND: att_hdl=%d\r\n", att_hdl);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(opcode, att_hdl, 0x0a);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_WRITE(uint16_t att_hdl, uint32_t offset, char *att_value, int value_len, uint8_t resp)
|
|||
|
|
{
|
|||
|
|
int i = 0;
|
|||
|
|
struct hgic_gatt_characteristic_value *v;
|
|||
|
|
|
|||
|
|
for (i = 0; i < ARRAY_SIZE(att_table); i++) {
|
|||
|
|
if (att_table[i]->att_hdl == att_hdl && (att_table[i]->priv_type == 4 || att_table[i]->priv_type == 41)) {
|
|||
|
|
v = (struct hgic_gatt_characteristic_value *)att_table[i];
|
|||
|
|
if (v->write_cb) {
|
|||
|
|
v->write_cb(att_table[i]->att_hdl, offset, att_value, value_len);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (resp) {
|
|||
|
|
hgic_gatt_send_data(&resp, 1);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
printf("==>ATT_NOT_FOUND: att_hdl=%d, resp=0x%x\r\n", att_hdl, resp & 0xff);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(resp, att_hdl, 0x0a);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_FIND_INFORMATION_REQ(uint16_t start_hdl, uint16_t end_hdl)
|
|||
|
|
{
|
|||
|
|
int i = 0;
|
|||
|
|
int off = 2;
|
|||
|
|
char buff[ATT_MTU];
|
|||
|
|
int item_len = 0;
|
|||
|
|
int parse_end = 0;
|
|||
|
|
|
|||
|
|
buff[0] = 0x05;
|
|||
|
|
buff[1] = 0x1;
|
|||
|
|
|
|||
|
|
for (i = 0; buff[1] && i < ARRAY_SIZE(att_table) && !parse_end; i++) {
|
|||
|
|
if (att_table[i]->att_hdl >= start_hdl && att_table[i]->att_hdl <= end_hdl) {
|
|||
|
|
if (item_len == 0) {
|
|||
|
|
item_len = (att_table[i]->priv_type == 21 || att_table[i]->priv_type == 41) ? 18 : 4;
|
|||
|
|
} else if (item_len != ((att_table[i]->priv_type == 21 || att_table[i]->priv_type == 41) ? 18 : 4)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (att_table[i]->priv_type == 21 || att_table[i]->priv_type == 41) { //uuid 128
|
|||
|
|
put_unaligned_le16(att_table[i]->att_hdl, buff + off); off += 2;
|
|||
|
|
memcpy(buff + off, att_table[i]->att_type_128, 16); off += 16;
|
|||
|
|
}else{ // uuid 16
|
|||
|
|
put_unaligned_le16(att_table[i]->att_hdl, buff + off); off += 2;
|
|||
|
|
put_unaligned_le16(att_table[i]->att_type, buff + off); off += 2;
|
|||
|
|
}
|
|||
|
|
if (off > (att_mtu - item_len)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (off > 2) {
|
|||
|
|
buff[1] = (item_len == 4 ? 0x1 : 02); //foramt
|
|||
|
|
hgic_gatt_send_data(buff, off);
|
|||
|
|
} else {
|
|||
|
|
printf("==>ATT_NOT_FOUND: start_hdl=%d, end_hdl=%d\r\n", start_hdl, end_hdl);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(0x04, start_hdl, 0x0a);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_READ_BY_TYPE_REQ(uint16_t start_hdl, uint16_t end_hdl, uint16_t att_type)
|
|||
|
|
{
|
|||
|
|
int item_len = 0;
|
|||
|
|
int i = 0;
|
|||
|
|
int off = 2;
|
|||
|
|
char buff[ATT_MTU];
|
|||
|
|
int parse_end = 0;
|
|||
|
|
struct hgic_gatt_characteristic *c;
|
|||
|
|
|
|||
|
|
buff[0] = 0x09;
|
|||
|
|
for (i = 0; i < ARRAY_SIZE(att_table) && !parse_end; i++) {
|
|||
|
|
if (att_table[i]->att_hdl >= start_hdl && att_table[i]->att_hdl <= end_hdl && att_table[i]->att_type == att_type) {
|
|||
|
|
switch (att_type) {
|
|||
|
|
case 0x2803: /*read Characteristic*/
|
|||
|
|
c = (struct hgic_gatt_characteristic *)att_table[i];
|
|||
|
|
if (item_len == 0) {
|
|||
|
|
item_len = (c->hdr.priv_type == 21 || c->hdr.priv_type == 41) ? 21 : 7;
|
|||
|
|
} else if (item_len != ((c->hdr.priv_type == 21 || c->hdr.priv_type == 41) ? 21 : 7)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (c->hdr.priv_type == 21 || c->hdr.priv_type == 41) { //uuid 128
|
|||
|
|
put_unaligned_le16(c->hdr.att_hdl, buff + off); off += 2;
|
|||
|
|
buff[off] = c->properties; off += 1;
|
|||
|
|
put_unaligned_le16(c->value_hdl, buff + off); off += 2;
|
|||
|
|
memcpy(buff + off, c->value_type_128, 16); off += 16;
|
|||
|
|
}else{ // uuid 16
|
|||
|
|
put_unaligned_le16(c->hdr.att_hdl, buff + off); off += 2;
|
|||
|
|
buff[off] = c->properties; off += 1;
|
|||
|
|
put_unaligned_le16(c->value_hdl, buff + off); off += 2;
|
|||
|
|
put_unaligned_le16(c->value_type, buff + off); off += 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (off > (att_mtu - item_len)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (off > 2) {
|
|||
|
|
buff[1] = item_len;
|
|||
|
|
hgic_gatt_send_data(buff, off);
|
|||
|
|
} else {
|
|||
|
|
printf("==>ATT_NOT_FOUND: start_hdl=%d, end_hdl=%d, att_type=0x%x\r\n", start_hdl, end_hdl, att_type);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(0x08, start_hdl, 0x0a);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_gatt_READ_BY_GROUP_TYPE_REQ(uint16_t start_hdl, uint16_t end_hdl, uint16_t group_type)
|
|||
|
|
{
|
|||
|
|
int item_len = 0;
|
|||
|
|
int off = 2;
|
|||
|
|
int i = 0;
|
|||
|
|
char buff[ATT_MTU];
|
|||
|
|
int start_idx = -1;
|
|||
|
|
int end_indx = -1;
|
|||
|
|
int parse_end = 0;
|
|||
|
|
struct hgic_gatt_primary_service *p;
|
|||
|
|
|
|||
|
|
buff[0] = 0x11;
|
|||
|
|
buff[1] = 0;
|
|||
|
|
for (i = 0; i < ARRAY_SIZE(att_table) && !parse_end; i++) {
|
|||
|
|
if (att_table[i]->att_hdl >= start_hdl && att_table[i]->att_hdl <= end_hdl) {
|
|||
|
|
switch (group_type) {
|
|||
|
|
case 0x2800: /*read Primary Service*/
|
|||
|
|
if (att_table[i]->att_type == 0x2800) { //find a primary service
|
|||
|
|
if (end_indx > 0) { //last group end
|
|||
|
|
p = (struct hgic_gatt_primary_service *)att_table[start_idx];
|
|||
|
|
put_unaligned_le16(att_table[end_indx]->att_hdl, buff + off); off += 2;
|
|||
|
|
if (p->hdr.priv_type == 11) { // uuid 128
|
|||
|
|
memcpy(buff+off, p->att_type_128, 16); off += 16;
|
|||
|
|
} else { // uuid 16
|
|||
|
|
put_unaligned_le16(p->att_type, buff + off); off += 2;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (item_len == 0) {
|
|||
|
|
item_len = (att_table[i]->priv_type == 11 ? 20 : 6);
|
|||
|
|
} else if (item_len != (att_table[i]->priv_type == 11 ? 20 : 6)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
start_idx = -1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (off > (att_mtu - item_len)) {
|
|||
|
|
parse_end = 1;
|
|||
|
|
start_idx = -1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
start_idx = i; //new group start
|
|||
|
|
put_unaligned_le16(att_table[start_idx]->att_hdl, buff + off); off += 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (start_idx >= 0) end_indx = i;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (off > 2) {
|
|||
|
|
buff[1] = item_len;
|
|||
|
|
if (start_idx >= 0) {
|
|||
|
|
p = (struct hgic_gatt_primary_service *)att_table[start_idx];
|
|||
|
|
put_unaligned_le16(att_table[end_indx]->att_hdl, buff + off); off += 2;
|
|||
|
|
if (p->hdr.priv_type == 11) { // uuid 128
|
|||
|
|
memcpy(buff+off, p->att_type_128, 16); off += 16;
|
|||
|
|
} else { // uuid 16
|
|||
|
|
put_unaligned_le16(p->att_type, buff + off); off += 2;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
hgic_gatt_send_data(buff, off);
|
|||
|
|
} else {
|
|||
|
|
printf("==>ATT_NOT_FOUND: start_hdl=%d, end_hdl=%d, att_type=0x%x\r\n", start_hdl, end_hdl, group_type);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(0x10, start_hdl, 0x0a);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hgic_recv_ble_gatt_data(char *data, int len)
|
|||
|
|
{
|
|||
|
|
unsigned char opcode = data[0];
|
|||
|
|
printf("recv att data, opcode=0x%x\r\n", opcode);
|
|||
|
|
switch (opcode) {
|
|||
|
|
case 0x02: //EXCHANGE_MTU_REQ
|
|||
|
|
hgic_gatt_EXCHANGE_MTU(get_unaligned_le16(data + 1), 1);
|
|||
|
|
break;
|
|||
|
|
case 0x03: //EXCHANGE_MTU_RESP
|
|||
|
|
hgic_gatt_EXCHANGE_MTU(get_unaligned_le16(data + 1), 0);
|
|||
|
|
break;
|
|||
|
|
case 0x04: //FIND_INFORMATION_REQ
|
|||
|
|
hgic_gatt_FIND_INFORMATION_REQ(get_unaligned_le16(data + 1),
|
|||
|
|
get_unaligned_le16(data + 3));
|
|||
|
|
break;
|
|||
|
|
case 0x06: //FIND_BY_TYPE_VALUE_REQ
|
|||
|
|
printf("==>FIND_BY_TYPE_VALUE_REQ: not support\r\n");
|
|||
|
|
hgic_gatt_send_ATT_ERROR(opcode, get_unaligned_le16(data + 1), 0x06);
|
|||
|
|
break;
|
|||
|
|
case 0x08: //READ_BY_TYPE_REQ
|
|||
|
|
hgic_gatt_READ_BY_TYPE_REQ(get_unaligned_le16(data + 1),
|
|||
|
|
get_unaligned_le16(data + 3),
|
|||
|
|
get_unaligned_le16(data + 5));
|
|||
|
|
break;
|
|||
|
|
case 0x0A: //READ_REQ
|
|||
|
|
hgic_gatt_READ_REQ(get_unaligned_le16(data + 1), 0, 0x0A);
|
|||
|
|
break;
|
|||
|
|
case 0x0C: //READ_BLOB_REQ
|
|||
|
|
hgic_gatt_READ_REQ(get_unaligned_le16(data + 1), get_unaligned_le16(data + 3), 0x0C);
|
|||
|
|
break;
|
|||
|
|
case 0x0e: //READ_MULTIPLE_REQ
|
|||
|
|
printf("==>READ_MULTIPLE_REQ: not support\r\n");
|
|||
|
|
hgic_gatt_send_ATT_ERROR(opcode, get_unaligned_le16(data + 1), 0x06);
|
|||
|
|
break;
|
|||
|
|
case 0x10: // READ_BY_GROUP_TYPE_REQ
|
|||
|
|
hgic_gatt_READ_BY_GROUP_TYPE_REQ(get_unaligned_le16(data + 1),
|
|||
|
|
get_unaligned_le16(data + 3),
|
|||
|
|
get_unaligned_le16(data + 5));
|
|||
|
|
break;
|
|||
|
|
case 0x12: //WRITE_REQ
|
|||
|
|
hgic_gatt_WRITE(get_unaligned_le16(data + 1), 0, data + 3, len - 3, 0x13);
|
|||
|
|
break;
|
|||
|
|
case 0x16: //PREPARE_WRITE_REQ
|
|||
|
|
hgic_gatt_WRITE(get_unaligned_le16(data + 1), get_unaligned_le16(data + 3), data + 5, len - 5, 0);
|
|||
|
|
hgic_gatt_send_PREPARE_WRITE_RESP(data, len);
|
|||
|
|
break;
|
|||
|
|
case 0x18: //EXECUTE_WRITE_REQ
|
|||
|
|
hgic_gatt_EXCUTE_WRITE(data[1]);
|
|||
|
|
break;
|
|||
|
|
case 0x52: //WRITE_CMD
|
|||
|
|
hgic_gatt_WRITE(get_unaligned_le16(data + 1), 0, data + 3, len - 3, 0);
|
|||
|
|
break;
|
|||
|
|
case 0xD2: //SIGNED_WRITE_CMD
|
|||
|
|
printf("==>SIGNED_WRITE_CMD: not support\r\n");
|
|||
|
|
hgic_gatt_send_ATT_ERROR(opcode, get_unaligned_le16(data + 1), 0x06);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
printf("==>unknow opcode: %x: not support\r\n", opcode);
|
|||
|
|
hgic_gatt_send_ATT_ERROR(opcode, get_unaligned_le16(data + 1), 0x06);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(mtu_exchanged == 0){
|
|||
|
|
hgic_gatt_send_EXCHANGE_MTU(0x02);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hgic_recv_l2cap_data(char type, char *data, int len)
|
|||
|
|
{
|
|||
|
|
static char frag_buff[ATT_MTU];
|
|||
|
|
static int frag_len = 0;
|
|||
|
|
static int tot_len = 0;
|
|||
|
|
int hdr_len;
|
|||
|
|
int hdr_cid;
|
|||
|
|
|
|||
|
|
if (tot_len == 0) {
|
|||
|
|
hdr_len = get_unaligned_le16(data);
|
|||
|
|
hdr_cid = get_unaligned_le16(data + 2);
|
|||
|
|
if (hdr_cid != 0x4) {
|
|||
|
|
printf("%s,%d:Not ATT DATA\n",__FUNCTION__,__LINE__);
|
|||
|
|
frag_len = tot_len = 0;
|
|||
|
|
return; // Is not ATT data.
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
data += BT_L2CAP_HDR_SIZE;
|
|||
|
|
len -= BT_L2CAP_HDR_SIZE;
|
|||
|
|
tot_len = hdr_len;
|
|||
|
|
frag_len = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (frag_len + len > ATT_MTU) {
|
|||
|
|
printf("ATT_MTU is not enough. L2CAP_PKTSIZE_MAX=%d, frag_len=%d, len=%d\r\n", ATT_MTU, frag_len, len);
|
|||
|
|
frag_len = tot_len = 0;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
memcpy(frag_buff + frag_len, data, len);
|
|||
|
|
frag_len += len;
|
|||
|
|
if (frag_len >= tot_len) {
|
|||
|
|
hgic_dump_hex("\r\nRECV:\r\n", frag_buff, frag_len, 1);
|
|||
|
|
hgic_recv_ble_gatt_data(frag_buff, frag_len);
|
|||
|
|
frag_len = tot_len = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hgic_recv_ble_event(char *data, int len)
|
|||
|
|
{
|
|||
|
|
switch (data[2]) {
|
|||
|
|
case 0x1:
|
|||
|
|
att_mtu = 23;
|
|||
|
|
mtu_exchanged = 0;
|
|||
|
|
ble_connected = 1;
|
|||
|
|
ble_ll_length = 27;
|
|||
|
|
printf("BLE Connected\r\n");
|
|||
|
|
//hgic_gatt_notify_test();
|
|||
|
|
break;
|
|||
|
|
case 0x07:
|
|||
|
|
ble_ll_length = get_unaligned_le16(data+3);
|
|||
|
|
printf("BLE Exchange LL_LENGTH: tx=%d, rx=%d\r\n", get_unaligned_le16(data+3), get_unaligned_le16(data+5));
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hgic_recv_bt_event(char *data, int len)
|
|||
|
|
{
|
|||
|
|
switch (data[0]) {
|
|||
|
|
case 0x05:
|
|||
|
|
att_mtu = 23;
|
|||
|
|
mtu_exchanged = 0;
|
|||
|
|
ble_connected = 0;
|
|||
|
|
ble_ll_length = 27;
|
|||
|
|
printf("Disconnect\r\n");
|
|||
|
|
break;
|
|||
|
|
case 0x3e:
|
|||
|
|
hgic_recv_ble_event(data, len);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
printf("%s,%d:Recv unknow evt:0x%x\n",__FUNCTION__,__LINE__,data[0]);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void hgic_proc_bt_data(char *data, int len)
|
|||
|
|
{
|
|||
|
|
extern struct hgic_fw_info hgic_fwinfo;
|
|||
|
|
struct hgic_ctrl_hdr *hdr = (struct hgic_ctrl_hdr *)data;
|
|||
|
|
|
|||
|
|
data += sizeof(struct hgic_ctrl_hdr);
|
|||
|
|
len -= sizeof(struct hgic_ctrl_hdr);
|
|||
|
|
switch (hdr->hci.type) {
|
|||
|
|
case 0x02: // ACL data
|
|||
|
|
if (hgic_fwinfo.version > 0x02040000) {
|
|||
|
|
data += sizeof(struct bt_rx_info);
|
|||
|
|
len -= sizeof(struct bt_rx_info);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
data += HCI_ACL_HDR_SIZE;
|
|||
|
|
len -= HCI_ACL_HDR_SIZE;
|
|||
|
|
//hgic_dump_hex("BT ACL DATA:\r\n", data, len, 1);
|
|||
|
|
//hgic_dump_hex("ORI DATA:\r\n", hdr, len + sizeof(struct hgic_ctrl_hdr), 1);
|
|||
|
|
hgic_recv_l2cap_data(hdr->hci.type, data, len);
|
|||
|
|
break;
|
|||
|
|
case 0x04: // Event
|
|||
|
|
hgic_recv_bt_event(data, len);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|