diff options
author | Wu zheng <wu.zheng@intel.com> | 2013-10-23 10:59:15 +0800 |
---|---|---|
committer | Wu zheng <wu.zheng@intel.com> | 2013-10-23 10:59:15 +0800 |
commit | 7b2a18f8fa9ca2a101244853e34bd44f9ce3b0a3 (patch) | |
tree | 38610dbb3a2920b9f57fc7638e0efed820a3acb9 /lib | |
parent | 71235d13fb107f879369e64385d8c97de0bb840e (diff) | |
download | bluez-7b2a18f8fa9ca2a101244853e34bd44f9ce3b0a3.tar.gz bluez-7b2a18f8fa9ca2a101244853e34bd44f9ce3b0a3.tar.bz2 bluez-7b2a18f8fa9ca2a101244853e34bd44f9ce3b0a3.zip |
Imported Upstream version 5.10upstream/5.10
Diffstat (limited to 'lib')
-rw-r--r-- | lib/a2mp.h | 38 | ||||
-rw-r--r-- | lib/amp.h | 172 | ||||
-rw-r--r-- | lib/bluetooth.c | 271 | ||||
-rw-r--r-- | lib/bluetooth.h | 71 | ||||
-rw-r--r-- | lib/bluez.pc.in | 10 | ||||
-rw-r--r-- | lib/hci.c | 23 | ||||
-rw-r--r-- | lib/hci.h | 71 | ||||
-rw-r--r-- | lib/hci_lib.h | 2 | ||||
-rw-r--r-- | lib/mgmt.h | 42 | ||||
-rw-r--r-- | lib/sdp.c | 603 | ||||
-rw-r--r-- | lib/sdp.h | 17 | ||||
-rw-r--r-- | lib/uuid.c | 5 | ||||
-rw-r--r-- | lib/uuid.h | 28 |
13 files changed, 1017 insertions, 336 deletions
@@ -142,44 +142,6 @@ struct a2mp_disconn_rsp { #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 #define A2MP_STATUS_SECURITY_VIOLATION 0x06 -#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 a2mp_tlv { - uint8_t type; - uint16_t len; - uint8_t val[0]; -} __attribute__ ((packed)); - -struct a2mp_pal_ver { - uint8_t ver; - uint16_t company_id; - uint16_t sub_ver; -} __attribute__ ((packed)); - -struct a2mp_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 a2mp_chan_list { - uint8_t country_code[3]; - struct a2mp_country_triplet triplets[0]; -} __attribute__ ((packed)); - #ifdef __cplusplus } #endif diff --git a/lib/amp.h b/lib/amp.h new file mode 100644 index 00000000..27aab1de --- /dev/null +++ b/lib/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.c b/lib/bluetooth.c index a0be884f..05fe2c3b 100644 --- a/lib/bluetooth.c +++ b/lib/bluetooth.c @@ -82,7 +82,6 @@ int ba2str(const bdaddr_t *ba, char *str) int str2ba(const char *str, bdaddr_t *ba) { - bdaddr_t b; int i; if (bachk(str) < 0) { @@ -90,10 +89,8 @@ int str2ba(const char *str, bdaddr_t *ba) return -1; } - for (i = 0; i < 6; i++, str += 3) - b.b[i] = strtol(str, NULL, 16); - - baswap(ba, &b); + for (i = 5; i >= 0; i--, str += 3) + ba->b[i] = strtol(str, NULL, 16); return 0; } @@ -261,7 +258,7 @@ int bt_error(uint16_t code) } } -char *bt_compidtostr(int compid) +const char *bt_compidtostr(int compid) { switch (compid) { case 0: @@ -293,13 +290,13 @@ char *bt_compidtostr(int compid) case 13: return "Texas Instruments Inc."; case 14: - return "Parthus Technologies Inc."; + return "Ceva, Inc. (formerly Parthus Technologies, Inc.)"; case 15: return "Broadcom Corporation"; case 16: return "Mitel Semiconductor"; case 17: - return "Widcomm, Inc."; + return "Widcomm, Inc"; case 18: return "Zeevo, Inc."; case 19: @@ -311,11 +308,11 @@ char *bt_compidtostr(int compid) case 22: return "KC Technology Inc."; case 23: - return "Newlogic"; + return "NewLogic"; case 24: return "Transilica, Inc."; case 25: - return "Rohde & Schwartz GmbH & Co. KG"; + return "Rohde & Schwarz GmbH & Co. KG"; case 26: return "TTPCom Limited"; case 27: @@ -363,7 +360,7 @@ char *bt_compidtostr(int compid) case 48: return "ST Microelectronics"; case 49: - return "Synopsys"; + return "Synopsis"; case 50: return "Red-M (Communications) Ltd"; case 51: @@ -389,19 +386,19 @@ char *bt_compidtostr(int compid) case 61: return "IPextreme, Inc."; case 62: - return "Systems and Chips, Inc"; + return "Systems and Chips, Inc."; case 63: - return "Bluetooth SIG, Inc"; + return "Bluetooth SIG, Inc."; case 64: return "Seiko Epson Corporation"; case 65: - return "Integrated Silicon Solution Taiwain, Inc."; + return "Integrated Silicon Solution Taiwan, Inc."; case 66: return "CONWISE Technology Corporation Ltd"; case 67: return "PARROT SA"; case 68: - return "Socket Communications"; + return "Socket Mobile"; case 69: return "Atheros Communications, Inc."; case 70: @@ -423,9 +420,9 @@ char *bt_compidtostr(int compid) case 78: return "Avago Technologies"; case 79: - return "APT Ltd."; + return "APT Licensing Ltd."; case 80: - return "SiRF Technology, Inc."; + return "SiRF Technology"; case 81: return "Tzero Technologies, Inc."; case 82: @@ -515,13 +512,251 @@ char *bt_compidtostr(int compid) case 124: return "A & R Cambridge"; case 125: - return "Seers Technology Co. Ltd."; + return "Seers Technology Co. Ltd"; case 126: return "Sports Tracking Technologies Ltd."; case 127: return "Autonet Mobile"; case 128: return "DeLorme Publishing Company, Inc."; + case 129: + return "WuXi Vimicro"; + case 130: + return "Sennheiser Communications A/S"; + case 131: + return "TimeKeeping Systems, Inc."; + case 132: + return "Ludus Helsinki Ltd."; + case 133: + return "BlueRadios, Inc."; + case 134: + return "equinox AG"; + case 135: + return "Garmin International, Inc."; + case 136: + return "Ecotest"; + case 137: + return "GN ReSound A/S"; + case 138: + return "Jawbone"; + case 139: + return "Topcorn Positioning Systems, LLC"; + case 140: + return "Qualcomm Labs, Inc."; + case 141: + return "Zscan Software"; + case 142: + return "Quintic Corp."; + case 143: + return "Stollman E+V GmbH"; + case 144: + return "Funai Electric Co., Ltd."; + case 145: + return "Advanced PANMOBIL Systems GmbH & Co. KG"; + case 146: + return "ThinkOptics, Inc."; + case 147: + return "Universal Electronics, Inc."; + case 148: + return "Airoha Technology Corp."; + case 149: + return "NEC Lighting, Ltd."; + case 150: + return "ODM Technology, Inc."; + case 151: + return "ConnecteDevice Ltd."; + case 152: + return "zer01.tv GmbH"; + case 153: + return "i.Tech Dynamic Global Distribution Ltd."; + case 154: + return "Alpwise"; + case 155: + return "Jiangsu Toppower Automotive Electronics Co., Ltd."; + case 156: + return "Colorfy, Inc."; + case 157: + return "Geoforce Inc."; + case 158: + return "Bose Corporation"; + case 159: + return "Suunto Oy"; + case 160: + return "Kensington Computer Products Group"; + case 161: + return "SR-Medizinelektronik"; + case 162: + return "Vertu Corporation Limited"; + case 163: + return "Meta Watch Ltd."; + case 164: + return "LINAK A/S"; + case 165: + return "OTL Dynamics LLC"; + case 166: + return "Panda Ocean Inc."; + case 167: + return "Visteon Corporation"; + case 168: + return "ARP Devices Limited"; + case 169: + return "Magneti Marelli S.p.A"; + case 170: + return "CAEN RFID srl"; + case 171: + return "Ingenieur-Systemgruppe Zahn GmbH"; + case 172: + return "Green Throttle Games"; + case 173: + return "Peter Systemtechnik GmbH"; + case 174: + return "Omegawave Oy"; + case 175: + return "Cinetix"; + case 176: + return "Passif Semiconductor Corp"; + case 177: + return "Saris Cycling Group, Inc"; + case 178: + return "Bekey A/S"; + case 179: + return "Clarinox Technologies Pty. Ltd."; + case 180: + return "BDE Technology Co., Ltd."; + case 181: + return "Swirl Networks"; + case 182: + return "Meso international"; + case 183: + return "TreLab Ltd"; + case 184: + return "Qualcomm Innovation Center, Inc. (QuIC)"; + case 185: + return "Johnson Controls, Inc."; + case 186: + return "Starkey Laboratories Inc."; + case 187: + return "S-Power Electronics Limited"; + case 188: + return "Ace Sensor Inc"; + case 189: + return "Aplix Corporation"; + case 190: + return "AAMP of America"; + case 191: + return "Stalmart Technology Limited"; + case 192: + return "AMICCOM Electronics Corporation"; + case 193: + return "Shenzhen Excelsecu Data Technology Co.,Ltd"; + case 194: + return "Geneq Inc."; + case 195: + return "adidas AG"; + case 196: + return "LG Electronics"; + case 197: + return "Onset Computer Corporation"; + case 198: + return "Selfly BV"; + case 199: + return "Quuppa Oy."; + case 200: + return "GeLo Inc"; + case 201: + return "Evluma"; + case 202: + return "MC10"; + case 203: + return "Binauric SE"; + case 204: + return "Beats Electronics"; + case 205: + return "Microchip Technology Inc."; + case 206: + return "Elgato Systems GmbH"; + case 207: + return "ARCHOS SA"; + case 209: + return "Polar Electro Europe B.V."; + case 210: + return "Dialog Semiconductor B.V."; + case 211: + return "Taixingbang Technology (HK) Co,. LTD."; + case 212: + return "Kawantech"; + case 213: + return "Austco Communication Systems"; + case 214: + return "Timex Group USA, Inc."; + case 215: + return "Qualcomm Technologies, Inc."; + case 216: + return "Qualcomm Connected Experiences, Inc."; + case 217: + return "Voyetra Turtle Beach"; + case 218: + return "txtr GmbH"; + case 219: + return "Biosentronics"; + case 220: + return "Procter & Gamble"; + case 221: + return "Hosiden Corporation"; + case 222: + return "Muzik LLC"; + case 223: + return "Misfit Wearables Corp"; + case 224: + return "Google"; + case 225: + return "Danlers Ltd"; + case 226: + return "Semilink Inc"; + case 227: + return "inMusic Brands, Inc"; + case 228: + return "L.S. Research Inc."; + case 229: + return "Eden Software Consultants Ltd."; + case 230: + return "Freshtemp"; + case 231: + return "KS Technologies"; + case 232: + return "ACTS Technologies"; + case 233: + return "Vtrack Systems"; + case 234: + return "Nielsen-Kellerman Company"; + case 235: + return "Server Technology, Inc."; + case 236: + return "BioResearch Associates"; + case 237: + return "Jolly Logic, LLC"; + case 238: + return "Above Average Outcomes, Inc."; + case 239: + return "Bitsplitters GmbH"; + case 240: + return "PayPal, Inc."; + case 241: + return "Witron Technology Limited"; + case 242: + return "Morse Project Inc."; + case 243: + return "Kent Displays Inc."; + case 244: + return "Nautilus Inc."; + case 245: + return "Smartifier Oy"; + case 246: + return "Elcometer Limited"; + case 247: + return "VSN Technologies Inc."; + case 248: + return "AceUni Corp., Ltd."; case 65535: return "internal use"; default: diff --git a/lib/bluetooth.h b/lib/bluetooth.h index 0fc4508a..012fde40 100644 --- a/lib/bluetooth.h +++ b/lib/bluetooth.h @@ -104,6 +104,14 @@ struct bt_security { */ #define BT_CHANNEL_POLICY_AMP_PREFERRED 2 +#define BT_VOICE 11 +struct bt_voice { + uint16_t setting; +}; + +#define BT_VOICE_TRANSPARENT 0x0003 +#define BT_VOICE_CVSD_16BIT 0x0060 + /* Connection and socket states */ enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ @@ -183,6 +191,37 @@ 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) { @@ -213,6 +252,36 @@ 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 @@ -258,7 +327,7 @@ void *bt_malloc(size_t size); void bt_free(void *ptr); int bt_error(uint16_t code); -char *bt_compidtostr(int id); +const char *bt_compidtostr(int id); typedef struct { uint8_t data[16]; diff --git a/lib/bluez.pc.in b/lib/bluez.pc.in new file mode 100644 index 00000000..3d6e5961 --- /dev/null +++ b/lib/bluez.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: BlueZ +Description: Bluetooth protocol stack for Linux +Version: @VERSION@ +Libs: -L${libdir} -lbluetooth +Cflags: -I${includedir} @@ -672,6 +672,21 @@ int lmp_strtover(char *str, unsigned int *ver) return hci_str2uint(ver_map, str, ver); } +static hci_map pal_map[] = { + { "3.0", 0x01 }, + { NULL } +}; + +char *pal_vertostr(unsigned int ver) +{ + return hci_uint2str(pal_map, ver); +} + +int pal_strtover(char *str, unsigned int *ver) +{ + return hci_str2uint(pal_map, str, ver); +} + /* LMP features mapping */ static hci_map lmp_features_map[8][9] = { { /* Byte 0 */ @@ -817,7 +832,7 @@ int hci_for_each_dev(int flag, int (*func)(int dd, int dev_id, long arg), int dev_id = -1; int i, sk, err = 0; - sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + sk = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (sk < 0) return -1; @@ -909,7 +924,7 @@ int hci_devinfo(int dev_id, struct hci_dev_info *di) { int dd, err, ret; - dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (dd < 0) return dd; @@ -965,7 +980,7 @@ int hci_inquiry(int dev_id, int len, int nrsp, const uint8_t *lap, } } - dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (dd < 0) return dd; @@ -1021,7 +1036,7 @@ int hci_open_dev(int dev_id) int dd, err; /* Create HCI socket */ - dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (dd < 0) return dd; @@ -34,7 +34,7 @@ extern "C" { #define HCI_MAX_DEV 16 -#define HCI_MAX_ACL_SIZE 1024 +#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) @@ -560,6 +560,13 @@ typedef struct { #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 { @@ -650,9 +657,9 @@ typedef struct { } __attribute__ ((packed)) hci_qos; #define HCI_QOS_CP_SIZE 17 typedef struct { - uint16_t handle; - uint8_t flags; /* Reserved */ - hci_qos qos; + 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) @@ -681,7 +688,7 @@ typedef struct { } __attribute__ ((packed)) read_link_policy_cp; #define READ_LINK_POLICY_CP_SIZE 2 typedef struct { - uint8_t status; + uint8_t status; uint16_t handle; uint16_t policy; } __attribute__ ((packed)) read_link_policy_rp; @@ -694,7 +701,7 @@ typedef struct { } __attribute__ ((packed)) write_link_policy_cp; #define WRITE_LINK_POLICY_CP_SIZE 4 typedef struct { - uint8_t status; + uint8_t status; uint16_t handle; } __attribute__ ((packed)) write_link_policy_rp; #define WRITE_LINK_POLICY_RP_SIZE 3 @@ -1326,6 +1333,14 @@ typedef struct { } __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 @@ -1342,7 +1357,7 @@ typedef struct { uint8_t status; uint16_t handle; } __attribute__ ((packed)) reset_failed_contact_counter_rp; -#define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 4 +#define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 3 #define OCF_READ_LINK_QUALITY 0x0003 typedef struct { @@ -1402,22 +1417,23 @@ typedef struct { #define OCF_READ_LOCAL_AMP_ASSOC 0x000A typedef struct { uint8_t handle; - uint16_t len_so_far; - uint16_t max_len; + 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 rem_len; - uint8_t frag[0]; + 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 assoc_length; + 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 @@ -1492,7 +1508,7 @@ typedef struct { #define OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER 0x0007 typedef struct { uint8_t status; - uint8_t level; + int8_t level; } __attribute__ ((packed)) le_read_advertising_channel_tx_power_rp; #define LE_READ_ADVERTISING_CHANNEL_TX_POWER_RP_SIZE 2 @@ -1716,7 +1732,7 @@ typedef struct { uint8_t link_type; uint8_t encr_mode; } __attribute__ ((packed)) evt_conn_complete; -#define EVT_CONN_COMPLETE_SIZE 13 +#define EVT_CONN_COMPLETE_SIZE 11 #define EVT_CONN_REQUEST 0x04 typedef struct { @@ -1755,7 +1771,7 @@ typedef struct { uint16_t handle; uint8_t encrypt; } __attribute__ ((packed)) evt_encrypt_change; -#define EVT_ENCRYPT_CHANGE_SIZE 5 +#define EVT_ENCRYPT_CHANGE_SIZE 4 #define EVT_CHANGE_CONN_LINK_KEY_COMPLETE 0x09 typedef struct { @@ -1799,14 +1815,14 @@ typedef struct { } __attribute__ ((packed)) evt_qos_setup_complete; #define EVT_QOS_SETUP_COMPLETE_SIZE (4 + HCI_QOS_CP_SIZE) -#define EVT_CMD_COMPLETE 0x0E +#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 +#define EVT_CMD_STATUS 0x0F typedef struct { uint8_t status; uint8_t ncmd; @@ -2198,6 +2214,16 @@ typedef struct { #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 { @@ -2232,25 +2258,25 @@ typedef struct { uint16_t opcode; /* OCF & OGF */ uint8_t plen; } __attribute__ ((packed)) hci_command_hdr; -#define HCI_COMMAND_HDR_SIZE 3 +#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 +#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 +#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 +#define HCI_SCO_HDR_SIZE 3 typedef struct { uint16_t device; @@ -2288,6 +2314,7 @@ struct sockaddr_hci { #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 diff --git a/lib/hci_lib.h b/lib/hci_lib.h index cf4a0ff1..50744c3b 100644 --- a/lib/hci_lib.h +++ b/lib/hci_lib.h @@ -158,6 +158,8 @@ 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); @@ -45,6 +45,7 @@ #define MGMT_STATUS_NOT_POWERED 0x0f #define MGMT_STATUS_CANCELLED 0x10 #define MGMT_STATUS_INVALID_INDEX 0x11 +#define MGMT_STATUS_RFKILLED 0x12 struct mgmt_hdr { uint16_t opcode; @@ -79,7 +80,7 @@ struct mgmt_rp_read_index_list { /* Reserve one extra byte for names in management messages so that they * are always guaranteed to be nul-terminated */ -#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) +#define MGMT_MAX_NAME_LENGTH (248 + 1) #define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) #define MGMT_SETTING_POWERED 0x00000001 @@ -92,6 +93,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_BREDR 0x00000080 #define MGMT_SETTING_HS 0x00000100 #define MGMT_SETTING_LE 0x00000200 +#define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { @@ -109,6 +111,10 @@ 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 @@ -314,6 +320,21 @@ struct mgmt_cp_set_device_id { 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_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { uint16_t opcode; @@ -369,9 +390,15 @@ struct mgmt_ev_device_connected { 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 @@ -437,6 +464,13 @@ 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; + static const char *mgmt_op[] = { "<0x0000>", "Read Version", @@ -479,6 +513,10 @@ static const char *mgmt_op[] = { "Block Device", "Unblock Device", "Set Device ID", + "Set Advertising", + "Set BR/EDR", + "Set Static Address", + "Set Scan Parameters", }; static const char *mgmt_ev[] = { @@ -505,6 +543,7 @@ static const char *mgmt_ev[] = { "Device Blocked", "Device Unblocked", "Device Unpaired", + "Passkey Notify", }; static const char *mgmt_status[] = { @@ -526,6 +565,7 @@ static const char *mgmt_status[] = { "Not Powered", "Cancelled", "Invalid Index", + "Blocked through rfkill", }; #ifndef NELEM @@ -125,7 +125,7 @@ static struct tupla ServiceClass[] = { { AV_REMOTE_TARGET_SVCLASS_ID, "AV Remote Target" }, { ADVANCED_AUDIO_SVCLASS_ID, "Advanced Audio" }, { AV_REMOTE_SVCLASS_ID, "AV Remote" }, - { VIDEO_CONF_SVCLASS_ID, "Video Conferencing" }, + { AV_REMOTE_CONTROLLER_SVCLASS_ID, "AV Remote Controller" }, { INTERCOM_SVCLASS_ID, "Intercom" }, { FAX_SVCLASS_ID, "Fax" }, { HEADSET_AGW_SVCLASS_ID, "Headset Audio Gateway" }, @@ -159,6 +159,9 @@ static struct tupla ServiceClass[] = { { PBAP_PCE_SVCLASS_ID, "Phonebook Access - PCE" }, { PBAP_PSE_SVCLASS_ID, "Phonebook Access - PSE" }, { PBAP_SVCLASS_ID, "Phonebook Access" }, + { MAP_MSE_SVCLASS_ID, "Message Access - MAS" }, + { MAP_MCE_SVCLASS_ID, "Message Access - MNS" }, + { MAP_SVCLASS_ID, "Message Access" }, { PNP_INFO_SVCLASS_ID, "PnP Information" }, { GENERIC_NETWORKING_SVCLASS_ID, "Generic Networking" }, { GENERIC_FILETRANS_SVCLASS_ID, "Generic File Transfer" }, @@ -193,7 +196,7 @@ static char *string_lookup(struct tupla *pt0, int index) return ""; } -static char *string_lookup_uuid(struct tupla *pt0, const uuid_t* uuid) +static char *string_lookup_uuid(struct tupla *pt0, const uuid_t *uuid) { uuid_t tmp_uuid; @@ -317,13 +320,13 @@ int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n) void sdp_uuid_print(const uuid_t *uuid) { if (uuid == NULL) { - SDPERR("Null passed to print UUID\n"); + SDPERR("Null passed to print UUID"); return; } if (uuid->type == SDP_UUID16) { - SDPDBG(" uint16_t : 0x%.4x\n", uuid->value.uuid16); + SDPDBG(" uint16_t : 0x%.4x", uuid->value.uuid16); } else if (uuid->type == SDP_UUID32) { - SDPDBG(" uint32_t : 0x%.8x\n", uuid->value.uuid32); + SDPDBG(" uint32_t : 0x%.8x", uuid->value.uuid32); } else if (uuid->type == SDP_UUID128) { unsigned int data0; unsigned short data1; @@ -339,14 +342,11 @@ void sdp_uuid_print(const uuid_t *uuid) memcpy(&data4, &uuid->value.uuid128.data[10], 4); memcpy(&data5, &uuid->value.uuid128.data[14], 2); - SDPDBG(" uint128_t : 0x%.8x-", ntohl(data0)); - SDPDBG("%.4x-", ntohs(data1)); - SDPDBG("%.4x-", ntohs(data2)); - SDPDBG("%.4x-", ntohs(data3)); - SDPDBG("%.8x", ntohl(data4)); - SDPDBG("%.4x\n", ntohs(data5)); + SDPDBG(" uint128_t : 0x%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + ntohl(data0), ntohs(data1), ntohs(data2), + ntohs(data3), ntohl(data4), ntohs(data5)); } else - SDPERR("Enum type of UUID not set\n"); + SDPERR("Enum type of UUID not set"); } #endif @@ -438,14 +438,14 @@ sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value, memcpy(d->val.str, value, length); } else { - SDPERR("Strings of size > USHRT_MAX not supported\n"); + SDPERR("Strings of size > USHRT_MAX not supported"); free(d); d = NULL; } break; case SDP_URL_STR32: case SDP_TEXT_STR32: - SDPERR("Strings of size > USHRT_MAX not supported\n"); + SDPERR("Strings of size > USHRT_MAX not supported"); break; case SDP_ALT8: case SDP_ALT16: @@ -532,7 +532,7 @@ sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length, curr = data; } - return sdp_data_alloc_with_length(SDP_SEQ8, seq, length[i]); + return sdp_data_alloc(SDP_SEQ8, seq); } sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len) @@ -567,7 +567,7 @@ static void extract_svclass_uuid(sdp_data_t *data, uuid_t *uuid) { sdp_data_t *d; - if (!data || data->dtd < SDP_SEQ8 || data->dtd > SDP_SEQ32) + if (!data || !SDP_IS_SEQ(data->dtd)) return; d = data->val.dataseq; @@ -622,60 +622,43 @@ void sdp_set_seq_len(uint8_t *ptr, uint32_t length) case SDP_ALT16: case SDP_TEXT_STR16: case SDP_URL_STR16: - bt_put_unaligned(htons(length), (uint16_t *) ptr); + bt_put_be16(length, ptr); break; case SDP_SEQ32: case SDP_ALT32: case SDP_TEXT_STR32: case SDP_URL_STR32: - bt_put_unaligned(htonl(length), (uint32_t *) ptr); + bt_put_be32(length, ptr); break; } } -static int sdp_get_data_type(sdp_buf_t *buf, uint8_t dtd) +static int sdp_get_data_type_size(uint8_t dtd) { - int data_type = 0; - - data_type += sizeof(uint8_t); + int size = sizeof(uint8_t); switch (dtd) { case SDP_SEQ8: case SDP_TEXT_STR8: case SDP_URL_STR8: case SDP_ALT8: - data_type += sizeof(uint8_t); + size += sizeof(uint8_t); break; case SDP_SEQ16: case SDP_TEXT_STR16: case SDP_URL_STR16: case SDP_ALT16: - data_type += sizeof(uint16_t); + size += sizeof(uint16_t); break; case SDP_SEQ32: case SDP_TEXT_STR32: case SDP_URL_STR32: case SDP_ALT32: - data_type += sizeof(uint32_t); + size += sizeof(uint32_t); break; } - if (!buf->data) - buf->buf_size += data_type; - - return data_type; -} - -static int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd) -{ - int data_type = 0; - uint8_t *p = buf->data + buf->data_size; - - *p = dtd; - data_type = sdp_get_data_type(buf, dtd); - buf->data_size += data_type; - - return data_type; + return size; } void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr) @@ -685,7 +668,7 @@ void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr) /* data type for attr */ *p++ = SDP_UINT16; buf->data_size = sizeof(uint8_t); - bt_put_unaligned(htons(attr), (uint16_t *) p); + bt_put_be16(attr, p); buf->data_size += sizeof(uint16_t); } @@ -774,9 +757,6 @@ static int sdp_get_data_size(sdp_buf_t *buf, sdp_data_t *d) break; } - if (!buf->data) - buf->buf_size += data_size; - return data_size; } @@ -795,8 +775,8 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d) /* attribute length */ buf->buf_size += sizeof(uint8_t) + sizeof(uint16_t); - sdp_get_data_type(buf, d->dtd); - sdp_get_data_size(buf, d); + buf->buf_size += sdp_get_data_type_size(d->dtd); + buf->buf_size += sdp_get_data_size(buf, d); if (buf->buf_size > UCHAR_MAX && d->dtd == SDP_SEQ8) buf->buf_size += sizeof(uint8_t); @@ -806,19 +786,29 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d) int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d) { - uint32_t pdu_size = 0, data_size = 0; + uint32_t pdu_size, data_size; unsigned char *src = NULL, is_seq = 0, is_alt = 0; - uint8_t dtd = d->dtd; uint16_t u16; uint32_t u32; uint64_t u64; uint128_t u128; uint8_t *seqp = buf->data + buf->data_size; + uint32_t orig_data_size = buf->data_size; + +recalculate: + pdu_size = sdp_get_data_type_size(d->dtd); + buf->data_size += pdu_size; - pdu_size = sdp_set_data_type(buf, dtd); data_size = sdp_get_data_size(buf, d); + if (data_size > UCHAR_MAX && d->dtd == SDP_SEQ8) { + buf->data_size = orig_data_size; + d->dtd = SDP_SEQ16; + goto recalculate; + } - switch (dtd) { + *seqp = d->dtd; + + switch (d->dtd) { case SDP_DATA_NIL: break; case SDP_UINT8: @@ -900,8 +890,8 @@ int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d) if (src && buf->buf_size >= buf->data_size + data_size) { memcpy(buf->data + buf->data_size, src, data_size); buf->data_size += data_size; - } else if (dtd != SDP_DATA_NIL) { - SDPDBG("Gen PDU : Can't copy from invalid source or dest\n"); + } else if (d->dtd != SDP_DATA_NIL) { + SDPDBG("Gen PDU : Can't copy from invalid source or dest"); } } @@ -1005,7 +995,7 @@ int sdp_uuid_extract(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned) type = *(const uint8_t *) p; if (!SDP_IS_UUID(type)) { - SDPERR("Unknown data type : %d expecting a svc UUID\n", type); + SDPERR("Unknown data type : %d expecting a svc UUID", type); return -1; } p += sizeof(uint8_t); @@ -1016,14 +1006,14 @@ int sdp_uuid_extract(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned) SDPERR("Not enough room for 16-bit UUID"); return -1; } - sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p))); + sdp_uuid16_create(uuid, bt_get_be16(p)); *scanned += sizeof(uint16_t); } else if (type == SDP_UUID32) { if (bufsize < (int) sizeof(uint32_t)) { SDPERR("Not enough room for 32-bit UUID"); return -1; } - sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p))); + sdp_uuid32_create(uuid, bt_get_be32(p)); *scanned += sizeof(uint32_t); } else { if (bufsize < (int) sizeof(uint128_t)) { @@ -1049,7 +1039,7 @@ static sdp_data_t *extract_int(const void *p, int bufsize, int *len) if (!d) return NULL; - SDPDBG("Extracting integer\n"); + SDPDBG("Extracting integer"); memset(d, 0, sizeof(sdp_data_t)); d->dtd = *(uint8_t *) p; p += sizeof(uint8_t); @@ -1078,7 +1068,7 @@ static sdp_data_t *extract_int(const void *p, int bufsize, int *len) return NULL; } *len += sizeof(uint16_t); - d->val.uint16 = ntohs(bt_get_unaligned((uint16_t *) p)); + d->val.uint16 = bt_get_be16(p); break; case SDP_INT32: case SDP_UINT32: @@ -1088,7 +1078,7 @@ static sdp_data_t *extract_int(const void *p, int bufsize, int *len) return NULL; } *len += sizeof(uint32_t); - d->val.uint32 = ntohl(bt_get_unaligned((uint32_t *) p)); + d->val.uint32 = bt_get_be32(p); break; case SDP_INT64: case SDP_UINT64: @@ -1098,7 +1088,7 @@ static sdp_data_t *extract_int(const void *p, int bufsize, int *len) return NULL; } *len += sizeof(uint64_t); - d->val.uint64 = ntoh64(bt_get_unaligned((uint64_t *) p)); + d->val.uint64 = bt_get_be64(p); break; case SDP_INT128: case SDP_UINT128: @@ -1181,13 +1171,13 @@ static sdp_data_t *extract_str(const void *p, int bufsize, int *len) free(d); return NULL; } - n = ntohs(bt_get_unaligned((uint16_t *) p)); + n = bt_get_be16(p); p += sizeof(uint16_t); - *len += sizeof(uint16_t) + n; + *len += sizeof(uint16_t); bufsize -= sizeof(uint16_t); break; default: - SDPERR("Sizeof text string > UINT16_MAX\n"); + SDPERR("Sizeof text string > UINT16_MAX"); free(d); return NULL; } @@ -1209,8 +1199,8 @@ static sdp_data_t *extract_str(const void *p, int bufsize, int *len) *len += n; - SDPDBG("Len : %d\n", n); - SDPDBG("Str : %s\n", s); + SDPDBG("Len : %d", n); + SDPDBG("Str : %s", s); d->val.str = s; d->unitSize = n + sizeof(uint8_t); @@ -1251,7 +1241,7 @@ int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *siz SDPERR("Unexpected end of packet"); return 0; } - *size = ntohs(bt_get_unaligned((uint16_t *) buf)); + *size = bt_get_be16(buf); scanned += sizeof(uint16_t); break; case SDP_SEQ32: @@ -1260,11 +1250,11 @@ int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *siz SDPERR("Unexpected end of packet"); return 0; } - *size = ntohl(bt_get_unaligned((uint32_t *) buf)); + *size = bt_get_be32(buf); scanned += sizeof(uint32_t); break; default: - SDPERR("Unknown sequence type, aborting\n"); + SDPERR("Unknown sequence type, aborting"); return 0; } return scanned; @@ -1283,7 +1273,7 @@ static sdp_data_t *extract_seq(const void *p, int bufsize, int *len, SDPDBG("Extracting SEQ"); memset(d, 0, sizeof(sdp_data_t)); *len = sdp_extract_seqtype(p, bufsize, &d->dtd, &seqlen); - SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen); + SDPDBG("Sequence Type : 0x%x length : 0x%x", d->dtd, seqlen); if (*len == 0) return d; @@ -1371,7 +1361,7 @@ sdp_data_t *sdp_extract_attr(const uint8_t *p, int bufsize, int *size, elem = extract_seq(p, bufsize, &n, rec); break; default: - SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd); + SDPERR("Unknown data descriptor : 0x%x terminating", dtd); return NULL; } *size += n; @@ -1383,21 +1373,21 @@ static void attr_print_func(void *value, void *userData) { sdp_data_t *d = (sdp_data_t *)value; - SDPDBG("=====================================\n"); - SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n", d->attrId); - SDPDBG("ATTRIBUTE VALUE PTR : %p\n", value); + SDPDBG("====================================="); + SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x", d->attrId); + SDPDBG("ATTRIBUTE VALUE PTR : %p", value); if (d) sdp_data_print(d); else - SDPDBG("NULL value\n"); - SDPDBG("=====================================\n"); + SDPDBG("NULL value"); + SDPDBG("====================================="); } void sdp_print_service_attr(sdp_list_t *svcAttrList) { - SDPDBG("Printing service attr list %p\n", svcAttrList); + SDPDBG("Printing service attr list %p", svcAttrList); sdp_list_foreach(svcAttrList, attr_print_func, NULL); - SDPDBG("Printed service attr list %p\n", svcAttrList); + SDPDBG("Printed service attr list %p", svcAttrList); } #endif @@ -1427,14 +1417,14 @@ sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int bufsize, int *scanned) } dtd = *(uint8_t *) p; - attr = ntohs(bt_get_unaligned((uint16_t *) (p + n))); + attr = bt_get_be16(p + n); n += sizeof(uint16_t); - SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr); + SDPDBG("DTD of attrId : %d Attr id : 0x%x ", dtd, attr); data = sdp_extract_attr(p + n, bufsize - n, &attrlen, rec); - SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen); + SDPDBG("Attr id : 0x%x attrValueLength : %d", attr, attrlen); n += attrlen; if (data == NULL) { @@ -1457,7 +1447,7 @@ sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int bufsize, int *scanned) seqlen, extracted); } #ifdef SDP_DEBUG - SDPDBG("Successful extracting of Svc Rec attributes\n"); + SDPDBG("Successful extracting of Svc Rec attributes"); sdp_print_service_attr(rec->attrlist); #endif *scanned += seqlen; @@ -1610,14 +1600,14 @@ static void print_dataseq(sdp_data_t *p) void sdp_record_print(const sdp_record_t *rec) { sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); - if (d) - printf("Service Name: %.*s\n", d->unitSize, d->val.str); + if (d && SDP_IS_TEXT_STR(d->dtd)) + printf("Service Name: %.*s", d->unitSize, d->val.str); d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY); - if (d) - printf("Service Description: %.*s\n", d->unitSize, d->val.str); + if (d && SDP_IS_TEXT_STR(d->dtd)) + printf("Service Description: %.*s", d->unitSize, d->val.str); d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY); - if (d) - printf("Service Provider: %.*s\n", d->unitSize, d->val.str); + if (d && SDP_IS_TEXT_STR(d->dtd)) + printf("Service Provider: %.*s", d->unitSize, d->val.str); } #ifdef SDP_DEBUG @@ -1625,7 +1615,7 @@ void sdp_data_print(sdp_data_t *d) { switch (d->dtd) { case SDP_DATA_NIL: - SDPDBG("NIL\n"); + SDPDBG("NIL"); break; case SDP_BOOL: case SDP_UINT8: @@ -1638,23 +1628,23 @@ void sdp_data_print(sdp_data_t *d) case SDP_INT32: case SDP_INT64: case SDP_INT128: - SDPDBG("Integer : 0x%x\n", d->val.uint32); + SDPDBG("Integer : 0x%x", d->val.uint32); break; case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: - SDPDBG("UUID\n"); + SDPDBG("UUID"); sdp_uuid_print(&d->val.uuid); break; case SDP_TEXT_STR8: case SDP_TEXT_STR16: case SDP_TEXT_STR32: - SDPDBG("Text : %s\n", d->val.str); + SDPDBG("Text : %s", d->val.str); break; case SDP_URL_STR8: case SDP_URL_STR16: case SDP_URL_STR32: - SDPDBG("URL : %s\n", d->val.str); + SDPDBG("URL : %s", d->val.str); break; case SDP_SEQ8: case SDP_SEQ16: @@ -1664,7 +1654,7 @@ void sdp_data_print(sdp_data_t *d) case SDP_ALT8: case SDP_ALT16: case SDP_ALT32: - SDPDBG("Data Sequence Alternates\n"); + SDPDBG("Data Sequence Alternates"); print_dataseq(d->val.dataseq); break; } @@ -1705,9 +1695,9 @@ static int sdp_read_rsp(sdp_session_t *session, uint8_t *buf, uint32_t size) FD_ZERO(&readFds); FD_SET(session->sock, &readFds); - SDPDBG("Waiting for response\n"); + SDPDBG("Waiting for response"); if (select(session->sock + 1, &readFds, NULL, NULL, &timeout) == 0) { - SDPERR("Client timed out\n"); + SDPERR("Client timed out"); errno = ETIMEDOUT; return -1; } @@ -1726,13 +1716,13 @@ int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *reqbuf, SDPDBG(""); if (0 > sdp_send_req(session, reqbuf, reqsize)) { - SDPERR("Error sending data:%s", strerror(errno)); + SDPERR("Error sending data:%m"); return -1; } n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); if (0 > n) return -1; - SDPDBG("Read : %d\n", n); + SDPDBG("Read : %d", n); if (n == 0 || reqhdr->tid != rsphdr->tid) { errno = EPROTO; return -1; @@ -1867,50 +1857,65 @@ sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto) return NULL; } -int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap) +static int sdp_get_proto_descs(uint16_t attr_id, const sdp_record_t *rec, + sdp_list_t **pap) { sdp_data_t *pdlist, *curr; - sdp_list_t *ap = 0; + sdp_list_t *ap = NULL; - pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST); + pdlist = sdp_data_get(rec, attr_id); if (pdlist == NULL) { errno = ENODATA; return -1; } - SDPDBG("AP type : 0%x\n", pdlist->dtd); + + SDPDBG("Attribute value type: 0x%02x", pdlist->dtd); + + if (attr_id == SDP_ATTR_ADD_PROTO_DESC_LIST) { + if (!SDP_IS_SEQ(pdlist->dtd)) { + errno = EINVAL; + return -1; + } + pdlist = pdlist->val.dataseq; + } for (; pdlist; pdlist = pdlist->next) { - sdp_list_t *pds = 0; - for (curr = pdlist->val.dataseq; curr; curr = curr->next) + sdp_list_t *pds = NULL; + + if (!SDP_IS_SEQ(pdlist->dtd) && !SDP_IS_ALT(pdlist->dtd)) + goto failed; + + for (curr = pdlist->val.dataseq; curr; curr = curr->next) { + if (!SDP_IS_SEQ(curr->dtd)) { + sdp_list_free(pds, NULL); + goto failed; + } pds = sdp_list_append(pds, curr->val.dataseq); + } + ap = sdp_list_append(ap, pds); } + *pap = ap; + return 0; -} -int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap) -{ - sdp_data_t *pdlist, *curr; - sdp_list_t *ap = 0; +failed: + sdp_list_foreach(ap, (sdp_list_func_t) sdp_list_free, NULL); + sdp_list_free(ap, NULL); + errno = EINVAL; - pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); - if (pdlist == NULL) { - errno = ENODATA; - return -1; - } - SDPDBG("AP type : 0%x\n", pdlist->dtd); + return -1; +} - pdlist = pdlist->val.dataseq; +int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap) +{ + return sdp_get_proto_descs(SDP_ATTR_PROTO_DESC_LIST, rec, pap); +} - for (; pdlist; pdlist = pdlist->next) { - sdp_list_t *pds = 0; - for (curr = pdlist->val.dataseq; curr; curr = curr->next) - pds = sdp_list_append(pds, curr->val.dataseq); - ap = sdp_list_append(ap, pds); - } - *pap = ap; - return 0; +int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap) +{ + return sdp_get_proto_descs(SDP_ATTR_ADD_PROTO_DESC_LIST, rec, pap); } int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, @@ -1919,7 +1924,7 @@ int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_data_t *sdpdata = sdp_data_get(rec, attr); *seqp = NULL; - if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) { + if (sdpdata && SDP_IS_SEQ(sdpdata->dtd)) { sdp_data_t *d; for (d = sdpdata->val.dataseq; d; d = d->next) { uuid_t *u; @@ -2011,19 +2016,30 @@ int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq) errno = ENODATA; return -1; } + + if (!SDP_IS_SEQ(sdpdata->dtd)) + goto invalid; curr_data = sdpdata->val.dataseq; + while (curr_data) { - sdp_data_t *pCode = curr_data; - sdp_data_t *pEncoding; - sdp_data_t *pOffset; + sdp_data_t *pCode, *pEncoding, *pOffset; + + pCode = curr_data; + if (pCode->dtd != SDP_UINT16) + goto invalid; + + /* LanguageBaseAttributeIDList entries are always grouped as + * triplets */ + if (!pCode->next || !pCode->next->next) + goto invalid; pEncoding = pCode->next; - if (!pEncoding) - break; + if (pEncoding->dtd != SDP_UINT16) + goto invalid; pOffset = pEncoding->next; - if (!pOffset) - break; + if (pOffset->dtd != SDP_UINT16) + goto invalid; lang = malloc(sizeof(sdp_lang_attr_t)); if (!lang) { @@ -2034,15 +2050,22 @@ int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq) lang->code_ISO639 = pCode->val.uint16; lang->encoding = pEncoding->val.uint16; lang->base_offset = pOffset->val.uint16; - SDPDBG("code_ISO639 : 0x%02x\n", lang->code_ISO639); - SDPDBG("encoding : 0x%02x\n", lang->encoding); - SDPDBG("base_offfset : 0x%02x\n", lang->base_offset); + SDPDBG("code_ISO639 : 0x%02x", lang->code_ISO639); + SDPDBG("encoding : 0x%02x", lang->encoding); + SDPDBG("base_offfset : 0x%02x", lang->base_offset); *langSeq = sdp_list_append(*langSeq, lang); curr_data = pOffset->next; } return 0; + +invalid: + sdp_list_free(*langSeq, free); + *langSeq = NULL; + errno = EINVAL; + + return -1; } int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) @@ -2052,15 +2075,24 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) *profDescSeq = NULL; sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST); - if (!sdpdata || !sdpdata->val.dataseq) { + if (sdpdata == NULL) { errno = ENODATA; return -1; } - for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) { + + if (!SDP_IS_SEQ(sdpdata->dtd) || sdpdata->val.dataseq == NULL) + goto invalid; + + for (seq = sdpdata->val.dataseq; seq; seq = seq->next) { uuid_t *uuid = NULL; uint16_t version = 0x100; if (SDP_IS_UUID(seq->dtd)) { + /* Mac OS X 10.7.3 and old Samsung phones do not comply + * to the SDP specification for + * BluetoothProfileDescriptorList. This workaround + * allows to properly parse UUID/version from SDP + * record published by these systems. */ sdp_data_t *next = seq->next; uuid = &seq->val.uuid; if (next && next->dtd == SDP_UINT16) { @@ -2068,13 +2100,21 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) seq = next; } } else if (SDP_IS_SEQ(seq->dtd)) { - sdp_data_t *puuid = seq->val.dataseq; - sdp_data_t *pVnum = seq->val.dataseq->next; - if (puuid && pVnum) { - uuid = &puuid->val.uuid; - version = pVnum->val.uint16; - } - } + sdp_data_t *puuid, *pVnum; + + puuid = seq->val.dataseq; + if (puuid == NULL || !SDP_IS_UUID(puuid->dtd)) + goto invalid; + + uuid = &puuid->val.uuid; + + pVnum = puuid->next; + if (pVnum == NULL || pVnum->dtd != SDP_UINT16) + goto invalid; + + version = pVnum->val.uint16; + } else + goto invalid; if (uuid != NULL) { profDesc = malloc(sizeof(sdp_profile_desc_t)); @@ -2087,12 +2127,19 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) profDesc->version = version; #ifdef SDP_DEBUG sdp_uuid_print(&profDesc->uuid); - SDPDBG("Vnum : 0x%04x\n", profDesc->version); + SDPDBG("Vnum : 0x%04x", profDesc->version); #endif *profDescSeq = sdp_list_append(*profDescSeq, profDesc); } } return 0; + +invalid: + sdp_list_free(*profDescSeq, free); + *profDescSeq = NULL; + errno = EINVAL; + + return -1; } int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16) @@ -2105,9 +2152,24 @@ int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16) errno = ENODATA; return -1; } - for (curr = d->val.dataseq; curr; curr = curr->next) + + if (!SDP_IS_SEQ(d->dtd) || d->val.dataseq == NULL) + goto invalid; + + for (curr = d->val.dataseq; curr; curr = curr->next) { + if (curr->dtd != SDP_UINT16) + goto invalid; *u16 = sdp_list_append(*u16, &curr->val.uint16); + } + return 0; + +invalid: + sdp_list_free(*u16, NULL); + *u16 = NULL; + errno = EINVAL; + + return -1; } /* flexible extraction of basic attributes - Jean II */ @@ -2135,9 +2197,7 @@ int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, sdp_data_t *sdpdata = sdp_data_get(rec, attrid); if (sdpdata) /* Verify that it is what the caller expects */ - if (sdpdata->dtd == SDP_TEXT_STR8 || - sdpdata->dtd == SDP_TEXT_STR16 || - sdpdata->dtd == SDP_TEXT_STR32) + if (SDP_IS_TEXT_STR(sdpdata->dtd)) if ((int) strlen(sdpdata->val.str) < valuelen) { strcpy(value, sdpdata->val.str); return 0; @@ -2486,6 +2546,7 @@ int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles) int i = 0, seqlen = sdp_list_len(profiles); void **seqDTDs, **seqs; const sdp_list_t *p; + sdp_data_t *pAPSeq; seqDTDs = malloc(seqlen * sizeof(void *)); if (!seqDTDs) @@ -2503,7 +2564,7 @@ int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles) sdp_profile_desc_t *profile = p->data; if (!profile) { status = -1; - break; + goto end; } switch (profile->uuid.type) { case SDP_UUID16: @@ -2520,22 +2581,26 @@ int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles) break; default: status = -1; - break; + goto end; } dtds[1] = &uint16; values[1] = &profile->version; seq = sdp_seq_alloc(dtds, values, 2); - if (seq) { - seqDTDs[i] = &seq->dtd; - seqs[i] = seq; - sdp_pattern_add_uuid(rec, &profile->uuid); + + if (seq == NULL) { + status = -1; + goto end; } + + seqDTDs[i] = &seq->dtd; + seqs[i] = seq; + sdp_pattern_add_uuid(rec, &profile->uuid); i++; } - if (status == 0) { - sdp_data_t *pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen); - sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq); - } + + pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen); + sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq); +end: free(seqDTDs); free(seqs); return status; @@ -2758,9 +2823,9 @@ void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len) uint8_t *p = dst->data; uint8_t dtd = *p; - SDPDBG("Append src size: %d\n", len); - SDPDBG("Append dst size: %d\n", dst->data_size); - SDPDBG("Dst buffer size: %d\n", dst->buf_size); + SDPDBG("Append src size: %d", len); + SDPDBG("Append dst size: %d", dst->data_size); + SDPDBG("Dst buffer size: %d", dst->buf_size); if (dst->data_size == 0 && dtd == 0) { /* create initial sequence */ *p = SDP_SEQ8; @@ -2787,10 +2852,10 @@ void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len) *(uint8_t *) p = dst->data_size - sizeof(uint8_t) - sizeof(uint8_t); break; case SDP_SEQ16: - bt_put_unaligned(htons(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t)), (uint16_t *) p); + bt_put_be16(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t), p); break; case SDP_SEQ32: - bt_put_unaligned(htonl(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t)), (uint32_t *) p); + bt_put_be32(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t), p); break; } } @@ -2887,7 +2952,7 @@ int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, goto end; } if (handle) - *handle = ntohl(bt_get_unaligned((uint32_t *) p)); + *handle = bt_get_be32(p); } end: @@ -2970,7 +3035,7 @@ int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device p = reqbuf + sizeof(sdp_pdu_hdr_t); reqsize = sizeof(sdp_pdu_hdr_t); - bt_put_unaligned(htonl(handle), (uint32_t *) p); + bt_put_be32(handle, p); reqsize += sizeof(uint32_t); reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); @@ -2987,7 +3052,6 @@ int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device rsphdr = (sdp_pdu_hdr_t *) rspbuf; p = rspbuf + sizeof(sdp_pdu_hdr_t); - status = bt_get_unaligned((uint16_t *) p); if (rsphdr->pdu_id == SDP_ERROR_RSP) { /* For this case the status always is invalid record handle */ @@ -2996,6 +3060,12 @@ int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device } else if (rsphdr->pdu_id != SDP_SVC_REMOVE_RSP) { errno = EPROTO; status = -1; + } else { + uint16_t tmp; + + memcpy(&tmp, p, sizeof(tmp)); + + status = tmp; } end: free(reqbuf); @@ -3063,7 +3133,7 @@ int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp p = reqbuf + sizeof(sdp_pdu_hdr_t); reqsize = sizeof(sdp_pdu_hdr_t); - bt_put_unaligned(htonl(handle), (uint32_t *) p); + bt_put_be32(handle, p); reqsize += sizeof(uint32_t); p += sizeof(uint32_t); @@ -3088,11 +3158,10 @@ int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp goto end; } - SDPDBG("Send req status : %d\n", status); + SDPDBG("Send req status : %d", status); rsphdr = (sdp_pdu_hdr_t *) rspbuf; p = rspbuf + sizeof(sdp_pdu_hdr_t); - status = bt_get_unaligned((uint16_t *) p); if (rsphdr->pdu_id == SDP_ERROR_RSP) { /* The status can be invalid sintax or invalid record handle */ @@ -3101,6 +3170,12 @@ int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp } else if (rsphdr->pdu_id != SDP_SVC_UPDATE_RSP) { errno = EPROTO; status = -1; + } else { + uint16_t tmp; + + memcpy(&tmp, p, sizeof(tmp)); + + status = tmp; } end: free(reqbuf); @@ -3139,15 +3214,15 @@ void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid) { uuid_t *uuid128 = sdp_uuid_to_uuid128(uuid); - SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); - SDPDBG("Trying to add : 0x%lx\n", (unsigned long) uuid128); + SDPDBG("Elements in target pattern : %d", sdp_list_len(rec->pattern)); + SDPDBG("Trying to add : 0x%lx", (unsigned long) uuid128); if (sdp_list_find(rec->pattern, uuid128, sdp_uuid128_cmp) == NULL) rec->pattern = sdp_list_insert_sorted(rec->pattern, uuid128, sdp_uuid128_cmp); else bt_free(uuid128); - SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); + SDPDBG("Elements in target pattern : %d", sdp_list_len(rec->pattern)); } void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq) @@ -3179,7 +3254,7 @@ static void extract_record_handle_seq(uint8_t *pdu, int bufsize, sdp_list_t **se pSvcRec = malloc(sizeof(uint32_t)); if (!pSvcRec) break; - *pSvcRec = ntohl(bt_get_unaligned((uint32_t *) pdata)); + *pSvcRec = bt_get_be32(pdata); pSeq = sdp_list_append(pSeq, pSvcRec); pdata += sizeof(uint32_t); *scanned += sizeof(uint32_t); @@ -3201,7 +3276,7 @@ static int gen_dataseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dtd) /* Fill up the value and the dtd arrays */ SDPDBG(""); - SDPDBG("Seq length : %d\n", seqlen); + SDPDBG("Seq length : %d", seqlen); types = malloc(seqlen * sizeof(void *)); if (!types) @@ -3240,9 +3315,9 @@ static int gen_dataseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dtd) return -ENOMEM; } - SDPDBG("Data Seq : 0x%p\n", seq); + SDPDBG("Data Seq : 0x%p", seq); seqlen = sdp_gen_pdu(&buf, dataseq); - SDPDBG("Copying : %d\n", buf.data_size); + SDPDBG("Copying : %d", buf.data_size); memcpy(dst, buf.data, buf.data_size); sdp_data_free(dataseq); @@ -3343,14 +3418,14 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, /* add service class IDs for search */ seqlen = gen_searchseq_pdu(pdata, search); - SDPDBG("Data seq added : %d\n", seqlen); + SDPDBG("Data seq added : %d", seqlen); /* set the length and increment the pointer */ reqsize += seqlen; pdata += seqlen; /* specify the maximum svc rec count that client expects */ - bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata); + bt_put_be16(max_rec_num, pdata); reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); @@ -3385,7 +3460,7 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, rsplen = ntohs(rsphdr->plen); if (rsphdr->pdu_id == SDP_ERROR_RSP) { - SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); + SDPDBG("Status : 0x%x", rsphdr->pdu_id); status = -1; goto end; } @@ -3403,20 +3478,20 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, pdata += sizeof(uint16_t); scanned += sizeof(uint16_t); pdata_len -= sizeof(uint16_t); - rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); + rec_count = bt_get_be16(pdata); pdata += sizeof(uint16_t); scanned += sizeof(uint16_t); pdata_len -= sizeof(uint16_t); - SDPDBG("Current svc count: %d\n", rec_count); - SDPDBG("ResponseLength: %d\n", rsplen); + SDPDBG("Current svc count: %d", rec_count); + SDPDBG("ResponseLength: %d", rsplen); if (!rec_count) { status = -1; goto end; } extract_record_handle_seq(pdata, pdata_len, rsp, rec_count, &scanned); - SDPDBG("BytesScanned : %d\n", scanned); + SDPDBG("BytesScanned : %d", scanned); if (rsplen > scanned) { uint8_t cstate_len; @@ -3431,7 +3506,7 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, cstate_len = *(uint8_t *) pdata; if (cstate_len > 0) { cstate = (sdp_cstate_t *)pdata; - SDPDBG("Cont state length: %d\n", cstate_len); + SDPDBG("Cont state length: %d", cstate_len); } else cstate = NULL; } @@ -3512,12 +3587,12 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, reqsize = sizeof(sdp_pdu_hdr_t); /* add the service record handle */ - bt_put_unaligned(htonl(handle), (uint32_t *) pdata); + bt_put_be32(handle, pdata); reqsize += sizeof(uint32_t); pdata += sizeof(uint32_t); /* specify the response limit */ - bt_put_unaligned(htons(65535), (uint16_t *) pdata); + bt_put_be16(65535, pdata); reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); @@ -3530,7 +3605,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, } pdata += seqlen; reqsize += seqlen; - SDPDBG("Attr list length : %d\n", seqlen); + SDPDBG("Attr list length : %d", seqlen); /* save before Continuation State */ _pdata = pdata; @@ -3558,7 +3633,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, rsphdr = (sdp_pdu_hdr_t *) rspbuf; if (rsphdr->pdu_id == SDP_ERROR_RSP) { - SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id); + SDPDBG("PDU ID : 0x%x", rsphdr->pdu_id); goto end; } pdata = rspbuf + sizeof(sdp_pdu_hdr_t); @@ -3569,7 +3644,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, goto end; } - rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); + rsp_count = bt_get_be16(pdata); attr_list_len += rsp_count; pdata += sizeof(uint16_t); pdata_len -= sizeof(uint16_t); @@ -3584,9 +3659,9 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, } cstate_len = *(uint8_t *) (pdata + rsp_count); - SDPDBG("Response id : %d\n", rsphdr->pdu_id); - SDPDBG("Attrlist byte count : %d\n", rsp_count); - SDPDBG("sdp_cstate_t length : %d\n", cstate_len); + SDPDBG("Response id : %d", rsphdr->pdu_id); + SDPDBG("Attrlist byte count : %d", rsp_count); + SDPDBG("sdp_cstate_t length : %d", cstate_len); /* * a split response: concatenate intermediate responses @@ -3765,13 +3840,13 @@ int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, u /* add service class IDs for search */ seqlen = gen_searchseq_pdu(pdata, search); - SDPDBG("Data seq added : %d\n", seqlen); + SDPDBG("Data seq added : %d", seqlen); /* now set the length and increment the pointer */ t->reqsize += seqlen; pdata += seqlen; - bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata); + bt_put_be16(max_rec_num, pdata); t->reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); @@ -3780,7 +3855,7 @@ int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, u reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { - SDPERR("Error sendind data:%s", strerror(errno)); + SDPERR("Error sendind data:%m"); t->err = errno; goto end; } @@ -3864,12 +3939,12 @@ int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_ t->reqsize = sizeof(sdp_pdu_hdr_t); /* add the service record handle */ - bt_put_unaligned(htonl(handle), (uint32_t *) pdata); + bt_put_be32(handle, pdata); t->reqsize += sizeof(uint32_t); pdata += sizeof(uint32_t); /* specify the response limit */ - bt_put_unaligned(htons(65535), (uint16_t *) pdata); + bt_put_be16(65535, pdata); t->reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); @@ -3884,14 +3959,14 @@ int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_ /* now set the length and increment the pointer */ t->reqsize += seqlen; pdata += seqlen; - SDPDBG("Attr list length : %d\n", seqlen); + SDPDBG("Attr list length : %d", seqlen); /* set the request header's param length */ cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { - SDPERR("Error sendind data:%s", strerror(errno)); + SDPERR("Error sendind data:%m"); t->err = errno; goto end; } @@ -3978,17 +4053,17 @@ int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *sear /* add service class IDs for search */ seqlen = gen_searchseq_pdu(pdata, search); - SDPDBG("Data seq added : %d\n", seqlen); + SDPDBG("Data seq added : %d", seqlen); /* now set the length and increment the pointer */ t->reqsize += seqlen; pdata += seqlen; - bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata); + bt_put_be16(SDP_MAX_ATTR_LEN, pdata); t->reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); - SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); + SDPDBG("Max attr byte count : %d", SDP_MAX_ATTR_LEN); /* get attr seq PDU form */ seqlen = gen_attridseq_pdu(pdata, attrid_list, @@ -3999,7 +4074,7 @@ int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *sear } pdata += seqlen; - SDPDBG("Attr list length : %d\n", seqlen); + SDPDBG("Attr list length : %d", seqlen); t->reqsize += seqlen; /* set the request header's param length */ @@ -4007,7 +4082,7 @@ int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *sear reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { - SDPERR("Error sendind data:%s", strerror(errno)); + SDPERR("Error sendind data:%m"); t->err = errno; goto end; } @@ -4083,8 +4158,7 @@ int sdp_process(sdp_session_t *session) rspbuf = malloc(SDP_RSP_BUFFER_SIZE); if (!rspbuf) { - SDPERR("Response buffer alloc failure:%s (%d)", - strerror(errno), errno); + SDPERR("Response buffer alloc failure:%m (%d)", errno); return -1; } @@ -4098,7 +4172,7 @@ int sdp_process(sdp_session_t *session) n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); if (n < 0) { - SDPERR("Read response:%s (%d)", strerror(errno), errno); + SDPERR("Read response:%m (%d)", errno); t->err = errno; goto end; } @@ -4120,9 +4194,9 @@ int sdp_process(sdp_session_t *session) * CSRC: Current Service Record Count (2 bytes) */ ssr_pdata = pdata; - tsrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata)); + tsrc = bt_get_be16(ssr_pdata); ssr_pdata += sizeof(uint16_t); - csrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata)); + csrc = bt_get_be16(ssr_pdata); /* csrc should never be larger than tsrc */ if (csrc > tsrc) { @@ -4131,8 +4205,8 @@ int sdp_process(sdp_session_t *session) goto end; } - SDPDBG("Total svc count: %d\n", tsrc); - SDPDBG("Current svc count: %d\n", csrc); + SDPDBG("Total svc count: %d", tsrc); + SDPDBG("Current svc count: %d", csrc); /* parameter length without continuation state */ plen = sizeof(tsrc) + sizeof(csrc) + csrc * 4; @@ -4140,26 +4214,43 @@ int sdp_process(sdp_session_t *session) if (t->rsp_concat_buf.data_size == 0) { /* first fragment */ rsp_count = sizeof(tsrc) + sizeof(csrc) + csrc * 4; - } else { + } else if (t->rsp_concat_buf.data_size >= sizeof(uint16_t) * 2) { /* point to the first csrc */ - uint16_t *pcsrc = (uint16_t *) (t->rsp_concat_buf.data + 2); + uint8_t *pcsrc = t->rsp_concat_buf.data + 2; + uint16_t tcsrc, tcsrc2; /* FIXME: update the interface later. csrc doesn't need be passed to clients */ pdata += sizeof(uint16_t); /* point to csrc */ /* the first csrc contains the sum of partial csrc responses */ - *pcsrc += bt_get_unaligned((uint16_t *) pdata); + memcpy(&tcsrc, pcsrc, sizeof(tcsrc)); + memcpy(&tcsrc2, pdata, sizeof(tcsrc2)); + tcsrc += tcsrc2; + memcpy(pcsrc, &tcsrc, sizeof(tcsrc)); pdata += sizeof(uint16_t); /* point to the first handle */ rsp_count = csrc * 4; + } else { + t->err = EPROTO; + SDPERR("Protocol error: invalid PDU size"); + status = SDP_INVALID_PDU_SIZE; + goto end; } status = 0x0000; break; case SDP_SVC_ATTR_RSP: case SDP_SVC_SEARCH_ATTR_RSP: - rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); - SDPDBG("Attrlist byte count : %d\n", rsp_count); + rsp_count = bt_get_be16(pdata); + SDPDBG("Attrlist byte count : %d", rsp_count); + + /* Valid range for rsp_count is 0x0002-0xFFFF */ + if (t->rsp_concat_buf.data_size == 0 && rsp_count < 0x0002) { + t->err = EPROTO; + SDPERR("Protocol error: invalid AttrList size"); + status = SDP_INVALID_PDU_SIZE; + goto end; + } /* * Number of bytes in the AttributeLists parameter(without @@ -4171,7 +4262,7 @@ int sdp_process(sdp_session_t *session) status = 0x0000; break; case SDP_ERROR_RSP: - status = ntohs(bt_get_unaligned((uint16_t *) pdata)); + status = bt_get_be16(pdata); size = ntohs(rsphdr->plen); goto end; @@ -4181,9 +4272,20 @@ int sdp_process(sdp_session_t *session) goto end; } + /* Out of bound check before using rsp_count as offset for + * continuation state, which has at least a one byte size + * field. + */ + if ((n - (int) sizeof(sdp_pdu_hdr_t)) < plen + 1) { + t->err = EPROTO; + SDPERR("Protocol error: invalid PDU size"); + status = SDP_INVALID_PDU_SIZE; + goto end; + } + pcstate = (sdp_cstate_t *) (pdata + rsp_count); - SDPDBG("Cstate length : %d\n", pcstate->length); + SDPDBG("Cstate length : %d", pcstate->length); /* * Check out of bound. Continuation state must have at least @@ -4221,7 +4323,7 @@ int sdp_process(sdp_session_t *session) reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); if (sdp_send_req(session, t->reqbuf, reqsize) < 0) { - SDPERR("Error sendind data:%s(%d)", strerror(errno), errno); + SDPERR("Error sendind data:%m(%d)", errno); status = 0xffff; t->err = errno; goto end; @@ -4325,28 +4427,34 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search /* add service class IDs for search */ seqlen = gen_searchseq_pdu(pdata, search); + if (seqlen < 0) { + errno = EINVAL; + status = -1; + goto end; + } - SDPDBG("Data seq added : %d\n", seqlen); + SDPDBG("Data seq added : %d", seqlen); /* now set the length and increment the pointer */ reqsize += seqlen; pdata += seqlen; - bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata); + bt_put_be16(SDP_MAX_ATTR_LEN, pdata); reqsize += sizeof(uint16_t); pdata += sizeof(uint16_t); - SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); + SDPDBG("Max attr byte count : %d", SDP_MAX_ATTR_LEN); /* get attr seq PDU form */ seqlen = gen_attridseq_pdu(pdata, attrids, reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32); if (seqlen == -1) { - status = EINVAL; + errno = EINVAL; + status = -1; goto end; } pdata += seqlen; - SDPDBG("Attr list length : %d\n", seqlen); + SDPDBG("Attr list length : %d", seqlen); reqsize += seqlen; *rsp = 0; @@ -4372,7 +4480,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search } if (status < 0) { - SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); + SDPDBG("Status : 0x%x", rsphdr->pdu_id); goto end; } @@ -4390,7 +4498,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search goto end; } - rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); + rsp_count = bt_get_be16(pdata); attr_list_len += rsp_count; pdata += sizeof(uint16_t); /* pdata points to attribute list */ pdata_len -= sizeof(uint16_t); @@ -4403,9 +4511,9 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search cstate_len = *(uint8_t *) (pdata + rsp_count); - SDPDBG("Attrlist byte count : %d\n", attr_list_len); - SDPDBG("Response byte count : %d\n", rsp_count); - SDPDBG("Cstate length : %d\n", cstate_len); + SDPDBG("Attrlist byte count : %d", attr_list_len); + SDPDBG("Response byte count : %d", rsp_count); + SDPDBG("Cstate length : %d", cstate_len); /* * This is a split response, need to concatenate intermediate * responses and the last one which will have cstate_len == 0 @@ -4439,8 +4547,8 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search */ scanned = sdp_extract_seqtype(pdata, pdata_len, &dataType, &seqlen); - SDPDBG("Bytes scanned : %d\n", scanned); - SDPDBG("Seq length : %d\n", seqlen); + SDPDBG("Bytes scanned : %d", scanned); + SDPDBG("Seq length : %d", seqlen); if (scanned && seqlen) { pdata += scanned; @@ -4449,7 +4557,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search int recsize = 0; sdp_record_t *rec = sdp_extract_pdu(pdata, pdata_len, &recsize); if (rec == NULL) { - SDPERR("SVC REC is null\n"); + SDPERR("SVC REC is null"); status = -1; goto end; } @@ -4461,14 +4569,14 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search pdata += recsize; pdata_len -= recsize; - SDPDBG("Loc seq length : %d\n", recsize); - SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle); - SDPDBG("Bytes scanned : %d\n", scanned); - SDPDBG("Attrlist byte count : %d\n", attr_list_len); + SDPDBG("Loc seq length : %d", recsize); + SDPDBG("Svc Rec Handle : 0x%x", rec->handle); + SDPDBG("Bytes scanned : %d", scanned); + SDPDBG("Attrlist byte count : %d", attr_list_len); rec_list = sdp_list_append(rec_list, rec); } while (scanned < attr_list_len && pdata_len > 0); - SDPDBG("Successful scan of service attr lists\n"); + SDPDBG("Successful scan of service attr lists"); *rsp = rec_list; } } @@ -4486,7 +4594,7 @@ int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *fo { int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0); if (n < 0) { - SDPERR("Inquiry failed:%s", strerror(errno)); + SDPERR("Inquiry failed:%m"); return -1; } *found = n; @@ -4525,7 +4633,7 @@ static int sdp_connect_local(sdp_session_t *session) { struct sockaddr_un sa; - session->sock = socket(PF_UNIX, SOCK_STREAM, 0); + session->sock = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (session->sock < 0) return -1; session->local = 1; @@ -4542,19 +4650,18 @@ static int sdp_connect_l2cap(const bdaddr_t *src, uint32_t flags = session->flags; struct sockaddr_l2 sa; int sk; + int sockflags = SOCK_SEQPACKET | SOCK_CLOEXEC; + + if (flags & SDP_NON_BLOCKING) + sockflags |= SOCK_NONBLOCK; - session->sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + session->sock = socket(PF_BLUETOOTH, sockflags, BTPROTO_L2CAP); if (session->sock < 0) return -1; session->local = 0; sk = session->sock; - if (flags & SDP_NON_BLOCKING) { - long arg = fcntl(sk, F_GETFL, 0); - fcntl(sk, F_SETFL, arg | O_NONBLOCK); - } - memset(&sa, 0, sizeof(sa)); sa.l2_family = AF_BLUETOOTH; @@ -4673,7 +4780,7 @@ int sdp_set_supp_feat(sdp_record_t *rec, const sdp_list_t *sf) goto fail; } for (r = p->data, j = 0; r; r = r->next, j++) { - sdp_data_t *data = (sdp_data_t*)r->data; + sdp_data_t *data = (sdp_data_t *) r->data; dtds[j] = &data->dtd; switch (data->dtd) { case SDP_URL_STR8: @@ -4734,7 +4841,7 @@ int sdp_get_supp_feat(const sdp_record_t *rec, sdp_list_t **seqp) sdpdata = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST); - if (!sdpdata || sdpdata->dtd < SDP_SEQ8 || sdpdata->dtd > SDP_SEQ32) + if (!sdpdata || !SDP_IS_SEQ(sdpdata->dtd)) return sdp_get_uuidseq_attr(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST, seqp); @@ -4742,7 +4849,7 @@ int sdp_get_supp_feat(const sdp_record_t *rec, sdp_list_t **seqp) sdp_data_t *dd; sdp_list_t *subseq; - if (d->dtd < SDP_SEQ8 || d->dtd > SDP_SEQ32) + if (!SDP_IS_SEQ(d->dtd)) goto fail; subseq = NULL; @@ -95,7 +95,7 @@ extern "C" { #define AV_REMOTE_TARGET_SVCLASS_ID 0x110c #define ADVANCED_AUDIO_SVCLASS_ID 0x110d #define AV_REMOTE_SVCLASS_ID 0x110e -#define VIDEO_CONF_SVCLASS_ID 0x110f +#define AV_REMOTE_CONTROLLER_SVCLASS_ID 0x110f #define INTERCOM_SVCLASS_ID 0x1110 #define FAX_SVCLASS_ID 0x1111 #define HEADSET_AGW_SVCLASS_ID 0x1112 @@ -129,6 +129,11 @@ extern "C" { #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 PNP_INFO_SVCLASS_ID 0x1200 #define GENERIC_NETWORKING_SVCLASS_ID 0x1201 #define GENERIC_FILETRANS_SVCLASS_ID 0x1202 @@ -260,12 +265,14 @@ extern "C" { #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_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 @@ -287,6 +294,8 @@ extern "C" { #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_SPECIFICATION_ID 0x0200 #define SDP_ATTR_VENDOR_ID 0x0201 @@ -431,8 +440,12 @@ typedef struct { } value; } uuid_t; -#define SDP_IS_UUID(x) ((x) == SDP_UUID16 || (x) == SDP_UUID32 || (x) ==SDP_UUID128) +#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 { @@ -271,3 +271,8 @@ int bt_string_to_uuid(bt_uuid_t *uuid, const char *string) return -EINVAL; } + +int bt_uuid_strcmp(const void *a, const void *b) +{ + return strcasecmp(a, b); +} @@ -63,26 +63,48 @@ extern "C" { #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 HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" #define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb" -#define GAP_SVC_UUID "00001800-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" + typedef struct { enum { BT_UUID_UNSPEC = 0, @@ -97,6 +119,8 @@ typedef struct { } 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); |