summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWu zheng <wu.zheng@intel.com>2013-10-23 10:59:15 +0800
committerWu zheng <wu.zheng@intel.com>2013-10-23 10:59:15 +0800
commit7b2a18f8fa9ca2a101244853e34bd44f9ce3b0a3 (patch)
tree38610dbb3a2920b9f57fc7638e0efed820a3acb9 /lib
parent71235d13fb107f879369e64385d8c97de0bb840e (diff)
downloadbluez-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.h38
-rw-r--r--lib/amp.h172
-rw-r--r--lib/bluetooth.c271
-rw-r--r--lib/bluetooth.h71
-rw-r--r--lib/bluez.pc.in10
-rw-r--r--lib/hci.c23
-rw-r--r--lib/hci.h71
-rw-r--r--lib/hci_lib.h2
-rw-r--r--lib/mgmt.h42
-rw-r--r--lib/sdp.c603
-rw-r--r--lib/sdp.h17
-rw-r--r--lib/uuid.c5
-rw-r--r--lib/uuid.h28
13 files changed, 1017 insertions, 336 deletions
diff --git a/lib/a2mp.h b/lib/a2mp.h
index 61f1c1e4..da937d13 100644
--- a/lib/a2mp.h
+++ b/lib/a2mp.h
@@ -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}
diff --git a/lib/hci.c b/lib/hci.c
index 66b2d5f0..6e378367 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -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;
diff --git a/lib/hci.h b/lib/hci.h
index f7be92df..0c948296 100644
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -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);
diff --git a/lib/mgmt.h b/lib/mgmt.h
index a58915b2..a896e523 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -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
diff --git a/lib/sdp.c b/lib/sdp.c
index 7cb930fc..cbdf15e5 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -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;
diff --git a/lib/sdp.h b/lib/sdp.h
index 2fe74d54..f2f24848 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -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 {
diff --git a/lib/uuid.c b/lib/uuid.c
index a3e2a1ad..4363aee4 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -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);
+}
diff --git a/lib/uuid.h b/lib/uuid.h
index 2c2b3511..95e5a9a8 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -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);