From f079816f69df4f1703fcf27e62ec376a66656e49 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Tue, 17 Aug 2021 05:25:39 +0800 Subject: [PATCH] Add bluetooth lib for dirrect access to some functions. --- Makefile | 3 +- MiSTer.ini | 5 + MiSTer.vcxproj | 2 +- lib/bluetooth/a2mp.h | 149 ++ lib/bluetooth/amp.h | 172 +++ lib/bluetooth/bluetooth.h | 423 ++++++ lib/bluetooth/bnep.h | 162 +++ lib/bluetooth/cmtp.h | 69 + lib/bluetooth/hci.h | 2454 +++++++++++++++++++++++++++++++++ lib/bluetooth/hci_lib.h | 242 ++++ lib/bluetooth/hidp.h | 85 ++ lib/bluetooth/l2cap.h | 279 ++++ lib/bluetooth/libbluetooth.so | Bin 0 -> 150312 bytes lib/bluetooth/mgmt.h | 991 +++++++++++++ lib/bluetooth/rfcomm.h | 99 ++ lib/bluetooth/sco.h | 62 + lib/bluetooth/sdp.h | 542 ++++++++ lib/bluetooth/sdp_lib.h | 634 +++++++++ lib/bluetooth/uuid.h | 199 +++ menu.cpp | 20 +- 20 files changed, 6575 insertions(+), 17 deletions(-) create mode 100644 lib/bluetooth/a2mp.h create mode 100644 lib/bluetooth/amp.h create mode 100644 lib/bluetooth/bluetooth.h create mode 100644 lib/bluetooth/bnep.h create mode 100644 lib/bluetooth/cmtp.h create mode 100644 lib/bluetooth/hci.h create mode 100644 lib/bluetooth/hci_lib.h create mode 100644 lib/bluetooth/hidp.h create mode 100644 lib/bluetooth/l2cap.h create mode 100644 lib/bluetooth/libbluetooth.so create mode 100644 lib/bluetooth/mgmt.h create mode 100644 lib/bluetooth/rfcomm.h create mode 100644 lib/bluetooth/sco.h create mode 100644 lib/bluetooth/sdp.h create mode 100644 lib/bluetooth/sdp_lib.h create mode 100644 lib/bluetooth/uuid.h diff --git a/Makefile b/Makefile index 46822b1..aa5a061 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ INCLUDE += -I./lib/lzma INCLUDE += -I./lib/libchdr/include INCLUDE += -I./lib/flac/include INCLUDE += -I./lib/flac/src/include +INCLUDE += -I./lib/bluetooth PRJ = MiSTer C_SRC = $(wildcard *.c) \ @@ -47,7 +48,7 @@ DEP = $(C_SRC:.c=.c.d) $(CPP_SRC:.cpp=.cpp.d) DFLAGS = $(INCLUDE) -D_7ZIP_ST -DPACKAGE_VERSION=\"1.3.3\" -DFLAC_API_EXPORTS -DFLAC__HAS_OGG=0 -DHAVE_LROUND -DHAVE_STDINT_H -DHAVE_STDLIB_H -DHAVE_SYS_PARAM_H -DENABLE_64_BIT_WORDS=0 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DVDATE=\"`date +"%y%m%d"`\" CFLAGS = $(DFLAGS) -Wall -Wextra -Wno-strict-aliasing -Wno-format-truncation -Wno-psabi -c -O3 -LFLAGS = -lc -lstdc++ -lm -lrt $(IMLIB2_LIB) +LFLAGS = -lc -lstdc++ -lm -lrt $(IMLIB2_LIB) -Llib/bluetooth -lbluetooth $(PRJ): $(OBJ) $(Q)$(info $@) diff --git a/MiSTer.ini b/MiSTer.ini index e6a9ff7..a14c937 100644 --- a/MiSTer.ini +++ b/MiSTer.ini @@ -166,3 +166,8 @@ gamepad_defaults=0 ; External application or script may parse the info and do some additional actions and/or send info to 3rd party server. ; Warning: it may slowdown the system or add lag while browsing the files in OSD depending on external app/script. log_file_entry=0 + +; Automatically disconnect (and shutdown) Bluetooth input device if not use specified amount of time. +; Some controllers have no automatic shutdown built in and will keep connection till battery dry out. +; 0 - don't disconnect automatically, otherwise it's amount of minutes. +bt_auto_disconnect=0 diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj index e906c7b..8de9bdc 100644 --- a/MiSTer.vcxproj +++ b/MiSTer.vcxproj @@ -30,7 +30,7 @@ MiSTer git.lnk ./clean.sh __arm__;__GNUC__;__USE_GNU ;_GNU_SOURCE;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions) - c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc75\lib\gcc\arm-linux-gnueabihf\7.5.0\include;c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\include\c++\7.5.0;c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\include\c++\7.5.0\arm-linux-gnueabihf;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng;lib\libchdr\include + c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc75\lib\gcc\arm-linux-gnueabihf\7.5.0\include;c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\include\c++\7.5.0;c:\Work\Git\opt\gcc75\arm-linux-gnueabihf\include\c++\7.5.0\arm-linux-gnueabihf;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng;lib\libchdr\include;lib\bluetooth $(TEMP) $(TEMP) diff --git a/lib/bluetooth/a2mp.h b/lib/bluetooth/a2mp.h new file mode 100644 index 0000000..da937d1 --- /dev/null +++ b/lib/bluetooth/a2mp.h @@ -0,0 +1,149 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012 Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __A2MP_H +#define __A2MP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* A2MP Protocol */ + +/* A2MP command codes */ + +#define A2MP_COMMAND_REJ 0x01 +#define A2MP_DISCOVER_REQ 0x02 +#define A2MP_DISCOVER_RSP 0x03 +#define A2MP_CHANGE_NOTIFY 0x04 +#define A2MP_CHANGE_RSP 0x05 +#define A2MP_INFO_REQ 0x06 +#define A2MP_INFO_RSP 0x07 +#define A2MP_ASSOC_REQ 0x08 +#define A2MP_ASSOC_RSP 0x09 +#define A2MP_CREATE_REQ 0x0a +#define A2MP_CREATE_RSP 0x0b +#define A2MP_DISCONN_REQ 0x0c +#define A2MP_DISCONN_RSP 0x0d + +struct a2mp_hdr { + uint8_t code; + uint8_t ident; + uint16_t len; +} __attribute__ ((packed)); +#define A2MP_HDR_SIZE 4 + +struct a2mp_command_rej { + uint16_t reason; +} __attribute__ ((packed)); + +struct a2mp_discover_req { + uint16_t mtu; + uint16_t mask; +} __attribute__ ((packed)); + +struct a2mp_ctrl { + uint8_t id; + uint8_t type; + uint8_t status; +} __attribute__ ((packed)); + +struct a2mp_discover_rsp { + uint16_t mtu; + uint16_t mask; + struct a2mp_ctrl ctrl_list[0]; +} __attribute__ ((packed)); + +struct a2mp_info_req { + uint8_t id; +} __attribute__ ((packed)); + +struct a2mp_info_rsp { + uint8_t id; + uint8_t status; + uint32_t total_bw; + uint32_t max_bw; + uint32_t min_latency; + uint16_t pal_caps; + uint16_t assoc_size; +} __attribute__ ((packed)); + +struct a2mp_assoc_req { + uint8_t id; +} __attribute__ ((packed)); + +struct a2mp_assoc_rsp { + uint8_t id; + uint8_t status; + uint8_t assoc_data[0]; +} __attribute__ ((packed)); + +struct a2mp_create_req { + uint8_t local_id; + uint8_t remote_id; + uint8_t assoc_data[0]; +} __attribute__ ((packed)); + +struct a2mp_create_rsp { + uint8_t local_id; + uint8_t remote_id; + uint8_t status; +} __attribute__ ((packed)); + +struct a2mp_disconn_req { + uint8_t local_id; + uint8_t remote_id; +} __attribute__ ((packed)); + +struct a2mp_disconn_rsp { + uint8_t local_id; + uint8_t remote_id; + uint8_t status; +} __attribute__ ((packed)); + +#define A2MP_COMMAND_NOT_RECOGNIZED 0x0000 + +/* AMP controller status */ +#define AMP_CTRL_POWERED_DOWN 0x00 +#define AMP_CTRL_BLUETOOTH_ONLY 0x01 +#define AMP_CTRL_NO_CAPACITY 0x02 +#define AMP_CTRL_LOW_CAPACITY 0x03 +#define AMP_CTRL_MEDIUM_CAPACITY 0x04 +#define AMP_CTRL_HIGH_CAPACITY 0x05 +#define AMP_CTRL_FULL_CAPACITY 0x06 + +/* A2MP response status */ +#define A2MP_STATUS_SUCCESS 0x00 +#define A2MP_STATUS_INVALID_CTRL_ID 0x01 +#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02 +#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 +#define A2MP_STATUS_COLLISION_OCCURED 0x03 +#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04 +#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 +#define A2MP_STATUS_SECURITY_VIOLATION 0x06 + +#ifdef __cplusplus +} +#endif + +#endif /* __A2MP_H */ diff --git a/lib/bluetooth/amp.h b/lib/bluetooth/amp.h new file mode 100644 index 0000000..27aab1d --- /dev/null +++ b/lib/bluetooth/amp.h @@ -0,0 +1,172 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2010-2011 Code Aurora Forum. All rights reserved. + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __AMP_H +#define __AMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define AMP_MGR_CID 0x03 + +/* AMP manager codes */ +#define AMP_COMMAND_REJ 0x01 +#define AMP_DISCOVER_REQ 0x02 +#define AMP_DISCOVER_RSP 0x03 +#define AMP_CHANGE_NOTIFY 0x04 +#define AMP_CHANGE_RSP 0x05 +#define AMP_INFO_REQ 0x06 +#define AMP_INFO_RSP 0x07 +#define AMP_ASSOC_REQ 0x08 +#define AMP_ASSOC_RSP 0x09 +#define AMP_LINK_REQ 0x0a +#define AMP_LINK_RSP 0x0b +#define AMP_DISCONN_REQ 0x0c +#define AMP_DISCONN_RSP 0x0d + +typedef struct { + uint8_t code; + uint8_t ident; + uint16_t len; +} __attribute__ ((packed)) amp_mgr_hdr; +#define AMP_MGR_HDR_SIZE 4 + +/* AMP ASSOC structure */ +typedef struct { + uint8_t type_id; + uint16_t len; + uint8_t data[0]; +} __attribute__ ((packed)) amp_assoc_tlv; + +typedef struct { + uint16_t reason; +} __attribute__ ((packed)) amp_cmd_rej_parms; + +typedef struct { + uint16_t mtu; + uint16_t mask; +} __attribute__ ((packed)) amp_discover_req_parms; + +typedef struct { + uint16_t mtu; + uint16_t mask; + uint8_t controller_list[0]; +} __attribute__ ((packed)) amp_discover_rsp_parms; + +typedef struct { + uint8_t id; +} __attribute__ ((packed)) amp_info_req_parms; + +typedef struct { + uint8_t id; + uint8_t status; + uint32_t total_bandwidth; + uint32_t max_bandwidth; + uint32_t min_latency; + uint16_t pal_caps; + uint16_t assoc_size; +} __attribute__ ((packed)) amp_info_rsp_parms; + +typedef struct { + uint8_t id; + uint8_t status; + amp_assoc_tlv assoc; +} __attribute__ ((packed)) amp_assoc_rsp_parms; + +typedef struct { + uint8_t local_id; + uint8_t remote_id; + amp_assoc_tlv assoc; +} __attribute__ ((packed)) amp_link_req_parms; + +typedef struct { + uint8_t local_id; + uint8_t remote_id; + uint8_t status; +} __attribute__ ((packed)) amp_link_rsp_parms; + +typedef struct { + uint8_t local_id; + uint8_t remote_id; +} __attribute__ ((packed)) amp_disconn_req_parms; + +#define A2MP_MAC_ADDR_TYPE 1 +#define A2MP_PREF_CHANLIST_TYPE 2 +#define A2MP_CONNECTED_CHAN 3 +#define A2MP_PAL_CAP_TYPE 4 +#define A2MP_PAL_VER_INFO 5 + +struct amp_tlv { + uint8_t type; + uint16_t len; + uint8_t val[0]; +} __attribute__ ((packed)); + +struct amp_pal_ver { + uint8_t ver; + uint16_t company_id; + uint16_t sub_ver; +} __attribute__ ((packed)); + +struct amp_country_triplet { + union { + struct { + uint8_t first_channel; + uint8_t num_channels; + int8_t max_power; + } __attribute__ ((packed)) chans; + struct { + uint8_t reg_extension_id; + uint8_t reg_class; + uint8_t coverage_class; + } __attribute__ ((packed)) ext; + }; +} __attribute__ ((packed)); + +struct amp_chan_list { + uint8_t country_code[3]; + struct amp_country_triplet triplets[0]; +} __attribute__ ((packed)); + +#define AMP_COMMAND_NOT_RECOGNIZED 0x0000 + +/* AMP controller status */ +#define AMP_CT_POWERED_DOWN 0x00 +#define AMP_CT_BLUETOOTH_ONLY 0x01 +#define AMP_CT_NO_CAPACITY 0x02 +#define AMP_CT_LOW_CAPACITY 0x03 +#define AMP_CT_MEDIUM_CAPACITY 0x04 +#define AMP_CT_HIGH_CAPACITY 0x05 +#define AMP_CT_FULL_CAPACITY 0x06 + +/* AMP response status */ +#define AMP_STATUS_SUCCESS 0x00 +#define AMP_STATUS_INVALID_CTRL_ID 0x01 +#define AMP_STATUS_UNABLE_START_LINK_CREATION 0x02 +#define AMP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 +#define AMP_STATUS_COLLISION_OCCURED 0x03 +#define AMP_STATUS_DISCONN_REQ_RECVD 0x04 +#define AMP_STATUS_PHYS_LINK_EXISTS 0x05 +#define AMP_STATUS_SECURITY_VIOLATION 0x06 + +#ifdef __cplusplus +} +#endif + +#endif /* __AMP_H */ diff --git a/lib/bluetooth/bluetooth.h b/lib/bluetooth/bluetooth.h new file mode 100644 index 0000000..d14217e --- /dev/null +++ b/lib/bluetooth/bluetooth.h @@ -0,0 +1,423 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLUETOOTH_H +#define __BLUETOOTH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef AF_BLUETOOTH +#define AF_BLUETOOTH 31 +#define PF_BLUETOOTH AF_BLUETOOTH +#endif + +#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 + +#ifndef SOL_BLUETOOTH +#define SOL_BLUETOOTH 274 +#endif + +#define BT_SECURITY 4 +struct bt_security { + uint8_t level; + uint8_t key_size; +}; +#define BT_SECURITY_SDP 0 +#define BT_SECURITY_LOW 1 +#define BT_SECURITY_MEDIUM 2 +#define BT_SECURITY_HIGH 3 +#define BT_SECURITY_FIPS 4 + +#define BT_DEFER_SETUP 7 + +#define BT_FLUSHABLE 8 + +#define BT_FLUSHABLE_OFF 0 +#define BT_FLUSHABLE_ON 1 + +#define BT_POWER 9 +struct bt_power { + uint8_t force_active; +}; +#define BT_POWER_FORCE_ACTIVE_OFF 0 +#define BT_POWER_FORCE_ACTIVE_ON 1 + +#define BT_CHANNEL_POLICY 10 + +/* BR/EDR only (default policy) + * AMP controllers cannot be used. + * Channel move requests from the remote device are denied. + * If the L2CAP channel is currently using AMP, move the channel to BR/EDR. + */ +#define BT_CHANNEL_POLICY_BREDR_ONLY 0 + +/* BR/EDR Preferred + * Allow use of AMP controllers. + * If the L2CAP channel is currently on AMP, move it to BR/EDR. + * Channel move requests from the remote device are allowed. + */ +#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1 + +/* AMP Preferred + * Allow use of AMP controllers + * If the L2CAP channel is currently on BR/EDR and AMP controller + * resources are available, initiate a channel move to AMP. + * Channel move requests from the remote device are allowed. + * If the L2CAP socket has not been connected yet, try to create + * and configure the channel directly on an AMP controller rather + * than BR/EDR. + */ +#define BT_CHANNEL_POLICY_AMP_PREFERRED 2 + +#define BT_VOICE 11 +struct bt_voice { + uint16_t setting; +}; + +#define BT_SNDMTU 12 +#define BT_RCVMTU 13 + +#define BT_VOICE_TRANSPARENT 0x0003 +#define BT_VOICE_CVSD_16BIT 0x0060 + +#define BT_PHY 14 + +#define BT_PHY_BR_1M_1SLOT 0x00000001 +#define BT_PHY_BR_1M_3SLOT 0x00000002 +#define BT_PHY_BR_1M_5SLOT 0x00000004 +#define BT_PHY_EDR_2M_1SLOT 0x00000008 +#define BT_PHY_EDR_2M_3SLOT 0x00000010 +#define BT_PHY_EDR_2M_5SLOT 0x00000020 +#define BT_PHY_EDR_3M_1SLOT 0x00000040 +#define BT_PHY_EDR_3M_3SLOT 0x00000080 +#define BT_PHY_EDR_3M_5SLOT 0x00000100 +#define BT_PHY_LE_1M_TX 0x00000200 +#define BT_PHY_LE_1M_RX 0x00000400 +#define BT_PHY_LE_2M_TX 0x00000800 +#define BT_PHY_LE_2M_RX 0x00001000 +#define BT_PHY_LE_CODED_TX 0x00002000 +#define BT_PHY_LE_CODED_RX 0x00004000 + +/* Connection and socket states */ +enum { + BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ + BT_OPEN, + BT_BOUND, + BT_LISTEN, + BT_CONNECT, + BT_CONNECT2, + BT_CONFIG, + BT_DISCONN, + BT_CLOSED +}; + +/* Byte order conversions */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobs(d) (d) +#define htobl(d) (d) +#define htobll(d) (d) +#define btohs(d) (d) +#define btohl(d) (d) +#define btohll(d) (d) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define htobs(d) bswap_16(d) +#define htobl(d) bswap_32(d) +#define htobll(d) bswap_64(d) +#define btohs(d) bswap_16(d) +#define btohl(d) bswap_32(d) +#define btohll(d) bswap_64(d) +#else +#error "Unknown byte order" +#endif + +/* Bluetooth unaligned access */ +#define bt_get_unaligned(ptr) \ +__extension__ ({ \ + struct __attribute__((packed)) { \ + __typeof__(*(ptr)) __v; \ + } *__p = (__typeof__(__p)) (ptr); \ + __p->__v; \ +}) + +#define bt_put_unaligned(val, ptr) \ +do { \ + struct __attribute__((packed)) { \ + __typeof__(*(ptr)) __v; \ + } *__p = (__typeof__(__p)) (ptr); \ + __p->__v = (val); \ +} while(0) + +#if __BYTE_ORDER == __LITTLE_ENDIAN +static inline uint64_t bt_get_le64(const void *ptr) +{ + return bt_get_unaligned((const uint64_t *) ptr); +} + +static inline uint64_t bt_get_be64(const void *ptr) +{ + return bswap_64(bt_get_unaligned((const uint64_t *) ptr)); +} + +static inline uint32_t bt_get_le32(const void *ptr) +{ + return bt_get_unaligned((const uint32_t *) ptr); +} + +static inline uint32_t bt_get_be32(const void *ptr) +{ + return bswap_32(bt_get_unaligned((const uint32_t *) ptr)); +} + +static inline uint16_t bt_get_le16(const void *ptr) +{ + return bt_get_unaligned((const uint16_t *) ptr); +} + +static inline uint16_t bt_get_be16(const void *ptr) +{ + return bswap_16(bt_get_unaligned((const uint16_t *) ptr)); +} + +static inline void bt_put_le64(uint64_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint64_t *) ptr); +} + +static inline void bt_put_be64(uint64_t val, const void *ptr) +{ + bt_put_unaligned(bswap_64(val), (uint64_t *) ptr); +} + +static inline void bt_put_le32(uint32_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint32_t *) ptr); +} + +static inline void bt_put_be32(uint32_t val, const void *ptr) +{ + bt_put_unaligned(bswap_32(val), (uint32_t *) ptr); +} + +static inline void bt_put_le16(uint16_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint16_t *) ptr); +} + +static inline void bt_put_be16(uint16_t val, const void *ptr) +{ + bt_put_unaligned(bswap_16(val), (uint16_t *) ptr); +} + +#elif __BYTE_ORDER == __BIG_ENDIAN +static inline uint64_t bt_get_le64(const void *ptr) +{ + return bswap_64(bt_get_unaligned((const uint64_t *) ptr)); +} + +static inline uint64_t bt_get_be64(const void *ptr) +{ + return bt_get_unaligned((const uint64_t *) ptr); +} + +static inline uint32_t bt_get_le32(const void *ptr) +{ + return bswap_32(bt_get_unaligned((const uint32_t *) ptr)); +} + +static inline uint32_t bt_get_be32(const void *ptr) +{ + return bt_get_unaligned((const uint32_t *) ptr); +} + +static inline uint16_t bt_get_le16(const void *ptr) +{ + return bswap_16(bt_get_unaligned((const uint16_t *) ptr)); +} + +static inline uint16_t bt_get_be16(const void *ptr) +{ + return bt_get_unaligned((const uint16_t *) ptr); +} + +static inline void bt_put_le64(uint64_t val, const void *ptr) +{ + bt_put_unaligned(bswap_64(val), (uint64_t *) ptr); +} + +static inline void bt_put_be64(uint64_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint64_t *) ptr); +} + +static inline void bt_put_le32(uint32_t val, const void *ptr) +{ + bt_put_unaligned(bswap_32(val), (uint32_t *) ptr); +} + +static inline void bt_put_be32(uint32_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint32_t *) ptr); +} + +static inline void bt_put_le16(uint16_t val, const void *ptr) +{ + bt_put_unaligned(bswap_16(val), (uint16_t *) ptr); +} + +static inline void bt_put_be16(uint16_t val, const void *ptr) +{ + bt_put_unaligned(val, (uint16_t *) ptr); +} +#else +#error "Unknown byte order" +#endif + +/* BD Address */ +typedef struct { + uint8_t b[6]; +} __attribute__((packed)) bdaddr_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}}) + +/* Copy, swap, convert BD Address */ +static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2) +{ + return memcmp(ba1, ba2, sizeof(bdaddr_t)); +} +static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src) +{ + memcpy(dst, src, sizeof(bdaddr_t)); +} + +void baswap(bdaddr_t *dst, const bdaddr_t *src); +bdaddr_t *strtoba(const char *str); +char *batostr(const bdaddr_t *ba); +int ba2str(const bdaddr_t *ba, char *str); +int ba2strlc(const bdaddr_t *ba, char *str); +int str2ba(const char *str, bdaddr_t *ba); +int ba2oui(const bdaddr_t *ba, char *oui); +int bachk(const char *str); + +int baprintf(const char *format, ...); +int bafprintf(FILE *stream, const char *format, ...); +int basprintf(char *str, const char *format, ...); +int basnprintf(char *str, size_t size, const char *format, ...); + +void *bt_malloc(size_t size); +void bt_free(void *ptr); + +int bt_error(uint16_t code); +const char *bt_compidtostr(int id); + +typedef struct { + uint8_t data[16]; +} uint128_t; + +static inline void bswap_128(const void *src, void *dst) +{ + const uint8_t *s = (const uint8_t *) src; + uint8_t *d = (uint8_t *) dst; + int i; + + for (i = 0; i < 16; i++) + d[15 - i] = s[i]; +} + +#if __BYTE_ORDER == __BIG_ENDIAN + +#define ntoh64(x) (x) + +static inline void ntoh128(const uint128_t *src, uint128_t *dst) +{ + memcpy(dst, src, sizeof(uint128_t)); +} + +static inline void btoh128(const uint128_t *src, uint128_t *dst) +{ + bswap_128(src, dst); +} + +#else + +static inline uint64_t ntoh64(uint64_t n) +{ + uint64_t h; + uint64_t tmp = ntohl(n & 0x00000000ffffffff); + + h = ntohl(n >> 32); + h |= tmp << 32; + + return h; +} + +static inline void ntoh128(const uint128_t *src, uint128_t *dst) +{ + bswap_128(src, dst); +} + +static inline void btoh128(const uint128_t *src, uint128_t *dst) +{ + memcpy(dst, src, sizeof(uint128_t)); +} + +#endif + +#define hton64(x) ntoh64(x) +#define hton128(x, y) ntoh128(x, y) +#define htob128(x, y) btoh128(x, y) + +#ifdef __cplusplus +} +#endif + +#endif /* __BLUETOOTH_H */ diff --git a/lib/bluetooth/bnep.h b/lib/bluetooth/bnep.h new file mode 100644 index 0000000..e7c2c87 --- /dev/null +++ b/lib/bluetooth/bnep.h @@ -0,0 +1,162 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BNEP_H +#define __BNEP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef ETH_ALEN +#define ETH_ALEN 6 /* from */ +#endif + +/* BNEP UUIDs */ +#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB +#define BNEP_UUID16 0x02 +#define BNEP_UUID32 0x04 +#define BNEP_UUID128 0x16 + +#define BNEP_SVC_PANU 0x1115 +#define BNEP_SVC_NAP 0x1116 +#define BNEP_SVC_GN 0x1117 + +/* BNEP packet types */ +#define BNEP_GENERAL 0x00 +#define BNEP_CONTROL 0x01 +#define BNEP_COMPRESSED 0x02 +#define BNEP_COMPRESSED_SRC_ONLY 0x03 +#define BNEP_COMPRESSED_DST_ONLY 0x04 + +/* BNEP control types */ +#define BNEP_CMD_NOT_UNDERSTOOD 0x00 +#define BNEP_SETUP_CONN_REQ 0x01 +#define BNEP_SETUP_CONN_RSP 0x02 +#define BNEP_FILTER_NET_TYPE_SET 0x03 +#define BNEP_FILTER_NET_TYPE_RSP 0x04 +#define BNEP_FILTER_MULT_ADDR_SET 0x05 +#define BNEP_FILTER_MULT_ADDR_RSP 0x06 + +/* BNEP response messages */ +#define BNEP_SUCCESS 0x00 + +#define BNEP_CONN_INVALID_DST 0x01 +#define BNEP_CONN_INVALID_SRC 0x02 +#define BNEP_CONN_INVALID_SVC 0x03 +#define BNEP_CONN_NOT_ALLOWED 0x04 + +#define BNEP_FILTER_UNSUPPORTED_REQ 0x01 +#define BNEP_FILTER_INVALID_RANGE 0x02 +#define BNEP_FILTER_INVALID_MCADDR 0x02 +#define BNEP_FILTER_LIMIT_REACHED 0x03 +#define BNEP_FILTER_DENIED_SECURITY 0x04 + +/* L2CAP settings */ +#define BNEP_MTU 1691 +#define BNEP_FLUSH_TO 0xffff +#define BNEP_CONNECT_TO 15 +#define BNEP_FILTER_TO 15 + +#ifndef BNEP_PSM +#define BNEP_PSM 0x0f +#endif + +/* BNEP headers */ +#define BNEP_TYPE_MASK 0x7f +#define BNEP_EXT_HEADER 0x80 + +struct bnep_setup_conn_req { + uint8_t type; + uint8_t ctrl; + uint8_t uuid_size; + uint8_t service[0]; +} __attribute__((packed)); + +struct bnep_set_filter_req { + uint8_t type; + uint8_t ctrl; + uint16_t len; + uint8_t list[0]; +} __attribute__((packed)); + +struct bnep_ctrl_cmd_not_understood_cmd { + uint8_t type; + uint8_t ctrl; + uint8_t unkn_ctrl; +} __attribute__((packed)); + +struct bnep_control_rsp { + uint8_t type; + uint8_t ctrl; + uint16_t resp; +} __attribute__((packed)); + +struct bnep_ext_hdr { + uint8_t type; + uint8_t len; + uint8_t data[0]; +} __attribute__((packed)); + +/* BNEP ioctl defines */ +#define BNEPCONNADD _IOW('B', 200, int) +#define BNEPCONNDEL _IOW('B', 201, int) +#define BNEPGETCONNLIST _IOR('B', 210, int) +#define BNEPGETCONNINFO _IOR('B', 211, int) +#define BNEPGETSUPPFEAT _IOR('B', 212, int) + +#define BNEP_SETUP_RESPONSE 0 + +struct bnep_connadd_req { + int sock; /* Connected socket */ + uint32_t flags; + uint16_t role; + char device[16]; /* Name of the Ethernet device */ +}; + +struct bnep_conndel_req { + uint32_t flags; + uint8_t dst[ETH_ALEN]; +}; + +struct bnep_conninfo { + uint32_t flags; + uint16_t role; + uint16_t state; + uint8_t dst[ETH_ALEN]; + char device[16]; +}; + +struct bnep_connlist_req { + uint32_t cnum; + struct bnep_conninfo *ci; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __BNEP_H */ diff --git a/lib/bluetooth/cmtp.h b/lib/bluetooth/cmtp.h new file mode 100644 index 0000000..ce937bd --- /dev/null +++ b/lib/bluetooth/cmtp.h @@ -0,0 +1,69 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CMTP_H +#define __CMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* CMTP defaults */ +#define CMTP_MINIMUM_MTU 152 +#define CMTP_DEFAULT_MTU 672 + +/* CMTP ioctl defines */ +#define CMTPCONNADD _IOW('C', 200, int) +#define CMTPCONNDEL _IOW('C', 201, int) +#define CMTPGETCONNLIST _IOR('C', 210, int) +#define CMTPGETCONNINFO _IOR('C', 211, int) + +#define CMTP_LOOPBACK 0 + +struct cmtp_connadd_req { + int sock; /* Connected socket */ + uint32_t flags; +}; + +struct cmtp_conndel_req { + bdaddr_t bdaddr; + uint32_t flags; +}; + +struct cmtp_conninfo { + bdaddr_t bdaddr; + uint32_t flags; + uint16_t state; + int num; +}; + +struct cmtp_connlist_req { + uint32_t cnum; + struct cmtp_conninfo *ci; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __CMTP_H */ diff --git a/lib/bluetooth/hci.h b/lib/bluetooth/hci.h new file mode 100644 index 0000000..794333b --- /dev/null +++ b/lib/bluetooth/hci.h @@ -0,0 +1,2454 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __HCI_H +#define __HCI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define HCI_MAX_DEV 16 + +#define HCI_MAX_ACL_SIZE (1492 + 4) +#define HCI_MAX_SCO_SIZE 255 +#define HCI_MAX_EVENT_SIZE 260 +#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) + +/* HCI dev events */ +#define HCI_DEV_REG 1 +#define HCI_DEV_UNREG 2 +#define HCI_DEV_UP 3 +#define HCI_DEV_DOWN 4 +#define HCI_DEV_SUSPEND 5 +#define HCI_DEV_RESUME 6 + +/* HCI bus types */ +#define HCI_VIRTUAL 0 +#define HCI_USB 1 +#define HCI_PCCARD 2 +#define HCI_UART 3 +#define HCI_RS232 4 +#define HCI_PCI 5 +#define HCI_SDIO 6 +#define HCI_SPI 7 +#define HCI_I2C 8 +#define HCI_SMD 9 + +/* HCI controller types */ +#define HCI_PRIMARY 0x00 +#define HCI_AMP 0x01 +#define HCI_BREDR HCI_PRIMARY + +/* HCI device flags */ +enum { + HCI_UP, + HCI_INIT, + HCI_RUNNING, + + HCI_PSCAN, + HCI_ISCAN, + HCI_AUTH, + HCI_ENCRYPT, + HCI_INQUIRY, + + HCI_RAW, +}; + +/* LE address type */ +enum { + LE_PUBLIC_ADDRESS = 0x00, + LE_RANDOM_ADDRESS = 0x01 +}; + +/* HCI ioctl defines */ +#define HCIDEVUP _IOW('H', 201, int) +#define HCIDEVDOWN _IOW('H', 202, int) +#define HCIDEVRESET _IOW('H', 203, int) +#define HCIDEVRESTAT _IOW('H', 204, int) + +#define HCIGETDEVLIST _IOR('H', 210, int) +#define HCIGETDEVINFO _IOR('H', 211, int) +#define HCIGETCONNLIST _IOR('H', 212, int) +#define HCIGETCONNINFO _IOR('H', 213, int) +#define HCIGETAUTHINFO _IOR('H', 215, int) + +#define HCISETRAW _IOW('H', 220, int) +#define HCISETSCAN _IOW('H', 221, int) +#define HCISETAUTH _IOW('H', 222, int) +#define HCISETENCRYPT _IOW('H', 223, int) +#define HCISETPTYPE _IOW('H', 224, int) +#define HCISETLINKPOL _IOW('H', 225, int) +#define HCISETLINKMODE _IOW('H', 226, int) +#define HCISETACLMTU _IOW('H', 227, int) +#define HCISETSCOMTU _IOW('H', 228, int) + +#define HCIBLOCKADDR _IOW('H', 230, int) +#define HCIUNBLOCKADDR _IOW('H', 231, int) + +#define HCIINQUIRY _IOR('H', 240, int) + +#ifndef __NO_HCI_DEFS + +/* HCI Packet types */ +#define HCI_COMMAND_PKT 0x01 +#define HCI_ACLDATA_PKT 0x02 +#define HCI_SCODATA_PKT 0x03 +#define HCI_EVENT_PKT 0x04 +#define HCI_VENDOR_PKT 0xff + +/* HCI Packet types */ +#define HCI_2DH1 0x0002 +#define HCI_3DH1 0x0004 +#define HCI_DM1 0x0008 +#define HCI_DH1 0x0010 +#define HCI_2DH3 0x0100 +#define HCI_3DH3 0x0200 +#define HCI_DM3 0x0400 +#define HCI_DH3 0x0800 +#define HCI_2DH5 0x1000 +#define HCI_3DH5 0x2000 +#define HCI_DM5 0x4000 +#define HCI_DH5 0x8000 + +#define HCI_HV1 0x0020 +#define HCI_HV2 0x0040 +#define HCI_HV3 0x0080 + +#define HCI_EV3 0x0008 +#define HCI_EV4 0x0010 +#define HCI_EV5 0x0020 +#define HCI_2EV3 0x0040 +#define HCI_3EV3 0x0080 +#define HCI_2EV5 0x0100 +#define HCI_3EV5 0x0200 + +#define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3) +#define ACL_PTYPE_MASK (HCI_DM1 | HCI_DH1 | HCI_DM3 | HCI_DH3 | HCI_DM5 | HCI_DH5) + +/* HCI Error codes */ +#define HCI_UNKNOWN_COMMAND 0x01 +#define HCI_NO_CONNECTION 0x02 +#define HCI_HARDWARE_FAILURE 0x03 +#define HCI_PAGE_TIMEOUT 0x04 +#define HCI_AUTHENTICATION_FAILURE 0x05 +#define HCI_PIN_OR_KEY_MISSING 0x06 +#define HCI_MEMORY_FULL 0x07 +#define HCI_CONNECTION_TIMEOUT 0x08 +#define HCI_MAX_NUMBER_OF_CONNECTIONS 0x09 +#define HCI_MAX_NUMBER_OF_SCO_CONNECTIONS 0x0a +#define HCI_ACL_CONNECTION_EXISTS 0x0b +#define HCI_COMMAND_DISALLOWED 0x0c +#define HCI_REJECTED_LIMITED_RESOURCES 0x0d +#define HCI_REJECTED_SECURITY 0x0e +#define HCI_REJECTED_PERSONAL 0x0f +#define HCI_HOST_TIMEOUT 0x10 +#define HCI_UNSUPPORTED_FEATURE 0x11 +#define HCI_INVALID_PARAMETERS 0x12 +#define HCI_OE_USER_ENDED_CONNECTION 0x13 +#define HCI_OE_LOW_RESOURCES 0x14 +#define HCI_OE_POWER_OFF 0x15 +#define HCI_CONNECTION_TERMINATED 0x16 +#define HCI_REPEATED_ATTEMPTS 0x17 +#define HCI_PAIRING_NOT_ALLOWED 0x18 +#define HCI_UNKNOWN_LMP_PDU 0x19 +#define HCI_UNSUPPORTED_REMOTE_FEATURE 0x1a +#define HCI_SCO_OFFSET_REJECTED 0x1b +#define HCI_SCO_INTERVAL_REJECTED 0x1c +#define HCI_AIR_MODE_REJECTED 0x1d +#define HCI_INVALID_LMP_PARAMETERS 0x1e +#define HCI_UNSPECIFIED_ERROR 0x1f +#define HCI_UNSUPPORTED_LMP_PARAMETER_VALUE 0x20 +#define HCI_ROLE_CHANGE_NOT_ALLOWED 0x21 +#define HCI_LMP_RESPONSE_TIMEOUT 0x22 +#define HCI_LMP_ERROR_TRANSACTION_COLLISION 0x23 +#define HCI_LMP_PDU_NOT_ALLOWED 0x24 +#define HCI_ENCRYPTION_MODE_NOT_ACCEPTED 0x25 +#define HCI_UNIT_LINK_KEY_USED 0x26 +#define HCI_QOS_NOT_SUPPORTED 0x27 +#define HCI_INSTANT_PASSED 0x28 +#define HCI_PAIRING_NOT_SUPPORTED 0x29 +#define HCI_TRANSACTION_COLLISION 0x2a +#define HCI_QOS_UNACCEPTABLE_PARAMETER 0x2c +#define HCI_QOS_REJECTED 0x2d +#define HCI_CLASSIFICATION_NOT_SUPPORTED 0x2e +#define HCI_INSUFFICIENT_SECURITY 0x2f +#define HCI_PARAMETER_OUT_OF_RANGE 0x30 +#define HCI_ROLE_SWITCH_PENDING 0x32 +#define HCI_SLOT_VIOLATION 0x34 +#define HCI_ROLE_SWITCH_FAILED 0x35 +#define HCI_EIR_TOO_LARGE 0x36 +#define HCI_SIMPLE_PAIRING_NOT_SUPPORTED 0x37 +#define HCI_HOST_BUSY_PAIRING 0x38 + +/* ACL flags */ +#define ACL_START_NO_FLUSH 0x00 +#define ACL_CONT 0x01 +#define ACL_START 0x02 +#define ACL_ACTIVE_BCAST 0x04 +#define ACL_PICO_BCAST 0x08 + +/* Baseband links */ +#define SCO_LINK 0x00 +#define ACL_LINK 0x01 +#define ESCO_LINK 0x02 + +/* LMP features */ +#define LMP_3SLOT 0x01 +#define LMP_5SLOT 0x02 +#define LMP_ENCRYPT 0x04 +#define LMP_SOFFSET 0x08 +#define LMP_TACCURACY 0x10 +#define LMP_RSWITCH 0x20 +#define LMP_HOLD 0x40 +#define LMP_SNIFF 0x80 + +#define LMP_PARK 0x01 +#define LMP_RSSI 0x02 +#define LMP_QUALITY 0x04 +#define LMP_SCO 0x08 +#define LMP_HV2 0x10 +#define LMP_HV3 0x20 +#define LMP_ULAW 0x40 +#define LMP_ALAW 0x80 + +#define LMP_CVSD 0x01 +#define LMP_PSCHEME 0x02 +#define LMP_PCONTROL 0x04 +#define LMP_TRSP_SCO 0x08 +#define LMP_BCAST_ENC 0x80 + +#define LMP_EDR_ACL_2M 0x02 +#define LMP_EDR_ACL_3M 0x04 +#define LMP_ENH_ISCAN 0x08 +#define LMP_ILACE_ISCAN 0x10 +#define LMP_ILACE_PSCAN 0x20 +#define LMP_RSSI_INQ 0x40 +#define LMP_ESCO 0x80 + +#define LMP_EV4 0x01 +#define LMP_EV5 0x02 +#define LMP_AFH_CAP_SLV 0x08 +#define LMP_AFH_CLS_SLV 0x10 +#define LMP_NO_BREDR 0x20 +#define LMP_LE 0x40 +#define LMP_EDR_3SLOT 0x80 + +#define LMP_EDR_5SLOT 0x01 +#define LMP_SNIFF_SUBR 0x02 +#define LMP_PAUSE_ENC 0x04 +#define LMP_AFH_CAP_MST 0x08 +#define LMP_AFH_CLS_MST 0x10 +#define LMP_EDR_ESCO_2M 0x20 +#define LMP_EDR_ESCO_3M 0x40 +#define LMP_EDR_3S_ESCO 0x80 + +#define LMP_EXT_INQ 0x01 +#define LMP_LE_BREDR 0x02 +#define LMP_SIMPLE_PAIR 0x08 +#define LMP_ENCAPS_PDU 0x10 +#define LMP_ERR_DAT_REP 0x20 +#define LMP_NFLUSH_PKTS 0x40 + +#define LMP_LSTO 0x01 +#define LMP_INQ_TX_PWR 0x02 +#define LMP_EPC 0x04 +#define LMP_EXT_FEAT 0x80 + +/* Extended LMP features */ +#define LMP_HOST_SSP 0x01 +#define LMP_HOST_LE 0x02 +#define LMP_HOST_LE_BREDR 0x04 + +/* Link policies */ +#define HCI_LP_RSWITCH 0x0001 +#define HCI_LP_HOLD 0x0002 +#define HCI_LP_SNIFF 0x0004 +#define HCI_LP_PARK 0x0008 + +/* Link mode */ +#define HCI_LM_ACCEPT 0x8000 +#define HCI_LM_MASTER 0x0001 +#define HCI_LM_AUTH 0x0002 +#define HCI_LM_ENCRYPT 0x0004 +#define HCI_LM_TRUSTED 0x0008 +#define HCI_LM_RELIABLE 0x0010 +#define HCI_LM_SECURE 0x0020 + +/* Link Key types */ +#define HCI_LK_COMBINATION 0x00 +#define HCI_LK_LOCAL_UNIT 0x01 +#define HCI_LK_REMOTE_UNIT 0x02 +#define HCI_LK_DEBUG_COMBINATION 0x03 +#define HCI_LK_UNAUTH_COMBINATION 0x04 +#define HCI_LK_AUTH_COMBINATION 0x05 +#define HCI_LK_CHANGED_COMBINATION 0x06 +#define HCI_LK_INVALID 0xFF + +/* ----- HCI Commands ----- */ + +/* Link Control */ +#define OGF_LINK_CTL 0x01 + +#define OCF_INQUIRY 0x0001 +typedef struct { + uint8_t lap[3]; + uint8_t length; /* 1.28s units */ + uint8_t num_rsp; +} __attribute__ ((packed)) inquiry_cp; +#define INQUIRY_CP_SIZE 5 + +typedef struct { + uint8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) status_bdaddr_rp; +#define STATUS_BDADDR_RP_SIZE 7 + +#define OCF_INQUIRY_CANCEL 0x0002 + +#define OCF_PERIODIC_INQUIRY 0x0003 +typedef struct { + uint16_t max_period; /* 1.28s units */ + uint16_t min_period; /* 1.28s units */ + uint8_t lap[3]; + uint8_t length; /* 1.28s units */ + uint8_t num_rsp; +} __attribute__ ((packed)) periodic_inquiry_cp; +#define PERIODIC_INQUIRY_CP_SIZE 9 + +#define OCF_EXIT_PERIODIC_INQUIRY 0x0004 + +#define OCF_CREATE_CONN 0x0005 +typedef struct { + bdaddr_t bdaddr; + uint16_t pkt_type; + uint8_t pscan_rep_mode; + uint8_t pscan_mode; + uint16_t clock_offset; + uint8_t role_switch; +} __attribute__ ((packed)) create_conn_cp; +#define CREATE_CONN_CP_SIZE 13 + +#define OCF_DISCONNECT 0x0006 +typedef struct { + uint16_t handle; + uint8_t reason; +} __attribute__ ((packed)) disconnect_cp; +#define DISCONNECT_CP_SIZE 3 + +#define OCF_ADD_SCO 0x0007 +typedef struct { + uint16_t handle; + uint16_t pkt_type; +} __attribute__ ((packed)) add_sco_cp; +#define ADD_SCO_CP_SIZE 4 + +#define OCF_CREATE_CONN_CANCEL 0x0008 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) create_conn_cancel_cp; +#define CREATE_CONN_CANCEL_CP_SIZE 6 + +#define OCF_ACCEPT_CONN_REQ 0x0009 +typedef struct { + bdaddr_t bdaddr; + uint8_t role; +} __attribute__ ((packed)) accept_conn_req_cp; +#define ACCEPT_CONN_REQ_CP_SIZE 7 + +#define OCF_REJECT_CONN_REQ 0x000A +typedef struct { + bdaddr_t bdaddr; + uint8_t reason; +} __attribute__ ((packed)) reject_conn_req_cp; +#define REJECT_CONN_REQ_CP_SIZE 7 + +#define OCF_LINK_KEY_REPLY 0x000B +typedef struct { + bdaddr_t bdaddr; + uint8_t link_key[16]; +} __attribute__ ((packed)) link_key_reply_cp; +#define LINK_KEY_REPLY_CP_SIZE 22 + +#define OCF_LINK_KEY_NEG_REPLY 0x000C + +#define OCF_PIN_CODE_REPLY 0x000D +typedef struct { + bdaddr_t bdaddr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __attribute__ ((packed)) pin_code_reply_cp; +#define PIN_CODE_REPLY_CP_SIZE 23 + +#define OCF_PIN_CODE_NEG_REPLY 0x000E + +#define OCF_SET_CONN_PTYPE 0x000F +typedef struct { + uint16_t handle; + uint16_t pkt_type; +} __attribute__ ((packed)) set_conn_ptype_cp; +#define SET_CONN_PTYPE_CP_SIZE 4 + +#define OCF_AUTH_REQUESTED 0x0011 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) auth_requested_cp; +#define AUTH_REQUESTED_CP_SIZE 2 + +#define OCF_SET_CONN_ENCRYPT 0x0013 +typedef struct { + uint16_t handle; + uint8_t encrypt; +} __attribute__ ((packed)) set_conn_encrypt_cp; +#define SET_CONN_ENCRYPT_CP_SIZE 3 + +#define OCF_CHANGE_CONN_LINK_KEY 0x0015 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) change_conn_link_key_cp; +#define CHANGE_CONN_LINK_KEY_CP_SIZE 2 + +#define OCF_MASTER_LINK_KEY 0x0017 +typedef struct { + uint8_t key_flag; +} __attribute__ ((packed)) master_link_key_cp; +#define MASTER_LINK_KEY_CP_SIZE 1 + +#define OCF_REMOTE_NAME_REQ 0x0019 +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t pscan_mode; + uint16_t clock_offset; +} __attribute__ ((packed)) remote_name_req_cp; +#define REMOTE_NAME_REQ_CP_SIZE 10 + +#define OCF_REMOTE_NAME_REQ_CANCEL 0x001A +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) remote_name_req_cancel_cp; +#define REMOTE_NAME_REQ_CANCEL_CP_SIZE 6 + +#define OCF_READ_REMOTE_FEATURES 0x001B +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) read_remote_features_cp; +#define READ_REMOTE_FEATURES_CP_SIZE 2 + +#define OCF_READ_REMOTE_EXT_FEATURES 0x001C +typedef struct { + uint16_t handle; + uint8_t page_num; +} __attribute__ ((packed)) read_remote_ext_features_cp; +#define READ_REMOTE_EXT_FEATURES_CP_SIZE 3 + +#define OCF_READ_REMOTE_VERSION 0x001D +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) read_remote_version_cp; +#define READ_REMOTE_VERSION_CP_SIZE 2 + +#define OCF_READ_CLOCK_OFFSET 0x001F +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) read_clock_offset_cp; +#define READ_CLOCK_OFFSET_CP_SIZE 2 + +#define OCF_READ_LMP_HANDLE 0x0020 + +#define OCF_SETUP_SYNC_CONN 0x0028 +typedef struct { + uint16_t handle; + uint32_t tx_bandwith; + uint32_t rx_bandwith; + uint16_t max_latency; + uint16_t voice_setting; + uint8_t retrans_effort; + uint16_t pkt_type; +} __attribute__ ((packed)) setup_sync_conn_cp; +#define SETUP_SYNC_CONN_CP_SIZE 17 + +#define OCF_ACCEPT_SYNC_CONN_REQ 0x0029 +typedef struct { + bdaddr_t bdaddr; + uint32_t tx_bandwith; + uint32_t rx_bandwith; + uint16_t max_latency; + uint16_t voice_setting; + uint8_t retrans_effort; + uint16_t pkt_type; +} __attribute__ ((packed)) accept_sync_conn_req_cp; +#define ACCEPT_SYNC_CONN_REQ_CP_SIZE 21 + +#define OCF_REJECT_SYNC_CONN_REQ 0x002A +typedef struct { + bdaddr_t bdaddr; + uint8_t reason; +} __attribute__ ((packed)) reject_sync_conn_req_cp; +#define REJECT_SYNC_CONN_REQ_CP_SIZE 7 + +#define OCF_IO_CAPABILITY_REPLY 0x002B +typedef struct { + bdaddr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __attribute__ ((packed)) io_capability_reply_cp; +#define IO_CAPABILITY_REPLY_CP_SIZE 9 + +#define OCF_USER_CONFIRM_REPLY 0x002C +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) user_confirm_reply_cp; +#define USER_CONFIRM_REPLY_CP_SIZE 6 + +#define OCF_USER_CONFIRM_NEG_REPLY 0x002D + +#define OCF_USER_PASSKEY_REPLY 0x002E +typedef struct { + bdaddr_t bdaddr; + uint32_t passkey; +} __attribute__ ((packed)) user_passkey_reply_cp; +#define USER_PASSKEY_REPLY_CP_SIZE 10 + +#define OCF_USER_PASSKEY_NEG_REPLY 0x002F + +#define OCF_REMOTE_OOB_DATA_REPLY 0x0030 +typedef struct { + bdaddr_t bdaddr; + uint8_t hash[16]; + uint8_t randomizer[16]; +} __attribute__ ((packed)) remote_oob_data_reply_cp; +#define REMOTE_OOB_DATA_REPLY_CP_SIZE 38 + +#define OCF_REMOTE_OOB_DATA_NEG_REPLY 0x0033 + +#define OCF_IO_CAPABILITY_NEG_REPLY 0x0034 +typedef struct { + bdaddr_t bdaddr; + uint8_t reason; +} __attribute__ ((packed)) io_capability_neg_reply_cp; +#define IO_CAPABILITY_NEG_REPLY_CP_SIZE 7 + +#define OCF_CREATE_PHYSICAL_LINK 0x0035 +typedef struct { + uint8_t handle; + uint8_t key_length; + uint8_t key_type; + uint8_t key[32]; +} __attribute__ ((packed)) create_physical_link_cp; +#define CREATE_PHYSICAL_LINK_CP_SIZE 35 + +#define OCF_ACCEPT_PHYSICAL_LINK 0x0036 +typedef struct { + uint8_t handle; + uint8_t key_length; + uint8_t key_type; + uint8_t key[32]; +} __attribute__ ((packed)) accept_physical_link_cp; +#define ACCEPT_PHYSICAL_LINK_CP_SIZE 35 + +#define OCF_DISCONNECT_PHYSICAL_LINK 0x0037 +typedef struct { + uint8_t handle; + uint8_t reason; +} __attribute__ ((packed)) disconnect_physical_link_cp; +#define DISCONNECT_PHYSICAL_LINK_CP_SIZE 2 + +#define OCF_CREATE_LOGICAL_LINK 0x0038 +typedef struct { + uint8_t handle; + uint8_t tx_flow[16]; + uint8_t rx_flow[16]; +} __attribute__ ((packed)) create_logical_link_cp; +#define CREATE_LOGICAL_LINK_CP_SIZE 33 + +#define OCF_ACCEPT_LOGICAL_LINK 0x0039 + +#define OCF_DISCONNECT_LOGICAL_LINK 0x003A +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) disconnect_logical_link_cp; +#define DISCONNECT_LOGICAL_LINK_CP_SIZE 2 + +#define OCF_LOGICAL_LINK_CANCEL 0x003B +typedef struct { + uint8_t handle; + uint8_t tx_flow_id; +} __attribute__ ((packed)) cancel_logical_link_cp; +#define LOGICAL_LINK_CANCEL_CP_SIZE 2 +typedef struct { + uint8_t status; + uint8_t handle; + uint8_t tx_flow_id; +} __attribute__ ((packed)) cancel_logical_link_rp; +#define LOGICAL_LINK_CANCEL_RP_SIZE 3 + +#define OCF_FLOW_SPEC_MODIFY 0x003C + +/* Link Policy */ +#define OGF_LINK_POLICY 0x02 + +#define OCF_HOLD_MODE 0x0001 +typedef struct { + uint16_t handle; + uint16_t max_interval; + uint16_t min_interval; +} __attribute__ ((packed)) hold_mode_cp; +#define HOLD_MODE_CP_SIZE 6 + +#define OCF_SNIFF_MODE 0x0003 +typedef struct { + uint16_t handle; + uint16_t max_interval; + uint16_t min_interval; + uint16_t attempt; + uint16_t timeout; +} __attribute__ ((packed)) sniff_mode_cp; +#define SNIFF_MODE_CP_SIZE 10 + +#define OCF_EXIT_SNIFF_MODE 0x0004 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) exit_sniff_mode_cp; +#define EXIT_SNIFF_MODE_CP_SIZE 2 + +#define OCF_PARK_MODE 0x0005 +typedef struct { + uint16_t handle; + uint16_t max_interval; + uint16_t min_interval; +} __attribute__ ((packed)) park_mode_cp; +#define PARK_MODE_CP_SIZE 6 + +#define OCF_EXIT_PARK_MODE 0x0006 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) exit_park_mode_cp; +#define EXIT_PARK_MODE_CP_SIZE 2 + +#define OCF_QOS_SETUP 0x0007 +typedef struct { + uint8_t service_type; /* 1 = best effort */ + uint32_t token_rate; /* Byte per seconds */ + uint32_t peak_bandwidth; /* Byte per seconds */ + uint32_t latency; /* Microseconds */ + uint32_t delay_variation; /* Microseconds */ +} __attribute__ ((packed)) hci_qos; +#define HCI_QOS_CP_SIZE 17 +typedef struct { + uint16_t handle; + uint8_t flags; /* Reserved */ + hci_qos qos; +} __attribute__ ((packed)) qos_setup_cp; +#define QOS_SETUP_CP_SIZE (3 + HCI_QOS_CP_SIZE) + +#define OCF_ROLE_DISCOVERY 0x0009 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) role_discovery_cp; +#define ROLE_DISCOVERY_CP_SIZE 2 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t role; +} __attribute__ ((packed)) role_discovery_rp; +#define ROLE_DISCOVERY_RP_SIZE 4 + +#define OCF_SWITCH_ROLE 0x000B +typedef struct { + bdaddr_t bdaddr; + uint8_t role; +} __attribute__ ((packed)) switch_role_cp; +#define SWITCH_ROLE_CP_SIZE 7 + +#define OCF_READ_LINK_POLICY 0x000C +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) read_link_policy_cp; +#define READ_LINK_POLICY_CP_SIZE 2 +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t policy; +} __attribute__ ((packed)) read_link_policy_rp; +#define READ_LINK_POLICY_RP_SIZE 5 + +#define OCF_WRITE_LINK_POLICY 0x000D +typedef struct { + uint16_t handle; + uint16_t policy; +} __attribute__ ((packed)) write_link_policy_cp; +#define WRITE_LINK_POLICY_CP_SIZE 4 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) write_link_policy_rp; +#define WRITE_LINK_POLICY_RP_SIZE 3 + +#define OCF_READ_DEFAULT_LINK_POLICY 0x000E + +#define OCF_WRITE_DEFAULT_LINK_POLICY 0x000F + +#define OCF_FLOW_SPECIFICATION 0x0010 + +#define OCF_SNIFF_SUBRATING 0x0011 +typedef struct { + uint16_t handle; + uint16_t max_latency; + uint16_t min_remote_timeout; + uint16_t min_local_timeout; +} __attribute__ ((packed)) sniff_subrating_cp; +#define SNIFF_SUBRATING_CP_SIZE 8 + +/* Host Controller and Baseband */ +#define OGF_HOST_CTL 0x03 + +#define OCF_SET_EVENT_MASK 0x0001 +typedef struct { + uint8_t mask[8]; +} __attribute__ ((packed)) set_event_mask_cp; +#define SET_EVENT_MASK_CP_SIZE 8 + +#define OCF_RESET 0x0003 + +#define OCF_SET_EVENT_FLT 0x0005 +typedef struct { + uint8_t flt_type; + uint8_t cond_type; + uint8_t condition[0]; +} __attribute__ ((packed)) set_event_flt_cp; +#define SET_EVENT_FLT_CP_SIZE 2 + +/* Filter types */ +#define FLT_CLEAR_ALL 0x00 +#define FLT_INQ_RESULT 0x01 +#define FLT_CONN_SETUP 0x02 +/* INQ_RESULT Condition types */ +#define INQ_RESULT_RETURN_ALL 0x00 +#define INQ_RESULT_RETURN_CLASS 0x01 +#define INQ_RESULT_RETURN_BDADDR 0x02 +/* CONN_SETUP Condition types */ +#define CONN_SETUP_ALLOW_ALL 0x00 +#define CONN_SETUP_ALLOW_CLASS 0x01 +#define CONN_SETUP_ALLOW_BDADDR 0x02 +/* CONN_SETUP Conditions */ +#define CONN_SETUP_AUTO_OFF 0x01 +#define CONN_SETUP_AUTO_ON 0x02 + +#define OCF_FLUSH 0x0008 + +#define OCF_READ_PIN_TYPE 0x0009 +typedef struct { + uint8_t status; + uint8_t pin_type; +} __attribute__ ((packed)) read_pin_type_rp; +#define READ_PIN_TYPE_RP_SIZE 2 + +#define OCF_WRITE_PIN_TYPE 0x000A +typedef struct { + uint8_t pin_type; +} __attribute__ ((packed)) write_pin_type_cp; +#define WRITE_PIN_TYPE_CP_SIZE 1 + +#define OCF_CREATE_NEW_UNIT_KEY 0x000B + +#define OCF_READ_STORED_LINK_KEY 0x000D +typedef struct { + bdaddr_t bdaddr; + uint8_t read_all; +} __attribute__ ((packed)) read_stored_link_key_cp; +#define READ_STORED_LINK_KEY_CP_SIZE 7 +typedef struct { + uint8_t status; + uint16_t max_keys; + uint16_t num_keys; +} __attribute__ ((packed)) read_stored_link_key_rp; +#define READ_STORED_LINK_KEY_RP_SIZE 5 + +#define OCF_WRITE_STORED_LINK_KEY 0x0011 +typedef struct { + uint8_t num_keys; + /* variable length part */ +} __attribute__ ((packed)) write_stored_link_key_cp; +#define WRITE_STORED_LINK_KEY_CP_SIZE 1 +typedef struct { + uint8_t status; + uint8_t num_keys; +} __attribute__ ((packed)) write_stored_link_key_rp; +#define READ_WRITE_LINK_KEY_RP_SIZE 2 + +#define OCF_DELETE_STORED_LINK_KEY 0x0012 +typedef struct { + bdaddr_t bdaddr; + uint8_t delete_all; +} __attribute__ ((packed)) delete_stored_link_key_cp; +#define DELETE_STORED_LINK_KEY_CP_SIZE 7 +typedef struct { + uint8_t status; + uint16_t num_keys; +} __attribute__ ((packed)) delete_stored_link_key_rp; +#define DELETE_STORED_LINK_KEY_RP_SIZE 3 + +#define HCI_MAX_NAME_LENGTH 248 + +#define OCF_CHANGE_LOCAL_NAME 0x0013 +typedef struct { + uint8_t name[HCI_MAX_NAME_LENGTH]; +} __attribute__ ((packed)) change_local_name_cp; +#define CHANGE_LOCAL_NAME_CP_SIZE 248 + +#define OCF_READ_LOCAL_NAME 0x0014 +typedef struct { + uint8_t status; + uint8_t name[HCI_MAX_NAME_LENGTH]; +} __attribute__ ((packed)) read_local_name_rp; +#define READ_LOCAL_NAME_RP_SIZE 249 + +#define OCF_READ_CONN_ACCEPT_TIMEOUT 0x0015 +typedef struct { + uint8_t status; + uint16_t timeout; +} __attribute__ ((packed)) read_conn_accept_timeout_rp; +#define READ_CONN_ACCEPT_TIMEOUT_RP_SIZE 3 + +#define OCF_WRITE_CONN_ACCEPT_TIMEOUT 0x0016 +typedef struct { + uint16_t timeout; +} __attribute__ ((packed)) write_conn_accept_timeout_cp; +#define WRITE_CONN_ACCEPT_TIMEOUT_CP_SIZE 2 + +#define OCF_READ_PAGE_TIMEOUT 0x0017 +typedef struct { + uint8_t status; + uint16_t timeout; +} __attribute__ ((packed)) read_page_timeout_rp; +#define READ_PAGE_TIMEOUT_RP_SIZE 3 + +#define OCF_WRITE_PAGE_TIMEOUT 0x0018 +typedef struct { + uint16_t timeout; +} __attribute__ ((packed)) write_page_timeout_cp; +#define WRITE_PAGE_TIMEOUT_CP_SIZE 2 + +#define OCF_READ_SCAN_ENABLE 0x0019 +typedef struct { + uint8_t status; + uint8_t enable; +} __attribute__ ((packed)) read_scan_enable_rp; +#define READ_SCAN_ENABLE_RP_SIZE 2 + +#define OCF_WRITE_SCAN_ENABLE 0x001A + #define SCAN_DISABLED 0x00 + #define SCAN_INQUIRY 0x01 + #define SCAN_PAGE 0x02 + +#define OCF_READ_PAGE_ACTIVITY 0x001B +typedef struct { + uint8_t status; + uint16_t interval; + uint16_t window; +} __attribute__ ((packed)) read_page_activity_rp; +#define READ_PAGE_ACTIVITY_RP_SIZE 5 + +#define OCF_WRITE_PAGE_ACTIVITY 0x001C +typedef struct { + uint16_t interval; + uint16_t window; +} __attribute__ ((packed)) write_page_activity_cp; +#define WRITE_PAGE_ACTIVITY_CP_SIZE 4 + +#define OCF_READ_INQ_ACTIVITY 0x001D +typedef struct { + uint8_t status; + uint16_t interval; + uint16_t window; +} __attribute__ ((packed)) read_inq_activity_rp; +#define READ_INQ_ACTIVITY_RP_SIZE 5 + +#define OCF_WRITE_INQ_ACTIVITY 0x001E +typedef struct { + uint16_t interval; + uint16_t window; +} __attribute__ ((packed)) write_inq_activity_cp; +#define WRITE_INQ_ACTIVITY_CP_SIZE 4 + +#define OCF_READ_AUTH_ENABLE 0x001F + +#define OCF_WRITE_AUTH_ENABLE 0x0020 + #define AUTH_DISABLED 0x00 + #define AUTH_ENABLED 0x01 + +#define OCF_READ_ENCRYPT_MODE 0x0021 + +#define OCF_WRITE_ENCRYPT_MODE 0x0022 + #define ENCRYPT_DISABLED 0x00 + #define ENCRYPT_P2P 0x01 + #define ENCRYPT_BOTH 0x02 + +#define OCF_READ_CLASS_OF_DEV 0x0023 +typedef struct { + uint8_t status; + uint8_t dev_class[3]; +} __attribute__ ((packed)) read_class_of_dev_rp; +#define READ_CLASS_OF_DEV_RP_SIZE 4 + +#define OCF_WRITE_CLASS_OF_DEV 0x0024 +typedef struct { + uint8_t dev_class[3]; +} __attribute__ ((packed)) write_class_of_dev_cp; +#define WRITE_CLASS_OF_DEV_CP_SIZE 3 + +#define OCF_READ_VOICE_SETTING 0x0025 +typedef struct { + uint8_t status; + uint16_t voice_setting; +} __attribute__ ((packed)) read_voice_setting_rp; +#define READ_VOICE_SETTING_RP_SIZE 3 + +#define OCF_WRITE_VOICE_SETTING 0x0026 +typedef struct { + uint16_t voice_setting; +} __attribute__ ((packed)) write_voice_setting_cp; +#define WRITE_VOICE_SETTING_CP_SIZE 2 + +#define OCF_READ_AUTOMATIC_FLUSH_TIMEOUT 0x0027 + +#define OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT 0x0028 + +#define OCF_READ_NUM_BROADCAST_RETRANS 0x0029 + +#define OCF_WRITE_NUM_BROADCAST_RETRANS 0x002A + +#define OCF_READ_HOLD_MODE_ACTIVITY 0x002B + +#define OCF_WRITE_HOLD_MODE_ACTIVITY 0x002C + +#define OCF_READ_TRANSMIT_POWER_LEVEL 0x002D +typedef struct { + uint16_t handle; + uint8_t type; +} __attribute__ ((packed)) read_transmit_power_level_cp; +#define READ_TRANSMIT_POWER_LEVEL_CP_SIZE 3 +typedef struct { + uint8_t status; + uint16_t handle; + int8_t level; +} __attribute__ ((packed)) read_transmit_power_level_rp; +#define READ_TRANSMIT_POWER_LEVEL_RP_SIZE 4 + +#define OCF_READ_SYNC_FLOW_ENABLE 0x002E + +#define OCF_WRITE_SYNC_FLOW_ENABLE 0x002F + +#define OCF_SET_CONTROLLER_TO_HOST_FC 0x0031 + +#define OCF_HOST_BUFFER_SIZE 0x0033 +typedef struct { + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_max_pkt; + uint16_t sco_max_pkt; +} __attribute__ ((packed)) host_buffer_size_cp; +#define HOST_BUFFER_SIZE_CP_SIZE 7 + +#define OCF_HOST_NUM_COMP_PKTS 0x0035 +typedef struct { + uint8_t num_hndl; + /* variable length part */ +} __attribute__ ((packed)) host_num_comp_pkts_cp; +#define HOST_NUM_COMP_PKTS_CP_SIZE 1 + +#define OCF_READ_LINK_SUPERVISION_TIMEOUT 0x0036 +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t timeout; +} __attribute__ ((packed)) read_link_supervision_timeout_rp; +#define READ_LINK_SUPERVISION_TIMEOUT_RP_SIZE 5 + +#define OCF_WRITE_LINK_SUPERVISION_TIMEOUT 0x0037 +typedef struct { + uint16_t handle; + uint16_t timeout; +} __attribute__ ((packed)) write_link_supervision_timeout_cp; +#define WRITE_LINK_SUPERVISION_TIMEOUT_CP_SIZE 4 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) write_link_supervision_timeout_rp; +#define WRITE_LINK_SUPERVISION_TIMEOUT_RP_SIZE 3 + +#define OCF_READ_NUM_SUPPORTED_IAC 0x0038 + +#define MAX_IAC_LAP 0x40 +#define OCF_READ_CURRENT_IAC_LAP 0x0039 +typedef struct { + uint8_t status; + uint8_t num_current_iac; + uint8_t lap[MAX_IAC_LAP][3]; +} __attribute__ ((packed)) read_current_iac_lap_rp; +#define READ_CURRENT_IAC_LAP_RP_SIZE 2+3*MAX_IAC_LAP + +#define OCF_WRITE_CURRENT_IAC_LAP 0x003A +typedef struct { + uint8_t num_current_iac; + uint8_t lap[MAX_IAC_LAP][3]; +} __attribute__ ((packed)) write_current_iac_lap_cp; +#define WRITE_CURRENT_IAC_LAP_CP_SIZE 1+3*MAX_IAC_LAP + +#define OCF_READ_PAGE_SCAN_PERIOD_MODE 0x003B + +#define OCF_WRITE_PAGE_SCAN_PERIOD_MODE 0x003C + +#define OCF_READ_PAGE_SCAN_MODE 0x003D + +#define OCF_WRITE_PAGE_SCAN_MODE 0x003E + +#define OCF_SET_AFH_CLASSIFICATION 0x003F +typedef struct { + uint8_t map[10]; +} __attribute__ ((packed)) set_afh_classification_cp; +#define SET_AFH_CLASSIFICATION_CP_SIZE 10 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) set_afh_classification_rp; +#define SET_AFH_CLASSIFICATION_RP_SIZE 1 + +#define OCF_READ_INQUIRY_SCAN_TYPE 0x0042 +typedef struct { + uint8_t status; + uint8_t type; +} __attribute__ ((packed)) read_inquiry_scan_type_rp; +#define READ_INQUIRY_SCAN_TYPE_RP_SIZE 2 + +#define OCF_WRITE_INQUIRY_SCAN_TYPE 0x0043 +typedef struct { + uint8_t type; +} __attribute__ ((packed)) write_inquiry_scan_type_cp; +#define WRITE_INQUIRY_SCAN_TYPE_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_inquiry_scan_type_rp; +#define WRITE_INQUIRY_SCAN_TYPE_RP_SIZE 1 + +#define OCF_READ_INQUIRY_MODE 0x0044 +typedef struct { + uint8_t status; + uint8_t mode; +} __attribute__ ((packed)) read_inquiry_mode_rp; +#define READ_INQUIRY_MODE_RP_SIZE 2 + +#define OCF_WRITE_INQUIRY_MODE 0x0045 +typedef struct { + uint8_t mode; +} __attribute__ ((packed)) write_inquiry_mode_cp; +#define WRITE_INQUIRY_MODE_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_inquiry_mode_rp; +#define WRITE_INQUIRY_MODE_RP_SIZE 1 + +#define OCF_READ_PAGE_SCAN_TYPE 0x0046 + +#define OCF_WRITE_PAGE_SCAN_TYPE 0x0047 + #define PAGE_SCAN_TYPE_STANDARD 0x00 + #define PAGE_SCAN_TYPE_INTERLACED 0x01 + +#define OCF_READ_AFH_MODE 0x0048 +typedef struct { + uint8_t status; + uint8_t mode; +} __attribute__ ((packed)) read_afh_mode_rp; +#define READ_AFH_MODE_RP_SIZE 2 + +#define OCF_WRITE_AFH_MODE 0x0049 +typedef struct { + uint8_t mode; +} __attribute__ ((packed)) write_afh_mode_cp; +#define WRITE_AFH_MODE_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_afh_mode_rp; +#define WRITE_AFH_MODE_RP_SIZE 1 + +#define HCI_MAX_EIR_LENGTH 240 + +#define OCF_READ_EXT_INQUIRY_RESPONSE 0x0051 +typedef struct { + uint8_t status; + uint8_t fec; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __attribute__ ((packed)) read_ext_inquiry_response_rp; +#define READ_EXT_INQUIRY_RESPONSE_RP_SIZE 242 + +#define OCF_WRITE_EXT_INQUIRY_RESPONSE 0x0052 +typedef struct { + uint8_t fec; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __attribute__ ((packed)) write_ext_inquiry_response_cp; +#define WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE 241 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_ext_inquiry_response_rp; +#define WRITE_EXT_INQUIRY_RESPONSE_RP_SIZE 1 + +#define OCF_REFRESH_ENCRYPTION_KEY 0x0053 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) refresh_encryption_key_cp; +#define REFRESH_ENCRYPTION_KEY_CP_SIZE 2 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) refresh_encryption_key_rp; +#define REFRESH_ENCRYPTION_KEY_RP_SIZE 1 + +#define OCF_READ_SIMPLE_PAIRING_MODE 0x0055 +typedef struct { + uint8_t status; + uint8_t mode; +} __attribute__ ((packed)) read_simple_pairing_mode_rp; +#define READ_SIMPLE_PAIRING_MODE_RP_SIZE 2 + +#define OCF_WRITE_SIMPLE_PAIRING_MODE 0x0056 +typedef struct { + uint8_t mode; +} __attribute__ ((packed)) write_simple_pairing_mode_cp; +#define WRITE_SIMPLE_PAIRING_MODE_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_simple_pairing_mode_rp; +#define WRITE_SIMPLE_PAIRING_MODE_RP_SIZE 1 + +#define OCF_READ_LOCAL_OOB_DATA 0x0057 +typedef struct { + uint8_t status; + uint8_t hash[16]; + uint8_t randomizer[16]; +} __attribute__ ((packed)) read_local_oob_data_rp; +#define READ_LOCAL_OOB_DATA_RP_SIZE 33 + +#define OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL 0x0058 +typedef struct { + uint8_t status; + int8_t level; +} __attribute__ ((packed)) read_inq_response_tx_power_level_rp; +#define READ_INQ_RESPONSE_TX_POWER_LEVEL_RP_SIZE 2 + +#define OCF_READ_INQUIRY_TRANSMIT_POWER_LEVEL 0x0058 +typedef struct { + uint8_t status; + int8_t level; +} __attribute__ ((packed)) read_inquiry_transmit_power_level_rp; +#define READ_INQUIRY_TRANSMIT_POWER_LEVEL_RP_SIZE 2 + +#define OCF_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL 0x0059 +typedef struct { + int8_t level; +} __attribute__ ((packed)) write_inquiry_transmit_power_level_cp; +#define WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_inquiry_transmit_power_level_rp; +#define WRITE_INQUIRY_TRANSMIT_POWER_LEVEL_RP_SIZE 1 + +#define OCF_READ_DEFAULT_ERROR_DATA_REPORTING 0x005A +typedef struct { + uint8_t status; + uint8_t reporting; +} __attribute__ ((packed)) read_default_error_data_reporting_rp; +#define READ_DEFAULT_ERROR_DATA_REPORTING_RP_SIZE 2 + +#define OCF_WRITE_DEFAULT_ERROR_DATA_REPORTING 0x005B +typedef struct { + uint8_t reporting; +} __attribute__ ((packed)) write_default_error_data_reporting_cp; +#define WRITE_DEFAULT_ERROR_DATA_REPORTING_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_default_error_data_reporting_rp; +#define WRITE_DEFAULT_ERROR_DATA_REPORTING_RP_SIZE 1 + +#define OCF_ENHANCED_FLUSH 0x005F +typedef struct { + uint16_t handle; + uint8_t type; +} __attribute__ ((packed)) enhanced_flush_cp; +#define ENHANCED_FLUSH_CP_SIZE 3 + +#define OCF_SEND_KEYPRESS_NOTIFY 0x0060 +typedef struct { + bdaddr_t bdaddr; + uint8_t type; +} __attribute__ ((packed)) send_keypress_notify_cp; +#define SEND_KEYPRESS_NOTIFY_CP_SIZE 7 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) send_keypress_notify_rp; +#define SEND_KEYPRESS_NOTIFY_RP_SIZE 1 + +#define OCF_READ_LOGICAL_LINK_ACCEPT_TIMEOUT 0x0061 +typedef struct { + uint8_t status; + uint16_t timeout; +} __attribute__ ((packed)) read_log_link_accept_timeout_rp; +#define READ_LOGICAL_LINK_ACCEPT_TIMEOUT_RP_SIZE 3 + +#define OCF_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT 0x0062 +typedef struct { + uint16_t timeout; +} __attribute__ ((packed)) write_log_link_accept_timeout_cp; +#define WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT_CP_SIZE 2 + +#define OCF_SET_EVENT_MASK_PAGE_2 0x0063 + +#define OCF_READ_LOCATION_DATA 0x0064 + +#define OCF_WRITE_LOCATION_DATA 0x0065 + +#define OCF_READ_FLOW_CONTROL_MODE 0x0066 + +#define OCF_WRITE_FLOW_CONTROL_MODE 0x0067 + +#define OCF_READ_ENHANCED_TRANSMIT_POWER_LEVEL 0x0068 +typedef struct { + uint8_t status; + uint16_t handle; + int8_t level_gfsk; + int8_t level_dqpsk; + int8_t level_8dpsk; +} __attribute__ ((packed)) read_enhanced_transmit_power_level_rp; +#define READ_ENHANCED_TRANSMIT_POWER_LEVEL_RP_SIZE 6 + +#define OCF_READ_BEST_EFFORT_FLUSH_TIMEOUT 0x0069 +typedef struct { + uint8_t status; + uint32_t timeout; +} __attribute__ ((packed)) read_best_effort_flush_timeout_rp; +#define READ_BEST_EFFORT_FLUSH_TIMEOUT_RP_SIZE 5 + +#define OCF_WRITE_BEST_EFFORT_FLUSH_TIMEOUT 0x006A +typedef struct { + uint16_t handle; + uint32_t timeout; +} __attribute__ ((packed)) write_best_effort_flush_timeout_cp; +#define WRITE_BEST_EFFORT_FLUSH_TIMEOUT_CP_SIZE 6 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_best_effort_flush_timeout_rp; +#define WRITE_BEST_EFFORT_FLUSH_TIMEOUT_RP_SIZE 1 + +#define OCF_READ_LE_HOST_SUPPORTED 0x006C +typedef struct { + uint8_t status; + uint8_t le; + uint8_t simul; +} __attribute__ ((packed)) read_le_host_supported_rp; +#define READ_LE_HOST_SUPPORTED_RP_SIZE 3 + +#define OCF_WRITE_LE_HOST_SUPPORTED 0x006D +typedef struct { + uint8_t le; + uint8_t simul; +} __attribute__ ((packed)) write_le_host_supported_cp; +#define WRITE_LE_HOST_SUPPORTED_CP_SIZE 2 + +/* Informational Parameters */ +#define OGF_INFO_PARAM 0x04 + +#define OCF_READ_LOCAL_VERSION 0x0001 +typedef struct { + uint8_t status; + uint8_t hci_ver; + uint16_t hci_rev; + uint8_t lmp_ver; + uint16_t manufacturer; + uint16_t lmp_subver; +} __attribute__ ((packed)) read_local_version_rp; +#define READ_LOCAL_VERSION_RP_SIZE 9 + +#define OCF_READ_LOCAL_COMMANDS 0x0002 +typedef struct { + uint8_t status; + uint8_t commands[64]; +} __attribute__ ((packed)) read_local_commands_rp; +#define READ_LOCAL_COMMANDS_RP_SIZE 65 + +#define OCF_READ_LOCAL_FEATURES 0x0003 +typedef struct { + uint8_t status; + uint8_t features[8]; +} __attribute__ ((packed)) read_local_features_rp; +#define READ_LOCAL_FEATURES_RP_SIZE 9 + +#define OCF_READ_LOCAL_EXT_FEATURES 0x0004 +typedef struct { + uint8_t page_num; +} __attribute__ ((packed)) read_local_ext_features_cp; +#define READ_LOCAL_EXT_FEATURES_CP_SIZE 1 +typedef struct { + uint8_t status; + uint8_t page_num; + uint8_t max_page_num; + uint8_t features[8]; +} __attribute__ ((packed)) read_local_ext_features_rp; +#define READ_LOCAL_EXT_FEATURES_RP_SIZE 11 + +#define OCF_READ_BUFFER_SIZE 0x0005 +typedef struct { + uint8_t status; + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_max_pkt; + uint16_t sco_max_pkt; +} __attribute__ ((packed)) read_buffer_size_rp; +#define READ_BUFFER_SIZE_RP_SIZE 8 + +#define OCF_READ_COUNTRY_CODE 0x0007 + +#define OCF_READ_BD_ADDR 0x0009 +typedef struct { + uint8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) read_bd_addr_rp; +#define READ_BD_ADDR_RP_SIZE 7 + +#define OCF_READ_DATA_BLOCK_SIZE 0x000A +typedef struct { + uint8_t status; + uint16_t max_acl_len; + uint16_t data_block_len; + uint16_t num_blocks; +} __attribute__ ((packed)) read_data_block_size_rp; + +/* Status params */ +#define OGF_STATUS_PARAM 0x05 + +#define OCF_READ_FAILED_CONTACT_COUNTER 0x0001 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t counter; +} __attribute__ ((packed)) read_failed_contact_counter_rp; +#define READ_FAILED_CONTACT_COUNTER_RP_SIZE 4 + +#define OCF_RESET_FAILED_CONTACT_COUNTER 0x0002 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) reset_failed_contact_counter_rp; +#define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 3 + +#define OCF_READ_LINK_QUALITY 0x0003 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t link_quality; +} __attribute__ ((packed)) read_link_quality_rp; +#define READ_LINK_QUALITY_RP_SIZE 4 + +#define OCF_READ_RSSI 0x0005 +typedef struct { + uint8_t status; + uint16_t handle; + int8_t rssi; +} __attribute__ ((packed)) read_rssi_rp; +#define READ_RSSI_RP_SIZE 4 + +#define OCF_READ_AFH_MAP 0x0006 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t mode; + uint8_t map[10]; +} __attribute__ ((packed)) read_afh_map_rp; +#define READ_AFH_MAP_RP_SIZE 14 + +#define OCF_READ_CLOCK 0x0007 +typedef struct { + uint16_t handle; + uint8_t which_clock; +} __attribute__ ((packed)) read_clock_cp; +#define READ_CLOCK_CP_SIZE 3 +typedef struct { + uint8_t status; + uint16_t handle; + uint32_t clock; + uint16_t accuracy; +} __attribute__ ((packed)) read_clock_rp; +#define READ_CLOCK_RP_SIZE 9 + +#define OCF_READ_LOCAL_AMP_INFO 0x0009 +typedef struct { + uint8_t status; + uint8_t amp_status; + uint32_t total_bandwidth; + uint32_t max_guaranteed_bandwidth; + uint32_t min_latency; + uint32_t max_pdu_size; + uint8_t controller_type; + uint16_t pal_caps; + uint16_t max_amp_assoc_length; + uint32_t max_flush_timeout; + uint32_t best_effort_flush_timeout; +} __attribute__ ((packed)) read_local_amp_info_rp; +#define READ_LOCAL_AMP_INFO_RP_SIZE 31 + +#define OCF_READ_LOCAL_AMP_ASSOC 0x000A +typedef struct { + uint8_t handle; + uint16_t length_so_far; + uint16_t assoc_length; +} __attribute__ ((packed)) read_local_amp_assoc_cp; +#define READ_LOCAL_AMP_ASSOC_CP_SIZE 5 +typedef struct { + uint8_t status; + uint8_t handle; + uint16_t length; + uint8_t fragment[HCI_MAX_NAME_LENGTH]; +} __attribute__ ((packed)) read_local_amp_assoc_rp; +#define READ_LOCAL_AMP_ASSOC_RP_SIZE 252 + +#define OCF_WRITE_REMOTE_AMP_ASSOC 0x000B +typedef struct { + uint8_t handle; + uint16_t length_so_far; + uint16_t remaining_length; + uint8_t fragment[HCI_MAX_NAME_LENGTH]; +} __attribute__ ((packed)) write_remote_amp_assoc_cp; +#define WRITE_REMOTE_AMP_ASSOC_CP_SIZE 253 +typedef struct { + uint8_t status; + uint8_t handle; +} __attribute__ ((packed)) write_remote_amp_assoc_rp; +#define WRITE_REMOTE_AMP_ASSOC_RP_SIZE 2 + +/* Testing commands */ +#define OGF_TESTING_CMD 0x3e + +#define OCF_READ_LOOPBACK_MODE 0x0001 + +#define OCF_WRITE_LOOPBACK_MODE 0x0002 + +#define OCF_ENABLE_DEVICE_UNDER_TEST_MODE 0x0003 + +#define OCF_WRITE_SIMPLE_PAIRING_DEBUG_MODE 0x0004 +typedef struct { + uint8_t mode; +} __attribute__ ((packed)) write_simple_pairing_debug_mode_cp; +#define WRITE_SIMPLE_PAIRING_DEBUG_MODE_CP_SIZE 1 +typedef struct { + uint8_t status; +} __attribute__ ((packed)) write_simple_pairing_debug_mode_rp; +#define WRITE_SIMPLE_PAIRING_DEBUG_MODE_RP_SIZE 1 + +/* LE commands */ +#define OGF_LE_CTL 0x08 + +#define OCF_LE_SET_EVENT_MASK 0x0001 +typedef struct { + uint8_t mask[8]; +} __attribute__ ((packed)) le_set_event_mask_cp; +#define LE_SET_EVENT_MASK_CP_SIZE 8 + +#define OCF_LE_READ_BUFFER_SIZE 0x0002 +typedef struct { + uint8_t status; + uint16_t pkt_len; + uint8_t max_pkt; +} __attribute__ ((packed)) le_read_buffer_size_rp; +#define LE_READ_BUFFER_SIZE_RP_SIZE 4 + +#define OCF_LE_READ_LOCAL_SUPPORTED_FEATURES 0x0003 +typedef struct { + uint8_t status; + uint8_t features[8]; +} __attribute__ ((packed)) le_read_local_supported_features_rp; +#define LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE 9 + +#define OCF_LE_SET_RANDOM_ADDRESS 0x0005 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) le_set_random_address_cp; +#define LE_SET_RANDOM_ADDRESS_CP_SIZE 6 + +#define OCF_LE_SET_ADVERTISING_PARAMETERS 0x0006 +typedef struct { + uint16_t min_interval; + uint16_t max_interval; + uint8_t advtype; + uint8_t own_bdaddr_type; + uint8_t direct_bdaddr_type; + bdaddr_t direct_bdaddr; + uint8_t chan_map; + uint8_t filter; +} __attribute__ ((packed)) le_set_advertising_parameters_cp; +#define LE_SET_ADVERTISING_PARAMETERS_CP_SIZE 15 + +#define OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER 0x0007 +typedef struct { + uint8_t status; + int8_t level; +} __attribute__ ((packed)) le_read_advertising_channel_tx_power_rp; +#define LE_READ_ADVERTISING_CHANNEL_TX_POWER_RP_SIZE 2 + +#define OCF_LE_SET_ADVERTISING_DATA 0x0008 +typedef struct { + uint8_t length; + uint8_t data[31]; +} __attribute__ ((packed)) le_set_advertising_data_cp; +#define LE_SET_ADVERTISING_DATA_CP_SIZE 32 + +#define OCF_LE_SET_SCAN_RESPONSE_DATA 0x0009 +typedef struct { + uint8_t length; + uint8_t data[31]; +} __attribute__ ((packed)) le_set_scan_response_data_cp; +#define LE_SET_SCAN_RESPONSE_DATA_CP_SIZE 32 + +#define OCF_LE_SET_ADVERTISE_ENABLE 0x000A +typedef struct { + uint8_t enable; +} __attribute__ ((packed)) le_set_advertise_enable_cp; +#define LE_SET_ADVERTISE_ENABLE_CP_SIZE 1 + +#define OCF_LE_SET_SCAN_PARAMETERS 0x000B +typedef struct { + uint8_t type; + uint16_t interval; + uint16_t window; + uint8_t own_bdaddr_type; + uint8_t filter; +} __attribute__ ((packed)) le_set_scan_parameters_cp; +#define LE_SET_SCAN_PARAMETERS_CP_SIZE 7 + +#define OCF_LE_SET_SCAN_ENABLE 0x000C +typedef struct { + uint8_t enable; + uint8_t filter_dup; +} __attribute__ ((packed)) le_set_scan_enable_cp; +#define LE_SET_SCAN_ENABLE_CP_SIZE 2 + +#define OCF_LE_CREATE_CONN 0x000D +typedef struct { + uint16_t interval; + uint16_t window; + uint8_t initiator_filter; + uint8_t peer_bdaddr_type; + bdaddr_t peer_bdaddr; + uint8_t own_bdaddr_type; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supervision_timeout; + uint16_t min_ce_length; + uint16_t max_ce_length; +} __attribute__ ((packed)) le_create_connection_cp; +#define LE_CREATE_CONN_CP_SIZE 25 + +#define OCF_LE_CREATE_CONN_CANCEL 0x000E + +#define OCF_LE_READ_WHITE_LIST_SIZE 0x000F +typedef struct { + uint8_t status; + uint8_t size; +} __attribute__ ((packed)) le_read_white_list_size_rp; +#define LE_READ_WHITE_LIST_SIZE_RP_SIZE 2 + +#define OCF_LE_CLEAR_WHITE_LIST 0x0010 + +#define OCF_LE_ADD_DEVICE_TO_WHITE_LIST 0x0011 +typedef struct { + uint8_t bdaddr_type; + bdaddr_t bdaddr; +} __attribute__ ((packed)) le_add_device_to_white_list_cp; +#define LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE 7 + +#define OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST 0x0012 +typedef struct { + uint8_t bdaddr_type; + bdaddr_t bdaddr; +} __attribute__ ((packed)) le_remove_device_from_white_list_cp; +#define LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE 7 + +#define OCF_LE_CONN_UPDATE 0x0013 +typedef struct { + uint16_t handle; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supervision_timeout; + uint16_t min_ce_length; + uint16_t max_ce_length; +} __attribute__ ((packed)) le_connection_update_cp; +#define LE_CONN_UPDATE_CP_SIZE 14 + +#define OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION 0x0014 +typedef struct { + uint8_t map[5]; +} __attribute__ ((packed)) le_set_host_channel_classification_cp; +#define LE_SET_HOST_CHANNEL_CLASSIFICATION_CP_SIZE 5 + +#define OCF_LE_READ_CHANNEL_MAP 0x0015 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) le_read_channel_map_cp; +#define LE_READ_CHANNEL_MAP_CP_SIZE 2 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t map[5]; +} __attribute__ ((packed)) le_read_channel_map_rp; +#define LE_READ_CHANNEL_MAP_RP_SIZE 8 + +#define OCF_LE_READ_REMOTE_USED_FEATURES 0x0016 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) le_read_remote_used_features_cp; +#define LE_READ_REMOTE_USED_FEATURES_CP_SIZE 2 + +#define OCF_LE_ENCRYPT 0x0017 +typedef struct { + uint8_t key[16]; + uint8_t plaintext[16]; +} __attribute__ ((packed)) le_encrypt_cp; +#define LE_ENCRYPT_CP_SIZE 32 +typedef struct { + uint8_t status; + uint8_t data[16]; +} __attribute__ ((packed)) le_encrypt_rp; +#define LE_ENCRYPT_RP_SIZE 17 + +#define OCF_LE_RAND 0x0018 +typedef struct { + uint8_t status; + uint64_t random; +} __attribute__ ((packed)) le_rand_rp; +#define LE_RAND_RP_SIZE 9 + +#define OCF_LE_START_ENCRYPTION 0x0019 +typedef struct { + uint16_t handle; + uint64_t random; + uint16_t diversifier; + uint8_t key[16]; +} __attribute__ ((packed)) le_start_encryption_cp; +#define LE_START_ENCRYPTION_CP_SIZE 28 + +#define OCF_LE_LTK_REPLY 0x001A +typedef struct { + uint16_t handle; + uint8_t key[16]; +} __attribute__ ((packed)) le_ltk_reply_cp; +#define LE_LTK_REPLY_CP_SIZE 18 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) le_ltk_reply_rp; +#define LE_LTK_REPLY_RP_SIZE 3 + +#define OCF_LE_LTK_NEG_REPLY 0x001B +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) le_ltk_neg_reply_cp; +#define LE_LTK_NEG_REPLY_CP_SIZE 2 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) le_ltk_neg_reply_rp; +#define LE_LTK_NEG_REPLY_RP_SIZE 3 + +#define OCF_LE_READ_SUPPORTED_STATES 0x001C +typedef struct { + uint8_t status; + uint64_t states; +} __attribute__ ((packed)) le_read_supported_states_rp; +#define LE_READ_SUPPORTED_STATES_RP_SIZE 9 + +#define OCF_LE_RECEIVER_TEST 0x001D +typedef struct { + uint8_t frequency; +} __attribute__ ((packed)) le_receiver_test_cp; +#define LE_RECEIVER_TEST_CP_SIZE 1 + +#define OCF_LE_TRANSMITTER_TEST 0x001E +typedef struct { + uint8_t frequency; + uint8_t length; + uint8_t payload; +} __attribute__ ((packed)) le_transmitter_test_cp; +#define LE_TRANSMITTER_TEST_CP_SIZE 3 + +#define OCF_LE_TEST_END 0x001F +typedef struct { + uint8_t status; + uint16_t num_pkts; +} __attribute__ ((packed)) le_test_end_rp; +#define LE_TEST_END_RP_SIZE 3 + +#define OCF_LE_ADD_DEVICE_TO_RESOLV_LIST 0x0027 +typedef struct { + uint8_t bdaddr_type; + bdaddr_t bdaddr; + uint8_t peer_irk[16]; + uint8_t local_irk[16]; +} __attribute__ ((packed)) le_add_device_to_resolv_list_cp; +#define LE_ADD_DEVICE_TO_RESOLV_LIST_CP_SIZE 39 + +#define OCF_LE_REMOVE_DEVICE_FROM_RESOLV_LIST 0x0028 +typedef struct { + uint8_t bdaddr_type; + bdaddr_t bdaddr; +} __attribute__ ((packed)) le_remove_device_from_resolv_list_cp; +#define LE_REMOVE_DEVICE_FROM_RESOLV_LIST_CP_SIZE 7 + +#define OCF_LE_CLEAR_RESOLV_LIST 0x0029 + +#define OCF_LE_READ_RESOLV_LIST_SIZE 0x002A +typedef struct { + uint8_t status; + uint8_t size; +} __attribute__ ((packed)) le_read_resolv_list_size_rp; +#define LE_READ_RESOLV_LIST_SIZE_RP_SIZE 2 + +#define OCF_LE_SET_ADDRESS_RESOLUTION_ENABLE 0x002D +typedef struct { + uint8_t enable; +} __attribute__ ((packed)) le_set_address_resolution_enable_cp; +#define LE_SET_ADDRESS_RESOLUTION_ENABLE_CP_SIZE 1 + +/* Vendor specific commands */ +#define OGF_VENDOR_CMD 0x3f + +/* ---- HCI Events ---- */ + +#define EVT_INQUIRY_COMPLETE 0x01 + +#define EVT_INQUIRY_RESULT 0x02 +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t pscan_period_mode; + uint8_t pscan_mode; + uint8_t dev_class[3]; + uint16_t clock_offset; +} __attribute__ ((packed)) inquiry_info; +#define INQUIRY_INFO_SIZE 14 + +#define EVT_CONN_COMPLETE 0x03 +typedef struct { + uint8_t status; + uint16_t handle; + bdaddr_t bdaddr; + uint8_t link_type; + uint8_t encr_mode; +} __attribute__ ((packed)) evt_conn_complete; +#define EVT_CONN_COMPLETE_SIZE 11 + +#define EVT_CONN_REQUEST 0x04 +typedef struct { + bdaddr_t bdaddr; + uint8_t dev_class[3]; + uint8_t link_type; +} __attribute__ ((packed)) evt_conn_request; +#define EVT_CONN_REQUEST_SIZE 10 + +#define EVT_DISCONN_COMPLETE 0x05 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t reason; +} __attribute__ ((packed)) evt_disconn_complete; +#define EVT_DISCONN_COMPLETE_SIZE 4 + +#define EVT_AUTH_COMPLETE 0x06 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) evt_auth_complete; +#define EVT_AUTH_COMPLETE_SIZE 3 + +#define EVT_REMOTE_NAME_REQ_COMPLETE 0x07 +typedef struct { + uint8_t status; + bdaddr_t bdaddr; + uint8_t name[HCI_MAX_NAME_LENGTH]; +} __attribute__ ((packed)) evt_remote_name_req_complete; +#define EVT_REMOTE_NAME_REQ_COMPLETE_SIZE 255 + +#define EVT_ENCRYPT_CHANGE 0x08 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t encrypt; +} __attribute__ ((packed)) evt_encrypt_change; +#define EVT_ENCRYPT_CHANGE_SIZE 4 + +#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE 0x09 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) evt_change_conn_link_key_complete; +#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE_SIZE 3 + +#define EVT_MASTER_LINK_KEY_COMPLETE 0x0A +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t key_flag; +} __attribute__ ((packed)) evt_master_link_key_complete; +#define EVT_MASTER_LINK_KEY_COMPLETE_SIZE 4 + +#define EVT_READ_REMOTE_FEATURES_COMPLETE 0x0B +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __attribute__ ((packed)) evt_read_remote_features_complete; +#define EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE 11 + +#define EVT_READ_REMOTE_VERSION_COMPLETE 0x0C +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t lmp_ver; + uint16_t manufacturer; + uint16_t lmp_subver; +} __attribute__ ((packed)) evt_read_remote_version_complete; +#define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8 + +#define EVT_QOS_SETUP_COMPLETE 0x0D +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t flags; /* Reserved */ + hci_qos qos; +} __attribute__ ((packed)) evt_qos_setup_complete; +#define EVT_QOS_SETUP_COMPLETE_SIZE (4 + HCI_QOS_CP_SIZE) + +#define EVT_CMD_COMPLETE 0x0E +typedef struct { + uint8_t ncmd; + uint16_t opcode; +} __attribute__ ((packed)) evt_cmd_complete; +#define EVT_CMD_COMPLETE_SIZE 3 + +#define EVT_CMD_STATUS 0x0F +typedef struct { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __attribute__ ((packed)) evt_cmd_status; +#define EVT_CMD_STATUS_SIZE 4 + +#define EVT_HARDWARE_ERROR 0x10 +typedef struct { + uint8_t code; +} __attribute__ ((packed)) evt_hardware_error; +#define EVT_HARDWARE_ERROR_SIZE 1 + +#define EVT_FLUSH_OCCURRED 0x11 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) evt_flush_occured; +#define EVT_FLUSH_OCCURRED_SIZE 2 + +#define EVT_ROLE_CHANGE 0x12 +typedef struct { + uint8_t status; + bdaddr_t bdaddr; + uint8_t role; +} __attribute__ ((packed)) evt_role_change; +#define EVT_ROLE_CHANGE_SIZE 8 + +#define EVT_NUM_COMP_PKTS 0x13 +typedef struct { + uint8_t num_hndl; + /* variable length part */ +} __attribute__ ((packed)) evt_num_comp_pkts; +#define EVT_NUM_COMP_PKTS_SIZE 1 + +#define EVT_MODE_CHANGE 0x14 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t mode; + uint16_t interval; +} __attribute__ ((packed)) evt_mode_change; +#define EVT_MODE_CHANGE_SIZE 6 + +#define EVT_RETURN_LINK_KEYS 0x15 +typedef struct { + uint8_t num_keys; + /* variable length part */ +} __attribute__ ((packed)) evt_return_link_keys; +#define EVT_RETURN_LINK_KEYS_SIZE 1 + +#define EVT_PIN_CODE_REQ 0x16 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_pin_code_req; +#define EVT_PIN_CODE_REQ_SIZE 6 + +#define EVT_LINK_KEY_REQ 0x17 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_link_key_req; +#define EVT_LINK_KEY_REQ_SIZE 6 + +#define EVT_LINK_KEY_NOTIFY 0x18 +typedef struct { + bdaddr_t bdaddr; + uint8_t link_key[16]; + uint8_t key_type; +} __attribute__ ((packed)) evt_link_key_notify; +#define EVT_LINK_KEY_NOTIFY_SIZE 23 + +#define EVT_LOOPBACK_COMMAND 0x19 + +#define EVT_DATA_BUFFER_OVERFLOW 0x1A +typedef struct { + uint8_t link_type; +} __attribute__ ((packed)) evt_data_buffer_overflow; +#define EVT_DATA_BUFFER_OVERFLOW_SIZE 1 + +#define EVT_MAX_SLOTS_CHANGE 0x1B +typedef struct { + uint16_t handle; + uint8_t max_slots; +} __attribute__ ((packed)) evt_max_slots_change; +#define EVT_MAX_SLOTS_CHANGE_SIZE 3 + +#define EVT_READ_CLOCK_OFFSET_COMPLETE 0x1C +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t clock_offset; +} __attribute__ ((packed)) evt_read_clock_offset_complete; +#define EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE 5 + +#define EVT_CONN_PTYPE_CHANGED 0x1D +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t ptype; +} __attribute__ ((packed)) evt_conn_ptype_changed; +#define EVT_CONN_PTYPE_CHANGED_SIZE 5 + +#define EVT_QOS_VIOLATION 0x1E +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) evt_qos_violation; +#define EVT_QOS_VIOLATION_SIZE 2 + +#define EVT_PSCAN_REP_MODE_CHANGE 0x20 +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; +} __attribute__ ((packed)) evt_pscan_rep_mode_change; +#define EVT_PSCAN_REP_MODE_CHANGE_SIZE 7 + +#define EVT_FLOW_SPEC_COMPLETE 0x21 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t flags; + uint8_t direction; + hci_qos qos; +} __attribute__ ((packed)) evt_flow_spec_complete; +#define EVT_FLOW_SPEC_COMPLETE_SIZE (5 + HCI_QOS_CP_SIZE) + +#define EVT_INQUIRY_RESULT_WITH_RSSI 0x22 +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t pscan_period_mode; + uint8_t dev_class[3]; + uint16_t clock_offset; + int8_t rssi; +} __attribute__ ((packed)) inquiry_info_with_rssi; +#define INQUIRY_INFO_WITH_RSSI_SIZE 14 +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t pscan_period_mode; + uint8_t pscan_mode; + uint8_t dev_class[3]; + uint16_t clock_offset; + int8_t rssi; +} __attribute__ ((packed)) inquiry_info_with_rssi_and_pscan_mode; +#define INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE 15 + +#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE 0x23 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t page_num; + uint8_t max_page_num; + uint8_t features[8]; +} __attribute__ ((packed)) evt_read_remote_ext_features_complete; +#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE 13 + +#define EVT_SYNC_CONN_COMPLETE 0x2C +typedef struct { + uint8_t status; + uint16_t handle; + bdaddr_t bdaddr; + uint8_t link_type; + uint8_t trans_interval; + uint8_t retrans_window; + uint16_t rx_pkt_len; + uint16_t tx_pkt_len; + uint8_t air_mode; +} __attribute__ ((packed)) evt_sync_conn_complete; +#define EVT_SYNC_CONN_COMPLETE_SIZE 17 + +#define EVT_SYNC_CONN_CHANGED 0x2D +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t trans_interval; + uint8_t retrans_window; + uint16_t rx_pkt_len; + uint16_t tx_pkt_len; +} __attribute__ ((packed)) evt_sync_conn_changed; +#define EVT_SYNC_CONN_CHANGED_SIZE 9 + +#define EVT_SNIFF_SUBRATING 0x2E +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t max_tx_latency; + uint16_t max_rx_latency; + uint16_t min_remote_timeout; + uint16_t min_local_timeout; +} __attribute__ ((packed)) evt_sniff_subrating; +#define EVT_SNIFF_SUBRATING_SIZE 11 + +#define EVT_EXTENDED_INQUIRY_RESULT 0x2F +typedef struct { + bdaddr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t pscan_period_mode; + uint8_t dev_class[3]; + uint16_t clock_offset; + int8_t rssi; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __attribute__ ((packed)) extended_inquiry_info; +#define EXTENDED_INQUIRY_INFO_SIZE 254 + +#define EVT_ENCRYPTION_KEY_REFRESH_COMPLETE 0x30 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) evt_encryption_key_refresh_complete; +#define EVT_ENCRYPTION_KEY_REFRESH_COMPLETE_SIZE 3 + +#define EVT_IO_CAPABILITY_REQUEST 0x31 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_io_capability_request; +#define EVT_IO_CAPABILITY_REQUEST_SIZE 6 + +#define EVT_IO_CAPABILITY_RESPONSE 0x32 +typedef struct { + bdaddr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __attribute__ ((packed)) evt_io_capability_response; +#define EVT_IO_CAPABILITY_RESPONSE_SIZE 9 + +#define EVT_USER_CONFIRM_REQUEST 0x33 +typedef struct { + bdaddr_t bdaddr; + uint32_t passkey; +} __attribute__ ((packed)) evt_user_confirm_request; +#define EVT_USER_CONFIRM_REQUEST_SIZE 10 + +#define EVT_USER_PASSKEY_REQUEST 0x34 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_user_passkey_request; +#define EVT_USER_PASSKEY_REQUEST_SIZE 6 + +#define EVT_REMOTE_OOB_DATA_REQUEST 0x35 +typedef struct { + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_remote_oob_data_request; +#define EVT_REMOTE_OOB_DATA_REQUEST_SIZE 6 + +#define EVT_SIMPLE_PAIRING_COMPLETE 0x36 +typedef struct { + uint8_t status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) evt_simple_pairing_complete; +#define EVT_SIMPLE_PAIRING_COMPLETE_SIZE 7 + +#define EVT_LINK_SUPERVISION_TIMEOUT_CHANGED 0x38 +typedef struct { + uint16_t handle; + uint16_t timeout; +} __attribute__ ((packed)) evt_link_supervision_timeout_changed; +#define EVT_LINK_SUPERVISION_TIMEOUT_CHANGED_SIZE 4 + +#define EVT_ENHANCED_FLUSH_COMPLETE 0x39 +typedef struct { + uint16_t handle; +} __attribute__ ((packed)) evt_enhanced_flush_complete; +#define EVT_ENHANCED_FLUSH_COMPLETE_SIZE 2 + +#define EVT_USER_PASSKEY_NOTIFY 0x3B +typedef struct { + bdaddr_t bdaddr; + uint32_t passkey; +} __attribute__ ((packed)) evt_user_passkey_notify; +#define EVT_USER_PASSKEY_NOTIFY_SIZE 10 + +#define EVT_KEYPRESS_NOTIFY 0x3C +typedef struct { + bdaddr_t bdaddr; + uint8_t type; +} __attribute__ ((packed)) evt_keypress_notify; +#define EVT_KEYPRESS_NOTIFY_SIZE 7 + +#define EVT_REMOTE_HOST_FEATURES_NOTIFY 0x3D +typedef struct { + bdaddr_t bdaddr; + uint8_t features[8]; +} __attribute__ ((packed)) evt_remote_host_features_notify; +#define EVT_REMOTE_HOST_FEATURES_NOTIFY_SIZE 14 + +#define EVT_LE_META_EVENT 0x3E +typedef struct { + uint8_t subevent; + uint8_t data[0]; +} __attribute__ ((packed)) evt_le_meta_event; +#define EVT_LE_META_EVENT_SIZE 1 + +#define EVT_LE_CONN_COMPLETE 0x01 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t role; + uint8_t peer_bdaddr_type; + bdaddr_t peer_bdaddr; + uint16_t interval; + uint16_t latency; + uint16_t supervision_timeout; + uint8_t master_clock_accuracy; +} __attribute__ ((packed)) evt_le_connection_complete; +#define EVT_LE_CONN_COMPLETE_SIZE 18 + +#define EVT_LE_ADVERTISING_REPORT 0x02 +typedef struct { + uint8_t evt_type; + uint8_t bdaddr_type; + bdaddr_t bdaddr; + uint8_t length; + uint8_t data[0]; +} __attribute__ ((packed)) le_advertising_info; +#define LE_ADVERTISING_INFO_SIZE 9 + +#define EVT_LE_CONN_UPDATE_COMPLETE 0x03 +typedef struct { + uint8_t status; + uint16_t handle; + uint16_t interval; + uint16_t latency; + uint16_t supervision_timeout; +} __attribute__ ((packed)) evt_le_connection_update_complete; +#define EVT_LE_CONN_UPDATE_COMPLETE_SIZE 9 + +#define EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04 +typedef struct { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __attribute__ ((packed)) evt_le_read_remote_used_features_complete; +#define EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE_SIZE 11 + +#define EVT_LE_LTK_REQUEST 0x05 +typedef struct { + uint16_t handle; + uint64_t random; + uint16_t diversifier; +} __attribute__ ((packed)) evt_le_long_term_key_request; +#define EVT_LE_LTK_REQUEST_SIZE 12 + +#define EVT_PHYSICAL_LINK_COMPLETE 0x40 +typedef struct { + uint8_t status; + uint8_t handle; +} __attribute__ ((packed)) evt_physical_link_complete; +#define EVT_PHYSICAL_LINK_COMPLETE_SIZE 2 + +#define EVT_CHANNEL_SELECTED 0x41 + +#define EVT_DISCONNECT_PHYSICAL_LINK_COMPLETE 0x42 +typedef struct { + uint8_t status; + uint8_t handle; + uint8_t reason; +} __attribute__ ((packed)) evt_disconn_physical_link_complete; +#define EVT_DISCONNECT_PHYSICAL_LINK_COMPLETE_SIZE 3 + +#define EVT_PHYSICAL_LINK_LOSS_EARLY_WARNING 0x43 +typedef struct { + uint8_t handle; + uint8_t reason; +} __attribute__ ((packed)) evt_physical_link_loss_warning; +#define EVT_PHYSICAL_LINK_LOSS_WARNING_SIZE 2 + +#define EVT_PHYSICAL_LINK_RECOVERY 0x44 +typedef struct { + uint8_t handle; +} __attribute__ ((packed)) evt_physical_link_recovery; +#define EVT_PHYSICAL_LINK_RECOVERY_SIZE 1 + +#define EVT_LOGICAL_LINK_COMPLETE 0x45 +typedef struct { + uint8_t status; + uint16_t log_handle; + uint8_t handle; + uint8_t tx_flow_id; +} __attribute__ ((packed)) evt_logical_link_complete; +#define EVT_LOGICAL_LINK_COMPLETE_SIZE 5 + +#define EVT_DISCONNECT_LOGICAL_LINK_COMPLETE 0x46 + +#define EVT_FLOW_SPEC_MODIFY_COMPLETE 0x47 +typedef struct { + uint8_t status; + uint16_t handle; +} __attribute__ ((packed)) evt_flow_spec_modify_complete; +#define EVT_FLOW_SPEC_MODIFY_COMPLETE_SIZE 3 + +#define EVT_NUMBER_COMPLETED_BLOCKS 0x48 +typedef struct { + uint16_t handle; + uint16_t num_cmplt_pkts; + uint16_t num_cmplt_blks; +} __attribute__ ((packed)) cmplt_handle; +typedef struct { + uint16_t total_num_blocks; + uint8_t num_handles; + cmplt_handle handles[0]; +} __attribute__ ((packed)) evt_num_completed_blocks; + +#define EVT_AMP_STATUS_CHANGE 0x4D +typedef struct { + uint8_t status; + uint8_t amp_status; +} __attribute__ ((packed)) evt_amp_status_change; +#define EVT_AMP_STATUS_CHANGE_SIZE 2 + +#define EVT_TESTING 0xFE + +#define EVT_VENDOR 0xFF + +/* Internal events generated by BlueZ stack */ +#define EVT_STACK_INTERNAL 0xFD +typedef struct { + uint16_t type; + uint8_t data[0]; +} __attribute__ ((packed)) evt_stack_internal; +#define EVT_STACK_INTERNAL_SIZE 2 + +#define EVT_SI_DEVICE 0x01 +typedef struct { + uint16_t event; + uint16_t dev_id; +} __attribute__ ((packed)) evt_si_device; +#define EVT_SI_DEVICE_SIZE 4 + +/* -------- HCI Packet structures -------- */ +#define HCI_TYPE_LEN 1 + +typedef struct { + uint16_t opcode; /* OCF & OGF */ + uint8_t plen; +} __attribute__ ((packed)) hci_command_hdr; +#define HCI_COMMAND_HDR_SIZE 3 + +typedef struct { + uint8_t evt; + uint8_t plen; +} __attribute__ ((packed)) hci_event_hdr; +#define HCI_EVENT_HDR_SIZE 2 + +typedef struct { + uint16_t handle; /* Handle & Flags(PB, BC) */ + uint16_t dlen; +} __attribute__ ((packed)) hci_acl_hdr; +#define HCI_ACL_HDR_SIZE 4 + +typedef struct { + uint16_t handle; + uint8_t dlen; +} __attribute__ ((packed)) hci_sco_hdr; +#define HCI_SCO_HDR_SIZE 3 + +typedef struct { + uint16_t device; + uint16_t type; + uint16_t plen; +} __attribute__ ((packed)) hci_msg_hdr; +#define HCI_MSG_HDR_SIZE 6 + +/* Command opcode pack/unpack */ +#define cmd_opcode_pack(ogf, ocf) (uint16_t)((ocf & 0x03ff)|(ogf << 10)) +#define cmd_opcode_ogf(op) (op >> 10) +#define cmd_opcode_ocf(op) (op & 0x03ff) + +/* ACL handle and flags pack/unpack */ +#define acl_handle_pack(h, f) (uint16_t)((h & 0x0fff)|(f << 12)) +#define acl_handle(h) (h & 0x0fff) +#define acl_flags(h) (h >> 12) + +#endif /* _NO_HCI_DEFS */ + +/* HCI Socket options */ +#define HCI_DATA_DIR 1 +#define HCI_FILTER 2 +#define HCI_TIME_STAMP 3 + +/* HCI CMSG flags */ +#define HCI_CMSG_DIR 0x0001 +#define HCI_CMSG_TSTAMP 0x0002 + +struct sockaddr_hci { + sa_family_t hci_family; + unsigned short hci_dev; + unsigned short hci_channel; +}; +#define HCI_DEV_NONE 0xffff + +#define HCI_CHANNEL_RAW 0 +#define HCI_CHANNEL_USER 1 +#define HCI_CHANNEL_MONITOR 2 +#define HCI_CHANNEL_CONTROL 3 +#define HCI_CHANNEL_LOGGING 4 + +struct hci_filter { + uint32_t type_mask; + uint32_t event_mask[2]; + uint16_t opcode; +}; + +#define HCI_FLT_TYPE_BITS 31 +#define HCI_FLT_EVENT_BITS 63 +#define HCI_FLT_OGF_BITS 63 +#define HCI_FLT_OCF_BITS 127 + +/* Ioctl requests structures */ +struct hci_dev_stats { + uint32_t err_rx; + uint32_t err_tx; + uint32_t cmd_tx; + uint32_t evt_rx; + uint32_t acl_tx; + uint32_t acl_rx; + uint32_t sco_tx; + uint32_t sco_rx; + uint32_t byte_rx; + uint32_t byte_tx; +}; + +struct hci_dev_info { + uint16_t dev_id; + char name[8]; + + bdaddr_t bdaddr; + + uint32_t flags; + uint8_t type; + + uint8_t features[8]; + + uint32_t pkt_type; + uint32_t link_policy; + uint32_t link_mode; + + uint16_t acl_mtu; + uint16_t acl_pkts; + uint16_t sco_mtu; + uint16_t sco_pkts; + + struct hci_dev_stats stat; +}; + +struct hci_conn_info { + uint16_t handle; + bdaddr_t bdaddr; + uint8_t type; + uint8_t out; + uint16_t state; + uint32_t link_mode; +}; + +struct hci_dev_req { + uint16_t dev_id; + uint32_t dev_opt; +}; + +struct hci_dev_list_req { + uint16_t dev_num; + struct hci_dev_req dev_req[0]; /* hci_dev_req structures */ +}; + +struct hci_conn_list_req { + uint16_t dev_id; + uint16_t conn_num; + struct hci_conn_info conn_info[0]; +}; + +struct hci_conn_info_req { + bdaddr_t bdaddr; + uint8_t type; + struct hci_conn_info conn_info[0]; +}; + +struct hci_auth_info_req { + bdaddr_t bdaddr; + uint8_t type; +}; + +struct hci_inquiry_req { + uint16_t dev_id; + uint16_t flags; + uint8_t lap[3]; + uint8_t length; + uint8_t num_rsp; +}; +#define IREQ_CACHE_FLUSH 0x0001 + +#ifdef __cplusplus +} +#endif + +#endif /* __HCI_H */ diff --git a/lib/bluetooth/hci_lib.h b/lib/bluetooth/hci_lib.h new file mode 100644 index 0000000..55aeb17 --- /dev/null +++ b/lib/bluetooth/hci_lib.h @@ -0,0 +1,242 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __HCI_LIB_H +#define __HCI_LIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct hci_request { + uint16_t ogf; + uint16_t ocf; + int event; + void *cparam; + int clen; + void *rparam; + int rlen; +}; + +struct hci_version { + uint16_t manufacturer; + uint8_t hci_ver; + uint16_t hci_rev; + uint8_t lmp_ver; + uint16_t lmp_subver; +}; + +int hci_open_dev(int dev_id); +int hci_close_dev(int dd); +int hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param); +int hci_send_req(int dd, struct hci_request *req, int timeout); + +int hci_create_connection(int dd, const bdaddr_t *bdaddr, uint16_t ptype, uint16_t clkoffset, uint8_t rswitch, uint16_t *handle, int to); +int hci_disconnect(int dd, uint16_t handle, uint8_t reason, int to); + +int hci_inquiry(int dev_id, int len, int num_rsp, const uint8_t *lap, inquiry_info **ii, long flags); +int hci_devinfo(int dev_id, struct hci_dev_info *di); +int hci_devba(int dev_id, bdaddr_t *bdaddr); +int hci_devid(const char *str); + +int hci_read_local_name(int dd, int len, char *name, int to); +int hci_write_local_name(int dd, const char *name, int to); +int hci_read_remote_name(int dd, const bdaddr_t *bdaddr, int len, char *name, int to); +int hci_read_remote_name_with_clock_offset(int dd, const bdaddr_t *bdaddr, uint8_t pscan_rep_mode, uint16_t clkoffset, int len, char *name, int to); +int hci_read_remote_name_cancel(int dd, const bdaddr_t *bdaddr, int to); +int hci_read_remote_version(int dd, uint16_t handle, struct hci_version *ver, int to); +int hci_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to); +int hci_read_remote_ext_features(int dd, uint16_t handle, uint8_t page, uint8_t *max_page, uint8_t *features, int to); +int hci_read_clock_offset(int dd, uint16_t handle, uint16_t *clkoffset, int to); +int hci_read_local_version(int dd, struct hci_version *ver, int to); +int hci_read_local_commands(int dd, uint8_t *commands, int to); +int hci_read_local_features(int dd, uint8_t *features, int to); +int hci_read_local_ext_features(int dd, uint8_t page, uint8_t *max_page, uint8_t *features, int to); +int hci_read_bd_addr(int dd, bdaddr_t *bdaddr, int to); +int hci_read_class_of_dev(int dd, uint8_t *cls, int to); +int hci_write_class_of_dev(int dd, uint32_t cls, int to); +int hci_read_voice_setting(int dd, uint16_t *vs, int to); +int hci_write_voice_setting(int dd, uint16_t vs, int to); +int hci_read_current_iac_lap(int dd, uint8_t *num_iac, uint8_t *lap, int to); +int hci_write_current_iac_lap(int dd, uint8_t num_iac, uint8_t *lap, int to); +int hci_read_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to); +int hci_write_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t *key, int to); +int hci_delete_stored_link_key(int dd, bdaddr_t *bdaddr, uint8_t all, int to); +int hci_authenticate_link(int dd, uint16_t handle, int to); +int hci_encrypt_link(int dd, uint16_t handle, uint8_t encrypt, int to); +int hci_change_link_key(int dd, uint16_t handle, int to); +int hci_switch_role(int dd, bdaddr_t *bdaddr, uint8_t role, int to); +int hci_park_mode(int dd, uint16_t handle, uint16_t max_interval, uint16_t min_interval, int to); +int hci_exit_park_mode(int dd, uint16_t handle, int to); +int hci_read_inquiry_scan_type(int dd, uint8_t *type, int to); +int hci_write_inquiry_scan_type(int dd, uint8_t type, int to); +int hci_read_inquiry_mode(int dd, uint8_t *mode, int to); +int hci_write_inquiry_mode(int dd, uint8_t mode, int to); +int hci_read_afh_mode(int dd, uint8_t *mode, int to); +int hci_write_afh_mode(int dd, uint8_t mode, int to); +int hci_read_ext_inquiry_response(int dd, uint8_t *fec, uint8_t *data, int to); +int hci_write_ext_inquiry_response(int dd, uint8_t fec, uint8_t *data, int to); +int hci_read_simple_pairing_mode(int dd, uint8_t *mode, int to); +int hci_write_simple_pairing_mode(int dd, uint8_t mode, int to); +int hci_read_local_oob_data(int dd, uint8_t *hash, uint8_t *randomizer, int to); +int hci_read_inq_response_tx_power_level(int dd, int8_t *level, int to); +int hci_read_inquiry_transmit_power_level(int dd, int8_t *level, int to); +int hci_write_inquiry_transmit_power_level(int dd, int8_t level, int to); +int hci_read_transmit_power_level(int dd, uint16_t handle, uint8_t type, int8_t *level, int to); +int hci_read_link_policy(int dd, uint16_t handle, uint16_t *policy, int to); +int hci_write_link_policy(int dd, uint16_t handle, uint16_t policy, int to); +int hci_read_link_supervision_timeout(int dd, uint16_t handle, uint16_t *timeout, int to); +int hci_write_link_supervision_timeout(int dd, uint16_t handle, uint16_t timeout, int to); +int hci_set_afh_classification(int dd, uint8_t *map, int to); +int hci_read_link_quality(int dd, uint16_t handle, uint8_t *link_quality, int to); +int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to); +int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map, int to); +int hci_read_clock(int dd, uint16_t handle, uint8_t which, uint32_t *clock, uint16_t *accuracy, int to); + +int hci_le_set_scan_enable(int dev_id, uint8_t enable, uint8_t filter_dup, int to); +int hci_le_set_scan_parameters(int dev_id, uint8_t type, uint16_t interval, + uint16_t window, uint8_t own_type, + uint8_t filter, int to); +int hci_le_set_advertise_enable(int dev_id, uint8_t enable, int to); +int hci_le_create_conn(int dd, uint16_t interval, uint16_t window, + uint8_t initiator_filter, uint8_t peer_bdaddr_type, + bdaddr_t peer_bdaddr, uint8_t own_bdaddr_type, + uint16_t min_interval, uint16_t max_interval, + uint16_t latency, uint16_t supervision_timeout, + uint16_t min_ce_length, uint16_t max_ce_length, + uint16_t *handle, int to); +int hci_le_conn_update(int dd, uint16_t handle, uint16_t min_interval, + uint16_t max_interval, uint16_t latency, + uint16_t supervision_timeout, int to); +int hci_le_add_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to); +int hci_le_rm_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to); +int hci_le_read_white_list_size(int dd, uint8_t *size, int to); +int hci_le_clear_white_list(int dd, int to); +int hci_le_add_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type, + uint8_t *peer_irk, uint8_t *local_irk, int to); +int hci_le_rm_resolving_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to); +int hci_le_clear_resolving_list(int dd, int to); +int hci_le_read_resolving_list_size(int dd, uint8_t *size, int to); +int hci_le_set_address_resolution_enable(int dev_id, uint8_t enable, int to); +int hci_le_read_remote_features(int dd, uint16_t handle, uint8_t *features, int to); + +int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg); +int hci_get_route(bdaddr_t *bdaddr); + +char *hci_bustostr(int bus); +char *hci_typetostr(int type); +char *hci_dtypetostr(int type); +char *hci_dflagstostr(uint32_t flags); +char *hci_ptypetostr(unsigned int ptype); +int hci_strtoptype(char *str, unsigned int *val); +char *hci_scoptypetostr(unsigned int ptype); +int hci_strtoscoptype(char *str, unsigned int *val); +char *hci_lptostr(unsigned int ptype); +int hci_strtolp(char *str, unsigned int *val); +char *hci_lmtostr(unsigned int ptype); +int hci_strtolm(char *str, unsigned int *val); + +char *hci_cmdtostr(unsigned int cmd); +char *hci_commandstostr(uint8_t *commands, char *pref, int width); + +char *hci_vertostr(unsigned int ver); +int hci_strtover(char *str, unsigned int *ver); +char *lmp_vertostr(unsigned int ver); +int lmp_strtover(char *str, unsigned int *ver); +char *pal_vertostr(unsigned int ver); +int pal_strtover(char *str, unsigned int *ver); + +char *lmp_featurestostr(uint8_t *features, char *pref, int width); + +static inline void hci_set_bit(int nr, void *addr) +{ + *((uint32_t *) addr + (nr >> 5)) |= (1 << (nr & 31)); +} + +static inline void hci_clear_bit(int nr, void *addr) +{ + *((uint32_t *) addr + (nr >> 5)) &= ~(1 << (nr & 31)); +} + +static inline int hci_test_bit(int nr, void *addr) +{ + return *((uint32_t *) addr + (nr >> 5)) & (1 << (nr & 31)); +} + +/* HCI filter tools */ +static inline void hci_filter_clear(struct hci_filter *f) +{ + memset(f, 0, sizeof(*f)); +} +static inline void hci_filter_set_ptype(int t, struct hci_filter *f) +{ + hci_set_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask); +} +static inline void hci_filter_clear_ptype(int t, struct hci_filter *f) +{ + hci_clear_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask); +} +static inline int hci_filter_test_ptype(int t, struct hci_filter *f) +{ + return hci_test_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask); +} +static inline void hci_filter_all_ptypes(struct hci_filter *f) +{ + memset((void *) &f->type_mask, 0xff, sizeof(f->type_mask)); +} +static inline void hci_filter_set_event(int e, struct hci_filter *f) +{ + hci_set_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask); +} +static inline void hci_filter_clear_event(int e, struct hci_filter *f) +{ + hci_clear_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask); +} +static inline int hci_filter_test_event(int e, struct hci_filter *f) +{ + return hci_test_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask); +} +static inline void hci_filter_all_events(struct hci_filter *f) +{ + memset((void *) f->event_mask, 0xff, sizeof(f->event_mask)); +} +static inline void hci_filter_set_opcode(int opcode, struct hci_filter *f) +{ + f->opcode = opcode; +} +static inline void hci_filter_clear_opcode(struct hci_filter *f) +{ + f->opcode = 0; +} +static inline int hci_filter_test_opcode(int opcode, struct hci_filter *f) +{ + return (f->opcode == opcode); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __HCI_LIB_H */ diff --git a/lib/bluetooth/hidp.h b/lib/bluetooth/hidp.h new file mode 100644 index 0000000..c5e6a78 --- /dev/null +++ b/lib/bluetooth/hidp.h @@ -0,0 +1,85 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2003-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __HIDP_H +#define __HIDP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* HIDP defaults */ +#define HIDP_MINIMUM_MTU 48 +#define HIDP_DEFAULT_MTU 48 + +/* HIDP ioctl defines */ +#define HIDPCONNADD _IOW('H', 200, int) +#define HIDPCONNDEL _IOW('H', 201, int) +#define HIDPGETCONNLIST _IOR('H', 210, int) +#define HIDPGETCONNINFO _IOR('H', 211, int) + +#define HIDP_VIRTUAL_CABLE_UNPLUG 0 +#define HIDP_BOOT_PROTOCOL_MODE 1 +#define HIDP_BLUETOOTH_VENDOR_ID 9 + +struct hidp_connadd_req { + int ctrl_sock; /* Connected control socket */ + int intr_sock; /* Connected interrupt socket */ + uint16_t parser; /* Parser version */ + uint16_t rd_size; /* Report descriptor size */ + uint8_t *rd_data; /* Report descriptor data */ + uint8_t country; + uint8_t subclass; + uint16_t vendor; + uint16_t product; + uint16_t version; + uint32_t flags; + uint32_t idle_to; + char name[128]; /* Device name */ +}; + +struct hidp_conndel_req { + bdaddr_t bdaddr; + uint32_t flags; +}; + +struct hidp_conninfo { + bdaddr_t bdaddr; + uint32_t flags; + uint16_t state; + uint16_t vendor; + uint16_t product; + uint16_t version; + char name[128]; +}; + +struct hidp_connlist_req { + uint32_t cnum; + struct hidp_conninfo *ci; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __HIDP_H */ diff --git a/lib/bluetooth/l2cap.h b/lib/bluetooth/l2cap.h new file mode 100644 index 0000000..5ce94c4 --- /dev/null +++ b/lib/bluetooth/l2cap.h @@ -0,0 +1,279 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * Copyright (c) 2012 Code Aurora Forum. All rights reserved. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __L2CAP_H +#define __L2CAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* L2CAP defaults */ +#define L2CAP_DEFAULT_MTU 672 +#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF + +/* L2CAP socket address */ +struct sockaddr_l2 { + sa_family_t l2_family; + unsigned short l2_psm; + bdaddr_t l2_bdaddr; + unsigned short l2_cid; + uint8_t l2_bdaddr_type; +}; + +/* L2CAP socket options */ +#define L2CAP_OPTIONS 0x01 +struct l2cap_options { + uint16_t omtu; + uint16_t imtu; + uint16_t flush_to; + uint8_t mode; + uint8_t fcs; + uint8_t max_tx; + uint16_t txwin_size; +}; + +#define L2CAP_CONNINFO 0x02 +struct l2cap_conninfo { + uint16_t hci_handle; + uint8_t dev_class[3]; +}; + +#define L2CAP_LM 0x03 +#define L2CAP_LM_MASTER 0x0001 +#define L2CAP_LM_AUTH 0x0002 +#define L2CAP_LM_ENCRYPT 0x0004 +#define L2CAP_LM_TRUSTED 0x0008 +#define L2CAP_LM_RELIABLE 0x0010 +#define L2CAP_LM_SECURE 0x0020 + +/* L2CAP command codes */ +#define L2CAP_COMMAND_REJ 0x01 +#define L2CAP_CONN_REQ 0x02 +#define L2CAP_CONN_RSP 0x03 +#define L2CAP_CONF_REQ 0x04 +#define L2CAP_CONF_RSP 0x05 +#define L2CAP_DISCONN_REQ 0x06 +#define L2CAP_DISCONN_RSP 0x07 +#define L2CAP_ECHO_REQ 0x08 +#define L2CAP_ECHO_RSP 0x09 +#define L2CAP_INFO_REQ 0x0a +#define L2CAP_INFO_RSP 0x0b +#define L2CAP_CREATE_REQ 0x0c +#define L2CAP_CREATE_RSP 0x0d +#define L2CAP_MOVE_REQ 0x0e +#define L2CAP_MOVE_RSP 0x0f +#define L2CAP_MOVE_CFM 0x10 +#define L2CAP_MOVE_CFM_RSP 0x11 + +/* L2CAP extended feature mask */ +#define L2CAP_FEAT_FLOWCTL 0x00000001 +#define L2CAP_FEAT_RETRANS 0x00000002 +#define L2CAP_FEAT_BIDIR_QOS 0x00000004 +#define L2CAP_FEAT_ERTM 0x00000008 +#define L2CAP_FEAT_STREAMING 0x00000010 +#define L2CAP_FEAT_FCS 0x00000020 +#define L2CAP_FEAT_EXT_FLOW 0x00000040 +#define L2CAP_FEAT_FIXED_CHAN 0x00000080 +#define L2CAP_FEAT_EXT_WINDOW 0x00000100 +#define L2CAP_FEAT_UCD 0x00000200 + +/* L2CAP fixed channels */ +#define L2CAP_FC_L2CAP 0x02 +#define L2CAP_FC_CONNLESS 0x04 +#define L2CAP_FC_A2MP 0x08 + +/* L2CAP structures */ +typedef struct { + uint16_t len; + uint16_t cid; +} __attribute__ ((packed)) l2cap_hdr; +#define L2CAP_HDR_SIZE 4 + +typedef struct { + uint8_t code; + uint8_t ident; + uint16_t len; +} __attribute__ ((packed)) l2cap_cmd_hdr; +#define L2CAP_CMD_HDR_SIZE 4 + +typedef struct { + uint16_t reason; +} __attribute__ ((packed)) l2cap_cmd_rej; +#define L2CAP_CMD_REJ_SIZE 2 + +typedef struct { + uint16_t psm; + uint16_t scid; +} __attribute__ ((packed)) l2cap_conn_req; +#define L2CAP_CONN_REQ_SIZE 4 + +typedef struct { + uint16_t dcid; + uint16_t scid; + uint16_t result; + uint16_t status; +} __attribute__ ((packed)) l2cap_conn_rsp; +#define L2CAP_CONN_RSP_SIZE 8 + +/* connect result */ +#define L2CAP_CR_SUCCESS 0x0000 +#define L2CAP_CR_PEND 0x0001 +#define L2CAP_CR_BAD_PSM 0x0002 +#define L2CAP_CR_SEC_BLOCK 0x0003 +#define L2CAP_CR_NO_MEM 0x0004 + +/* connect status */ +#define L2CAP_CS_NO_INFO 0x0000 +#define L2CAP_CS_AUTHEN_PEND 0x0001 +#define L2CAP_CS_AUTHOR_PEND 0x0002 + +typedef struct { + uint16_t dcid; + uint16_t flags; + uint8_t data[0]; +} __attribute__ ((packed)) l2cap_conf_req; +#define L2CAP_CONF_REQ_SIZE 4 + +typedef struct { + uint16_t scid; + uint16_t flags; + uint16_t result; + uint8_t data[0]; +} __attribute__ ((packed)) l2cap_conf_rsp; +#define L2CAP_CONF_RSP_SIZE 6 + +#define L2CAP_CONF_SUCCESS 0x0000 +#define L2CAP_CONF_UNACCEPT 0x0001 +#define L2CAP_CONF_REJECT 0x0002 +#define L2CAP_CONF_UNKNOWN 0x0003 +#define L2CAP_CONF_PENDING 0x0004 +#define L2CAP_CONF_EFS_REJECT 0x0005 + +typedef struct { + uint8_t type; + uint8_t len; + uint8_t val[0]; +} __attribute__ ((packed)) l2cap_conf_opt; +#define L2CAP_CONF_OPT_SIZE 2 + +#define L2CAP_CONF_MTU 0x01 +#define L2CAP_CONF_FLUSH_TO 0x02 +#define L2CAP_CONF_QOS 0x03 +#define L2CAP_CONF_RFC 0x04 +#define L2CAP_CONF_FCS 0x05 +#define L2CAP_CONF_EFS 0x06 +#define L2CAP_CONF_EWS 0x07 + +#define L2CAP_CONF_MAX_SIZE 22 + +#define L2CAP_MODE_BASIC 0x00 +#define L2CAP_MODE_RETRANS 0x01 +#define L2CAP_MODE_FLOWCTL 0x02 +#define L2CAP_MODE_ERTM 0x03 +#define L2CAP_MODE_STREAMING 0x04 + +#define L2CAP_SERVTYPE_NOTRAFFIC 0x00 +#define L2CAP_SERVTYPE_BESTEFFORT 0x01 +#define L2CAP_SERVTYPE_GUARANTEED 0x02 + +typedef struct { + uint16_t dcid; + uint16_t scid; +} __attribute__ ((packed)) l2cap_disconn_req; +#define L2CAP_DISCONN_REQ_SIZE 4 + +typedef struct { + uint16_t dcid; + uint16_t scid; +} __attribute__ ((packed)) l2cap_disconn_rsp; +#define L2CAP_DISCONN_RSP_SIZE 4 + +typedef struct { + uint16_t type; +} __attribute__ ((packed)) l2cap_info_req; +#define L2CAP_INFO_REQ_SIZE 2 + +typedef struct { + uint16_t type; + uint16_t result; + uint8_t data[0]; +} __attribute__ ((packed)) l2cap_info_rsp; +#define L2CAP_INFO_RSP_SIZE 4 + +/* info type */ +#define L2CAP_IT_CL_MTU 0x0001 +#define L2CAP_IT_FEAT_MASK 0x0002 + +/* info result */ +#define L2CAP_IR_SUCCESS 0x0000 +#define L2CAP_IR_NOTSUPP 0x0001 + +typedef struct { + uint16_t psm; + uint16_t scid; + uint8_t id; +} __attribute__ ((packed)) l2cap_create_req; +#define L2CAP_CREATE_REQ_SIZE 5 + +typedef struct { + uint16_t dcid; + uint16_t scid; + uint16_t result; + uint16_t status; +} __attribute__ ((packed)) l2cap_create_rsp; +#define L2CAP_CREATE_RSP_SIZE 8 + +typedef struct { + uint16_t icid; + uint8_t id; +} __attribute__ ((packed)) l2cap_move_req; +#define L2CAP_MOVE_REQ_SIZE 3 + +typedef struct { + uint16_t icid; + uint16_t result; +} __attribute__ ((packed)) l2cap_move_rsp; +#define L2CAP_MOVE_RSP_SIZE 4 + +typedef struct { + uint16_t icid; + uint16_t result; +} __attribute__ ((packed)) l2cap_move_cfm; +#define L2CAP_MOVE_CFM_SIZE 4 + +typedef struct { + uint16_t icid; +} __attribute__ ((packed)) l2cap_move_cfm_rsp; +#define L2CAP_MOVE_CFM_RSP_SIZE 2 + +#ifdef __cplusplus +} +#endif + +#endif /* __L2CAP_H */ diff --git a/lib/bluetooth/libbluetooth.so b/lib/bluetooth/libbluetooth.so new file mode 100644 index 0000000000000000000000000000000000000000..4a2df9b672ccff594634aaa01836dbf0c439a657 GIT binary patch literal 150312 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 z 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

