diff options
Diffstat (limited to 'meta/recipes-connectivity')
-rw-r--r-- | meta/recipes-connectivity/bluez5/bluez5.inc | 1 | ||||
-rw-r--r-- | meta/recipes-connectivity/bluez5/bluez5/0002-input-Fix-.device_probe-failing-if-SDP-record-is-not.patch | 313 |
2 files changed, 314 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/bluez5/bluez5.inc b/meta/recipes-connectivity/bluez5/bluez5.inc index e10158a6e5..a23e4e58a6 100644 --- a/meta/recipes-connectivity/bluez5/bluez5.inc +++ b/meta/recipes-connectivity/bluez5/bluez5.inc | |||
@@ -55,6 +55,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/bluetooth/bluez-${PV}.tar.xz \ | |||
55 | file://0001-tests-add-a-target-for-building-tests-without-runnin.patch \ | 55 | file://0001-tests-add-a-target-for-building-tests-without-runnin.patch \ |
56 | file://0001-test-gatt-Fix-hung-issue.patch \ | 56 | file://0001-test-gatt-Fix-hung-issue.patch \ |
57 | file://0004-src-shared-util.c-include-linux-limits.h.patch \ | 57 | file://0004-src-shared-util.c-include-linux-limits.h.patch \ |
58 | file://0002-input-Fix-.device_probe-failing-if-SDP-record-is-not.patch \ | ||
58 | " | 59 | " |
59 | S = "${WORKDIR}/bluez-${PV}" | 60 | S = "${WORKDIR}/bluez-${PV}" |
60 | 61 | ||
diff --git a/meta/recipes-connectivity/bluez5/bluez5/0002-input-Fix-.device_probe-failing-if-SDP-record-is-not.patch b/meta/recipes-connectivity/bluez5/bluez5/0002-input-Fix-.device_probe-failing-if-SDP-record-is-not.patch new file mode 100644 index 0000000000..d0884338db --- /dev/null +++ b/meta/recipes-connectivity/bluez5/bluez5/0002-input-Fix-.device_probe-failing-if-SDP-record-is-not.patch | |||
@@ -0,0 +1,313 @@ | |||
1 | From 3a9c637010f8dc1ba3e8382abe01065761d4f5bb Mon Sep 17 00:00:00 2001 | ||
2 | From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | ||
3 | Date: Tue, 10 Oct 2023 12:38:29 -0700 | ||
4 | Subject: [PATCH 02/40] input: Fix .device_probe failing if SDP record is not | ||
5 | found | ||
6 | |||
7 | Due to changes introduced by 67a26abe53bf | ||
8 | ("profile: Add probe_on_discover flag") profiles may get probed when | ||
9 | their profile UUID are discovered, rather than resolved, which means | ||
10 | the SDP record may not be available. | ||
11 | |||
12 | Fixes: https://github.com/bluez/bluez/issues/614 | ||
13 | |||
14 | Upstream-Status: Backport [https://github.com/bluez/bluez/commit/3a9c637010f8dc1ba3e8382abe01065761d4f5bb] | ||
15 | --- | ||
16 | profiles/input/device.c | 182 +++++++++++++++++++--------------------- | ||
17 | 1 file changed, 84 insertions(+), 98 deletions(-) | ||
18 | |||
19 | diff --git a/profiles/input/device.c b/profiles/input/device.c | ||
20 | index e2ac6ea60..4a50ea992 100644 | ||
21 | --- a/profiles/input/device.c | ||
22 | +++ b/profiles/input/device.c | ||
23 | @@ -60,7 +60,7 @@ struct input_device { | ||
24 | char *path; | ||
25 | bdaddr_t src; | ||
26 | bdaddr_t dst; | ||
27 | - uint32_t handle; | ||
28 | + const sdp_record_t *rec; | ||
29 | GIOChannel *ctrl_io; | ||
30 | GIOChannel *intr_io; | ||
31 | guint ctrl_watch; | ||
32 | @@ -754,7 +754,8 @@ static void epox_endian_quirk(unsigned char *data, int size) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | -static int create_hid_dev_name(sdp_record_t *rec, struct hidp_connadd_req *req) | ||
37 | +static int create_hid_dev_name(const sdp_record_t *rec, | ||
38 | + struct hidp_connadd_req *req) | ||
39 | { | ||
40 | char sdesc[sizeof(req->name) / 2]; | ||
41 | |||
42 | @@ -776,7 +777,7 @@ static int create_hid_dev_name(sdp_record_t *rec, struct hidp_connadd_req *req) | ||
43 | |||
44 | /* See HID profile specification v1.0, "7.11.6 HIDDescriptorList" for details | ||
45 | * on the attribute format. */ | ||
46 | -static int extract_hid_desc_data(sdp_record_t *rec, | ||
47 | +static int extract_hid_desc_data(const sdp_record_t *rec, | ||
48 | struct hidp_connadd_req *req) | ||
49 | { | ||
50 | sdp_data_t *d; | ||
51 | @@ -817,36 +818,40 @@ invalid_desc: | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | -static int extract_hid_record(sdp_record_t *rec, struct hidp_connadd_req *req) | ||
56 | +static int extract_hid_record(struct input_device *idev, | ||
57 | + struct hidp_connadd_req *req) | ||
58 | { | ||
59 | sdp_data_t *pdlist; | ||
60 | uint8_t attr_val; | ||
61 | int err; | ||
62 | |||
63 | - err = create_hid_dev_name(rec, req); | ||
64 | + if (!idev->rec) | ||
65 | + return -ENOENT; | ||
66 | + | ||
67 | + err = create_hid_dev_name(idev->rec, req); | ||
68 | if (err < 0) | ||
69 | DBG("No valid Service Name or Service Description found"); | ||
70 | |||
71 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_PARSER_VERSION); | ||
72 | + pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_PARSER_VERSION); | ||
73 | req->parser = pdlist ? pdlist->val.uint16 : 0x0100; | ||
74 | |||
75 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_DEVICE_SUBCLASS); | ||
76 | + pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_DEVICE_SUBCLASS); | ||
77 | req->subclass = pdlist ? pdlist->val.uint8 : 0; | ||
78 | |||
79 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_COUNTRY_CODE); | ||
80 | + pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_COUNTRY_CODE); | ||
81 | req->country = pdlist ? pdlist->val.uint8 : 0; | ||
82 | |||
83 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_VIRTUAL_CABLE); | ||
84 | + pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_VIRTUAL_CABLE); | ||
85 | attr_val = pdlist ? pdlist->val.uint8 : 0; | ||
86 | if (attr_val) | ||
87 | req->flags |= (1 << HIDP_VIRTUAL_CABLE_UNPLUG); | ||
88 | |||
89 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_BOOT_DEVICE); | ||
90 | + pdlist = sdp_data_get(idev->rec, SDP_ATTR_HID_BOOT_DEVICE); | ||
91 | attr_val = pdlist ? pdlist->val.uint8 : 0; | ||
92 | if (attr_val) | ||
93 | req->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE); | ||
94 | |||
95 | - err = extract_hid_desc_data(rec, req); | ||
96 | + err = extract_hid_desc_data(idev->rec, req); | ||
97 | if (err < 0) | ||
98 | return err; | ||
99 | |||
100 | @@ -1035,11 +1040,6 @@ static gboolean encrypt_notify(GIOChannel *io, GIOCondition condition, | ||
101 | static int hidp_add_connection(struct input_device *idev) | ||
102 | { | ||
103 | struct hidp_connadd_req *req; | ||
104 | - sdp_record_t *rec; | ||
105 | - char src_addr[18], dst_addr[18]; | ||
106 | - char filename[PATH_MAX]; | ||
107 | - GKeyFile *key_file; | ||
108 | - char handle[11], *str; | ||
109 | GError *gerr = NULL; | ||
110 | int err; | ||
111 | |||
112 | @@ -1049,33 +1049,7 @@ static int hidp_add_connection(struct input_device *idev) | ||
113 | req->flags = 0; | ||
114 | req->idle_to = idle_timeout; | ||
115 | |||
116 | - ba2str(&idev->src, src_addr); | ||
117 | - ba2str(&idev->dst, dst_addr); | ||
118 | - | ||
119 | - snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr, | ||
120 | - dst_addr); | ||
121 | - sprintf(handle, "0x%8.8X", idev->handle); | ||
122 | - | ||
123 | - key_file = g_key_file_new(); | ||
124 | - if (!g_key_file_load_from_file(key_file, filename, 0, &gerr)) { | ||
125 | - error("Unable to load key file from %s: (%s)", filename, | ||
126 | - gerr->message); | ||
127 | - g_clear_error(&gerr); | ||
128 | - } | ||
129 | - str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL); | ||
130 | - g_key_file_free(key_file); | ||
131 | - | ||
132 | - if (!str) { | ||
133 | - error("Rejected connection from unknown device %s", dst_addr); | ||
134 | - err = -EPERM; | ||
135 | - goto cleanup; | ||
136 | - } | ||
137 | - | ||
138 | - rec = record_from_string(str); | ||
139 | - g_free(str); | ||
140 | - | ||
141 | - err = extract_hid_record(rec, req); | ||
142 | - sdp_record_free(rec); | ||
143 | + err = extract_hid_record(idev, req); | ||
144 | if (err < 0) { | ||
145 | error("Could not parse HID SDP record: %s (%d)", strerror(-err), | ||
146 | -err); | ||
147 | @@ -1091,7 +1065,7 @@ static int hidp_add_connection(struct input_device *idev) | ||
148 | |||
149 | /* Make sure the device is bonded if required */ | ||
150 | if (classic_bonded_only && !input_device_bonded(idev)) { | ||
151 | - error("Rejected connection from !bonded device %s", dst_addr); | ||
152 | + error("Rejected connection from !bonded device %s", idev->path); | ||
153 | goto cleanup; | ||
154 | } | ||
155 | |||
156 | @@ -1161,6 +1135,68 @@ static int connection_disconnect(struct input_device *idev, uint32_t flags) | ||
157 | return ioctl_disconnect(idev, flags); | ||
158 | } | ||
159 | |||
160 | +static bool is_device_sdp_disable(const sdp_record_t *rec) | ||
161 | +{ | ||
162 | + sdp_data_t *data; | ||
163 | + | ||
164 | + data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE); | ||
165 | + | ||
166 | + return data && data->val.uint8; | ||
167 | +} | ||
168 | + | ||
169 | +static enum reconnect_mode_t hid_reconnection_mode(bool reconnect_initiate, | ||
170 | + bool normally_connectable) | ||
171 | +{ | ||
172 | + if (!reconnect_initiate && !normally_connectable) | ||
173 | + return RECONNECT_NONE; | ||
174 | + else if (!reconnect_initiate && normally_connectable) | ||
175 | + return RECONNECT_HOST; | ||
176 | + else if (reconnect_initiate && !normally_connectable) | ||
177 | + return RECONNECT_DEVICE; | ||
178 | + else /* (reconnect_initiate && normally_connectable) */ | ||
179 | + return RECONNECT_ANY; | ||
180 | +} | ||
181 | + | ||
182 | +static void extract_hid_props(struct input_device *idev, | ||
183 | + const sdp_record_t *rec) | ||
184 | +{ | ||
185 | + /* Extract HID connectability */ | ||
186 | + bool reconnect_initiate, normally_connectable; | ||
187 | + sdp_data_t *pdlist; | ||
188 | + | ||
189 | + /* HIDNormallyConnectable is optional and assumed FALSE if not | ||
190 | + * present. | ||
191 | + */ | ||
192 | + pdlist = sdp_data_get(rec, SDP_ATTR_HID_RECONNECT_INITIATE); | ||
193 | + reconnect_initiate = pdlist ? pdlist->val.uint8 : TRUE; | ||
194 | + | ||
195 | + pdlist = sdp_data_get(rec, SDP_ATTR_HID_NORMALLY_CONNECTABLE); | ||
196 | + normally_connectable = pdlist ? pdlist->val.uint8 : FALSE; | ||
197 | + | ||
198 | + /* Update local values */ | ||
199 | + idev->reconnect_mode = | ||
200 | + hid_reconnection_mode(reconnect_initiate, normally_connectable); | ||
201 | +} | ||
202 | + | ||
203 | +static void input_device_update_rec(struct input_device *idev) | ||
204 | +{ | ||
205 | + struct btd_profile *p = btd_service_get_profile(idev->service); | ||
206 | + const sdp_record_t *rec; | ||
207 | + | ||
208 | + rec = btd_device_get_record(idev->device, p->remote_uuid); | ||
209 | + if (!rec || idev->rec == rec) | ||
210 | + return; | ||
211 | + | ||
212 | + idev->rec = rec; | ||
213 | + idev->disable_sdp = is_device_sdp_disable(rec); | ||
214 | + | ||
215 | + /* Initialize device properties */ | ||
216 | + extract_hid_props(idev, rec); | ||
217 | + | ||
218 | + if (idev->disable_sdp) | ||
219 | + device_set_refresh_discovery(idev->device, false); | ||
220 | +} | ||
221 | + | ||
222 | static int input_device_connected(struct input_device *idev) | ||
223 | { | ||
224 | int err; | ||
225 | @@ -1168,6 +1204,9 @@ static int input_device_connected(struct input_device *idev) | ||
226 | if (idev->intr_io == NULL || idev->ctrl_io == NULL) | ||
227 | return -ENOTCONN; | ||
228 | |||
229 | + /* Attempt to update SDP record if it had changed */ | ||
230 | + input_device_update_rec(idev); | ||
231 | + | ||
232 | err = hidp_add_connection(idev); | ||
233 | if (err < 0) | ||
234 | return err; | ||
235 | @@ -1411,74 +1450,21 @@ int input_device_disconnect(struct btd_service *service) | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | -static bool is_device_sdp_disable(const sdp_record_t *rec) | ||
240 | -{ | ||
241 | - sdp_data_t *data; | ||
242 | - | ||
243 | - data = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE); | ||
244 | - | ||
245 | - return data && data->val.uint8; | ||
246 | -} | ||
247 | - | ||
248 | -static enum reconnect_mode_t hid_reconnection_mode(bool reconnect_initiate, | ||
249 | - bool normally_connectable) | ||
250 | -{ | ||
251 | - if (!reconnect_initiate && !normally_connectable) | ||
252 | - return RECONNECT_NONE; | ||
253 | - else if (!reconnect_initiate && normally_connectable) | ||
254 | - return RECONNECT_HOST; | ||
255 | - else if (reconnect_initiate && !normally_connectable) | ||
256 | - return RECONNECT_DEVICE; | ||
257 | - else /* (reconnect_initiate && normally_connectable) */ | ||
258 | - return RECONNECT_ANY; | ||
259 | -} | ||
260 | - | ||
261 | -static void extract_hid_props(struct input_device *idev, | ||
262 | - const sdp_record_t *rec) | ||
263 | -{ | ||
264 | - /* Extract HID connectability */ | ||
265 | - bool reconnect_initiate, normally_connectable; | ||
266 | - sdp_data_t *pdlist; | ||
267 | - | ||
268 | - /* HIDNormallyConnectable is optional and assumed FALSE | ||
269 | - * if not present. */ | ||
270 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_RECONNECT_INITIATE); | ||
271 | - reconnect_initiate = pdlist ? pdlist->val.uint8 : TRUE; | ||
272 | - | ||
273 | - pdlist = sdp_data_get(rec, SDP_ATTR_HID_NORMALLY_CONNECTABLE); | ||
274 | - normally_connectable = pdlist ? pdlist->val.uint8 : FALSE; | ||
275 | - | ||
276 | - /* Update local values */ | ||
277 | - idev->reconnect_mode = | ||
278 | - hid_reconnection_mode(reconnect_initiate, normally_connectable); | ||
279 | -} | ||
280 | - | ||
281 | static struct input_device *input_device_new(struct btd_service *service) | ||
282 | { | ||
283 | struct btd_device *device = btd_service_get_device(service); | ||
284 | - struct btd_profile *p = btd_service_get_profile(service); | ||
285 | const char *path = device_get_path(device); | ||
286 | - const sdp_record_t *rec = btd_device_get_record(device, p->remote_uuid); | ||
287 | struct btd_adapter *adapter = device_get_adapter(device); | ||
288 | struct input_device *idev; | ||
289 | |||
290 | - if (!rec) | ||
291 | - return NULL; | ||
292 | - | ||
293 | idev = g_new0(struct input_device, 1); | ||
294 | bacpy(&idev->src, btd_adapter_get_address(adapter)); | ||
295 | bacpy(&idev->dst, device_get_address(device)); | ||
296 | idev->service = btd_service_ref(service); | ||
297 | idev->device = btd_device_ref(device); | ||
298 | idev->path = g_strdup(path); | ||
299 | - idev->handle = rec->handle; | ||
300 | - idev->disable_sdp = is_device_sdp_disable(rec); | ||
301 | - | ||
302 | - /* Initialize device properties */ | ||
303 | - extract_hid_props(idev, rec); | ||
304 | |||
305 | - if (idev->disable_sdp) | ||
306 | - device_set_refresh_discovery(device, false); | ||
307 | + input_device_update_rec(idev); | ||
308 | |||
309 | return idev; | ||
310 | } | ||
311 | -- | ||
312 | 2.42.0 | ||
313 | |||