源码编译分析:
=================================================================================
相关蓝牙库
=================================================================================
shared_sources = src/shared/io.h src/shared/timeout.h \
src/shared/queue.h src/shared/queue.c \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/crypto.h src/shared/crypto.c \
src/shared/ecc.h src/shared/ecc.c \
src/shared/ringbuf.h src/shared/ringbuf.c \
src/shared/tester.h src/shared/tester.c \
src/shared/hci.h src/shared/hci.c \
src/shared/hci-crypto.h src/shared/hci-crypto.c \
src/shared/hfp.h src/shared/hfp.c \
src/shared/uhid.h src/shared/uhid.c \
src/shared/pcap.h src/shared/pcap.c \
src/shared/btsnoop.h src/shared/btsnoop.c \
src/shared/ad.h src/shared/ad.c \
src/shared/att-types.h \
src/shared/att.h src/shared/att.c \
src/shared/gatt-helpers.h src/shared/gatt-helpers.c \
src/shared/gatt-client.h src/shared/gatt-client.c \
src/shared/gatt-server.h src/shared/gatt-server.c \
src/shared/gatt-db.h src/shared/gatt-db.c \
src/shared/gap.h src/shared/gap.c \
src/shared/tty.hsrc_libshared_glib_la_SOURCES = $(shared_sources) \
src/shared/io-glib.c \
src/shared/timeout-glib.csrc_libshared_mainloop_la_SOURCES = $(shared_sources) \
src/shared/io-mainloop.c \
src/shared/timeout-mainloop.c \
src/shared/mainloop.h src/shared/mainloop.csrc_libshared_glib_la_SOURCES与src_libshared_mainloop_la_SOURCES要分开编译
=================================================================================
Bluetooth Attribute
=================================================================================
参考 << gatttool >>
#define ATT_CID 4
#define ATT_PSM 31main:
bluez-attribute
if (opt_primary)
operation = primary;
else if (opt_characteristics)
operation = characteristics;
else if (opt_char_read)
operation = characteristics_read;
else if (opt_char_write)
operation = characteristics_write;
else if (opt_char_write_req)
operation = characteristics_write_req;
else if (opt_char_desc)
operation = characteristics_desc;
chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
opt_psm, opt_mtu, connect_cb, &gerr);
bt_io_connect
case BT_IO_L2CAP:
err = l2cap_connect(sock, &opts.dst, opts.dst_type,
opts.psm, opts.cid);
break;
case BT_IO_RFCOMM:
err = rfcomm_connect(sock, &opts.dst, opts.channel);
break;
case BT_IO_SCO:
err = sco_connect(sock, &opts.dst);
connect_cb
operation(attrib);=================================================================================
Bluetooth periperhal ver 5.45
=================================================================================static const struct {
const char *fstype;
const char *target;
const char *options;
unsigned long flags;
} mount_table[] = {
{ "sysfs", "/sys", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
{ "proc", "/proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
{ "devtmpfs", "/dev", NULL, MS_NOSUID|MS_STRICTATIME },
{ "efivarfs", "/sys/firmware/efi/efivars",
NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
{ "pstore", "/sys/fs/pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
{ }
};static const struct {
const char *target;
const char *linkpath;
} dev_table[] = {
{ "/proc/self/fd", "/dev/fd" },
{ "/proc/self/fd/0", "/dev/stdin" },
{ "/proc/self/fd/1", "/dev/stdout" },
{ "/proc/self/fd/2", "/dev/stderr" },
{ }
};=================================================================================
Bluetooth monitor
=================================================================================./btmon -h
btmon - Bluetooth monitor
Usage:
btmon [options]
options:
-r, --readRead traces in btsnoop format
-w, --writeSave traces in btsnoop format
-a, --analyzeAnalyze traces in btsnoop format
-s, --serverStart monitor server socket
-p, --priorityShow only priority or lower
-i, --indexShow only specified controller
-d, --ttyRead data from TTY
-B, --tty-speedSet TTY speed (default 115200)
-t, --time Show time instead of time offset
-T, --date Show time and date information
-S, --sco Dump SCO traffic
-A, --a2dp Dump A2DP stream traffic
-E, --ellisys [ip] Send Ellisys HCI Injection
-h, --help Show help optionsoptions:
-r
-E, --ellisys [ip]
ellisys_enable
control_reader
case BTSNOOP_FORMAT_HCI/BTSNOOP_FORMAT_UART/BTSNOOP_FORMAT_MONITOR:
packet_monitor
case BTSNOOP_OPCODE_COMMAND_PKT:
packet_hci_command
case BTSNOOP_OPCODE_EVENT_PKT:
packet_hci_event
case BTSNOOP_OPCODE_ACL_TX_PKT:
case BTSNOOP_OPCODE_ACL_RX_PKT:
packet_hci_acldata
l2cap_packet
case BTSNOOP_OPCODE_SCO_TX_PKT:
packet_hci_scodata
case BTSNOOP_OPCODE_CTRL_[OPEN|CLOSE|COMMAND|EVENT]:
packet_ctrl_*
ellisys_inject_hci
case BTSNOOP_FORMAT_SIMULATOR:
packet_simulator
ll_packet
advertising_packet
ADV_IND ADV_DIRECT_IND ADV_NONCONN_IND SCAN_REQ SCAN_RSP CONNECT_REQ ADV_SCAN_IND
data_packet
llcp_packet
llcp_data->func此处有回调:数据发完之后的处理回调?
-s
control_server
mainloop_add_fd(socket_fd, server_accept_callback)
server_accept_callback
mainloop_add_fd(accept_fd, client_callback)
client_callback
packet_monitor=================================================================================
Bluetooth Socket
=================================================================================/* Create L2CAP socket */
l2cap_sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); // #define BTPROTO_L2CAP 0 // lib/bluetooth.h
/* Create local Unix socket */
unix_sock = socket(PF_UNIX, SOCK_STREAM, 0);
sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); // #define BTPROTO_RFCOMM 3 // lib/bluetooth.h// 1. rfcomm
ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
// 2. hcidump hciconfig
/* Create HCI socket */
sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); // #define BTPROTO_HCI 1 // BTPROTO_HCI本地与hci通信交互
// 3. ciptool
ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_CMTP) // #define BTPROTO_CMTP 5typedef struct {
uint8_t type;
union {
uint16_t uuid16;
uint32_t uuid32;
uint128_t uuid128;
} value;
} uuid_t;/* BD Address */
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;typedef struct {
uint8_t data[16];
} uint128_t;/* BD Address type */
#define BDADDR_BREDR 0x00
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7#define SOL_HCI 0
#define SOL_L2CAP 6
#define SOL_SCO 17
#define SOL_RFCOMM 18#define SOL_BLUETOOTH 274
#define BT_SECURITY 4
#define MAX_LEN_UUID_STR 37
=================================================================================
GOptionContext
=================================================================================
struct _GOptionEntry
{
const gchar *long_name;
gchar short_name;
gint flags;GOptionArg arg;
gpointer arg_data;
const gchar *description;
const gchar *arg_description;
};struct _GOptionGroup
{
gchar *name;
gchar *description;
gchar *help_description;gint ref_count;
GDestroyNotify destroy_notify;
gpointer user_data;GTranslateFunc translate_func;
GDestroyNotify translate_notify;
gpointer translate_data;GOptionEntry *entries;
gint n_entries;GOptionParseFunc pre_parse_func;
GOptionParseFunc post_parse_func;
GOptionErrorFunc error_func;
};struct _GOptionContext
{
GList *groups;gchar *parameter_string;
gchar *summary;
gchar *description;GTranslateFunc translate_func;
GDestroyNotify translate_notify;
gpointer translate_data;guint help_enabled : 1;
guint ignore_unknown : 1;
guint strv_mode : 1;
guint strict_posix : 1;GOptionGroup *main_group;
/* We keep a list of change so we can revert them */
GList *changes;/* We also keep track of all argv elements
* that should be NULLed or modified.
*/
GList *pending_nulls;
};struct _GError
{
GQuark domain;
gint code;
gchar *message;
};=================================================================================
GMainLoop
=================================================================================
struct _GMainLoop
{
GMainContext *context;
gboolean is_running;
gint ref_count;
};struct _GMainContext
{
/* The following lock is used for both the list of sources
* and the list of poll records
*/
GMutex mutex;
GCond cond;
GThread *owner;
guint owner_count;
GSList *waiters;gint ref_count;
GHashTable *sources; /* guint -> GSource */
GPtrArray *pending_dispatches;
gint timeout; /* Timeout for current iteration */guint next_id;
GList *source_lists;
gboolean in_check_or_prepare;
gboolean need_wakeup;GPollRec *poll_records;
guint n_poll_records;
GPollFD *cached_poll_array;
guint cached_poll_array_size;GWakeup *wakeup;
GPollFD wake_up_rec;
/* Flag indicating whether the set of fd's changed during a poll */
gboolean poll_changed;GPollFunc poll_func;
gint64 time;
gboolean time_is_fresh;
};=================================================================================
DBUS GDBUS
=================================================================================
g_dbus_client_set_ready_watch(client, client_ready, NULL);
g_dbus_client_set_proxy_handlers
get_managed_objectsg_dbus_client_new
g_dbus_client_new_full
client->watch = g_dbus_add_service_watch(connection, service,
service_connect,
service_disconnect,
client, NULL);
service_connect
get_managed_objects
dbus_pending_call_set_notify(client->get_objects_call,
get_managed_objects_reply,
client, NULL);
get_managed_objects_reply ->
if (client->ready)
client->ready(client, client->ready_data);
=================================================================================
gatt-service.c
=================================================================================
attrib/gatt-service.c => bluetoothd*
attrib_sources <- src_bluetoothd_SOURCES <- SOURCES
am__src_bluetoothd_SOURCES_DIST <- DIST_SOURCES <- DISTFILES <- distdir-am: $(DISTFILES)tools/gatt-service.c => ./tools/gatt-service*
=================================================================================
emulator
=================================================================================
serial_open
open_pty
enum serial_type {
SERIAL_TYPE_BREDRLE,
SERIAL_TYPE_BREDR,
SERIAL_TYPE_LE,
SERIAL_TYPE_AMP,
};
bt_le_new
vhci_read_callback
process_command
=================================================================================
btgatt
=================================================================================
share/mainloop.c
api>>>
share/mainloop.h
ps:
signal>>>
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
mainloop_set_signal(&mask, signal_cb, NULL, NULL);
static void signal_cb(int signum, void *user_data)
{
switch (signum) {
case SIGINT:
case SIGTERM:
mainloop_quit();
break;
default:
break;
}
}tools/用法
btgatt-server.c
ready...
l2cap_le_att_listen_and_accept(bdaddr_t *src, int sec, uint8_t src_type)
// src:当前蓝牙设备地址; sec:BT_SECURITY_LOW/BT_SECURITY_MEDIUM/BT_SECURITY_HIGH; src_type:BDADDR_LE_RANDOM/BDADDR_LE_PUBLIC
struct sockaddr_l2 srcaddr, addr; // srcaddr : 当前蓝牙设备地址相关信息.
// addr : 请求连接的蓝牙设备地址相关信息.
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);/* Set up source address */
memset(&srcaddr, 0, sizeof(srcaddr));
srcaddr.l2_family = AF_BLUETOOTH;
srcaddr.l2_cid = htobs(ATT_CID); // #define ATT_CID 4
srcaddr.l2_bdaddr_type = src_type;
bacpy(&srcaddr.l2_bdaddr, src); // lib/bluetooth.h/* Set the security level */
if (bind(sk, (struct sockaddr *) &srcaddr, sizeof(srcaddr)) < 0) {}
if (listen(sk, 10) < 0) {}
int nsk = accept(sk, (struct sockaddr *) &addr, &optlen);char ba[18];
ba2str(&addr.l2_bdaddr, ba); // lib/bluetooth.h
printf("Connect from %s\n", ba);working...
btgatt-client.c
ready...
l2cap_le_att_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type, int sec)
// src_addr:当前蓝牙设备地址; dst:所连接的server蓝牙地址
struct sockaddr_l2 srcaddr, dstaddr; // srcaddr : 当前蓝牙设备地址相关信息.
// dstaddr : 请求连接的蓝牙设备地址相关信息.
sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);/* Set up source address */
memset(&srcaddr, 0, sizeof(srcaddr));
srcaddr.l2_family = AF_BLUETOOTH;
srcaddr.l2_cid = htobs(ATT_CID);
srcaddr.l2_bdaddr_type = 0;
bacpy(&srcaddr.l2_bdaddr, src);/* Set the security level */
/* Set up destination address */
memset(&dstaddr, 0, sizeof(dstaddr));
dstaddr.l2_family = AF_BLUETOOTH;
dstaddr.l2_cid = htobs(ATT_CID);
dstaddr.l2_bdaddr_type = dst_type;
bacpy(&dstaddr.l2_bdaddr, dst);if (connect(sock, (struct sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) {}
working...
建立连接后,server与client之间是如何交互的?
server:
自定义了一个结构体server
struct server {
int fd;
struct bt_att *att; // 存储回调接口相关
struct gatt_db *db; // 存储service相关
struct bt_gatt_server *gatt; // 封装上面两个uint8_t *device_name;
size_t name_len;uint16_t gatt_svc_chngd_handle;
bool svc_chngd_enabled;uint16_t hr_handle;
uint16_t hr_msrmt_handle;
uint16_t hr_energy_expended;
bool hr_visible;
bool hr_msrmt_enabled;
int hr_ee_count;
unsigned int hr_timeout_id;
};client:
自定义了一个结构体client
struct client {
int fd;
struct bt_att *att; // 存储回调接口相关
struct gatt_db *db; // [mtu交换,]发现服务(discovery_op)
struct bt_gatt_client *gatt; // 封装上面两个unsigned int reliable_session_id;
};=================================================================================
bt_att-gatt_db-bt_gatt_client
=================================================================================
struct bt_att {
int ref_count;
int fd;
struct io *io; // io-mainloop.c中有一个 io-glib.c中也有一个
bool io_on_l2cap;
int io_sec_level; /* Only used for non-L2CAP */struct queue *req_queue; /* Queued ATT protocol requests */
struct att_send_op *pending_req;
struct queue *ind_queue; /* Queued ATT protocol indications */
struct att_send_op *pending_ind;
struct queue *write_queue; /* Queue of PDUs ready to send */
bool writer_active;struct queue *notify_list; /* List of registered callbacks */
struct queue *disconn_list; /* List of disconnect handlers */bool in_req; /* There's a pending incoming request */
uint8_t *buf;
uint16_t mtu;unsigned int next_send_id; /* IDs for "send" ops */
unsigned int next_reg_id; /* IDs for registered callbacks */bt_att_timeout_func_t timeout_callback;
bt_att_destroy_func_t timeout_destroy;
void *timeout_data;bt_att_debug_func_t debug_callback;
bt_att_destroy_func_t debug_destroy;
void *debug_data;struct bt_crypto *crypto;
struct sign_info *local_sign;
struct sign_info *remote_sign;
};->ready => notify_client_ready => service_changed_register_cb => register_service_changed => init_complete
=> init_complete => discovery_op_create(init_complete ) => gatt_client_init
->in_init => gatt_client_init} command[] = {
cmd_services
-u/--uuid
bt_uuid_to_uuid128(&tmp, &uuid);
print_services_by_uuid(cli, &uuid);
-a/--handle
print_services_by_handle
有个疑问? handle传过去,没有用到,怎么过滤的了?cmd_read_value
bt_gatt_client_read_value(cli->gatt, handle, read_cb, NULL, NULL)
a> objreq
b> bt_att_send(client->att, BT_ATT_OP_READ_REQ, pdu, sizeof(pdu), read_cb(不同上面的,该接口会调用上面的回调), req, request_unref);
1> create_att_send_op(上面7个参数) => obj然后根据type插入到对应的队列( write_queue > req_queue > ind_queue )
req_queue -> objpending_req
ind_queue -> objpending_ind
write_queue
2> wakeup_writer(att)
io_set_write_handler(att->io, can_write_data, att, write_watch_destroy))
can_write_data (1. 先从队列中选一个 att_send_op 对象
struct bt_gatt_client {
struct bt_att *att;
int ref_count;struct bt_gatt_client *parent;
struct queue *clones;bt_gatt_client_callback_t ready_callback;
bt_gatt_client_destroy_func_t ready_destroy;
void *ready_data;bt_gatt_client_service_changed_callback_t svc_chngd_callback;
bt_gatt_client_destroy_func_t svc_chngd_destroy;
void *svc_chngd_data;bt_gatt_client_debug_func_t debug_callback;
bt_gatt_client_destroy_func_t debug_destroy;
void *debug_data;struct gatt_db *db;
bool in_init;
bool ready;/*
* Queue of long write requests. An error during "prepare write"
* requests can result in a cancel through "execute write". To prevent
* cancelation of prepared writes to the wrong attribute and multiple
* requests to the same attribute that may result in a corrupted final
* value, we avoid interleaving prepared writes.
*/
struct queue *long_write_queue;
bool in_long_write;unsigned int reliable_write_session_id;
/* List of registered disconnect/notification/indication callbacks */
struct queue *notify_list;
struct queue *notify_chrcs;
int next_reg_id;
unsigned int disc_id, notify_id, ind_id;/*
* Handles of the GATT Service and the Service Changed characteristic
* value handle. These will have the value 0 if they are not present on
* the remote peripheral.
*/
unsigned int svc_chngd_ind_id;
bool svc_chngd_registered;
struct queue *svc_chngd_queue; /* Queued service changed events */
bool in_svc_chngd;/*
* List of pending read/write operations. For operations that span
* across multiple PDUs, this list provides a mapping from an operation
* id to an ATT request id.
*/
struct queue *pending_requests;
unsigned int next_request_id;struct bt_gatt_request *discovery_req;
unsigned int mtu_req_id;
};=================================================================================
attrib/gatttool
=================================================================================
0. 建立连接 opr=gatt_connect
gatt_connect 设置回调函数( connect_cb ) 此回调什么时候调用?
需要指定: 本地蓝牙mac, 远端(蓝牙mac,type:public/random,level:low/medium/high,psm(基于br/edr的gatt/att):0/<0,mtu,)
psm:
=0 使用ATT_CID,不使用mtu(即默认mtu=23default) BT_IO_OPT_CID
>0 使用psm,设置mtu BT_IO_OPT_PSM, 应该会有系统分配cid(channel id != ATT_CID)
bt_io_connect: btio/btio.c
BT_IO_OPT_PSM:
type = BT_IO_L2CAP;
BT_IO_OPT_CID:
type = BT_IO_L2CAP;
l2cap_connect:
connect
connect_add:
回调函数( connect_cb ) 设置为->connect,通过g_io_add_watch_full ( GIOFunc:connect_cb此接口先调用,成功后调用前面的->connect ) 加入
至于GIOFunc:connect_cb什么时候会回调?可以参考g_io_***相关
1. 发现服务(srv) opr=primary
gatt_discover_primary
a: 指定了uuid 并设置回调函数( primary_by_uuid_cb ) 此回调什么时候调用?
输出:
struct att_range {
uint16_t start;
uint16_t end;
};
b: 没有指定uuid 并设置回调函数( primary_all_cb ) 此回调什么时候调用?
输出:
struct gatt_primary {
char uuid[MAX_LEN_UUID_STR + 1]; // #define MAX_LEN_UUID_STR 37
gboolean changed;
struct att_range range;
};
gatt.c中gatt_discover_primary: primary_by_uuid_cb/primary_all_cb 是->result_func , 上面的回调 primary_by_uuid_cb/primary_all_cb是->cb, 和其他数据封装为user_data一起加入到queue中.
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func, 把数据全部取出后执行->cb (在此回调)2. 发现特征值(char) opr=characteristics
gatt_discover_char 设置回调函数( char_discovered_cb ) 此回调什么时候调用?
输出:
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
uint8_t properties;
uint16_t value_handle;
};
gatt.c中gatt_discover_char: char_discovered_cb 是->result_func, 上面的回调char_discovered_cb 是->cb
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func, 把数据全部取出后执行->cb (在此回调)3. 特征值读 opr=characteristics_read
a: 指定了uuid: gatt_read_char_by_uuid 设置回调函数( char_read_by_uuid_cb ) 此回调什么时候调用?
输出: handle value
b: 没有指定uuid: gatt_read_char 设置回调函数( char_read_cb ) 此回调什么时候调用?
输出: Characteristic value/descriptor:
a:
gatt.c中的gatt_read_char_by_uuid: char_read_by_uuid_cb 是->result_func ,
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func (在此回调)
b:
gatt.c中的gatt_read_char:read_char_helper 是->result_func, 上面的回调char_read_cb 是->func ,
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func, 把数据全部取出后执行->func (在此回调)4. 特征值写 opr=characteristics_write
gatt.c中的 gatt_write_cmd
gattrib.c中的 g_attrib_send 可以简单看成send, 就send over了5. 特征值写带req opr=characteristics_write_req
gatt_write_char 设置回调函数( char_write_req_cb ) 此回调什么时候调用?
输出: 判断返回的状态
gatt.c中的 gatt_write_char: prepare_write_cb 是->result_func, char_write_req_cb 是->func,
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func, 收到完整数据后调用 execute_write (再次g_attrib_send后执行->func (在此回调))6. 特征值描述符 opr=characteristics_desc
gatt_discover_desc 设置回调函数( char_desc_cb ) 此回调什么时候调用?
gatt.c中的 gatt_discover_desc: desc_discovered_cb 是->result_func, char_desc_cb 是->cb,
gattrib.c中的 g_attrib_send 可以简单看成send, 并设置了响应函数 attrib_callback_result
收到对端回复后,在响应函数attrib_callback_result中执行->result_func, 把数据全部取出后执行->cb (在此回调)characteristics
gatt_discover_char(user_cb: char_discovered_cb)
g_attrib_send(char_discovered_cb -> user_cb: )
primary
gatt_discover_primary(user_cb: primary_by_uuid_cb/primary_all_cb)
g_attrib_send(primary_all_cb/primary_by_uuid_cb -> user_cb:)
characteristics_read
gatt_read_char_by_uuid(user_cb: char_read_by_uuid_cb)
g_attrib_send(user_cb: )
gatt_read_char(user_cb: char_read_cb)
g_attrib_send(read_char_helper,long_read(->func=user_cb))
read_char_helper:
g_attrib_send(read_blob_helper,long_read(->func=user_cb))
=================================================================================
bluetoothd*
=================================================================================
src_bluetoothd_SOURCES = $(builtin_sources) \
$(attrib_sources) $(btio_sources) \
src/bluetooth.ver \
src/main.c src/log.h src/log.c \
src/backtrace.h src/backtrace.c \
src/rfkill.c src/hcid.h src/sdpd.h \
src/sdpd-server.c src/sdpd-request.c \
src/sdpd-service.c src/sdpd-database.c \
src/attrib-server.h src/attrib-server.c \
src/gatt-database.h src/gatt-database.c \
src/sdp-xml.h src/sdp-xml.c \
src/sdp-client.h src/sdp-client.c \
src/textfile.h src/textfile.c \
src/uuid-helper.h src/uuid-helper.c \
src/uinput.h \
src/plugin.h src/plugin.c \
src/storage.h src/storage.c \
src/advertising.h src/advertising.c \
src/agent.h src/agent.c \
src/error.h src/error.c \
src/adapter.h src/adapter.c \
src/profile.h src/profile.c \
src/service.h src/service.c \
src/gatt-client.h src/gatt-client.c \
src/device.h src/device.c \
src/dbus-common.c src/dbus-common.h \
src/eir.h src/eir.cbuiltin_sources = plugins/hostname.c plugins/wiimote.c \
plugins/autopair.c plugins/policy.c $(am__append_7) \
$(am__append_9) $(am__append_11) $(am__append_13) \
$(am__append_15) $(am__append_17) $(am__append_19) \
$(am__append_22) profiles/gap/gas.c profiles/scanparam/scan.c \
profiles/deviceinfo/deviceinfo.c $(am__append_24) \
profiles/battery/battery.c#am__append_7 = plugins/neard.c
#am__append_9 = profiles/sap/main.c profiles/sap/manager.h \
# profiles/sap/manager.c profiles/sap/server.h \
# profiles/sap/server.c profiles/sap/sap.h \
# profiles/sap/sap-dummy.c
am__append_11 = profiles/audio/source.h profiles/audio/source.c \
profiles/audio/sink.h profiles/audio/sink.c \
profiles/audio/a2dp.h profiles/audio/a2dp.c \
profiles/audio/avdtp.h profiles/audio/avdtp.c \
profiles/audio/media.h profiles/audio/media.c \
profiles/audio/transport.h profiles/audio/transport.c \
profiles/audio/a2dp-codecs.h
am__append_13 = profiles/audio/control.h profiles/audio/control.c \
profiles/audio/avctp.h profiles/audio/avctp.c \
profiles/audio/avrcp.h profiles/audio/avrcp.c \
profiles/audio/player.h profiles/audio/player.c
am__append_15 = profiles/network/manager.c \
profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/server.h profiles/network/server.c \
profiles/network/connection.h \
profiles/network/connection.c
am__append_17 = profiles/input/manager.c \
profiles/input/server.h profiles/input/server.c \
profiles/input/device.h profiles/input/device.c \
profiles/input/hidp_defs.h profiles/input/sixaxis.h
am__append_19 = profiles/input/hog.c profiles/input/uhid_copy.h \
profiles/input/hog-lib.c profiles/input/hog-lib.h \
profiles/deviceinfo/dis.c profiles/deviceinfo/dis.h \
profiles/battery/bas.c profiles/battery/bas.h \
profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
profiles/input/suspend.h profiles/input/suspend-none.c
am__append_22 = profiles/health/mcap.h profiles/health/mcap.c \
profiles/health/hdp_main.c profiles/health/hdp_types.h \
profiles/health/hdp_manager.h \
profiles/health/hdp_manager.c \
profiles/health/hdp.h profiles/health/hdp.c \
profiles/health/hdp_util.h profiles/health/hdp_util.c
#am__append_24 = profiles/midi/midi.c \
# profiles/midi/libmidi.h \
# profiles/midi/libmidi.cattrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
attrib/gatt.h attrib/gatt.c \
attrib/gattrib.h attrib/gattrib.c \
attrib/gatt-service.h attrib/gatt-service.cbtio_sources = btio/btio.h btio/btio.c
流程分析:
/* Directory for the Android daemon storage files */
#define ANDROID_STORAGEDIR "/tmp/bluez5/var/lib/bluetooth/android"/* Directory for the configuration files */
#define CONFIGDIR "/tmp/bluez5/etc/bluetooth"/* Directory for the mesh daemon storage files */
#define MESH_STORAGEDIR "/tmp/bluez5/var/lib/bluetooth/mesh"/* Name of package */
#define PACKAGE "bluez"/* Define to the full name of this package. */
#define PACKAGE_NAME "bluez"/* Directory for the storage files */
#define STORAGEDIR "/tmp/bluez5/var/lib/bluetooth"
step1:context options 解析
g_option_context_new ->context
g_option_context_add_main_entries(context, options, NULL)
g_option_context_parse(context, arg*)
g_option_context_free(context)
step2: 可以使用backtrace来记录
step3: mainloop_init
step4: 加载配置 main.conf(使用GKeyFile) 并解析
step5: 创建通信实体 DBusConnection ,并将适配器初始化 adapter_init
step6: btd相关初始化:
btd_device_init();
btd_agent_init();
btd_profile_init();
step7: 启动sdp服务器 start_sdp_server 并且注册 register_device_id, 新增MPS(Multi Profile)相关服务
step8: 插件初始化 plugin_init
step9: rfkill相关初始化, 监控 /dev/rfkill 的输入事件
step10: 设置信号处理接口 setup_signalfd
step11: 进入主循环体 mainloop_run
..........分步分析:
connect_dbus: 创建通信实体 DBusConnection
1. g_dbus_setup_bus 创建system级的conn
2. set_dbus_connection 通信实体指定
3. 设置disconnect回调: disconnected_dbus(程序退出)
4. g_dbus_attach_object_manager 新增 dbus-interfaceadapter_init: 适配器初始化
1. dbus_conn 指向通信实体
2. 创建(绑定一个hci的socket)
3. 给发送 MGMT_OP_READ_VERSION 事件 请求
4. 处理请求结果 read_version_complete
Bluetooth management interface %u.%u initialized(version, revision)
4.1 给发送 MGMT_OP_READ_COMMANDS 请求(adapter支持哪些cmd?)
请求处理的流程: read_commands_complete
4.2 注册 MGMT_EV_INDEX_ADDED / MGMT_EV_INDEX_REMOVED 事件
事件处理的流程: index_added / index_removed
4.3 给发送 MGMT_OP_READ_INDEX_LIST 请求(adapter支持哪些cmd?)
请求处理的流程: read_index_list_complete
p0: 发送请求接口: mgmt_send
注册事件接口: mgmt_register=================================================================================
profile/cups
=================================================================================
蓝牙打印工具(命令)
Usage: printer-uri job-id user title copies options [file]
Usage: bluetooth job-id user title copies options [file]
bluetooth --get-deviceid [bdaddr]
两种协议
spp:
channel
sdp_search_spp
BTPROTO_RFCOMM : 仿真串口
source: rc_channel = 0
destination: rc_channel = channel
hcrp:
psm
sdp_search_hcrp
BTPROTO_L2CAP
source: l2_psm = psm
destination: l2_psm = psm
mtu
两个socket:
ctrl_sk : credit grant check
data_sk : 发送数据=================================================================================
tools/sdptool
=================================================================================
// 以下是基本功能表
static struct {
char *cmd;
int (*func)(int argc, char **argv);
char *doc;
} command[] = {
{ "search", cmd_search, "Search for a service" },
{ "browse", cmd_browse, "Browse all available services" },
{ "records", cmd_records, "Request all records" },
{ "add", cmd_add, "Add local service" },
{ "del", cmd_del, "Delete local service" },
{ "get", cmd_get, "Get local service" },
{ "setattr", cmd_setattr, "Set/Add attribute to a SDP record" },
{ "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" },
{ 0, 0, 0 }
};
根据argv来选择一个func执行,
cmd_search>>>
处理args,然后调用do_search:
需要指定uuid(例如0x1000)或者名称,名称不限于如下
Services:
DID SP DUN LAN FAX OPUSH FTP PRINT HS HSAG HF HFAG SAP PBAP MAP
NAP GN PANU HCRP HID KEYB WIIMOTE CIP CTP A2SRC A2SNK AVRCT AVRTG
UDIUE UDITE SEMCHLA SR1 SYNCML SYNCMLSERV ACTIVESYNC HOTSYNC
PALMOS NOKID PCSUITE NFTP NSYNCML NGAGE APPLE IAP ISYNC GATT
如果是名称,会通过service[]转换.构造search_context(class(2B,4B)与uuid(16B)选一个来初始化其成员uuid_t)
A:没有指定bdaddr(查询所有有此uuid的设备)
找到20个,然后执行B
B:指定bdaddr
1. 调用libbluetooth.so:sdp_connect创建
2. 调用libbluetooth.so:sdp_service_search_attr_req来获取返回的<>
3. 处理每一个
4. doit
cmd_browse>>>
处理args,然后调用do_search:
同上
cmd_add>>>
return add_service(0, &si);
sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
session = sdp_create(-1, flags);
if (sdp_connect_local(session) < 0)
session->sock = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
return connect(session->sock, (struct sockaddr *) &sa, sizeof(sa));
if (service[i].add)
ret = service[i].add(sess, si);// 以下是服务列表
struct {
char *name;
uint32_t class;
int (*add)(sdp_session_t *sess, svc_info_t *si);
unsigned char *uuid;
} service[] = {
{ "DID", PNP_INFO_SVCLASS_ID, NULL, },{ "SP", SERIAL_PORT_SVCLASS_ID, add_sp },
{ "DUN", DIALUP_NET_SVCLASS_ID, add_dun },
{ "LAN", LAN_ACCESS_SVCLASS_ID, add_lan },
{ "FAX", FAX_SVCLASS_ID, add_fax },
{ "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush },
{ "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp },
{ "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint },{ "HS", HEADSET_SVCLASS_ID, add_headset },
{ "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag },
{ "HF", HANDSFREE_SVCLASS_ID, add_handsfree },
{ "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag},
{ "SAP", SAP_SVCLASS_ID, add_simaccess },
{ "PBAP", PBAP_SVCLASS_ID, add_pbap, },{ "MAP", MAP_SVCLASS_ID, add_map, },
{ "NAP", NAP_SVCLASS_ID, add_nap },
{ "GN", GN_SVCLASS_ID, add_gn },
{ "PANU", PANU_SVCLASS_ID, add_panu },{ "HCRP", HCR_SVCLASS_ID, NULL },
{ "HID", HID_SVCLASS_ID, NULL },
{ "KEYB", HID_SVCLASS_ID, add_hid_keyb },
{ "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote },
{ "CIP", CIP_SVCLASS_ID, add_cip },
{ "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp },{ "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source },
{ "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink },
{ "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct },
{ "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg },{ "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue },
{ "UDITE", UDI_TA_SVCLASS_ID, add_udi_te },{ "SEMCHLA", 0x8e771301, add_semchla },
{ "SR1", 0, add_sr1, sr1_uuid },
{ "SYNCML", 0, add_syncml, syncmlc_uuid },
{ "SYNCMLSERV", 0, NULL, syncmls_uuid },
{ "ACTIVESYNC", 0, add_activesync, async_uuid },
{ "HOTSYNC", 0, add_hotsync, hotsync_uuid },
{ "PALMOS", 0, add_palmos, palmos_uuid },
{ "NOKID", 0, add_nokiaid, nokid_uuid },
{ "PCSUITE", 0, add_pcsuite, pcsuite_uuid },
{ "NFTP", 0, NULL, nftp_uuid },
{ "NSYNCML", 0, NULL, nsyncml_uuid },
{ "NGAGE", 0, NULL, ngage_uuid },
{ "APPLE", 0, add_apple, apple_uuid },
{ "IAP", 0, NULL, iap_uuid },{ "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, },
{ "GATT", GENERIC_ATTRIB_SVCLASS_ID, add_gatt, },{ 0 }
};
=================================================================================
gdbus
=================================================================================
封装dbus
gdbus/gdbus.h
1. create conn object
2. request_name conn
a. 向dbus_service提出申请
什么时候注册的?dbus-daemon?
b. 有哪些api
register : "hello"
get_user : "GetConnectionUser"
get_id : "GetId"
request_name : "RequestName"
release_name : "ReleaseName"
name_has_owner? : "NameHasOwner"
startservicebyname : "StartServiceByName"
add/remove_watch : "Add/RemoveWatch"
3. set_func:
watch
timeout
dispatch_status
4. do your job
5. complete preparation
=================================================================================
profiles/input
=================================================================================
以hid设备为例:
static struct btd_profile input_profile = {
.name = "input-hid",
.local_uuid = HID_UUID,
.remote_uuid = HID_UUID,.auto_connect = true,
.connect = input_device_connect,
.disconnect = input_device_disconnect,.device_probe = input_device_register,
.device_remove = input_device_unregister,.adapter_probe = hid_server_probe,`
.adapter_remove = hid_server_remove,
};系统启动后,调用BLUETOOTH_PLUGIN_DEFINE(input, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
input_init, input_exit)来加载插件(驱动)
input_init:
1. 解析 /tmp/bluez5/etc/bluetooth/input.conf 配置文件,主要是 idle_timeout 和 uhid 设备开启设置
2. 调用 btd_profile_register(&input_profile); 添加到系统的 profile 单链表中
3. 等待 bluetoothd 执行过程触发 input_profile 中的接口执行
input_device_connect:
input_device_register:
主要是创建 input_device
hid_server_probe:
1. 调用 server_start 去启动 server
// 在ctrl通道(L2CAP_PSM_HIDP_CTRL 0x11)上listen,回调函数 connect_event_cb
connect_event_cb :
// 得到该设备的源地址和目的地址,psm等
bt_io_get(chan, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_PSM, &psm, BT_IO_OPT_INVALID);
// 设置 input_device , 如果是非法设备,并且当前是控制通道,那么根据HID协议,需要向对方发送“unplug virtual cable”消息
input_device_set_channel(&src, &dst, psm, chan);
// 根据对方设备的地址,从HID设备链表中找到对应的input_dev设备。这里有一个问题,就是对应的input_dev设备是什么时候登记到链表中的???请参考 input_device_register ???
// 当ctrl通道和intr通道都被设置后,才会进入input_device_connadd。目前我们是沿着L2CAP_PSM_HIDP_CTRL的回调函数connect_event_cb看到这里的,所以暂时先不深入研究
if (iconn->intr_io && iconn->ctrl_io)
input_device_connadd(idev, iconn);
// 在intr通道(L2CAP_PSM_HIDP_INTR 0x13)上listen,回调函数 confirm_event_cb
confirm_event_cb :
bt_io_get(chan, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_INVALID);
// 请求authorization操作,并指定完成后的回调函数为auth_callback
btd_request_authorization(&src, &dst, HID_UUID, auth_callback, server);
auth_callback :
// 判断设备是否存在以及是否是sixaxis
input_device_exists && dev_is_sixaxis
bt_io_accept同样指定回调函数为connect_event_cb. 此时connect_event_cb会设置intr通道,并最终调用input_device_connadd函数
// 加入连接
input_device_connadd :
input_device_connected :
hidp_add_connection : 加入hidp连接
btd_service_connecting_complete :
change_state(service, BTD_SERVICE_STATE_CONNECTED, 0);Input-headset的流程比较特殊,与input-hid的区别至少有以下几点:
1. HID设备的连接建立在l2cap上,headset的连接建立在rfcomm上。
2. HID设备会通知内核建立一个HID设备或input设备,headset则只是实例化一个uinput设备。
3. 前文提到的ctrl通道、intr通道都不能适用于headset,因为他们都是在l2cap上的连接。
如果是本地主动连接远端的headset设备,同样是由应用程序调用”connect”方法启动连接过程,具体实现可查看代码。
=================================================================================
android
=================================================================================
--enable-android=================================================================================
ell
=================================================================================
--enable-ell Embedded Linux library
=================================================================================
bt-core(pdf)
=================================================================================
There are two forms of Bluetooth wireless technology systems: Basic Rate (BR) and Low Energy (LE).
Both systems include device discovery, connection establishment and connection mechanisms.The Basic Rate system includes optional Enhanced Data Rate (EDR) Alternate Media Access Control (MAC)
and Physical (PHY) layer extensions. The Basic Rate system offers synchronous and asynchronous
connections with data rates of 721.2 kb/s for Basic Rate, 2.1 Mb/s for Enhanced Data Rate
and high speed operation up to 54 Mb/s with the 802.11 AMP.The LE system includes features designed to enable products that require lower current consumption,
lower complexity and lower cost than BR/EDR.
The LE system is also designed for use cases and applications with lower data rates
and has lower duty cycles(占空比). Depending on the use case or application,
one system including any optional parts may be more optimal than the other.=================================================================================
opcode_table
=================================================================================
static const struct opcode_data opcode_table[] = {
{ 0x0000, -1, "NOP" },/* OGF 1 - Link Control */
{ 0x0401, 0, "Inquiry",
inquiry_cmd, 5, true },
{ 0x0402, 1, "Inquiry Cancel",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x0403, 2, "Periodic Inquiry Mode",
periodic_inquiry_cmd, 9, true,
status_rsp, 1, true },
{ 0x0404, 3, "Exit Periodic Inquiry Mode",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x0405, 4, "Create Connection",
create_conn_cmd, 13, true },
{ 0x0406, 5, "Disconnect",
disconnect_cmd, 3, true },
{ 0x0407, 6, "Add SCO Connection",
add_sco_conn_cmd, 4, true },
{ 0x0408, 7, "Create Connection Cancel",
create_conn_cancel_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x0409, 8, "Accept Connection Request",
accept_conn_request_cmd, 7, true },
{ 0x040a, 9, "Reject Connection Request",
reject_conn_request_cmd, 7, true },
{ 0x040b, 10, "Link Key Request Reply",
link_key_request_reply_cmd, 22, true,
status_bdaddr_rsp, 7, true },
{ 0x040c, 11, "Link Key Request Negative Reply",
link_key_request_neg_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x040d, 12, "PIN Code Request Reply",
pin_code_request_reply_cmd, 23, true,
status_bdaddr_rsp, 7, true },
{ 0x040e, 13, "PIN Code Request Negative Reply",
pin_code_request_neg_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x040f, 14, "Change Connection Packet Type",
change_conn_pkt_type_cmd, 4, true },
{ 0x0411, 15, "Authentication Requested",
auth_requested_cmd, 2, true },
{ 0x0413, 16, "Set Connection Encryption",
set_conn_encrypt_cmd, 3, true },
{ 0x0415, 17, "Change Connection Link Key",
change_conn_link_key_cmd, 2, true },
{ 0x0417, 18, "Master Link Key",
master_link_key_cmd, 1, true },
{ 0x0419, 19, "Remote Name Request",
remote_name_request_cmd, 10, true },
{ 0x041a, 20, "Remote Name Request Cancel",
remote_name_request_cancel_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x041b, 21, "Read Remote Supported Features",
read_remote_features_cmd, 2, true },
{ 0x041c, 22, "Read Remote Extended Features",
read_remote_ext_features_cmd, 3, true },
{ 0x041d, 23, "Read Remote Version Information",
read_remote_version_cmd, 2, true },
{ 0x041f, 24, "Read Clock Offset",
read_clock_offset_cmd, 2, true },
{ 0x0420, 25, "Read LMP Handle",
read_lmp_handle_cmd, 2, true,
read_lmp_handle_rsp, 8, true },
{ 0x0428, 131, "Setup Synchronous Connection",
setup_sync_conn_cmd, 17, true },
{ 0x0429, 132, "Accept Synchronous Connection Request",
accept_sync_conn_request_cmd, 21, true },
{ 0x042a, 133, "Reject Synchronous Connection Request",
reject_sync_conn_request_cmd, 7, true },
{ 0x042b, 151, "IO Capability Request Reply",
io_capability_request_reply_cmd, 9, true,
status_bdaddr_rsp, 7, true },
{ 0x042c, 152, "User Confirmation Request Reply",
user_confirm_request_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x042d, 153, "User Confirmation Request Neg Reply",
user_confirm_request_neg_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x042e, 154, "User Passkey Request Reply",
user_passkey_request_reply_cmd, 10, true,
status_bdaddr_rsp, 7, true },
{ 0x042f, 155, "User Passkey Request Negative Reply",
user_passkey_request_neg_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x0430, 156, "Remote OOB Data Request Reply",
remote_oob_data_request_reply_cmd, 38, true,
status_bdaddr_rsp, 7, true },
{ 0x0433, 159, "Remote OOB Data Request Neg Reply",
remote_oob_data_request_neg_reply_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x0434, 163, "IO Capability Request Negative Reply",
io_capability_request_neg_reply_cmd, 7, true,
status_bdaddr_rsp, 7, true },
{ 0x0435, 168, "Create Physical Link",
create_phy_link_cmd, 3, false },
{ 0x0436, 169, "Accept Physical Link",
accept_phy_link_cmd, 3, false },
{ 0x0437, 170, "Disconnect Physical Link",
disconn_phy_link_cmd, 2, true },
{ 0x0438, 171, "Create Logical Link",
create_logic_link_cmd, 33, true },
{ 0x0439, 172, "Accept Logical Link",
accept_logic_link_cmd, 33, true },
{ 0x043a, 173, "Disconnect Logical Link",
disconn_logic_link_cmd, 2, true },
{ 0x043b, 174, "Logical Link Cancel",
logic_link_cancel_cmd, 2, true,
logic_link_cancel_rsp, 3, true },
{ 0x043c, 175, "Flow Specifcation Modify",
flow_spec_modify_cmd, 34, true },
{ 0x043d, 235, "Enhanced Setup Synchronous Connection",
enhanced_setup_sync_conn_cmd, 59, true },
{ 0x043e, 236, "Enhanced Accept Synchronous Connection Request",
enhanced_accept_sync_conn_request_cmd, 63, true },
{ 0x043f, 246, "Truncated Page",
truncated_page_cmd, 9, true },
{ 0x0440, 247, "Truncated Page Cancel",
truncated_page_cancel_cmd, 6, true,
status_bdaddr_rsp, 7, true },
{ 0x0441, 248, "Set Connectionless Slave Broadcast",
set_slave_broadcast_cmd, 11, true,
set_slave_broadcast_rsp, 4, true },
{ 0x0442, 249, "Set Connectionless Slave Broadcast Receive",
set_slave_broadcast_receive_cmd, 34, true,
set_slave_broadcast_receive_rsp, 8, true },
{ 0x0443, 250, "Start Synchronization Train",
null_cmd, 0, true },
{ 0x0444, 251, "Receive Synchronization Train",
receive_sync_train_cmd, 12, true },
{ 0x0445, 257, "Remote OOB Extended Data Request Reply",
remote_oob_ext_data_request_reply_cmd, 70, true,
status_bdaddr_rsp, 7, true },/* OGF 2 - Link Policy */
{ 0x0801, 33, "Hold Mode",
hold_mode_cmd, 6, true },
{ 0x0803, 34, "Sniff Mode",
sniff_mode_cmd, 10, true },
{ 0x0804, 35, "Exit Sniff Mode",
exit_sniff_mode_cmd, 2, true },
{ 0x0805, 36, "Park State",
park_state_cmd, 6, true },
{ 0x0806, 37, "Exit Park State",
exit_park_state_cmd, 2, true },
{ 0x0807, 38, "QoS Setup",
qos_setup_cmd, 20, true },
{ 0x0809, 39, "Role Discovery",
role_discovery_cmd, 2, true,
role_discovery_rsp, 4, true },
{ 0x080b, 40, "Switch Role",
switch_role_cmd, 7, true },
{ 0x080c, 41, "Read Link Policy Settings",
read_link_policy_cmd, 2, true,
read_link_policy_rsp, 5, true },
{ 0x080d, 42, "Write Link Policy Settings",
write_link_policy_cmd, 4, true,
write_link_policy_rsp, 3, true },
{ 0x080e, 43, "Read Default Link Policy Settings",
null_cmd, 0, true,
read_default_link_policy_rsp, 3, true },
{ 0x080f, 44, "Write Default Link Policy Settings",
write_default_link_policy_cmd, 2, true,
status_rsp, 1, true },
{ 0x0810, 45, "Flow Specification",
flow_spec_cmd, 21, true },
{ 0x0811, 140, "Sniff Subrating",
sniff_subrating_cmd, 8, true,
sniff_subrating_rsp, 3, true },/* OGF 3 - Host Control */
{ 0x0c01, 46, "Set Event Mask",
set_event_mask_cmd, 8, true,
status_rsp, 1, true },
{ 0x0c03, 47, "Reset",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x0c05, 48, "Set Event Filter",
set_event_filter_cmd, 1, false,
status_rsp, 1, true },
{ 0x0c08, 49, "Flush",
flush_cmd, 2, true,
flush_rsp, 3, true },
{ 0x0c09, 50, "Read PIN Type",
null_cmd, 0, true,
read_pin_type_rsp, 2, true },
{ 0x0c0a, 51, "Write PIN Type",
write_pin_type_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c0b, 52, "Create New Unit Key",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x0c0d, 53, "Read Stored Link Key",
read_stored_link_key_cmd, 7, true,
read_stored_link_key_rsp, 5, true },
{ 0x0c11, 54, "Write Stored Link Key",
write_stored_link_key_cmd, 1, false,
write_stored_link_key_rsp, 2, true },
{ 0x0c12, 55, "Delete Stored Link Key",
delete_stored_link_key_cmd, 7, true,
delete_stored_link_key_rsp, 3, true },
{ 0x0c13, 56, "Write Local Name",
write_local_name_cmd, 248, true,
status_rsp, 1, true },
{ 0x0c14, 57, "Read Local Name",
null_cmd, 0, true,
read_local_name_rsp, 249, true },
{ 0x0c15, 58, "Read Connection Accept Timeout",
null_cmd, 0, true,
read_conn_accept_timeout_rsp, 3, true },
{ 0x0c16, 59, "Write Connection Accept Timeout",
write_conn_accept_timeout_cmd, 2, true,
status_rsp, 1, true },
{ 0x0c17, 60, "Read Page Timeout",
null_cmd, 0, true,
read_page_timeout_rsp, 3, true },
{ 0x0c18, 61, "Write Page Timeout",
write_page_timeout_cmd, 2, true,
status_rsp, 1, true },
{ 0x0c19, 62, "Read Scan Enable",
null_cmd, 0, true,
read_scan_enable_rsp, 2, true },
{ 0x0c1a, 63, "Write Scan Enable",
write_scan_enable_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c1b, 64, "Read Page Scan Activity",
null_cmd, 0, true,
read_page_scan_activity_rsp, 5, true },
{ 0x0c1c, 65, "Write Page Scan Activity",
write_page_scan_activity_cmd, 4, true,
status_rsp, 1, true },
{ 0x0c1d, 66, "Read Inquiry Scan Activity",
null_cmd, 0, true,
read_inquiry_scan_activity_rsp, 5, true },
{ 0x0c1e, 67, "Write Inquiry Scan Activity",
write_inquiry_scan_activity_cmd, 4, true,
status_rsp, 1, true },
{ 0x0c1f, 68, "Read Authentication Enable",
null_cmd, 0, true,
read_auth_enable_rsp, 2, true },
{ 0x0c20, 69, "Write Authentication Enable",
write_auth_enable_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c21, 70, "Read Encryption Mode",
null_cmd, 0, true,
read_encrypt_mode_rsp, 2, true },
{ 0x0c22, 71, "Write Encryption Mode",
write_encrypt_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c23, 72, "Read Class of Device",
null_cmd, 0, true,
read_class_of_dev_rsp, 4, true },
{ 0x0c24, 73, "Write Class of Device",
write_class_of_dev_cmd, 3, true,
status_rsp, 1, true },
{ 0x0c25, 74, "Read Voice Setting",
null_cmd, 0, true,
read_voice_setting_rsp, 3, true },
{ 0x0c26, 75, "Write Voice Setting",
write_voice_setting_cmd, 2, true,
status_rsp, 1, true },
{ 0x0c27, 76, "Read Automatic Flush Timeout",
read_auto_flush_timeout_cmd, 2, true,
read_auto_flush_timeout_rsp, 5, true },
{ 0x0c28, 77, "Write Automatic Flush Timeout",
write_auto_flush_timeout_cmd, 4, true,
write_auto_flush_timeout_rsp, 3, true },
{ 0x0c29, 78, "Read Num Broadcast Retransmissions",
null_cmd, 0, true,
read_num_broadcast_retrans_rsp, 2, true },
{ 0x0c2a, 79, "Write Num Broadcast Retransmissions",
write_num_broadcast_retrans_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c2b, 80, "Read Hold Mode Activity",
null_cmd, 0, true,
read_hold_mode_activity_rsp, 2, true },
{ 0x0c2c, 81, "Write Hold Mode Activity",
write_hold_mode_activity_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c2d, 82, "Read Transmit Power Level",
read_tx_power_cmd, 3, true,
read_tx_power_rsp, 4, true },
{ 0x0c2e, 83, "Read Sync Flow Control Enable",
null_cmd, 0, true,
read_sync_flow_control_rsp, 2, true },
{ 0x0c2f, 84, "Write Sync Flow Control Enable",
write_sync_flow_control_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c31, 85, "Set Controller To Host Flow Control",
set_host_flow_control_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c33, 86, "Host Buffer Size",
host_buffer_size_cmd, 7, true,
status_rsp, 1, true },
{ 0x0c35, 87, "Host Number of Completed Packets",
host_num_completed_packets_cmd, 5, false },
{ 0x0c36, 88, "Read Link Supervision Timeout",
read_link_supv_timeout_cmd, 2, true,
read_link_supv_timeout_rsp, 5, true },
{ 0x0c37, 89, "Write Link Supervision Timeout",
write_link_supv_timeout_cmd, 4, true,
write_link_supv_timeout_rsp, 3, true },
{ 0x0c38, 90, "Read Number of Supported IAC",
null_cmd, 0, true,
read_num_supported_iac_rsp, 2, true },
{ 0x0c39, 91, "Read Current IAC LAP",
null_cmd, 0, true,
read_current_iac_lap_rsp, 2, false },
{ 0x0c3a, 92, "Write Current IAC LAP",
write_current_iac_lap_cmd, 1, false,
status_rsp, 1, true },
{ 0x0c3b, 93, "Read Page Scan Period Mode",
null_cmd, 0, true,
read_page_scan_period_mode_rsp, 2, true },
{ 0x0c3c, 94, "Write Page Scan Period Mode",
write_page_scan_period_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c3d, 95, "Read Page Scan Mode",
null_cmd, 0, true,
read_page_scan_mode_rsp, 2, true },
{ 0x0c3e, 96, "Write Page Scan Mode",
write_page_scan_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c3f, 97, "Set AFH Host Channel Classification",
set_afh_host_classification_cmd, 10, true,
status_rsp, 1, true },
{ 0x0c42, 100, "Read Inquiry Scan Type",
null_cmd, 0, true,
read_inquiry_scan_type_rsp, 2, true },
{ 0x0c43, 101, "Write Inquiry Scan Type",
write_inquiry_scan_type_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c44, 102, "Read Inquiry Mode",
null_cmd, 0, true,
read_inquiry_mode_rsp, 2, true },
{ 0x0c45, 103, "Write Inquiry Mode",
write_inquiry_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c46, 104, "Read Page Scan Type",
null_cmd, 0, true,
read_page_scan_type_rsp, 2, true },
{ 0x0c47, 105, "Write Page Scan Type",
write_page_scan_type_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c48, 106, "Read AFH Channel Assessment Mode",
null_cmd, 0, true,
read_afh_assessment_mode_rsp, 2, true },
{ 0x0c49, 107, "Write AFH Channel Assessment Mode",
write_afh_assessment_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c51, 136, "Read Extended Inquiry Response",
null_cmd, 0, true,
read_ext_inquiry_response_rsp, 242, true },
{ 0x0c52, 137, "Write Extended Inquiry Response",
write_ext_inquiry_response_cmd, 241, true,
status_rsp, 1, true },
{ 0x0c53, 138, "Refresh Encryption Key",
refresh_encrypt_key_cmd, 2, true },
{ 0x0c55, 141, "Read Simple Pairing Mode",
null_cmd, 0, true,
read_simple_pairing_mode_rsp, 2, true },
{ 0x0c56, 142, "Write Simple Pairing Mode",
write_simple_pairing_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c57, 143, "Read Local OOB Data",
null_cmd, 0, true,
read_local_oob_data_rsp, 33, true },
{ 0x0c58, 144, "Read Inquiry Response TX Power Level",
null_cmd, 0, true,
read_inquiry_resp_tx_power_rsp, 2, true },
{ 0x0c59, 145, "Write Inquiry Transmit Power Level",
write_inquiry_tx_power_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c5a, 146, "Read Default Erroneous Data Reporting",
null_cmd, 0, true,
read_erroneous_reporting_rsp, 2, true },
{ 0x0c5b, 147, "Write Default Erroneous Data Reporting",
write_erroneous_reporting_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c5f, 158, "Enhanced Flush",
enhanced_flush_cmd, 3, true },
{ 0x0c60, 162, "Send Keypress Notification",
send_keypress_notify_cmd, 7, true,
send_keypress_notify_rsp, 7, true },
{ 0x0c61, 176, "Read Logical Link Accept Timeout" },
{ 0x0c62, 177, "Write Logical Link Accept Timeout" },
{ 0x0c63, 178, "Set Event Mask Page 2",
set_event_mask_page2_cmd, 8, true,
status_rsp, 1, true },
{ 0x0c64, 179, "Read Location Data",
null_cmd, 0, true,
read_location_data_rsp, 6, true },
{ 0x0c65, 180, "Write Location Data",
write_location_data_cmd, 5, true,
status_rsp, 1, true },
{ 0x0c66, 184, "Read Flow Control Mode",
null_cmd, 0, true,
read_flow_control_mode_rsp, 2, true },
{ 0x0c67, 185, "Write Flow Control Mode",
write_flow_control_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c68, 192, "Read Enhanced Transmit Power Level",
read_enhanced_tx_power_cmd, 3, true,
read_enhanced_tx_power_rsp, 6, true },
{ 0x0c69, 194, "Read Best Effort Flush Timeout" },
{ 0x0c6a, 195, "Write Best Effort Flush Timeout" },
{ 0x0c6b, 196, "Short Range Mode",
short_range_mode_cmd, 2, true },
{ 0x0c6c, 197, "Read LE Host Supported",
null_cmd, 0, true,
read_le_host_supported_rsp, 3, true },
{ 0x0c6d, 198, "Write LE Host Supported",
write_le_host_supported_cmd, 2, true,
status_rsp, 1, true },
{ 0x0c6e, 238, "Set MWS Channel Parameters" },
{ 0x0c6f, 239, "Set External Frame Configuration" },
{ 0x0c70, 240, "Set MWS Signaling" },
{ 0x0c71, 241, "Set MWS Transport Layer" },
{ 0x0c72, 242, "Set MWS Scan Frequency Table" },
{ 0x0c73, 244, "Set MWS Pattern Configuration" },
{ 0x0c74, 252, "Set Reserved LT_ADDR",
set_reserved_lt_addr_cmd, 1, true,
set_reserved_lt_addr_rsp, 2, true },
{ 0x0c75, 253, "Delete Reserved LT_ADDR",
delete_reserved_lt_addr_cmd, 1, true,
delete_reserved_lt_addr_rsp, 2, true },
{ 0x0c76, 254, "Set Connectionless Slave Broadcast Data",
set_slave_broadcast_data_cmd, 3, false,
set_slave_broadcast_data_rsp, 2, true },
{ 0x0c77, 255, "Read Synchronization Train Parameters",
null_cmd, 0, true,
read_sync_train_params_rsp, 8, true },
{ 0x0c78, 256, "Write Synchronization Train Parameters",
write_sync_train_params_cmd, 9, true,
write_sync_train_params_rsp, 3, true },
{ 0x0c79, 258, "Read Secure Connections Host Support",
null_cmd, 0, true,
read_secure_conn_support_rsp, 2, true },
{ 0x0c7a, 259, "Write Secure Connections Host Support",
write_secure_conn_support_cmd, 1, true,
status_rsp, 1, true },
{ 0x0c7b, 260, "Read Authenticated Payload Timeout",
read_auth_payload_timeout_cmd, 2, true,
read_auth_payload_timeout_rsp, 5, true },
{ 0x0c7c, 261, "Write Authenticated Payload Timeout",
write_auth_payload_timeout_cmd, 4, true,
write_auth_payload_timeout_rsp, 3, true },
{ 0x0c7d, 262, "Read Local OOB Extended Data",
null_cmd, 0, true,
read_local_oob_ext_data_rsp, 65, true },
{ 0x0c7e, 264, "Read Extended Page Timeout",
null_cmd, 0, true,
read_ext_page_timeout_rsp, 3, true },
{ 0x0c7f, 265, "Write Extended Page Timeout",
write_ext_page_timeout_cmd, 2, true,
status_rsp, 1, true },
{ 0x0c80, 266, "Read Extended Inquiry Length",
null_cmd, 0, true,
read_ext_inquiry_length_rsp, 3, true },
{ 0x0c81, 267, "Write Extended Inquiry Length",
write_ext_inquiry_length_cmd, 2, true,
status_rsp, 1, true },/* OGF 4 - Information Parameter */
{ 0x1001, 115, "Read Local Version Information",
null_cmd, 0, true,
read_local_version_rsp, 9, true },
{ 0x1002, 116, "Read Local Supported Commands",
null_cmd, 0, true,
read_local_commands_rsp, 65, true },
{ 0x1003, 117, "Read Local Supported Features",
null_cmd, 0, true,
read_local_features_rsp, 9, true },
{ 0x1004, 118, "Read Local Extended Features",
read_local_ext_features_cmd, 1, true,
read_local_ext_features_rsp, 11, true },
{ 0x1005, 119, "Read Buffer Size",
null_cmd, 0, true,
read_buffer_size_rsp, 8, true },
{ 0x1007, 120, "Read Country Code",
null_cmd, 0, true,
read_country_code_rsp, 2, true },
{ 0x1009, 121, "Read BD ADDR",
null_cmd, 0, true,
read_bd_addr_rsp, 7, true },
{ 0x100a, 186, "Read Data Block Size",
null_cmd, 0, true,
read_data_block_size_rsp, 7, true },
{ 0x100b, 237, "Read Local Supported Codecs",
null_cmd, 0, true,
read_local_codecs_rsp, 3, false },/* OGF 5 - Status Parameter */
{ 0x1401, 122, "Read Failed Contact Counter",
read_failed_contact_counter_cmd, 2, true,
read_failed_contact_counter_rsp, 5, true },
{ 0x1402, 123, "Reset Failed Contact Counter",
reset_failed_contact_counter_cmd, 2, true,
reset_failed_contact_counter_rsp, 3, true },
{ 0x1403, 124, "Read Link Quality",
read_link_quality_cmd, 2, true,
read_link_quality_rsp, 4, true },
{ 0x1405, 125, "Read RSSI",
read_rssi_cmd, 2, true,
read_rssi_rsp, 4, true },
{ 0x1406, 126, "Read AFH Channel Map",
read_afh_channel_map_cmd, 2, true,
read_afh_channel_map_rsp, 14, true },
{ 0x1407, 127, "Read Clock",
read_clock_cmd, 3, true,
read_clock_rsp, 9, true },
{ 0x1408, 164, "Read Encryption Key Size",
read_encrypt_key_size_cmd, 2, true,
read_encrypt_key_size_rsp, 4, true },
{ 0x1409, 181, "Read Local AMP Info",
null_cmd, 0, true,
read_local_amp_info_rsp, 31, true },
{ 0x140a, 182, "Read Local AMP ASSOC",
read_local_amp_assoc_cmd, 5, true,
read_local_amp_assoc_rsp, 5, false },
{ 0x140b, 183, "Write Remote AMP ASSOC",
write_remote_amp_assoc_cmd, 6, false,
write_remote_amp_assoc_rsp, 2, true },
{ 0x140c, 243, "Get MWS Transport Layer Configuration",
null_cmd, 0, true,
get_mws_transport_config_rsp, 2, false },
{ 0x140d, 245, "Set Triggered Clock Capture",
set_triggered_clock_capture_cmd, 6, true,
status_rsp, 1, true },/* OGF 6 - Testing */
{ 0x1801, 128, "Read Loopback Mode",
null_cmd, 0, true,
read_loopback_mode_rsp, 2, true },
{ 0x1802, 129, "Write Loopback Mode",
write_loopback_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x1803, 130, "Enable Device Under Test Mode",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x1804, 157, "Write Simple Pairing Debug Mode",
write_ssp_debug_mode_cmd, 1, true,
status_rsp, 1, true },
{ 0x1807, 189, "Enable AMP Receiver Reports" },
{ 0x1808, 190, "AMP Test End" },
{ 0x1809, 191, "AMP Test" },
{ 0x180a, 263, "Write Secure Connections Test Mode" },/* OGF 8 - LE Control */
{ 0x2001, 200, "LE Set Event Mask",
le_set_event_mask_cmd, 8, true,
status_rsp, 1, true },
{ 0x2002, 201, "LE Read Buffer Size",
null_cmd, 0, true,
le_read_buffer_size_rsp, 4, true },
{ 0x2003, 202, "LE Read Local Supported Features",
null_cmd, 0, true,
le_read_local_features_rsp, 9, true },
{ 0x2005, 204, "LE Set Random Address",
le_set_random_address_cmd, 6, true,
status_rsp, 1, true },
{ 0x2006, 205, "LE Set Advertising Parameters",
le_set_adv_parameters_cmd, 15, true,
status_rsp, 1, true },
{ 0x2007, 206, "LE Read Advertising Channel TX Power",
null_cmd, 0, true,
le_read_adv_tx_power_rsp, 2, true },
{ 0x2008, 207, "LE Set Advertising Data",
le_set_adv_data_cmd, 32, true,
status_rsp, 1, true },
{ 0x2009, 208, "LE Set Scan Response Data",
le_set_scan_rsp_data_cmd, 32, true,
status_rsp, 1, true },
{ 0x200a, 209, "LE Set Advertise Enable",
le_set_adv_enable_cmd, 1, true,
status_rsp, 1, true },
{ 0x200b, 210, "LE Set Scan Parameters",
le_set_scan_parameters_cmd, 7, true,
status_rsp, 1, true },
{ 0x200c, 211, "LE Set Scan Enable",
le_set_scan_enable_cmd, 2, true,
status_rsp, 1, true },
{ 0x200d, 212, "LE Create Connection",
le_create_conn_cmd, 25, true },
{ 0x200e, 213, "LE Create Connection Cancel",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x200f, 214, "LE Read White List Size",
null_cmd, 0, true,
le_read_white_list_size_rsp, 2, true },
{ 0x2010, 215, "LE Clear White List",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x2011, 216, "LE Add Device To White List",
le_add_to_white_list_cmd, 7, true,
status_rsp, 1, true },
{ 0x2012, 217, "LE Remove Device From White List",
le_remove_from_white_list_cmd, 7, true,
status_rsp, 1, true },
{ 0x2013, 218, "LE Connection Update",
le_conn_update_cmd, 14, true },
{ 0x2014, 219, "LE Set Host Channel Classification",
le_set_host_classification_cmd, 5, true,
status_rsp, 1, true },
{ 0x2015, 220, "LE Read Channel Map",
le_read_channel_map_cmd, 2, true,
le_read_channel_map_rsp, 8, true },
{ 0x2016, 221, "LE Read Remote Used Features",
le_read_remote_features_cmd, 2, true },
{ 0x2017, 222, "LE Encrypt",
le_encrypt_cmd, 32, true,
le_encrypt_rsp, 17, true },
{ 0x2018, 223, "LE Rand",
null_cmd, 0, true,
le_rand_rsp, 9, true },
{ 0x2019, 224, "LE Start Encryption",
le_start_encrypt_cmd, 28, true },
{ 0x201a, 225, "LE Long Term Key Request Reply",
le_ltk_req_reply_cmd, 18, true,
le_ltk_req_reply_rsp, 3, true },
{ 0x201b, 226, "LE Long Term Key Request Neg Reply",
le_ltk_req_neg_reply_cmd, 2, true,
le_ltk_req_neg_reply_rsp, 3, true },
{ 0x201c, 227, "LE Read Supported States",
null_cmd, 0, true,
le_read_supported_states_rsp, 9, true },
{ 0x201d, 228, "LE Receiver Test",
le_receiver_test_cmd, 1, true,
status_rsp, 1, true },
{ 0x201e, 229, "LE Transmitter Test",
le_transmitter_test_cmd, 3, true,
status_rsp, 1, true },
{ 0x201f, 230, "LE Test End",
null_cmd, 0, true,
le_test_end_rsp, 3, true },
{ 0x2020, 268, "LE Remote Connection Parameter Request Reply",
le_conn_param_req_reply_cmd, 14, true,
le_conn_param_req_reply_rsp, 3, true },
{ 0x2021, 269, "LE Remote Connection Parameter Request Negative Reply",
le_conn_param_req_neg_reply_cmd, 3, true,
le_conn_param_req_neg_reply_rsp, 3, true },
{ 0x2022, 270, "LE Set Data Length",
le_set_data_length_cmd, 6, true,
le_set_data_length_rsp, 3, true },
{ 0x2023, 271, "LE Read Suggested Default Data Length",
null_cmd, 0, true,
le_read_default_data_length_rsp, 5, true },
{ 0x2024, 272, "LE Write Suggested Default Data Length",
le_write_default_data_length_cmd, 4, true,
status_rsp, 1, true },
{ 0x2025, 273, "LE Read Local P-256 Public Key",
null_cmd, 0, true },
{ 0x2026, 274, "LE Generate DHKey",
le_generate_dhkey_cmd, 64, true },
{ 0x2027, 275, "LE Add Device To Resolving List",
le_add_to_resolv_list_cmd, 39, true,
status_rsp, 1, true },
{ 0x2028, 276, "LE Remove Device From Resolving List",
le_remove_from_resolv_list_cmd, 7, true,
status_rsp, 1, true },
{ 0x2029, 277, "LE Clear Resolving List",
null_cmd, 0, true,
status_rsp, 1, true },
{ 0x202a, 278, "LE Read Resolving List Size",
null_cmd, 0, true,
le_read_resolv_list_size_rsp, 2, true },
{ 0x202b, 279, "LE Read Peer Resolvable Address",
le_read_peer_resolv_addr_cmd, 7, true,
le_read_peer_resolv_addr_rsp, 7, true },
{ 0x202c, 280, "LE Read Local Resolvable Address",
le_read_local_resolv_addr_cmd, 7, true,
le_read_local_resolv_addr_rsp, 7, true },
{ 0x202d, 281, "LE Set Address Resolution Enable",
le_set_resolv_enable_cmd, 1, true,
status_rsp, 1, true },
{ 0x202e, 282, "LE Set Resolvable Private Address Timeout",
le_set_resolv_timeout_cmd, 2, true,
status_rsp, 1, true },
{ 0x202f, 283, "LE Read Maximum Data Length",
null_cmd, 0, true,
le_read_max_data_length_rsp, 9, true },
{ 0x2030, 284, "LE Read PHY",
le_read_phy_cmd, 2, true,
le_read_phy_rsp, 5, true},
{ 0x2031, 285, "LE Set Default PHY",
le_set_default_phy_cmd, 3, true,
status_rsp, 1, true },
{ 0x2032, 286, "LE Set PHY",
le_set_phy_cmd, 7, true},
{ 0x2033, 287, "LE Enhanced Receiver Test" },
{ 0x2034, 288, "LE Enhanced Transmitter Test" },
{ 0x2035, 289, "LE Set Advertising Set Random Address" },
{ 0x2036, 290, "LE Set Extended Advertising Parameters" },
{ 0x2037, 291, "LE Set Extended Advertising Data" },
{ 0x2038, 292, "LE Set Extended Scan Response Data" },
{ 0x2039, 293, "LE Set Extended Advertising Enable" },
{ 0x203a, 294, "LE Read Maximum Advertising Data Length" },
{ 0x203b, 295, "LE Read Number of Supported Advertising Sets" },
{ 0x203c, 296, "LE Remove Advertising Set" },
{ 0x203d, 297, "LE Clear Advertising Sets" },
{ 0x203e, 298, "LE Set Periodic Advertising Parameters" },
{ 0x203f, 299, "LE Set Periodic Advertising Data" },
{ 0x2040, 300, "LE Set Periodic Advertising Enable" },
{ 0x2041, 301, "LE Set Extended Scan Parameters" },
{ 0x2042, 302, "LE Set Extended Scan Enable" },
{ 0x2043, 303, "LE Extended Create Connection" },
{ 0x2044, 304, "LE Periodic Advertising Create Sync" },
{ 0x2045, 305, "LE Periodic Advertising Create Sync Cancel" },
{ 0x2046, 306, "LE Periodic Advertising Terminate Sync" },
{ 0x2047, 307, "LE Add Device To Periodic Advertiser List" },
{ 0x2048, 308, "LE Remove Device From Periodic Advertiser List" },
{ 0x2049, 309, "LE Clear Periodic Advertiser List" },
{ 0x204a, 310, "LE Read Periodic Advertiser List Size" },
{ 0x204b, 311, "LE Read Transmit Power" },
{ 0x204c, 312, "LE Read RF Path Compensation" },
{ 0x204d, 313, "LE Write RF Path Compensation" },
{ 0x204e, 314, "LE Set Privacy Mode" },
{ }
};