9)s;Y 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%0DJO4!m`E{q0SU=^uk0zoG1pA|KBm1_#+W(L=GU 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 QpFIRn{n3>HOWXH<0eD + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#define MGMT_INDEX_NONE 0xFFFF + +#define MGMT_STATUS_SUCCESS 0x00 +#define MGMT_STATUS_UNKNOWN_COMMAND 0x01 +#define MGMT_STATUS_NOT_CONNECTED 0x02 +#define MGMT_STATUS_FAILED 0x03 +#define MGMT_STATUS_CONNECT_FAILED 0x04 +#define MGMT_STATUS_AUTH_FAILED 0x05 +#define MGMT_STATUS_NOT_PAIRED 0x06 +#define MGMT_STATUS_NO_RESOURCES 0x07 +#define MGMT_STATUS_TIMEOUT 0x08 +#define MGMT_STATUS_ALREADY_CONNECTED 0x09 +#define MGMT_STATUS_BUSY 0x0a +#define MGMT_STATUS_REJECTED 0x0b +#define MGMT_STATUS_NOT_SUPPORTED 0x0c +#define MGMT_STATUS_INVALID_PARAMS 0x0d +#define MGMT_STATUS_DISCONNECTED 0x0e +#define MGMT_STATUS_NOT_POWERED 0x0f +#define MGMT_STATUS_CANCELLED 0x10 +#define MGMT_STATUS_INVALID_INDEX 0x11 +#define MGMT_STATUS_RFKILLED 0x12 +#define MGMT_STATUS_ALREADY_PAIRED 0x13 +#define MGMT_STATUS_PERMISSION_DENIED 0x14 + +struct mgmt_hdr { + uint16_t opcode; + uint16_t index; + uint16_t len; +} __packed; +#define MGMT_HDR_SIZE 6 + +struct mgmt_addr_info { + bdaddr_t bdaddr; + uint8_t type; +} __packed; + +#define MGMT_OP_READ_VERSION 0x0001 +struct mgmt_rp_read_version { + uint8_t version; + uint16_t revision; +} __packed; + +#define MGMT_OP_READ_COMMANDS 0x0002 +struct mgmt_rp_read_commands { + uint16_t num_commands; + uint16_t num_events; + uint16_t opcodes[0]; +} __packed; + +#define MGMT_OP_READ_INDEX_LIST 0x0003 +struct mgmt_rp_read_index_list { + uint16_t num_controllers; + uint16_t index[0]; +} __packed; + +/* Reserve one extra byte for names in management messages so that they + * are always guaranteed to be nul-terminated */ +#define MGMT_MAX_NAME_LENGTH (248 + 1) +#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) + +#define MGMT_SETTING_POWERED 0x00000001 +#define MGMT_SETTING_CONNECTABLE 0x00000002 +#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 +#define MGMT_SETTING_DISCOVERABLE 0x00000008 +#define MGMT_SETTING_BONDABLE 0x00000010 +#define MGMT_SETTING_LINK_SECURITY 0x00000020 +#define MGMT_SETTING_SSP 0x00000040 +#define MGMT_SETTING_BREDR 0x00000080 +#define MGMT_SETTING_HS 0x00000100 +#define MGMT_SETTING_LE 0x00000200 +#define MGMT_SETTING_ADVERTISING 0x00000400 +#define MGMT_SETTING_SECURE_CONN 0x00000800 +#define MGMT_SETTING_DEBUG_KEYS 0x00001000 +#define MGMT_SETTING_PRIVACY 0x00002000 +#define MGMT_SETTING_CONFIGURATION 0x00004000 +#define MGMT_SETTING_STATIC_ADDRESS 0x00008000 +#define MGMT_SETTING_PHY_CONFIGURATION 0x00010000 +#define MGMT_SETTING_WIDEBAND_SPEECH 0x00020000 + +#define MGMT_OP_READ_INFO 0x0004 +struct mgmt_rp_read_info { + bdaddr_t bdaddr; + uint8_t version; + uint16_t manufacturer; + uint32_t supported_settings; + uint32_t current_settings; + uint8_t dev_class[3]; + uint8_t name[MGMT_MAX_NAME_LENGTH]; + uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH]; +} __packed; + +struct mgmt_mode { + uint8_t val; +} __packed; + +struct mgmt_cod { + uint8_t val[3]; +} __packed; + +#define MGMT_OP_SET_POWERED 0x0005 + +#define MGMT_OP_SET_DISCOVERABLE 0x0006 +struct mgmt_cp_set_discoverable { + uint8_t val; + uint16_t timeout; +} __packed; + +#define MGMT_OP_SET_CONNECTABLE 0x0007 + +#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008 + +#define MGMT_OP_SET_BONDABLE 0x0009 + +#define MGMT_OP_SET_LINK_SECURITY 0x000A + +#define MGMT_OP_SET_SSP 0x000B + +#define MGMT_OP_SET_HS 0x000C + +#define MGMT_OP_SET_LE 0x000D + +#define MGMT_OP_SET_DEV_CLASS 0x000E +struct mgmt_cp_set_dev_class { + uint8_t major; + uint8_t minor; +} __packed; + +#define MGMT_OP_SET_LOCAL_NAME 0x000F +struct mgmt_cp_set_local_name { + uint8_t name[MGMT_MAX_NAME_LENGTH]; + uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH]; +} __packed; + +#define MGMT_OP_ADD_UUID 0x0010 +struct mgmt_cp_add_uuid { + uint8_t uuid[16]; + uint8_t svc_hint; +} __packed; + +#define MGMT_OP_REMOVE_UUID 0x0011 +struct mgmt_cp_remove_uuid { + uint8_t uuid[16]; +} __packed; + +struct mgmt_link_key_info { + struct mgmt_addr_info addr; + uint8_t type; + uint8_t val[16]; + uint8_t pin_len; +} __packed; + +#define MGMT_OP_LOAD_LINK_KEYS 0x0012 +struct mgmt_cp_load_link_keys { + uint8_t debug_keys; + uint16_t key_count; + struct mgmt_link_key_info keys[0]; +} __packed; + +struct mgmt_ltk_info { + struct mgmt_addr_info addr; + uint8_t type; + uint8_t master; + uint8_t enc_size; + uint16_t ediv; + uint64_t rand; + uint8_t val[16]; +} __packed; + +#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013 +struct mgmt_cp_load_long_term_keys { + uint16_t key_count; + struct mgmt_ltk_info keys[0]; +} __packed; + +#define MGMT_OP_DISCONNECT 0x0014 +struct mgmt_cp_disconnect { + struct mgmt_addr_info addr; +} __packed; +struct mgmt_rp_disconnect { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_GET_CONNECTIONS 0x0015 +struct mgmt_rp_get_connections { + uint16_t conn_count; + struct mgmt_addr_info addr[0]; +} __packed; + +#define MGMT_OP_PIN_CODE_REPLY 0x0016 +struct mgmt_cp_pin_code_reply { + struct mgmt_addr_info addr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __packed; + +#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017 +struct mgmt_cp_pin_code_neg_reply { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_SET_IO_CAPABILITY 0x0018 +struct mgmt_cp_set_io_capability { + uint8_t io_capability; +} __packed; + +#define MGMT_OP_PAIR_DEVICE 0x0019 +struct mgmt_cp_pair_device { + struct mgmt_addr_info addr; + uint8_t io_cap; +} __packed; +struct mgmt_rp_pair_device { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_CANCEL_PAIR_DEVICE 0x001A + +#define MGMT_OP_UNPAIR_DEVICE 0x001B +struct mgmt_cp_unpair_device { + struct mgmt_addr_info addr; + uint8_t disconnect; +} __packed; +struct mgmt_rp_unpair_device { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_USER_CONFIRM_REPLY 0x001C +struct mgmt_cp_user_confirm_reply { + struct mgmt_addr_info addr; +} __packed; +struct mgmt_rp_user_confirm_reply { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001D + +#define MGMT_OP_USER_PASSKEY_REPLY 0x001E +struct mgmt_cp_user_passkey_reply { + struct mgmt_addr_info addr; + uint32_t passkey; +} __packed; +struct mgmt_rp_user_passkey_reply { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001F +struct mgmt_cp_user_passkey_neg_reply { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020 +struct mgmt_rp_read_local_oob_data { + uint8_t hash192[16]; + uint8_t rand192[16]; + uint8_t hash256[16]; + uint8_t rand256[16]; +} __packed; + +#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021 +struct mgmt_cp_add_remote_oob_data { + struct mgmt_addr_info addr; + uint8_t hash192[16]; + uint8_t rand192[16]; + uint8_t hash256[16]; + uint8_t rand256[16]; +} __packed; + +#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022 +struct mgmt_cp_remove_remote_oob_data { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_START_DISCOVERY 0x0023 +struct mgmt_cp_start_discovery { + uint8_t type; +} __packed; + +#define MGMT_OP_STOP_DISCOVERY 0x0024 +struct mgmt_cp_stop_discovery { + uint8_t type; +} __packed; + +#define MGMT_OP_CONFIRM_NAME 0x0025 +struct mgmt_cp_confirm_name { + struct mgmt_addr_info addr; + uint8_t name_known; +} __packed; +struct mgmt_rp_confirm_name { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_BLOCK_DEVICE 0x0026 +struct mgmt_cp_block_device { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_UNBLOCK_DEVICE 0x0027 +struct mgmt_cp_unblock_device { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_SET_DEVICE_ID 0x0028 +struct mgmt_cp_set_device_id { + uint16_t source; + uint16_t vendor; + uint16_t product; + uint16_t version; +} __packed; + +#define MGMT_OP_SET_ADVERTISING 0x0029 + +#define MGMT_OP_SET_BREDR 0x002A + +#define MGMT_OP_SET_STATIC_ADDRESS 0x002B +struct mgmt_cp_set_static_address { + bdaddr_t bdaddr; +} __packed; + +#define MGMT_OP_SET_SCAN_PARAMS 0x002C +struct mgmt_cp_set_scan_params { + uint16_t interval; + uint16_t window; +} __packed; + +#define MGMT_OP_SET_SECURE_CONN 0x002D + +#define MGMT_OP_SET_DEBUG_KEYS 0x002E + +struct mgmt_irk_info { + struct mgmt_addr_info addr; + uint8_t val[16]; +} __packed; + +#define MGMT_OP_SET_PRIVACY 0x002F +struct mgmt_cp_set_privacy { + uint8_t privacy; + uint8_t irk[16]; +} __packed; + +#define MGMT_OP_LOAD_IRKS 0x0030 +struct mgmt_cp_load_irks { + uint16_t irk_count; + struct mgmt_irk_info irks[0]; +} __packed; + +#define MGMT_OP_GET_CONN_INFO 0x0031 +struct mgmt_cp_get_conn_info { + struct mgmt_addr_info addr; +} __packed; +struct mgmt_rp_get_conn_info { + struct mgmt_addr_info addr; + int8_t rssi; + int8_t tx_power; + int8_t max_tx_power; +} __packed; + +#define MGMT_OP_GET_CLOCK_INFO 0x0032 +struct mgmt_cp_get_clock_info { + struct mgmt_addr_info addr; +} __packed; +struct mgmt_rp_get_clock_info { + struct mgmt_addr_info addr; + uint32_t local_clock; + uint32_t piconet_clock; + uint16_t accuracy; +} __packed; + +#define MGMT_OP_ADD_DEVICE 0x0033 +struct mgmt_cp_add_device { + struct mgmt_addr_info addr; + uint8_t action; +} __packed; +struct mgmt_rp_add_device { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_OP_REMOVE_DEVICE 0x0034 +struct mgmt_cp_remove_device { + struct mgmt_addr_info addr; +} __packed; +struct mgmt_rp_remove_device { + struct mgmt_addr_info addr; +} __packed; + +struct mgmt_conn_param { + struct mgmt_addr_info addr; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define MGMT_OP_LOAD_CONN_PARAM 0x0035 +struct mgmt_cp_load_conn_param { + uint16_t param_count; + struct mgmt_conn_param params[0]; +} __packed; + +#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036 +struct mgmt_rp_read_unconf_index_list { + uint16_t num_controllers; + uint16_t index[0]; +} __packed; + +#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001 +#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002 + +#define MGMT_OP_READ_CONFIG_INFO 0x0037 +struct mgmt_rp_read_config_info { + uint16_t manufacturer; + uint32_t supported_options; + uint32_t missing_options; +} __packed; + +#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038 +struct mgmt_cp_set_external_config { + uint8_t config; +} __packed; + +#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039 +struct mgmt_cp_set_public_address { + bdaddr_t bdaddr; +} __packed; + +#define MGMT_OP_START_SERVICE_DISCOVERY 0x003A +struct mgmt_cp_start_service_discovery { + uint8_t type; + int8_t rssi; + uint16_t uuid_count; + uint8_t uuids[0][16]; +} __packed; + +#define MGMT_OP_READ_LOCAL_OOB_EXT_DATA 0x003B +struct mgmt_cp_read_local_oob_ext_data { + uint8_t type; +} __packed; +struct mgmt_rp_read_local_oob_ext_data { + uint8_t type; + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C +struct mgmt_rp_read_ext_index_list { + uint16_t num_controllers; + struct { + uint16_t index; + uint8_t type; + uint8_t bus; + } entry[0]; +} __packed; + +#define MGMT_OP_READ_ADV_FEATURES 0x003D +struct mgmt_rp_read_adv_features { + uint32_t supported_flags; + uint8_t max_adv_data_len; + uint8_t max_scan_rsp_len; + uint8_t max_instances; + uint8_t num_instances; + uint8_t instance[0]; +} __packed; + +#define MGMT_OP_ADD_ADVERTISING 0x003E +struct mgmt_cp_add_advertising { + uint8_t instance; + uint32_t flags; + uint16_t duration; + uint16_t timeout; + uint8_t adv_data_len; + uint8_t scan_rsp_len; + uint8_t data[0]; +} __packed; +struct mgmt_rp_add_advertising { + uint8_t instance; +} __packed; + +#define MGMT_ADV_FLAG_CONNECTABLE (1 << 0) +#define MGMT_ADV_FLAG_DISCOV (1 << 1) +#define MGMT_ADV_FLAG_LIMITED_DISCOV (1 << 2) +#define MGMT_ADV_FLAG_MANAGED_FLAGS (1 << 3) +#define MGMT_ADV_FLAG_TX_POWER (1 << 4) +#define MGMT_ADV_FLAG_APPEARANCE (1 << 5) +#define MGMT_ADV_FLAG_LOCAL_NAME (1 << 6) +#define MGMT_ADV_FLAG_SEC_1M (1 << 7) +#define MGMT_ADV_FLAG_SEC_2M (1 << 8) +#define MGMT_ADV_FLAG_SEC_CODED (1 << 9) + +#define MGMT_OP_REMOVE_ADVERTISING 0x003F +struct mgmt_cp_remove_advertising { + uint8_t instance; +} __packed; +#define MGMT_REMOVE_ADVERTISING_SIZE 1 +struct mgmt_rp_remove_advertising { + uint8_t instance; +} __packed; + +#define MGMT_OP_GET_ADV_SIZE_INFO 0x0040 +struct mgmt_cp_get_adv_size_info { + uint8_t instance; + uint32_t flags; +} __packed; +#define MGMT_GET_ADV_SIZE_INFO_SIZE 5 +struct mgmt_rp_get_adv_size_info { + uint8_t instance; + uint32_t flags; + uint8_t max_adv_data_len; + uint8_t max_scan_rsp_len; +} __packed; + +#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041 + +#define MGMT_OP_READ_EXT_INFO 0x0042 +struct mgmt_rp_read_ext_info { + bdaddr_t bdaddr; + uint8_t version; + uint16_t manufacturer; + uint32_t supported_settings; + uint32_t current_settings; + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_OP_SET_APPEARANCE 0x0043 +struct mgmt_cp_set_appearance { + uint16_t appearance; +} __packed; + +#define MGMT_OP_GET_PHY_CONFIGURATION 0x0044 +struct mgmt_rp_get_phy_confguration { + uint32_t supported_phys; + uint32_t configurable_phys; + uint32_t selected_phys; +} __packed; + +#define MGMT_PHY_BR_1M_1SLOT 0x00000001 +#define MGMT_PHY_BR_1M_3SLOT 0x00000002 +#define MGMT_PHY_BR_1M_5SLOT 0x00000004 +#define MGMT_PHY_EDR_2M_1SLOT 0x00000008 +#define MGMT_PHY_EDR_2M_3SLOT 0x00000010 +#define MGMT_PHY_EDR_2M_5SLOT 0x00000020 +#define MGMT_PHY_EDR_3M_1SLOT 0x00000040 +#define MGMT_PHY_EDR_3M_3SLOT 0x00000080 +#define MGMT_PHY_EDR_3M_5SLOT 0x00000100 +#define MGMT_PHY_LE_1M_TX 0x00000200 +#define MGMT_PHY_LE_1M_RX 0x00000400 +#define MGMT_PHY_LE_2M_TX 0x00000800 +#define MGMT_PHY_LE_2M_RX 0x00001000 +#define MGMT_PHY_LE_CODED_TX 0x00002000 +#define MGMT_PHY_LE_CODED_RX 0x00004000 + +#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \ + MGMT_PHY_LE_CODED_TX) +#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \ + MGMT_PHY_LE_CODED_RX) + +#define MGMT_OP_SET_PHY_CONFIGURATION 0x0045 +struct mgmt_cp_set_phy_confguration { + uint32_t selected_phys; +} __packed; + +#define MGMT_OP_SET_BLOCKED_KEYS 0x0046 + +#define HCI_BLOCKED_KEY_TYPE_LINKKEY 0x00 +#define HCI_BLOCKED_KEY_TYPE_LTK 0x01 +#define HCI_BLOCKED_KEY_TYPE_IRK 0x02 + +struct mgmt_blocked_key_info { + uint8_t type; + uint8_t val[16]; +} __packed; + +struct mgmt_cp_set_blocked_keys { + uint16_t key_count; + struct mgmt_blocked_key_info keys[0]; +} __packed; + +#define MGMT_OP_SET_WIDEBAND_SPEECH 0x0047 + +#define MGMT_EV_CMD_COMPLETE 0x0001 +struct mgmt_ev_cmd_complete { + uint16_t opcode; + uint8_t status; + uint8_t data[0]; +} __packed; + +#define MGMT_EV_CMD_STATUS 0x0002 +struct mgmt_ev_cmd_status { + uint16_t opcode; + uint8_t status; +} __packed; + +#define MGMT_EV_CONTROLLER_ERROR 0x0003 +struct mgmt_ev_controller_error { + uint8_t error_code; +} __packed; + +#define MGMT_EV_INDEX_ADDED 0x0004 + +#define MGMT_EV_INDEX_REMOVED 0x0005 + +#define MGMT_EV_NEW_SETTINGS 0x0006 + +#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007 +struct mgmt_ev_class_of_dev_changed { + uint8_t dev_class[3]; +} __packed; + +#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008 +struct mgmt_ev_local_name_changed { + uint8_t name[MGMT_MAX_NAME_LENGTH]; + uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH]; +} __packed; + +#define MGMT_EV_NEW_LINK_KEY 0x0009 +struct mgmt_ev_new_link_key { + uint8_t store_hint; + struct mgmt_link_key_info key; +} __packed; + +#define MGMT_EV_NEW_LONG_TERM_KEY 0x000A +struct mgmt_ev_new_long_term_key { + uint8_t store_hint; + struct mgmt_ltk_info key; +} __packed; + +#define MGMT_EV_DEVICE_CONNECTED 0x000B +struct mgmt_ev_device_connected { + struct mgmt_addr_info addr; + uint32_t flags; + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_DEV_DISCONN_UNKNOWN 0x00 +#define MGMT_DEV_DISCONN_TIMEOUT 0x01 +#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02 +#define MGMT_DEV_DISCONN_REMOTE 0x03 + +#define MGMT_EV_DEVICE_DISCONNECTED 0x000C +struct mgmt_ev_device_disconnected { + struct mgmt_addr_info addr; + uint8_t reason; +} __packed; + +#define MGMT_EV_CONNECT_FAILED 0x000D +struct mgmt_ev_connect_failed { + struct mgmt_addr_info addr; + uint8_t status; +} __packed; + +#define MGMT_EV_PIN_CODE_REQUEST 0x000E +struct mgmt_ev_pin_code_request { + struct mgmt_addr_info addr; + uint8_t secure; +} __packed; + +#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F +struct mgmt_ev_user_confirm_request { + struct mgmt_addr_info addr; + uint8_t confirm_hint; + uint32_t value; +} __packed; + +#define MGMT_EV_USER_PASSKEY_REQUEST 0x0010 +struct mgmt_ev_user_passkey_request { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_AUTH_FAILED 0x0011 +struct mgmt_ev_auth_failed { + struct mgmt_addr_info addr; + uint8_t status; +} __packed; + +#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01 +#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02 +#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04 + +#define MGMT_EV_DEVICE_FOUND 0x0012 +struct mgmt_ev_device_found { + struct mgmt_addr_info addr; + int8_t rssi; + uint32_t flags; + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_EV_DISCOVERING 0x0013 +struct mgmt_ev_discovering { + uint8_t type; + uint8_t discovering; +} __packed; + +#define MGMT_EV_DEVICE_BLOCKED 0x0014 +struct mgmt_ev_device_blocked { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_DEVICE_UNBLOCKED 0x0015 +struct mgmt_ev_device_unblocked { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_DEVICE_UNPAIRED 0x0016 +struct mgmt_ev_device_unpaired { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_PASSKEY_NOTIFY 0x0017 +struct mgmt_ev_passkey_notify { + struct mgmt_addr_info addr; + uint32_t passkey; + uint8_t entered; +} __packed; + +#define MGMT_EV_NEW_IRK 0x0018 +struct mgmt_ev_new_irk { + uint8_t store_hint; + bdaddr_t rpa; + struct mgmt_irk_info key; +} __packed; + +struct mgmt_csrk_info { + struct mgmt_addr_info addr; + uint8_t type; + uint8_t val[16]; +} __packed; + +#define MGMT_EV_NEW_CSRK 0x0019 +struct mgmt_ev_new_csrk { + uint8_t store_hint; + struct mgmt_csrk_info key; +} __packed; + +#define MGMT_EV_DEVICE_ADDED 0x001a +struct mgmt_ev_device_added { + struct mgmt_addr_info addr; + uint8_t action; +} __packed; + +#define MGMT_EV_DEVICE_REMOVED 0x001b +struct mgmt_ev_device_removed { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_NEW_CONN_PARAM 0x001c +struct mgmt_ev_new_conn_param { + struct mgmt_addr_info addr; + uint8_t store_hint; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d + +#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e + +#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f + +#define MGMT_EV_EXT_INDEX_ADDED 0x0020 +struct mgmt_ev_ext_index_added { + uint8_t type; + uint8_t bus; +} __packed; + +#define MGMT_EV_EXT_INDEX_REMOVED 0x0021 +struct mgmt_ev_ext_index_removed { + uint8_t type; + uint8_t bus; +} __packed; + +#define MGMT_EV_LOCAL_OOB_DATA_UPDATED 0x0022 +struct mgmt_ev_local_oob_data_updated { + uint8_t type; + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_EV_ADVERTISING_ADDED 0x0023 +struct mgmt_ev_advertising_added { + uint8_t instance; +} __packed; + +#define MGMT_EV_ADVERTISING_REMOVED 0x0024 +struct mgmt_ev_advertising_removed { + uint8_t instance; +} __packed; + +#define MGMT_EV_EXT_INFO_CHANGED 0x0025 +struct mgmt_ev_ext_info_changed { + uint16_t eir_len; + uint8_t eir[0]; +} __packed; + +#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026 +struct mgmt_ev_phy_configuration_changed { + uint16_t selected_phys; +} __packed; + +static const char *mgmt_op[] = { + "<0x0000>", + "Read Version", + "Read Commands", + "Read Index List", + "Read Controller Info", + "Set Powered", + "Set Discoverable", + "Set Connectable", + "Set Fast Connectable", /* 0x0008 */ + "Set Bondable", + "Set Link Security", + "Set Secure Simple Pairing", + "Set High Speed", + "Set Low Energy", + "Set Dev Class", + "Set Local Name", + "Add UUID", /* 0x0010 */ + "Remove UUID", + "Load Link Keys", + "Load Long Term Keys", + "Disconnect", + "Get Connections", + "PIN Code Reply", + "PIN Code Neg Reply", + "Set IO Capability", /* 0x0018 */ + "Pair Device", + "Cancel Pair Device", + "Unpair Device", + "User Confirm Reply", + "User Confirm Neg Reply", + "User Passkey Reply", + "User Passkey Neg Reply", + "Read Local OOB Data", /* 0x0020 */ + "Add Remote OOB Data", + "Remove Remove OOB Data", + "Start Discovery", + "Stop Discovery", + "Confirm Name", + "Block Device", + "Unblock Device", + "Set Device ID", /* 0x0028 */ + "Set Advertising", + "Set BR/EDR", + "Set Static Address", + "Set Scan Parameters", + "Set Secure Connections", + "Set Debug Keys", + "Set Privacy", + "Load Identity Resolving Keys", /* 0x0030 */ + "Get Connection Information", + "Get Clock Information", + "Add Device", + "Remove Device", + "Load Connection Parameters", + "Read Unconfigured Index List", + "Read Controller Configuration Information", + "Set External Configuration", /* 0x0038 */ + "Set Public Address", + "Start Service Discovery", + "Read Local Out Of Band Extended Data", + "Read Extended Controller Index List", + "Read Advertising Features", + "Add Advertising", + "Remove Advertising", + "Get Advertising Size Information", /* 0x0040 */ + "Start Limited Discovery", + "Read Extended Controller Information", + "Set Appearance", + "Get PHY Configuration", + "Set PHY Configuration", + "Set Blocked Keys", +}; + +static const char *mgmt_ev[] = { + "<0x0000>", + "Command Complete", + "Command Status", + "Controller Error", + "Index Added", + "Index Removed", + "New Settings", + "Class of Device Changed", + "Local Name Changed", /* 0x0008 */ + "New Link Key", + "New Long Term Key", + "Device Connected", + "Device Disconnected", + "Connect Failed", + "PIN Code Request", + "User Confirm Request", + "User Passkey Request", /* 0x0010 */ + "Authentication Failed", + "Device Found", + "Discovering", + "Device Blocked", + "Device Unblocked", + "Device Unpaired", + "Passkey Notify", + "New Identity Resolving Key", /* 0x0018 */ + "New Signature Resolving Key", + "Device Added", + "Device Removed", + "New Connection Parameter", + "Unconfigured Index Added", + "Unconfigured Index Removed", + "New Configuration Options", + "Extended Index Added", /* 0x0020 */ + "Extended Index Removed", + "Local Out Of Band Extended Data Updated", + "Advertising Added", + "Advertising Removed", + "Extended Controller Information Changed", + "PHY Configuration Changed", +}; + +static const char *mgmt_status[] = { + "Success", + "Unknown Command", + "Not Connected", + "Failed", + "Connect Failed", + "Authentication Failed", + "Not Paired", + "No Resources", + "Timeout", + "Already Connected", + "Busy", + "Rejected", + "Not Supported", + "Invalid Parameters", + "Disconnected", + "Not Powered", + "Cancelled", + "Invalid Index", + "Blocked through rfkill", + "Already Paired", + "Permission Denied", +}; + +#ifndef NELEM +#define NELEM(x) (sizeof(x) / sizeof((x)[0])) +#endif + +static inline const char *mgmt_opstr(uint16_t op) +{ + if (op >= NELEM(mgmt_op)) + return ""; + return mgmt_op[op]; +} + +static inline const char *mgmt_evstr(uint16_t ev) +{ + if (ev >= NELEM(mgmt_ev)) + return ""; + return mgmt_ev[ev]; +} + +static inline const char *mgmt_errstr(uint8_t status) +{ + if (status >= NELEM(mgmt_status)) + return ""; + return mgmt_status[status]; +} diff --git a/lib/bluetooth/rfcomm.h b/lib/bluetooth/rfcomm.h new file mode 100644 index 0000000..ad6c0e1 --- /dev/null +++ b/lib/bluetooth/rfcomm.h @@ -0,0 +1,99 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __RFCOMM_H +#define __RFCOMM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* RFCOMM defaults */ +#define RFCOMM_DEFAULT_MTU 127 + +#define RFCOMM_PSM 3 + +/* RFCOMM socket address */ +struct sockaddr_rc { + sa_family_t rc_family; + bdaddr_t rc_bdaddr; + uint8_t rc_channel; +}; + +/* RFCOMM socket options */ +#define RFCOMM_CONNINFO 0x02 +struct rfcomm_conninfo { + uint16_t hci_handle; + uint8_t dev_class[3]; +}; + +#define RFCOMM_LM 0x03 +#define RFCOMM_LM_MASTER 0x0001 +#define RFCOMM_LM_AUTH 0x0002 +#define RFCOMM_LM_ENCRYPT 0x0004 +#define RFCOMM_LM_TRUSTED 0x0008 +#define RFCOMM_LM_RELIABLE 0x0010 +#define RFCOMM_LM_SECURE 0x0020 + +/* RFCOMM TTY support */ +#define RFCOMM_MAX_DEV 256 + +#define RFCOMMCREATEDEV _IOW('R', 200, int) +#define RFCOMMRELEASEDEV _IOW('R', 201, int) +#define RFCOMMGETDEVLIST _IOR('R', 210, int) +#define RFCOMMGETDEVINFO _IOR('R', 211, int) + +struct rfcomm_dev_req { + int16_t dev_id; + uint32_t flags; + bdaddr_t src; + bdaddr_t dst; + uint8_t channel; +}; +#define RFCOMM_REUSE_DLC 0 +#define RFCOMM_RELEASE_ONHUP 1 +#define RFCOMM_HANGUP_NOW 2 +#define RFCOMM_TTY_ATTACHED 3 + +struct rfcomm_dev_info { + int16_t id; + uint32_t flags; + uint16_t state; + bdaddr_t src; + bdaddr_t dst; + uint8_t channel; +}; + +struct rfcomm_dev_list_req { + uint16_t dev_num; + struct rfcomm_dev_info dev_info[0]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __RFCOMM_H */ diff --git a/lib/bluetooth/sco.h b/lib/bluetooth/sco.h new file mode 100644 index 0000000..75336a5 --- /dev/null +++ b/lib/bluetooth/sco.h @@ -0,0 +1,62 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __SCO_H +#define __SCO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* SCO defaults */ +#define SCO_DEFAULT_MTU 500 +#define SCO_DEFAULT_FLUSH_TO 0xFFFF + +#define SCO_CONN_TIMEOUT (HZ * 40) +#define SCO_DISCONN_TIMEOUT (HZ * 2) +#define SCO_CONN_IDLE_TIMEOUT (HZ * 60) + +/* SCO socket address */ +struct sockaddr_sco { + sa_family_t sco_family; + bdaddr_t sco_bdaddr; +}; + +/* set/get sockopt defines */ +#define SCO_OPTIONS 0x01 +struct sco_options { + uint16_t mtu; +}; + +#define SCO_CONNINFO 0x02 +struct sco_conninfo { + uint16_t hci_handle; + uint8_t dev_class[3]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __SCO_H */ diff --git a/lib/bluetooth/sdp.h b/lib/bluetooth/sdp.h new file mode 100644 index 0000000..f586eb5 --- /dev/null +++ b/lib/bluetooth/sdp.h @@ -0,0 +1,542 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2001-2002 Nokia Corporation + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * Copyright (C) 2002-2003 Stephen Crane + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __SDP_H +#define __SDP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define SDP_UNIX_PATH "/var/run/sdp" +#define SDP_RESPONSE_TIMEOUT 20 +#define SDP_REQ_BUFFER_SIZE 2048 +#define SDP_RSP_BUFFER_SIZE 65535 +#define SDP_PDU_CHUNK_SIZE 1024 + +/* + * All definitions are based on Bluetooth Assigned Numbers + * of the Bluetooth Specification + */ +#define SDP_PSM 0x0001 + +/* + * Protocol UUIDs + */ +#define SDP_UUID 0x0001 +#define UDP_UUID 0x0002 +#define RFCOMM_UUID 0x0003 +#define TCP_UUID 0x0004 +#define TCS_BIN_UUID 0x0005 +#define TCS_AT_UUID 0x0006 +#define ATT_UUID 0x0007 +#define OBEX_UUID 0x0008 +#define IP_UUID 0x0009 +#define FTP_UUID 0x000a +#define HTTP_UUID 0x000c +#define WSP_UUID 0x000e +#define BNEP_UUID 0x000f +#define UPNP_UUID 0x0010 +#define HIDP_UUID 0x0011 +#define HCRP_CTRL_UUID 0x0012 +#define HCRP_DATA_UUID 0x0014 +#define HCRP_NOTE_UUID 0x0016 +#define AVCTP_UUID 0x0017 +#define AVDTP_UUID 0x0019 +#define CMTP_UUID 0x001b +#define UDI_UUID 0x001d +#define MCAP_CTRL_UUID 0x001e +#define MCAP_DATA_UUID 0x001f +#define L2CAP_UUID 0x0100 + +/* + * Service class identifiers of standard services and service groups + */ +#define SDP_SERVER_SVCLASS_ID 0x1000 +#define BROWSE_GRP_DESC_SVCLASS_ID 0x1001 +#define PUBLIC_BROWSE_GROUP 0x1002 +#define SERIAL_PORT_SVCLASS_ID 0x1101 +#define LAN_ACCESS_SVCLASS_ID 0x1102 +#define DIALUP_NET_SVCLASS_ID 0x1103 +#define IRMC_SYNC_SVCLASS_ID 0x1104 +#define OBEX_OBJPUSH_SVCLASS_ID 0x1105 +#define OBEX_FILETRANS_SVCLASS_ID 0x1106 +#define IRMC_SYNC_CMD_SVCLASS_ID 0x1107 +#define HEADSET_SVCLASS_ID 0x1108 +#define CORDLESS_TELEPHONY_SVCLASS_ID 0x1109 +#define AUDIO_SOURCE_SVCLASS_ID 0x110a +#define AUDIO_SINK_SVCLASS_ID 0x110b +#define AV_REMOTE_TARGET_SVCLASS_ID 0x110c +#define ADVANCED_AUDIO_SVCLASS_ID 0x110d +#define AV_REMOTE_SVCLASS_ID 0x110e +#define AV_REMOTE_CONTROLLER_SVCLASS_ID 0x110f +#define INTERCOM_SVCLASS_ID 0x1110 +#define FAX_SVCLASS_ID 0x1111 +#define HEADSET_AGW_SVCLASS_ID 0x1112 +#define WAP_SVCLASS_ID 0x1113 +#define WAP_CLIENT_SVCLASS_ID 0x1114 +#define PANU_SVCLASS_ID 0x1115 +#define NAP_SVCLASS_ID 0x1116 +#define GN_SVCLASS_ID 0x1117 +#define DIRECT_PRINTING_SVCLASS_ID 0x1118 +#define REFERENCE_PRINTING_SVCLASS_ID 0x1119 +#define IMAGING_SVCLASS_ID 0x111a +#define IMAGING_RESPONDER_SVCLASS_ID 0x111b +#define IMAGING_ARCHIVE_SVCLASS_ID 0x111c +#define IMAGING_REFOBJS_SVCLASS_ID 0x111d +#define HANDSFREE_SVCLASS_ID 0x111e +#define HANDSFREE_AGW_SVCLASS_ID 0x111f +#define DIRECT_PRT_REFOBJS_SVCLASS_ID 0x1120 +#define REFLECTED_UI_SVCLASS_ID 0x1121 +#define BASIC_PRINTING_SVCLASS_ID 0x1122 +#define PRINTING_STATUS_SVCLASS_ID 0x1123 +#define HID_SVCLASS_ID 0x1124 +#define HCR_SVCLASS_ID 0x1125 +#define HCR_PRINT_SVCLASS_ID 0x1126 +#define HCR_SCAN_SVCLASS_ID 0x1127 +#define CIP_SVCLASS_ID 0x1128 +#define VIDEO_CONF_GW_SVCLASS_ID 0x1129 +#define UDI_MT_SVCLASS_ID 0x112a +#define UDI_TA_SVCLASS_ID 0x112b +#define AV_SVCLASS_ID 0x112c +#define SAP_SVCLASS_ID 0x112d +#define PBAP_PCE_SVCLASS_ID 0x112e +#define PBAP_PSE_SVCLASS_ID 0x112f +#define PBAP_SVCLASS_ID 0x1130 +#define MAP_MSE_SVCLASS_ID 0x1132 +#define MAP_MCE_SVCLASS_ID 0x1133 +#define MAP_SVCLASS_ID 0x1134 +#define GNSS_SVCLASS_ID 0x1135 +#define GNSS_SERVER_SVCLASS_ID 0x1136 +#define MPS_SC_SVCLASS_ID 0x113A +#define MPS_SVCLASS_ID 0x113B +#define PNP_INFO_SVCLASS_ID 0x1200 +#define GENERIC_NETWORKING_SVCLASS_ID 0x1201 +#define GENERIC_FILETRANS_SVCLASS_ID 0x1202 +#define GENERIC_AUDIO_SVCLASS_ID 0x1203 +#define GENERIC_TELEPHONY_SVCLASS_ID 0x1204 +#define UPNP_SVCLASS_ID 0x1205 +#define UPNP_IP_SVCLASS_ID 0x1206 +#define UPNP_PAN_SVCLASS_ID 0x1300 +#define UPNP_LAP_SVCLASS_ID 0x1301 +#define UPNP_L2CAP_SVCLASS_ID 0x1302 +#define VIDEO_SOURCE_SVCLASS_ID 0x1303 +#define VIDEO_SINK_SVCLASS_ID 0x1304 +#define VIDEO_DISTRIBUTION_SVCLASS_ID 0x1305 +#define HDP_SVCLASS_ID 0x1400 +#define HDP_SOURCE_SVCLASS_ID 0x1401 +#define HDP_SINK_SVCLASS_ID 0x1402 +#define GENERIC_ACCESS_SVCLASS_ID 0x1800 +#define GENERIC_ATTRIB_SVCLASS_ID 0x1801 +#define APPLE_AGENT_SVCLASS_ID 0x2112 + +/* + * Standard profile descriptor identifiers; note these + * may be identical to some of the service classes defined above + */ +#define SDP_SERVER_PROFILE_ID SDP_SERVER_SVCLASS_ID +#define BROWSE_GRP_DESC_PROFILE_ID BROWSE_GRP_DESC_SVCLASS_ID +#define SERIAL_PORT_PROFILE_ID SERIAL_PORT_SVCLASS_ID +#define LAN_ACCESS_PROFILE_ID LAN_ACCESS_SVCLASS_ID +#define DIALUP_NET_PROFILE_ID DIALUP_NET_SVCLASS_ID +#define IRMC_SYNC_PROFILE_ID IRMC_SYNC_SVCLASS_ID +#define OBEX_OBJPUSH_PROFILE_ID OBEX_OBJPUSH_SVCLASS_ID +#define OBEX_FILETRANS_PROFILE_ID OBEX_FILETRANS_SVCLASS_ID +#define IRMC_SYNC_CMD_PROFILE_ID IRMC_SYNC_CMD_SVCLASS_ID +#define HEADSET_PROFILE_ID HEADSET_SVCLASS_ID +#define CORDLESS_TELEPHONY_PROFILE_ID CORDLESS_TELEPHONY_SVCLASS_ID +#define AUDIO_SOURCE_PROFILE_ID AUDIO_SOURCE_SVCLASS_ID +#define AUDIO_SINK_PROFILE_ID AUDIO_SINK_SVCLASS_ID +#define AV_REMOTE_TARGET_PROFILE_ID AV_REMOTE_TARGET_SVCLASS_ID +#define ADVANCED_AUDIO_PROFILE_ID ADVANCED_AUDIO_SVCLASS_ID +#define AV_REMOTE_PROFILE_ID AV_REMOTE_SVCLASS_ID +#define INTERCOM_PROFILE_ID INTERCOM_SVCLASS_ID +#define FAX_PROFILE_ID FAX_SVCLASS_ID +#define HEADSET_AGW_PROFILE_ID HEADSET_AGW_SVCLASS_ID +#define WAP_PROFILE_ID WAP_SVCLASS_ID +#define WAP_CLIENT_PROFILE_ID WAP_CLIENT_SVCLASS_ID +#define PANU_PROFILE_ID PANU_SVCLASS_ID +#define NAP_PROFILE_ID NAP_SVCLASS_ID +#define GN_PROFILE_ID GN_SVCLASS_ID +#define DIRECT_PRINTING_PROFILE_ID DIRECT_PRINTING_SVCLASS_ID +#define REFERENCE_PRINTING_PROFILE_ID REFERENCE_PRINTING_SVCLASS_ID +#define IMAGING_PROFILE_ID IMAGING_SVCLASS_ID +#define IMAGING_RESPONDER_PROFILE_ID IMAGING_RESPONDER_SVCLASS_ID +#define IMAGING_ARCHIVE_PROFILE_ID IMAGING_ARCHIVE_SVCLASS_ID +#define IMAGING_REFOBJS_PROFILE_ID IMAGING_REFOBJS_SVCLASS_ID +#define HANDSFREE_PROFILE_ID HANDSFREE_SVCLASS_ID +#define HANDSFREE_AGW_PROFILE_ID HANDSFREE_AGW_SVCLASS_ID +#define DIRECT_PRT_REFOBJS_PROFILE_ID DIRECT_PRT_REFOBJS_SVCLASS_ID +#define REFLECTED_UI_PROFILE_ID REFLECTED_UI_SVCLASS_ID +#define BASIC_PRINTING_PROFILE_ID BASIC_PRINTING_SVCLASS_ID +#define PRINTING_STATUS_PROFILE_ID PRINTING_STATUS_SVCLASS_ID +#define HID_PROFILE_ID HID_SVCLASS_ID +#define HCR_PROFILE_ID HCR_SCAN_SVCLASS_ID +#define HCR_PRINT_PROFILE_ID HCR_PRINT_SVCLASS_ID +#define HCR_SCAN_PROFILE_ID HCR_SCAN_SVCLASS_ID +#define CIP_PROFILE_ID CIP_SVCLASS_ID +#define VIDEO_CONF_GW_PROFILE_ID VIDEO_CONF_GW_SVCLASS_ID +#define UDI_MT_PROFILE_ID UDI_MT_SVCLASS_ID +#define UDI_TA_PROFILE_ID UDI_TA_SVCLASS_ID +#define AV_PROFILE_ID AV_SVCLASS_ID +#define SAP_PROFILE_ID SAP_SVCLASS_ID +#define PBAP_PCE_PROFILE_ID PBAP_PCE_SVCLASS_ID +#define PBAP_PSE_PROFILE_ID PBAP_PSE_SVCLASS_ID +#define PBAP_PROFILE_ID PBAP_SVCLASS_ID +#define MAP_PROFILE_ID MAP_SVCLASS_ID +#define PNP_INFO_PROFILE_ID PNP_INFO_SVCLASS_ID +#define GENERIC_NETWORKING_PROFILE_ID GENERIC_NETWORKING_SVCLASS_ID +#define GENERIC_FILETRANS_PROFILE_ID GENERIC_FILETRANS_SVCLASS_ID +#define GENERIC_AUDIO_PROFILE_ID GENERIC_AUDIO_SVCLASS_ID +#define GENERIC_TELEPHONY_PROFILE_ID GENERIC_TELEPHONY_SVCLASS_ID +#define UPNP_PROFILE_ID UPNP_SVCLASS_ID +#define UPNP_IP_PROFILE_ID UPNP_IP_SVCLASS_ID +#define UPNP_PAN_PROFILE_ID UPNP_PAN_SVCLASS_ID +#define UPNP_LAP_PROFILE_ID UPNP_LAP_SVCLASS_ID +#define UPNP_L2CAP_PROFILE_ID UPNP_L2CAP_SVCLASS_ID +#define VIDEO_SOURCE_PROFILE_ID VIDEO_SOURCE_SVCLASS_ID +#define VIDEO_SINK_PROFILE_ID VIDEO_SINK_SVCLASS_ID +#define VIDEO_DISTRIBUTION_PROFILE_ID VIDEO_DISTRIBUTION_SVCLASS_ID +#define HDP_PROFILE_ID HDP_SVCLASS_ID +#define HDP_SOURCE_PROFILE_ID HDP_SOURCE_SVCLASS_ID +#define HDP_SINK_PROFILE_ID HDP_SINK_SVCLASS_ID +#define GENERIC_ACCESS_PROFILE_ID GENERIC_ACCESS_SVCLASS_ID +#define GENERIC_ATTRIB_PROFILE_ID GENERIC_ATTRIB_SVCLASS_ID +#define APPLE_AGENT_PROFILE_ID APPLE_AGENT_SVCLASS_ID +#define MPS_PROFILE_ID MPS_SC_SVCLASS_ID + +/* + * Compatibility macros for the old MDP acronym + */ +#define MDP_SVCLASS_ID HDP_SVCLASS_ID +#define MDP_SOURCE_SVCLASS_ID HDP_SOURCE_SVCLASS_ID +#define MDP_SINK_SVCLASS_ID HDP_SINK_SVCLASS_ID +#define MDP_PROFILE_ID HDP_PROFILE_ID +#define MDP_SOURCE_PROFILE_ID HDP_SOURCE_PROFILE_ID +#define MDP_SINK_PROFILE_ID HDP_SINK_PROFILE_ID + +/* + * Attribute identifier codes + */ +#define SDP_SERVER_RECORD_HANDLE 0x0000 + +/* + * Possible values for attribute-id are listed below. + * See SDP Spec, section "Service Attribute Definitions" for more details. + */ +#define SDP_ATTR_RECORD_HANDLE 0x0000 +#define SDP_ATTR_SVCLASS_ID_LIST 0x0001 +#define SDP_ATTR_RECORD_STATE 0x0002 +#define SDP_ATTR_SERVICE_ID 0x0003 +#define SDP_ATTR_PROTO_DESC_LIST 0x0004 +#define SDP_ATTR_BROWSE_GRP_LIST 0x0005 +#define SDP_ATTR_LANG_BASE_ATTR_ID_LIST 0x0006 +#define SDP_ATTR_SVCINFO_TTL 0x0007 +#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008 +#define SDP_ATTR_PFILE_DESC_LIST 0x0009 +#define SDP_ATTR_DOC_URL 0x000a +#define SDP_ATTR_CLNT_EXEC_URL 0x000b +#define SDP_ATTR_ICON_URL 0x000c +#define SDP_ATTR_ADD_PROTO_DESC_LIST 0x000d + +#define SDP_ATTR_GROUP_ID 0x0200 +#define SDP_ATTR_IP_SUBNET 0x0200 +#define SDP_ATTR_VERSION_NUM_LIST 0x0200 +#define SDP_ATTR_SUPPORTED_FEATURES_LIST 0x0200 +#define SDP_ATTR_GOEP_L2CAP_PSM 0x0200 +#define SDP_ATTR_SVCDB_STATE 0x0201 + +#define SDP_ATTR_MPSD_SCENARIOS 0x0200 +#define SDP_ATTR_MPMD_SCENARIOS 0x0201 +#define SDP_ATTR_MPS_DEPENDENCIES 0x0202 + +#define SDP_ATTR_SERVICE_VERSION 0x0300 +#define SDP_ATTR_EXTERNAL_NETWORK 0x0301 +#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301 +#define SDP_ATTR_DATA_EXCHANGE_SPEC 0x0301 +#define SDP_ATTR_NETWORK 0x0301 +#define SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302 +#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302 +#define SDP_ATTR_MCAP_SUPPORTED_PROCEDURES 0x0302 +#define SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303 +#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303 +#define SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304 +#define SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305 +#define SDP_ATTR_NETWORK_ADDRESS 0x0306 +#define SDP_ATTR_WAP_GATEWAY 0x0307 +#define SDP_ATTR_HOMEPAGE_URL 0x0308 +#define SDP_ATTR_WAP_STACK_TYPE 0x0309 +#define SDP_ATTR_SECURITY_DESC 0x030a +#define SDP_ATTR_NET_ACCESS_TYPE 0x030b +#define SDP_ATTR_MAX_NET_ACCESSRATE 0x030c +#define SDP_ATTR_IP4_SUBNET 0x030d +#define SDP_ATTR_IP6_SUBNET 0x030e +#define SDP_ATTR_SUPPORTED_CAPABILITIES 0x0310 +#define SDP_ATTR_SUPPORTED_FEATURES 0x0311 +#define SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312 +#define SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313 +#define SDP_ATTR_SUPPORTED_REPOSITORIES 0x0314 +#define SDP_ATTR_MAS_INSTANCE_ID 0x0315 +#define SDP_ATTR_SUPPORTED_MESSAGE_TYPES 0x0316 +#define SDP_ATTR_PBAP_SUPPORTED_FEATURES 0x0317 +#define SDP_ATTR_MAP_SUPPORTED_FEATURES 0x0317 + +#define SDP_ATTR_SPECIFICATION_ID 0x0200 +#define SDP_ATTR_VENDOR_ID 0x0201 +#define SDP_ATTR_PRODUCT_ID 0x0202 +#define SDP_ATTR_VERSION 0x0203 +#define SDP_ATTR_PRIMARY_RECORD 0x0204 +#define SDP_ATTR_VENDOR_ID_SOURCE 0x0205 + +#define SDP_ATTR_HID_DEVICE_RELEASE_NUMBER 0x0200 +#define SDP_ATTR_HID_PARSER_VERSION 0x0201 +#define SDP_ATTR_HID_DEVICE_SUBCLASS 0x0202 +#define SDP_ATTR_HID_COUNTRY_CODE 0x0203 +#define SDP_ATTR_HID_VIRTUAL_CABLE 0x0204 +#define SDP_ATTR_HID_RECONNECT_INITIATE 0x0205 +#define SDP_ATTR_HID_DESCRIPTOR_LIST 0x0206 +#define SDP_ATTR_HID_LANG_ID_BASE_LIST 0x0207 +#define SDP_ATTR_HID_SDP_DISABLE 0x0208 +#define SDP_ATTR_HID_BATTERY_POWER 0x0209 +#define SDP_ATTR_HID_REMOTE_WAKEUP 0x020a +#define SDP_ATTR_HID_PROFILE_VERSION 0x020b +#define SDP_ATTR_HID_SUPERVISION_TIMEOUT 0x020c +#define SDP_ATTR_HID_NORMALLY_CONNECTABLE 0x020d +#define SDP_ATTR_HID_BOOT_DEVICE 0x020e + +/* + * These identifiers are based on the SDP spec stating that + * "base attribute id of the primary (universal) language must be 0x0100" + * + * Other languages should have their own offset; e.g.: + * #define XXXLangBase yyyy + * #define AttrServiceName_XXX 0x0000+XXXLangBase + */ +#define SDP_PRIMARY_LANG_BASE 0x0100 + +#define SDP_ATTR_SVCNAME_PRIMARY 0x0000 + SDP_PRIMARY_LANG_BASE +#define SDP_ATTR_SVCDESC_PRIMARY 0x0001 + SDP_PRIMARY_LANG_BASE +#define SDP_ATTR_PROVNAME_PRIMARY 0x0002 + SDP_PRIMARY_LANG_BASE + +/* + * The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec) + * These are the exact data type+size descriptor values + * that go into the PDU buffer. + * + * The datatype (leading 5bits) + size descriptor (last 3 bits) + * is 8 bits. The size descriptor is critical to extract the + * right number of bytes for the data value from the PDU. + * + * For most basic types, the datatype+size descriptor is + * straightforward. However for constructed types and strings, + * the size of the data is in the next "n" bytes following the + * 8 bits (datatype+size) descriptor. Exactly what the "n" is + * specified in the 3 bits of the data size descriptor. + * + * TextString and URLString can be of size 2^{8, 16, 32} bytes + * DataSequence and DataSequenceAlternates can be of size 2^{8, 16, 32} + * The size are computed post-facto in the API and are not known apriori + */ +#define SDP_DATA_NIL 0x00 +#define SDP_UINT8 0x08 +#define SDP_UINT16 0x09 +#define SDP_UINT32 0x0A +#define SDP_UINT64 0x0B +#define SDP_UINT128 0x0C +#define SDP_INT8 0x10 +#define SDP_INT16 0x11 +#define SDP_INT32 0x12 +#define SDP_INT64 0x13 +#define SDP_INT128 0x14 +#define SDP_UUID_UNSPEC 0x18 +#define SDP_UUID16 0x19 +#define SDP_UUID32 0x1A +#define SDP_UUID128 0x1C +#define SDP_TEXT_STR_UNSPEC 0x20 +#define SDP_TEXT_STR8 0x25 +#define SDP_TEXT_STR16 0x26 +#define SDP_TEXT_STR32 0x27 +#define SDP_BOOL 0x28 +#define SDP_SEQ_UNSPEC 0x30 +#define SDP_SEQ8 0x35 +#define SDP_SEQ16 0x36 +#define SDP_SEQ32 0x37 +#define SDP_ALT_UNSPEC 0x38 +#define SDP_ALT8 0x3D +#define SDP_ALT16 0x3E +#define SDP_ALT32 0x3F +#define SDP_URL_STR_UNSPEC 0x40 +#define SDP_URL_STR8 0x45 +#define SDP_URL_STR16 0x46 +#define SDP_URL_STR32 0x47 + +/* + * The PDU identifiers of SDP packets between client and server + */ +#define SDP_ERROR_RSP 0x01 +#define SDP_SVC_SEARCH_REQ 0x02 +#define SDP_SVC_SEARCH_RSP 0x03 +#define SDP_SVC_ATTR_REQ 0x04 +#define SDP_SVC_ATTR_RSP 0x05 +#define SDP_SVC_SEARCH_ATTR_REQ 0x06 +#define SDP_SVC_SEARCH_ATTR_RSP 0x07 + +/* + * Some additions to support service registration. + * These are outside the scope of the Bluetooth specification + */ +#define SDP_SVC_REGISTER_REQ 0x75 +#define SDP_SVC_REGISTER_RSP 0x76 +#define SDP_SVC_UPDATE_REQ 0x77 +#define SDP_SVC_UPDATE_RSP 0x78 +#define SDP_SVC_REMOVE_REQ 0x79 +#define SDP_SVC_REMOVE_RSP 0x80 + +/* + * SDP Error codes + */ +#define SDP_INVALID_VERSION 0x0001 +#define SDP_INVALID_RECORD_HANDLE 0x0002 +#define SDP_INVALID_SYNTAX 0x0003 +#define SDP_INVALID_PDU_SIZE 0x0004 +#define SDP_INVALID_CSTATE 0x0005 + +/* + * SDP PDU + */ +typedef struct { + uint8_t pdu_id; + uint16_t tid; + uint16_t plen; +} __attribute__ ((packed)) sdp_pdu_hdr_t; + +/* + * Common definitions for attributes in the SDP. + * Should the type of any of these change, you need only make a change here. + */ + +typedef struct { + uint8_t type; + union { + uint16_t uuid16; + uint32_t uuid32; + uint128_t uuid128; + } value; +} uuid_t; + +#define SDP_IS_UUID(x) ((x) == SDP_UUID16 || (x) == SDP_UUID32 || \ + (x) == SDP_UUID128) +#define SDP_IS_ALT(x) ((x) == SDP_ALT8 || (x) == SDP_ALT16 || (x) == SDP_ALT32) +#define SDP_IS_SEQ(x) ((x) == SDP_SEQ8 || (x) == SDP_SEQ16 || (x) == SDP_SEQ32) +#define SDP_IS_TEXT_STR(x) ((x) == SDP_TEXT_STR8 || (x) == SDP_TEXT_STR16 || \ + (x) == SDP_TEXT_STR32) + +typedef struct _sdp_list sdp_list_t; +struct _sdp_list { + sdp_list_t *next; + void *data; +}; + +/* + * User-visible strings can be in many languages + * in addition to the universal language. + * + * Language meta-data includes language code in ISO639 + * followed by the encoding format. The third field in this + * structure is the attribute offset for the language. + * User-visible strings in the specified language can be + * obtained at this offset. + */ +typedef struct { + uint16_t code_ISO639; + uint16_t encoding; + uint16_t base_offset; +} sdp_lang_attr_t; + +/* + * Profile descriptor is the Bluetooth profile metadata. If a + * service conforms to a well-known profile, then its profile + * identifier (UUID) is an attribute of the service. In addition, + * if the profile has a version number it is specified here. + */ +typedef struct { + uuid_t uuid; + uint16_t version; +} sdp_profile_desc_t; + +typedef struct { + uint8_t major; + uint8_t minor; +} sdp_version_t; + +typedef struct { + uint8_t *data; + uint32_t data_size; + uint32_t buf_size; +} sdp_buf_t; + +typedef struct { + uint32_t handle; + + /* Search pattern: a sequence of all UUIDs seen in this record */ + sdp_list_t *pattern; + sdp_list_t *attrlist; + + /* Main service class for Extended Inquiry Response */ + uuid_t svclass; +} sdp_record_t; + +typedef struct sdp_data_struct sdp_data_t; +struct sdp_data_struct { + uint8_t dtd; + uint16_t attrId; + union { + int8_t int8; + int16_t int16; + int32_t int32; + int64_t int64; + uint128_t int128; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + uint128_t uint128; + uuid_t uuid; + char *str; + sdp_data_t *dataseq; + } val; + sdp_data_t *next; + int unitSize; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __SDP_H */ diff --git a/lib/bluetooth/sdp_lib.h b/lib/bluetooth/sdp_lib.h new file mode 100644 index 0000000..3ded393 --- /dev/null +++ b/lib/bluetooth/sdp_lib.h @@ -0,0 +1,634 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2001-2002 Nokia Corporation + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2010 Marcel Holtmann + * Copyright (C) 2002-2003 Stephen Crane + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __SDP_LIB_H +#define __SDP_LIB_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SDP lists + */ +typedef void(*sdp_list_func_t)(void *, void *); +typedef void(*sdp_free_func_t)(void *); +typedef int (*sdp_comp_func_t)(const void *, const void *); + +sdp_list_t *sdp_list_append(sdp_list_t *list, void *d); +sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d); +sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *data, sdp_comp_func_t f); +void sdp_list_free(sdp_list_t *list, sdp_free_func_t f); + +static inline int sdp_list_len(const sdp_list_t *list) +{ + int n = 0; + for (; list; list = list->next) + n++; + return n; +} + +static inline sdp_list_t *sdp_list_find(sdp_list_t *list, void *u, sdp_comp_func_t f) +{ + for (; list; list = list->next) + if (f(list->data, u) == 0) + return list; + return NULL; +} + +static inline void sdp_list_foreach(sdp_list_t *list, sdp_list_func_t f, void *u) +{ + for (; list; list = list->next) + f(list->data, u); +} + +/* + * Values of the flags parameter to sdp_record_register + */ +#define SDP_RECORD_PERSIST 0x01 +#define SDP_DEVICE_RECORD 0x02 + +/* + * Values of the flags parameter to sdp_connect + */ +#define SDP_RETRY_IF_BUSY 0x01 +#define SDP_WAIT_ON_CLOSE 0x02 +#define SDP_NON_BLOCKING 0x04 +#define SDP_LARGE_MTU 0x08 + +/* + * a session with an SDP server + */ +typedef struct { + int sock; + int state; + int local; + int flags; + uint16_t tid; /* Current transaction ID */ + void *priv; +} sdp_session_t; + +typedef enum { + /* + * Attributes are specified as individual elements + */ + SDP_ATTR_REQ_INDIVIDUAL = 1, + /* + * Attributes are specified as a range + */ + SDP_ATTR_REQ_RANGE +} sdp_attrreq_type_t; + +/* + * When the pdu_id(type) is a sdp error response, check the status value + * to figure out the error reason. For status values 0x0001-0x0006 check + * Bluetooth SPEC. If the status is 0xffff, call sdp_get_error function + * to get the real reason: + * - wrong transaction ID(EPROTO) + * - wrong PDU id or(EPROTO) + * - I/O error + */ +typedef void sdp_callback_t(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *udata); + +/* + * create an L2CAP connection to a Bluetooth device + * + * INPUT: + * + * bdaddr_t *src: + * Address of the local device to use to make the connection + * (or BDADDR_ANY) + * + * bdaddr_t *dst: + * Address of the SDP server device + */ +sdp_session_t *sdp_connect(const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags); +int sdp_close(sdp_session_t *session); +int sdp_get_socket(const sdp_session_t *session); + +/* + * SDP transaction: functions for asynchronous search. + */ +sdp_session_t *sdp_create(int sk, uint32_t flags); +int sdp_get_error(sdp_session_t *session); +int sdp_process(sdp_session_t *session); +int sdp_set_notify(sdp_session_t *session, sdp_callback_t *func, void *udata); + +int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num); +int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list); +int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list); + +uint16_t sdp_gen_tid(sdp_session_t *session); + +/* + * find all devices in the piconet + */ +int sdp_general_inquiry(inquiry_info *ii, int dev_num, int duration, uint8_t *found); + +/* flexible extraction of basic attributes - Jean II */ +int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attr, int *value); +int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attr, char *value, int valuelen); + +/* + * Basic sdp data functions + */ +sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value); +sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value, uint32_t length); +void sdp_data_free(sdp_data_t *data); +sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attr_id); + +sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len); +sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length, int len); +sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *data); + +int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *data); +void sdp_attr_remove(sdp_record_t *rec, uint16_t attr); +void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *data); +int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t attr, sdp_list_t *seq); +int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp); + +/* + * NOTE that none of the functions below will update the SDP server, + * unless the {register, update}sdp_record_t() function is invoked. + * All functions which return an integer value, return 0 on success + * or -1 on failure. + */ + +/* + * Create an attribute and add it to the service record's attribute list. + * This consists of the data type descriptor of the attribute, + * the value of the attribute and the attribute identifier. + */ +int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *p); + +/* + * Set the information attributes of the service record. + * The set of attributes comprises service name, description + * and provider name + */ +void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc); + +/* + * Set the ServiceClassID attribute to the sequence specified by seq. + * Note that the identifiers need to be in sorted order from the most + * specific to the most generic service class that this service + * conforms to. + */ +static inline int sdp_set_service_classes(sdp_record_t *rec, sdp_list_t *seq) +{ + return sdp_set_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seq); +} + +/* + * Get the service classes to which the service conforms. + * + * When set, the list contains elements of ServiceClassIdentifer(uint16_t) + * ordered from most specific to most generic + */ +static inline int sdp_get_service_classes(const sdp_record_t *rec, sdp_list_t **seqp) +{ + return sdp_get_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seqp); +} + +/* + * Set the BrowseGroupList attribute to the list specified by seq. + * + * A service can belong to one or more service groups + * and the list comprises such group identifiers (UUIDs) + */ +static inline int sdp_set_browse_groups(sdp_record_t *rec, sdp_list_t *seq) +{ + return sdp_set_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seq); +} + +/* + * Set the access protocols of the record to those specified in proto + */ +int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *proto); + +/* + * Set the additional access protocols of the record to those specified in proto + */ +int sdp_set_add_access_protos(sdp_record_t *rec, const sdp_list_t *proto); + +/* + * Get protocol port (i.e. PSM for L2CAP, Channel for RFCOMM) + */ +int sdp_get_proto_port(const sdp_list_t *list, int proto); + +/* + * Get protocol descriptor. + */ +sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto); + +/* + * Set the LanguageBase attributes to the values specified in list + * (a linked list of sdp_lang_attr_t objects, one for each language in + * which user-visible attributes are present). + */ +int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *list); + +/* + * Set the ServiceInfoTimeToLive attribute of the service. + * This is the number of seconds that this record is guaranteed + * not to change after being obtained by a client. + */ +static inline int sdp_set_service_ttl(sdp_record_t *rec, uint32_t ttl) +{ + return sdp_attr_add_new(rec, SDP_ATTR_SVCINFO_TTL, SDP_UINT32, &ttl); +} + +/* + * Set the ServiceRecordState attribute of a service. This is + * guaranteed to change if there is any kind of modification to + * the record. + */ +static inline int sdp_set_record_state(sdp_record_t *rec, uint32_t state) +{ + return sdp_attr_add_new(rec, SDP_ATTR_RECORD_STATE, SDP_UINT32, &state); +} + +/* + * Set the ServiceID attribute of a service. + */ +void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid); + +/* + * Set the GroupID attribute of a service + */ +void sdp_set_group_id(sdp_record_t *rec, uuid_t grouuuid); + +/* + * Set the ServiceAvailability attribute of a service. + * + * Note that this represents the relative availability + * of the service: 0x00 means completely unavailable; + * 0xFF means maximum availability. + */ +static inline int sdp_set_service_avail(sdp_record_t *rec, uint8_t avail) +{ + return sdp_attr_add_new(rec, SDP_ATTR_SERVICE_AVAILABILITY, SDP_UINT8, &avail); +} + +/* + * Set the profile descriptor list attribute of a record. + * + * Each element in the list is an object of type + * sdp_profile_desc_t which is a definition of the + * Bluetooth profile that this service conforms to. + */ +int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *desc); + +/* + * Set URL attributes of a record. + * + * ClientExecutableURL: a URL to a client's platform specific (WinCE, + * PalmOS) executable code that can be used to access this service. + * + * DocumentationURL: a URL pointing to service documentation + * + * IconURL: a URL to an icon that can be used to represent this service. + * + * Note: pass NULL for any URLs that you don't want to set or remove + */ +void sdp_set_url_attr(sdp_record_t *rec, const char *clientExecURL, const char *docURL, const char *iconURL); + +/* + * a service search request. + * + * INPUT : + * + * sdp_list_t *search + * list containing elements of the search + * pattern. Each entry in the list is a UUID + * of the service to be searched + * + * uint16_t max_rec_num + * An integer specifying the maximum number of + * entries that the client can handle in the response. + * + * OUTPUT : + * + * int return value + * 0 + * The request completed successfully. This does not + * mean the requested services were found + * -1 + * The request completed unsuccessfully + * + * sdp_list_t *rsp_list + * This variable is set on a successful return if there are + * non-zero service handles. It is a singly linked list of + * service record handles (uint16_t) + */ +int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num, sdp_list_t **rsp_list); + +/* + * a service attribute request. + * + * INPUT : + * + * uint32_t handle + * The handle of the service for which the attribute(s) are + * requested + * + * sdp_attrreq_type_t reqtype + * Attribute identifiers are 16 bit unsigned integers specified + * in one of 2 ways described below : + * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers + * They are the actual attribute identifiers in ascending order + * + * SDP_ATTR_REQ_RANGE - 32bit identifier range + * The high-order 16bits is the start of range + * the low-order 16bits are the end of range + * 0x0000 to 0xFFFF gets all attributes + * + * sdp_list_t *attrid_list + * Singly linked list containing attribute identifiers desired. + * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) + * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) + * + * OUTPUT : + * int return value + * 0 + * The request completed successfully. This does not + * mean the requested services were found + * -1 + * The request completed unsuccessfully due to a timeout + */ +sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list); + +/* + * This is a service search request combined with the service + * attribute request. First a service class match is done and + * for matching service, requested attributes are extracted + * + * INPUT : + * + * sdp_list_t *search + * Singly linked list containing elements of the search + * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16) + * of the service to be searched + * + * AttributeSpecification attrSpec + * Attribute identifiers are 16 bit unsigned integers specified + * in one of 2 ways described below : + * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers + * They are the actual attribute identifiers in ascending order + * + * SDP_ATTR_REQ_RANGE - 32bit identifier range + * The high-order 16bits is the start of range + * the low-order 16bits are the end of range + * 0x0000 to 0xFFFF gets all attributes + * + * sdp_list_t *attrid_list + * Singly linked list containing attribute identifiers desired. + * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) + * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) + * + * OUTPUT : + * int return value + * 0 + * The request completed successfully. This does not + * mean the requested services were found + * -1 + * The request completed unsuccessfully due to a timeout + * + * sdp_list_t *rsp_list + * This variable is set on a successful return to point to + * service(s) found. Each element of this list is of type + * sdp_record_t *. + */ +int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list, sdp_list_t **rsp_list); + +/* + * Allocate/free a service record and its attributes + */ +sdp_record_t *sdp_record_alloc(void); +void sdp_record_free(sdp_record_t *rec); + +/* + * Register a service record. + * + * Note: It is the responsbility of the Service Provider to create the + * record first and set its attributes using setXXX() methods. + * + * The service provider must then call sdp_record_register() to make + * the service record visible to SDP clients. This function returns 0 + * on success or -1 on failure (and sets errno). + */ +int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, uint8_t *data, uint32_t size, uint8_t flags, uint32_t *handle); +int sdp_device_record_register(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec, uint8_t flags); +int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags); + +/* + * Unregister a service record. + */ +int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle); +int sdp_device_record_unregister(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec); +int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec); + +/* + * Update an existing service record. (Calling this function + * before a previous call to sdp_record_register() will result + * in an error.) + */ +int sdp_device_record_update_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle, uint8_t *data, uint32_t size); +int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp_record_t *rec); +int sdp_record_update(sdp_session_t *sess, const sdp_record_t *rec); + +void sdp_record_print(const sdp_record_t *rec); + +/* + * UUID functions + */ +uuid_t *sdp_uuid16_create(uuid_t *uuid, uint16_t data); +uuid_t *sdp_uuid32_create(uuid_t *uuid, uint32_t data); +uuid_t *sdp_uuid128_create(uuid_t *uuid, const void *data); +int sdp_uuid16_cmp(const void *p1, const void *p2); +int sdp_uuid128_cmp(const void *p1, const void *p2); +int sdp_uuid_cmp(const void *p1, const void *p2); +uuid_t *sdp_uuid_to_uuid128(const uuid_t *uuid); +void sdp_uuid16_to_uuid128(uuid_t *uuid128, const uuid_t *uuid16); +void sdp_uuid32_to_uuid128(uuid_t *uuid128, const uuid_t *uuid32); +int sdp_uuid128_to_uuid(uuid_t *uuid); +int sdp_uuid_to_proto(uuid_t *uuid); +int sdp_uuid_extract(const uint8_t *buffer, int bufsize, uuid_t *uuid, int *scanned); +void sdp_uuid_print(const uuid_t *uuid); + +#define MAX_LEN_UUID_STR 37 +#define MAX_LEN_PROTOCOL_UUID_STR 8 +#define MAX_LEN_SERVICECLASS_UUID_STR 28 +#define MAX_LEN_PROFILEDESCRIPTOR_UUID_STR 28 + +int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n); +int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n); +int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n); +int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n); + +/* + * In all the sdp_get_XXX(handle, XXX *xxx) functions below, + * the XXX * is set to point to the value, should it exist + * and 0 is returned. If the value does not exist, -1 is + * returned and errno set to ENODATA. + * + * In all the methods below, the memory management rules are + * simple. Don't free anything! The pointer returned, in the + * case of constructed types, is a pointer to the contents + * of the sdp_record_t. + */ + +/* + * Get the access protocols from the service record + */ +int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **protos); + +/* + * Get the additional access protocols from the service record + */ +int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **protos); + +/* + * Extract the list of browse groups to which the service belongs. + * When set, seqp contains elements of GroupID (uint16_t) + */ +static inline int sdp_get_browse_groups(const sdp_record_t *rec, sdp_list_t **seqp) +{ + return sdp_get_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seqp); +} + +/* + * Extract language attribute meta-data of the service record. + * For each language in the service record, LangSeq has a struct of type + * sdp_lang_attr_t. + */ +int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq); + +/* + * Extract the Bluetooth profile descriptor sequence from a record. + * Each element in the list is of type sdp_profile_desc_t + * which contains the UUID of the profile and its version number + * (encoded as major and minor in the high-order 8bits + * and low-order 8bits respectively of the uint16_t) + */ +int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDesc); + +/* + * Extract SDP server version numbers + * + * Note: that this is an attribute of the SDP server only and + * contains a list of uint16_t each of which represent the + * major and minor SDP version numbers supported by this server + */ +int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **pVnumList); + +int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid); +int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid); +int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState); +int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail); +int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo); +int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState); + +static inline int sdp_get_service_name(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_SVCNAME_PRIMARY, str, len); +} + +static inline int sdp_get_service_desc(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_SVCDESC_PRIMARY, str, len); +} + +static inline int sdp_get_provider_name(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_PROVNAME_PRIMARY, str, len); +} + +static inline int sdp_get_doc_url(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_DOC_URL, str, len); +} + +static inline int sdp_get_clnt_exec_url(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_CLNT_EXEC_URL, str, len); +} + +static inline int sdp_get_icon_url(const sdp_record_t *rec, char *str, int len) +{ + return sdp_get_string_attr(rec, SDP_ATTR_ICON_URL, str, len); +} + +/* + * Set the supported features + * sf should be a list of list with each feature data + * Returns 0 on success -1 on fail + */ +int sdp_set_supp_feat(sdp_record_t *rec, const sdp_list_t *sf); + +/* + * Get the supported features + * seqp is set to a list of list with each feature data + * Returns 0 on success, if an error occurred -1 is returned and errno is set + */ +int sdp_get_supp_feat(const sdp_record_t *rec, sdp_list_t **seqp); + +sdp_record_t *sdp_extract_pdu(const uint8_t *pdata, int bufsize, int *scanned); +sdp_record_t *sdp_copy_record(sdp_record_t *rec); + +void sdp_data_print(sdp_data_t *data); +void sdp_print_service_attr(sdp_list_t *alist); + +int sdp_attrid_comp_func(const void *key1, const void *key2); + +void sdp_set_seq_len(uint8_t *ptr, uint32_t length); +void sdp_set_attrid(sdp_buf_t *pdu, uint16_t id); +void sdp_append_to_pdu(sdp_buf_t *dst, sdp_data_t *d); +void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len); + +int sdp_gen_pdu(sdp_buf_t *pdu, sdp_data_t *data); +int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *pdu); + +int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size); + +sdp_data_t *sdp_extract_attr(const uint8_t *pdata, int bufsize, int *extractedLength, sdp_record_t *rec); + +void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid); +void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq); + +int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *req, uint8_t *rsp, uint32_t reqsize, uint32_t *rspsize); + +void sdp_add_lang_attr(sdp_record_t *rec); + +#ifdef __cplusplus +} +#endif + +#endif /* __SDP_LIB_H */ diff --git a/lib/bluetooth/uuid.h b/lib/bluetooth/uuid.h new file mode 100644 index 0000000..ebdcf72 --- /dev/null +++ b/lib/bluetooth/uuid.h @@ -0,0 +1,199 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2011 Nokia Corporation + * Copyright (C) 2011 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLUETOOTH_UUID_H +#define __BLUETOOTH_UUID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805f9b34fb" + +#define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" +#define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb" + +#define HFP_HS_UUID "0000111e-0000-1000-8000-00805f9b34fb" +#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb" + +#define ADVANCED_AUDIO_UUID "0000110d-0000-1000-8000-00805f9b34fb" + +#define A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb" +#define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb" + +#define AVRCP_REMOTE_UUID "0000110e-0000-1000-8000-00805f9b34fb" +#define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb" + +#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" +#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" +#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" +#define BNEP_SVC_UUID "0000000f-0000-1000-8000-00805f9b34fb" + +#define PNPID_UUID "00002a50-0000-1000-8000-00805f9b34fb" +#define DEVICE_INFORMATION_UUID "0000180a-0000-1000-8000-00805f9b34fb" + +#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb" +#define IMMEDIATE_ALERT_UUID "00001802-0000-1000-8000-00805f9b34fb" +#define LINK_LOSS_UUID "00001803-0000-1000-8000-00805f9b34fb" +#define TX_POWER_UUID "00001804-0000-1000-8000-00805f9b34fb" +#define BATTERY_UUID "0000180f-0000-1000-8000-00805f9b34fb" +#define SCAN_PARAMETERS_UUID "00001813-0000-1000-8000-00805f9b34fb" + +#define SAP_UUID "0000112D-0000-1000-8000-00805f9b34fb" + +#define HEART_RATE_UUID "0000180d-0000-1000-8000-00805f9b34fb" +#define HEART_RATE_MEASUREMENT_UUID "00002a37-0000-1000-8000-00805f9b34fb" +#define BODY_SENSOR_LOCATION_UUID "00002a38-0000-1000-8000-00805f9b34fb" +#define HEART_RATE_CONTROL_POINT_UUID "00002a39-0000-1000-8000-00805f9b34fb" + +#define HEALTH_THERMOMETER_UUID "00001809-0000-1000-8000-00805f9b34fb" +#define TEMPERATURE_MEASUREMENT_UUID "00002a1c-0000-1000-8000-00805f9b34fb" +#define TEMPERATURE_TYPE_UUID "00002a1d-0000-1000-8000-00805f9b34fb" +#define INTERMEDIATE_TEMPERATURE_UUID "00002a1e-0000-1000-8000-00805f9b34fb" +#define MEASUREMENT_INTERVAL_UUID "00002a21-0000-1000-8000-00805f9b34fb" + +#define CYCLING_SC_UUID "00001816-0000-1000-8000-00805f9b34fb" +#define CSC_MEASUREMENT_UUID "00002a5b-0000-1000-8000-00805f9b34fb" +#define CSC_FEATURE_UUID "00002a5c-0000-1000-8000-00805f9b34fb" +#define SENSOR_LOCATION_UUID "00002a5d-0000-1000-8000-00805f9b34fb" +#define SC_CONTROL_POINT_UUID "00002a55-0000-1000-8000-00805f9b34fb" + +#define RFCOMM_UUID_STR "00000003-0000-1000-8000-00805f9b34fb" + +#define HDP_UUID "00001400-0000-1000-8000-00805f9b34fb" +#define HDP_SOURCE_UUID "00001401-0000-1000-8000-00805f9b34fb" +#define HDP_SINK_UUID "00001402-0000-1000-8000-00805f9b34fb" + +#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" + +#define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb" + +#define GAP_UUID "00001800-0000-1000-8000-00805f9b34fb" +#define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb" + +#define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb" + +#define OBEX_SYNC_UUID "00001104-0000-1000-8000-00805f9b34fb" +#define OBEX_OPP_UUID "00001105-0000-1000-8000-00805f9b34fb" +#define OBEX_FTP_UUID "00001106-0000-1000-8000-00805f9b34fb" +#define OBEX_PCE_UUID "0000112e-0000-1000-8000-00805f9b34fb" +#define OBEX_PSE_UUID "0000112f-0000-1000-8000-00805f9b34fb" +#define OBEX_PBAP_UUID "00001130-0000-1000-8000-00805f9b34fb" +#define OBEX_MAS_UUID "00001132-0000-1000-8000-00805f9b34fb" +#define OBEX_MNS_UUID "00001133-0000-1000-8000-00805f9b34fb" +#define OBEX_MAP_UUID "00001134-0000-1000-8000-00805f9b34fb" + +/* GATT UUIDs section */ +#define GATT_PRIM_SVC_UUID 0x2800 +#define GATT_SND_SVC_UUID 0x2801 +#define GATT_INCLUDE_UUID 0x2802 +#define GATT_CHARAC_UUID 0x2803 + +/* GATT Characteristic Types */ +#define GATT_CHARAC_DEVICE_NAME 0x2A00 +#define GATT_CHARAC_APPEARANCE 0x2A01 +#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02 +#define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03 +#define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04 +#define GATT_CHARAC_SERVICE_CHANGED 0x2A05 +#define GATT_CHARAC_BATTERY_LEVEL 0x2A19 +#define GATT_CHARAC_SYSTEM_ID 0x2A23 +#define GATT_CHARAC_MODEL_NUMBER_STRING 0x2A24 +#define GATT_CHARAC_SERIAL_NUMBER_STRING 0x2A25 +#define GATT_CHARAC_FIRMWARE_REVISION_STRING 0x2A26 +#define GATT_CHARAC_HARDWARE_REVISION_STRING 0x2A27 +#define GATT_CHARAC_SOFTWARE_REVISION_STRING 0x2A28 +#define GATT_CHARAC_MANUFACTURER_NAME_STRING 0x2A29 +#define GATT_CHARAC_PNP_ID 0x2A50 + +/* GATT Characteristic Descriptors */ +#define GATT_CHARAC_EXT_PROPER_UUID 0x2900 +#define GATT_CHARAC_USER_DESC_UUID 0x2901 +#define GATT_CLIENT_CHARAC_CFG_UUID 0x2902 +#define GATT_SERVER_CHARAC_CFG_UUID 0x2903 +#define GATT_CHARAC_FMT_UUID 0x2904 +#define GATT_CHARAC_AGREG_FMT_UUID 0x2905 +#define GATT_CHARAC_VALID_RANGE_UUID 0x2906 +#define GATT_EXTERNAL_REPORT_REFERENCE 0x2907 +#define GATT_REPORT_REFERENCE 0x2908 + +/* GATT Mesh Services */ +#define MESH_PROV_SVC_UUID "00001827-0000-1000-8000-00805f9b34fb" +#define MESH_PROXY_SVC_UUID "00001828-0000-1000-8000-00805f9b34fb" + +/* GATT Mesh Characteristic Types */ +#define MESH_PROVISIONING_DATA_IN 0x2ADB +#define MESH_PROVISIONING_DATA_OUT 0x2ADC +#define MESH_PROXY_DATA_IN 0x2ADD +#define MESH_PROXY_DATA_OUT 0x2ADE + +/* GATT Caching attributes */ +#define GATT_CHARAC_CLI_FEAT 0x2B29 +#define GATT_CHARAC_DB_HASH 0x2B2A + +/* GATT Server Supported features */ +#define GATT_CHARAC_SERVER_FEAT 0x2B3A + +typedef struct { + enum { + BT_UUID_UNSPEC = 0, + BT_UUID16 = 16, + BT_UUID32 = 32, + BT_UUID128 = 128, + } type; + union { + uint16_t u16; + uint32_t u32; + uint128_t u128; + } value; +} bt_uuid_t; + +int bt_uuid_strcmp(const void *a, const void *b); + +int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value); +int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value); +int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value); + +int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2); +void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst); + +#define MAX_LEN_UUID_STR 37 + +int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n); +int bt_string_to_uuid(bt_uuid_t *uuid, const char *string); + +int bt_uuid_to_le(const bt_uuid_t *uuid, void *dst); + +static inline int bt_uuid_len(const bt_uuid_t *uuid) +{ + return uuid->type / 8; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __BLUETOOTH_UUID_H */ diff --git a/menu.cpp b/menu.cpp index ca85ab1..ab3db4e 100644 --- a/menu.cpp +++ b/menu.cpp @@ -41,6 +41,9 @@ along with this program. If not, see . #include #include #include +#include +#include +#include #include "file_io.h" #include "osd.h" @@ -606,20 +609,7 @@ static uint32_t menu_key_get(void) static int has_bt() { - FILE *fp; - static char out[1035]; - - fp = popen("hcitool dev | grep hci0", "r"); - if (!fp) return 0; - - int ret = 0; - while (fgets(out, sizeof(out) - 1, fp) != NULL) - { - if (strlen(out)) ret = 1; - } - - pclose(fp); - return ret; + return hci_get_route(0) >= 0; } static int toggle_wminput() @@ -1120,7 +1110,7 @@ void HandleUI(void) break; case KEY_F11: - if (user_io_osd_is_visible()) + if (user_io_osd_is_visible() && (menustate != MENU_SCRIPTS1 || script_exited)) { menustate = MENU_BTPAIR; }