| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: hci_event.c,v 1.22 2010/11/22 19:56:51 plunky Exp $ */ | | 1 | /* $NetBSD: hci_event.c,v 1.23 2011/07/27 10:25:09 plunky Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2005 Iain Hibbert. | | 4 | * Copyright (c) 2005 Iain Hibbert. |
5 | * Copyright (c) 2006 Itronix Inc. | | 5 | * Copyright (c) 2006 Itronix Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY |
24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 24 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | | 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
27 | * ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.22 2010/11/22 19:56:51 plunky Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.23 2011/07/27 10:25:09 plunky Exp $"); |
35 | | | 35 | |
36 | #include <sys/param.h> | | 36 | #include <sys/param.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | #include <sys/malloc.h> | | 38 | #include <sys/malloc.h> |
39 | #include <sys/mbuf.h> | | 39 | #include <sys/mbuf.h> |
40 | #include <sys/proc.h> | | 40 | #include <sys/proc.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
42 | | | 42 | |
43 | #include <netbt/bluetooth.h> | | 43 | #include <netbt/bluetooth.h> |
44 | #include <netbt/hci.h> | | 44 | #include <netbt/hci.h> |
45 | #include <netbt/sco.h> | | 45 | #include <netbt/sco.h> |
46 | | | 46 | |
47 | static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *); | | 47 | static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *); |
| @@ -147,41 +147,44 @@ hci_eventstr(unsigned int event) | | | @@ -147,41 +147,44 @@ hci_eventstr(unsigned int event) |
147 | | | 147 | |
148 | case HCI_EVENT_VENDOR: /* 0xff */ | | 148 | case HCI_EVENT_VENDOR: /* 0xff */ |
149 | return "VENDOR"; | | 149 | return "VENDOR"; |
150 | } | | 150 | } |
151 | | | 151 | |
152 | return "UNKNOWN"; | | 152 | return "UNKNOWN"; |
153 | } | | 153 | } |
154 | #endif /* BLUETOOTH_DEBUG */ | | 154 | #endif /* BLUETOOTH_DEBUG */ |
155 | | | 155 | |
156 | /* | | 156 | /* |
157 | * process HCI Events | | 157 | * process HCI Events |
158 | * | | 158 | * |
159 | * We will free the mbuf at the end, no need for any sub | | 159 | * We will free the mbuf at the end, no need for any sub |
160 | * functions to handle that. We kind of assume that the | | 160 | * functions to handle that. |
161 | * device sends us valid events. | | | |
162 | */ | | 161 | */ |
163 | void | | 162 | void |
164 | hci_event(struct mbuf *m, struct hci_unit *unit) | | 163 | hci_event(struct mbuf *m, struct hci_unit *unit) |
165 | { | | 164 | { |
166 | hci_event_hdr_t hdr; | | 165 | hci_event_hdr_t hdr; |
167 | | | 166 | |
168 | KASSERT(m->m_flags & M_PKTHDR); | | 167 | KASSERT(m->m_flags & M_PKTHDR); |
169 | | | 168 | |
170 | KASSERT(m->m_pkthdr.len >= sizeof(hdr)); | | 169 | if (m->m_pkthdr.len < sizeof(hdr)) |
| | | 170 | goto done; |
| | | 171 | |
171 | m_copydata(m, 0, sizeof(hdr), &hdr); | | 172 | m_copydata(m, 0, sizeof(hdr), &hdr); |
172 | m_adj(m, sizeof(hdr)); | | 173 | m_adj(m, sizeof(hdr)); |
173 | | | 174 | |
174 | KASSERT(hdr.type == HCI_EVENT_PKT); | | 175 | KASSERT(hdr.type == HCI_EVENT_PKT); |
| | | 176 | if (m->m_pkthdr.len != hdr.length) |
| | | 177 | goto done; |
175 | | | 178 | |
176 | DPRINTFN(1, "(%s) event %s\n", | | 179 | DPRINTFN(1, "(%s) event %s\n", |
177 | device_xname(unit->hci_dev), hci_eventstr(hdr.event)); | | 180 | device_xname(unit->hci_dev), hci_eventstr(hdr.event)); |
178 | | | 181 | |
179 | switch(hdr.event) { | | 182 | switch(hdr.event) { |
180 | case HCI_EVENT_COMMAND_STATUS: | | 183 | case HCI_EVENT_COMMAND_STATUS: |
181 | hci_event_command_status(unit, m); | | 184 | hci_event_command_status(unit, m); |
182 | break; | | 185 | break; |
183 | | | 186 | |
184 | case HCI_EVENT_COMMAND_COMPL: | | 187 | case HCI_EVENT_COMMAND_COMPL: |
185 | hci_event_command_compl(unit, m); | | 188 | hci_event_command_compl(unit, m); |
186 | break; | | 189 | break; |
187 | | | 190 | |
| @@ -223,40 +226,43 @@ hci_event(struct mbuf *m, struct hci_uni | | | @@ -223,40 +226,43 @@ hci_event(struct mbuf *m, struct hci_uni |
223 | | | 226 | |
224 | case HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL: | | 227 | case HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL: |
225 | hci_event_change_con_link_key_compl(unit, m); | | 228 | hci_event_change_con_link_key_compl(unit, m); |
226 | break; | | 229 | break; |
227 | | | 230 | |
228 | case HCI_EVENT_READ_CLOCK_OFFSET_COMPL: | | 231 | case HCI_EVENT_READ_CLOCK_OFFSET_COMPL: |
229 | hci_event_read_clock_offset_compl(unit, m); | | 232 | hci_event_read_clock_offset_compl(unit, m); |
230 | break; | | 233 | break; |
231 | | | 234 | |
232 | default: | | 235 | default: |
233 | break; | | 236 | break; |
234 | } | | 237 | } |
235 | | | 238 | |
| | | 239 | done: |
236 | m_freem(m); | | 240 | m_freem(m); |
237 | } | | 241 | } |
238 | | | 242 | |
239 | /* | | 243 | /* |
240 | * Command Status | | 244 | * Command Status |
241 | * | | 245 | * |
242 | * Restart command queue and post-process any pending commands | | 246 | * Restart command queue and post-process any pending commands |
243 | */ | | 247 | */ |
244 | static void | | 248 | static void |
245 | hci_event_command_status(struct hci_unit *unit, struct mbuf *m) | | 249 | hci_event_command_status(struct hci_unit *unit, struct mbuf *m) |
246 | { | | 250 | { |
247 | hci_command_status_ep ep; | | 251 | hci_command_status_ep ep; |
248 | | | 252 | |
249 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 253 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 254 | return; |
| | | 255 | |
250 | m_copydata(m, 0, sizeof(ep), &ep); | | 256 | m_copydata(m, 0, sizeof(ep), &ep); |
251 | m_adj(m, sizeof(ep)); | | 257 | m_adj(m, sizeof(ep)); |
252 | | | 258 | |
253 | ep.opcode = le16toh(ep.opcode); | | 259 | ep.opcode = le16toh(ep.opcode); |
254 | | | 260 | |
255 | DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n", | | 261 | DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n", |
256 | device_xname(unit->hci_dev), | | 262 | device_xname(unit->hci_dev), |
257 | HCI_OGF(ep.opcode), HCI_OCF(ep.opcode), | | 263 | HCI_OGF(ep.opcode), HCI_OCF(ep.opcode), |
258 | ep.status, | | 264 | ep.status, |
259 | ep.num_cmd_pkts); | | 265 | ep.num_cmd_pkts); |
260 | | | 266 | |
261 | hci_num_cmds(unit, ep.num_cmd_pkts); | | 267 | hci_num_cmds(unit, ep.num_cmd_pkts); |
262 | | | 268 | |
| @@ -282,27 +288,29 @@ hci_event_command_status(struct hci_unit | | | @@ -282,27 +288,29 @@ hci_event_command_status(struct hci_unit |
282 | } | | 288 | } |
283 | | | 289 | |
284 | /* | | 290 | /* |
285 | * Command Complete | | 291 | * Command Complete |
286 | * | | 292 | * |
287 | * Restart command queue and handle the completed command | | 293 | * Restart command queue and handle the completed command |
288 | */ | | 294 | */ |
289 | static void | | 295 | static void |
290 | hci_event_command_compl(struct hci_unit *unit, struct mbuf *m) | | 296 | hci_event_command_compl(struct hci_unit *unit, struct mbuf *m) |
291 | { | | 297 | { |
292 | hci_command_compl_ep ep; | | 298 | hci_command_compl_ep ep; |
293 | hci_status_rp rp; | | 299 | hci_status_rp rp; |
294 | | | 300 | |
295 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 301 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 302 | return; |
| | | 303 | |
296 | m_copydata(m, 0, sizeof(ep), &ep); | | 304 | m_copydata(m, 0, sizeof(ep), &ep); |
297 | m_adj(m, sizeof(ep)); | | 305 | m_adj(m, sizeof(ep)); |
298 | | | 306 | |
299 | DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n", | | 307 | DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n", |
300 | device_xname(unit->hci_dev), | | 308 | device_xname(unit->hci_dev), |
301 | HCI_OGF(le16toh(ep.opcode)), HCI_OCF(le16toh(ep.opcode)), | | 309 | HCI_OGF(le16toh(ep.opcode)), HCI_OCF(le16toh(ep.opcode)), |
302 | ep.num_cmd_pkts); | | 310 | ep.num_cmd_pkts); |
303 | | | 311 | |
304 | hci_num_cmds(unit, ep.num_cmd_pkts); | | 312 | hci_num_cmds(unit, ep.num_cmd_pkts); |
305 | | | 313 | |
306 | /* | | 314 | /* |
307 | * I am not sure if this is completely correct, it is not guaranteed | | 315 | * I am not sure if this is completely correct, it is not guaranteed |
308 | * that a command_complete packet will contain the status though most | | 316 | * that a command_complete packet will contain the status though most |
| @@ -359,27 +367,29 @@ hci_event_command_compl(struct hci_unit | | | @@ -359,27 +367,29 @@ hci_event_command_compl(struct hci_unit |
359 | * buffers are now freed up and which handle was using them. From | | 367 | * buffers are now freed up and which handle was using them. From |
360 | * this we determine which type of buffer it was and add the qty | | 368 | * this we determine which type of buffer it was and add the qty |
361 | * back into the relevant packet counter, then restart output on | | 369 | * back into the relevant packet counter, then restart output on |
362 | * links that have halted. | | 370 | * links that have halted. |
363 | */ | | 371 | */ |
364 | static void | | 372 | static void |
365 | hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m) | | 373 | hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m) |
366 | { | | 374 | { |
367 | hci_num_compl_pkts_ep ep; | | 375 | hci_num_compl_pkts_ep ep; |
368 | struct hci_link *link, *next; | | 376 | struct hci_link *link, *next; |
369 | uint16_t handle, num; | | 377 | uint16_t handle, num; |
370 | int num_acl = 0, num_sco = 0; | | 378 | int num_acl = 0, num_sco = 0; |
371 | | | 379 | |
372 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 380 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 381 | return; |
| | | 382 | |
373 | m_copydata(m, 0, sizeof(ep), &ep); | | 383 | m_copydata(m, 0, sizeof(ep), &ep); |
374 | m_adj(m, sizeof(ep)); | | 384 | m_adj(m, sizeof(ep)); |
375 | | | 385 | |
376 | while (ep.num_con_handles--) { | | 386 | while (ep.num_con_handles--) { |
377 | m_copydata(m, 0, sizeof(handle), &handle); | | 387 | m_copydata(m, 0, sizeof(handle), &handle); |
378 | m_adj(m, sizeof(handle)); | | 388 | m_adj(m, sizeof(handle)); |
379 | handle = le16toh(handle); | | 389 | handle = le16toh(handle); |
380 | | | 390 | |
381 | m_copydata(m, 0, sizeof(num), &num); | | 391 | m_copydata(m, 0, sizeof(num), &num); |
382 | m_adj(m, sizeof(num)); | | 392 | m_adj(m, sizeof(num)); |
383 | num = le16toh(num); | | 393 | num = le16toh(num); |
384 | | | 394 | |
385 | link = hci_link_lookup_handle(unit, handle); | | 395 | link = hci_link_lookup_handle(unit, handle); |
| @@ -429,35 +439,39 @@ hci_event_num_compl_pkts(struct hci_unit | | | @@ -429,35 +439,39 @@ hci_event_num_compl_pkts(struct hci_unit |
429 | /* | | 439 | /* |
430 | * Inquiry Result | | 440 | * Inquiry Result |
431 | * | | 441 | * |
432 | * keep a note of devices seen, so we know which unit to use | | 442 | * keep a note of devices seen, so we know which unit to use |
433 | * on outgoing connections | | 443 | * on outgoing connections |
434 | */ | | 444 | */ |
435 | static void | | 445 | static void |
436 | hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m) | | 446 | hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m) |
437 | { | | 447 | { |
438 | hci_inquiry_result_ep ep; | | 448 | hci_inquiry_result_ep ep; |
439 | hci_inquiry_response ir; | | 449 | hci_inquiry_response ir; |
440 | struct hci_memo *memo; | | 450 | struct hci_memo *memo; |
441 | | | 451 | |
442 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 452 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 453 | return; |
| | | 454 | |
443 | m_copydata(m, 0, sizeof(ep), &ep); | | 455 | m_copydata(m, 0, sizeof(ep), &ep); |
444 | m_adj(m, sizeof(ep)); | | 456 | m_adj(m, sizeof(ep)); |
445 | | | 457 | |
446 | DPRINTFN(1, "%d response%s\n", ep.num_responses, | | 458 | DPRINTFN(1, "%d response%s\n", ep.num_responses, |
447 | (ep.num_responses == 1 ? "" : "s")); | | 459 | (ep.num_responses == 1 ? "" : "s")); |
448 | | | 460 | |
449 | while(ep.num_responses--) { | | 461 | while(ep.num_responses--) { |
450 | KASSERT(m->m_pkthdr.len >= sizeof(ir)); | | 462 | if (m->m_pkthdr.len < sizeof(ir)) |
| | | 463 | return; |
| | | 464 | |
451 | m_copydata(m, 0, sizeof(ir), &ir); | | 465 | m_copydata(m, 0, sizeof(ir), &ir); |
452 | m_adj(m, sizeof(ir)); | | 466 | m_adj(m, sizeof(ir)); |
453 | | | 467 | |
454 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", | | 468 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", |
455 | ir.bdaddr.b[5], ir.bdaddr.b[4], ir.bdaddr.b[3], | | 469 | ir.bdaddr.b[5], ir.bdaddr.b[4], ir.bdaddr.b[3], |
456 | ir.bdaddr.b[2], ir.bdaddr.b[1], ir.bdaddr.b[0]); | | 470 | ir.bdaddr.b[2], ir.bdaddr.b[1], ir.bdaddr.b[0]); |
457 | | | 471 | |
458 | memo = hci_memo_new(unit, &ir.bdaddr); | | 472 | memo = hci_memo_new(unit, &ir.bdaddr); |
459 | if (memo != NULL) { | | 473 | if (memo != NULL) { |
460 | memo->page_scan_rep_mode = ir.page_scan_rep_mode; | | 474 | memo->page_scan_rep_mode = ir.page_scan_rep_mode; |
461 | memo->page_scan_mode = ir.page_scan_mode; | | 475 | memo->page_scan_mode = ir.page_scan_mode; |
462 | memo->clock_offset = ir.clock_offset; | | 476 | memo->clock_offset = ir.clock_offset; |
463 | } | | 477 | } |
| @@ -466,35 +480,39 @@ hci_event_inquiry_result(struct hci_unit | | | @@ -466,35 +480,39 @@ hci_event_inquiry_result(struct hci_unit |
466 | | | 480 | |
467 | /* | | 481 | /* |
468 | * Inquiry Result with RSSI | | 482 | * Inquiry Result with RSSI |
469 | * | | 483 | * |
470 | * as above but different packet when RSSI result is enabled | | 484 | * as above but different packet when RSSI result is enabled |
471 | */ | | 485 | */ |
472 | static void | | 486 | static void |
473 | hci_event_rssi_result(struct hci_unit *unit, struct mbuf *m) | | 487 | hci_event_rssi_result(struct hci_unit *unit, struct mbuf *m) |
474 | { | | 488 | { |
475 | hci_rssi_result_ep ep; | | 489 | hci_rssi_result_ep ep; |
476 | hci_rssi_response rr; | | 490 | hci_rssi_response rr; |
477 | struct hci_memo *memo; | | 491 | struct hci_memo *memo; |
478 | | | 492 | |
479 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 493 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 494 | return; |
| | | 495 | |
480 | m_copydata(m, 0, sizeof(ep), &ep); | | 496 | m_copydata(m, 0, sizeof(ep), &ep); |
481 | m_adj(m, sizeof(ep)); | | 497 | m_adj(m, sizeof(ep)); |
482 | | | 498 | |
483 | DPRINTFN(1, "%d response%s\n", ep.num_responses, | | 499 | DPRINTFN(1, "%d response%s\n", ep.num_responses, |
484 | (ep.num_responses == 1 ? "" : "s")); | | 500 | (ep.num_responses == 1 ? "" : "s")); |
485 | | | 501 | |
486 | while(ep.num_responses--) { | | 502 | while(ep.num_responses--) { |
487 | KASSERT(m->m_pkthdr.len >= sizeof(rr)); | | 503 | if (m->m_pkthdr.len < sizeof(rr)) |
| | | 504 | return; |
| | | 505 | |
488 | m_copydata(m, 0, sizeof(rr), &rr); | | 506 | m_copydata(m, 0, sizeof(rr), &rr); |
489 | m_adj(m, sizeof(rr)); | | 507 | m_adj(m, sizeof(rr)); |
490 | | | 508 | |
491 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", | | 509 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", |
492 | rr.bdaddr.b[5], rr.bdaddr.b[4], rr.bdaddr.b[3], | | 510 | rr.bdaddr.b[5], rr.bdaddr.b[4], rr.bdaddr.b[3], |
493 | rr.bdaddr.b[2], rr.bdaddr.b[1], rr.bdaddr.b[0]); | | 511 | rr.bdaddr.b[2], rr.bdaddr.b[1], rr.bdaddr.b[0]); |
494 | | | 512 | |
495 | memo = hci_memo_new(unit, &rr.bdaddr); | | 513 | memo = hci_memo_new(unit, &rr.bdaddr); |
496 | if (memo != NULL) { | | 514 | if (memo != NULL) { |
497 | memo->page_scan_rep_mode = rr.page_scan_rep_mode; | | 515 | memo->page_scan_rep_mode = rr.page_scan_rep_mode; |
498 | memo->page_scan_mode = 0; | | 516 | memo->page_scan_mode = 0; |
499 | memo->clock_offset = rr.clock_offset; | | 517 | memo->clock_offset = rr.clock_offset; |
500 | } | | 518 | } |
| @@ -502,27 +520,29 @@ hci_event_rssi_result(struct hci_unit *u | | | @@ -502,27 +520,29 @@ hci_event_rssi_result(struct hci_unit *u |
502 | } | | 520 | } |
503 | | | 521 | |
504 | /* | | 522 | /* |
505 | * Extended Inquiry Result | | 523 | * Extended Inquiry Result |
506 | * | | 524 | * |
507 | * as above but provides only one response and extended service info | | 525 | * as above but provides only one response and extended service info |
508 | */ | | 526 | */ |
509 | static void | | 527 | static void |
510 | hci_event_extended_result(struct hci_unit *unit, struct mbuf *m) | | 528 | hci_event_extended_result(struct hci_unit *unit, struct mbuf *m) |
511 | { | | 529 | { |
512 | hci_extended_result_ep ep; | | 530 | hci_extended_result_ep ep; |
513 | struct hci_memo *memo; | | 531 | struct hci_memo *memo; |
514 | | | 532 | |
515 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 533 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 534 | return; |
| | | 535 | |
516 | m_copydata(m, 0, sizeof(ep), &ep); | | 536 | m_copydata(m, 0, sizeof(ep), &ep); |
517 | m_adj(m, sizeof(ep)); | | 537 | m_adj(m, sizeof(ep)); |
518 | | | 538 | |
519 | if (ep.num_responses != 1) | | 539 | if (ep.num_responses != 1) |
520 | return; | | 540 | return; |
521 | | | 541 | |
522 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", | | 542 | DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n", |
523 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], | | 543 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], |
524 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0]); | | 544 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0]); |
525 | | | 545 | |
526 | memo = hci_memo_new(unit, &ep.bdaddr); | | 546 | memo = hci_memo_new(unit, &ep.bdaddr); |
527 | if (memo != NULL) { | | 547 | if (memo != NULL) { |
528 | memo->page_scan_rep_mode = ep.page_scan_rep_mode; | | 548 | memo->page_scan_rep_mode = ep.page_scan_rep_mode; |
| @@ -536,27 +556,29 @@ hci_event_extended_result(struct hci_uni | | | @@ -536,27 +556,29 @@ hci_event_extended_result(struct hci_uni |
536 | * | | 556 | * |
537 | * Sent to us when a connection is made. If there is no link | | 557 | * Sent to us when a connection is made. If there is no link |
538 | * structure already allocated for this, we must have changed | | 558 | * structure already allocated for this, we must have changed |
539 | * our mind, so just disconnect. | | 559 | * our mind, so just disconnect. |
540 | */ | | 560 | */ |
541 | static void | | 561 | static void |
542 | hci_event_con_compl(struct hci_unit *unit, struct mbuf *m) | | 562 | hci_event_con_compl(struct hci_unit *unit, struct mbuf *m) |
543 | { | | 563 | { |
544 | hci_con_compl_ep ep; | | 564 | hci_con_compl_ep ep; |
545 | hci_write_link_policy_settings_cp cp; | | 565 | hci_write_link_policy_settings_cp cp; |
546 | struct hci_link *link; | | 566 | struct hci_link *link; |
547 | int err; | | 567 | int err; |
548 | | | 568 | |
549 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 569 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 570 | return; |
| | | 571 | |
550 | m_copydata(m, 0, sizeof(ep), &ep); | | 572 | m_copydata(m, 0, sizeof(ep), &ep); |
551 | m_adj(m, sizeof(ep)); | | 573 | m_adj(m, sizeof(ep)); |
552 | | | 574 | |
553 | DPRINTFN(1, "(%s) %s connection complete for " | | 575 | DPRINTFN(1, "(%s) %s connection complete for " |
554 | "%02x:%02x:%02x:%02x:%02x:%02x status %#x\n", | | 576 | "%02x:%02x:%02x:%02x:%02x:%02x status %#x\n", |
555 | device_xname(unit->hci_dev), | | 577 | device_xname(unit->hci_dev), |
556 | (ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"), | | 578 | (ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"), |
557 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], | | 579 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], |
558 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0], | | 580 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0], |
559 | ep.status); | | 581 | ep.status); |
560 | | | 582 | |
561 | link = hci_link_lookup_bdaddr(unit, &ep.bdaddr, ep.link_type); | | 583 | link = hci_link_lookup_bdaddr(unit, &ep.bdaddr, ep.link_type); |
562 | | | 584 | |
| @@ -631,54 +653,58 @@ hci_event_con_compl(struct hci_unit *uni | | | @@ -631,54 +653,58 @@ hci_event_con_compl(struct hci_unit *uni |
631 | | | 653 | |
632 | /* | | 654 | /* |
633 | * Disconnection Complete | | 655 | * Disconnection Complete |
634 | * | | 656 | * |
635 | * This is sent in response to a disconnection request, but also if | | 657 | * This is sent in response to a disconnection request, but also if |
636 | * the remote device goes out of range. | | 658 | * the remote device goes out of range. |
637 | */ | | 659 | */ |
638 | static void | | 660 | static void |
639 | hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m) | | 661 | hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m) |
640 | { | | 662 | { |
641 | hci_discon_compl_ep ep; | | 663 | hci_discon_compl_ep ep; |
642 | struct hci_link *link; | | 664 | struct hci_link *link; |
643 | | | 665 | |
644 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 666 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 667 | return; |
| | | 668 | |
645 | m_copydata(m, 0, sizeof(ep), &ep); | | 669 | m_copydata(m, 0, sizeof(ep), &ep); |
646 | m_adj(m, sizeof(ep)); | | 670 | m_adj(m, sizeof(ep)); |
647 | | | 671 | |
648 | ep.con_handle = le16toh(ep.con_handle); | | 672 | ep.con_handle = le16toh(ep.con_handle); |
649 | | | 673 | |
650 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); | | 674 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); |
651 | | | 675 | |
652 | link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle)); | | 676 | link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle)); |
653 | if (link) | | 677 | if (link) |
654 | hci_link_free(link, ENOLINK); | | 678 | hci_link_free(link, ENOLINK); |
655 | } | | 679 | } |
656 | | | 680 | |
657 | /* | | 681 | /* |
658 | * Connect Request | | 682 | * Connect Request |
659 | * | | 683 | * |
660 | * We check upstream for appropriate listeners and accept connections | | 684 | * We check upstream for appropriate listeners and accept connections |
661 | * that are wanted. | | 685 | * that are wanted. |
662 | */ | | 686 | */ |
663 | static void | | 687 | static void |
664 | hci_event_con_req(struct hci_unit *unit, struct mbuf *m) | | 688 | hci_event_con_req(struct hci_unit *unit, struct mbuf *m) |
665 | { | | 689 | { |
666 | hci_con_req_ep ep; | | 690 | hci_con_req_ep ep; |
667 | hci_accept_con_cp ap; | | 691 | hci_accept_con_cp ap; |
668 | hci_reject_con_cp rp; | | 692 | hci_reject_con_cp rp; |
669 | struct hci_link *link; | | 693 | struct hci_link *link; |
670 | | | 694 | |
671 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 695 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 696 | return; |
| | | 697 | |
672 | m_copydata(m, 0, sizeof(ep), &ep); | | 698 | m_copydata(m, 0, sizeof(ep), &ep); |
673 | m_adj(m, sizeof(ep)); | | 699 | m_adj(m, sizeof(ep)); |
674 | | | 700 | |
675 | DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " | | 701 | DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " |
676 | "class %2.2x%2.2x%2.2x type %s\n", | | 702 | "class %2.2x%2.2x%2.2x type %s\n", |
677 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], | | 703 | ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3], |
678 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0], | | 704 | ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0], |
679 | ep.uclass[0], ep.uclass[1], ep.uclass[2], | | 705 | ep.uclass[0], ep.uclass[1], ep.uclass[2], |
680 | ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"); | | 706 | ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"); |
681 | | | 707 | |
682 | if (ep.link_type == HCI_LINK_ACL) | | 708 | if (ep.link_type == HCI_LINK_ACL) |
683 | link = hci_acl_newconn(unit, &ep.bdaddr); | | 709 | link = hci_acl_newconn(unit, &ep.bdaddr); |
684 | else | | 710 | else |
| @@ -705,27 +731,29 @@ hci_event_con_req(struct hci_unit *unit, | | | @@ -705,27 +731,29 @@ hci_event_con_req(struct hci_unit *unit, |
705 | /* | | 731 | /* |
706 | * Auth Complete | | 732 | * Auth Complete |
707 | * | | 733 | * |
708 | * Authentication has been completed on an ACL link. We can notify the | | 734 | * Authentication has been completed on an ACL link. We can notify the |
709 | * upper layer protocols unless further mode changes are pending. | | 735 | * upper layer protocols unless further mode changes are pending. |
710 | */ | | 736 | */ |
711 | static void | | 737 | static void |
712 | hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m) | | 738 | hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m) |
713 | { | | 739 | { |
714 | hci_auth_compl_ep ep; | | 740 | hci_auth_compl_ep ep; |
715 | struct hci_link *link; | | 741 | struct hci_link *link; |
716 | int err; | | 742 | int err; |
717 | | | 743 | |
718 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 744 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 745 | return; |
| | | 746 | |
719 | m_copydata(m, 0, sizeof(ep), &ep); | | 747 | m_copydata(m, 0, sizeof(ep), &ep); |
720 | m_adj(m, sizeof(ep)); | | 748 | m_adj(m, sizeof(ep)); |
721 | | | 749 | |
722 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); | | 750 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); |
723 | | | 751 | |
724 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); | | 752 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); |
725 | | | 753 | |
726 | link = hci_link_lookup_handle(unit, ep.con_handle); | | 754 | link = hci_link_lookup_handle(unit, ep.con_handle); |
727 | if (link == NULL || link->hl_type != HCI_LINK_ACL) | | 755 | if (link == NULL || link->hl_type != HCI_LINK_ACL) |
728 | return; | | 756 | return; |
729 | | | 757 | |
730 | if (ep.status == 0) { | | 758 | if (ep.status == 0) { |
731 | link->hl_flags |= HCI_LINK_AUTH; | | 759 | link->hl_flags |= HCI_LINK_AUTH; |
| @@ -747,27 +775,29 @@ hci_event_auth_compl(struct hci_unit *un | | | @@ -747,27 +775,29 @@ hci_event_auth_compl(struct hci_unit *un |
747 | * The encryption status has changed. Basically, we note the change | | 775 | * The encryption status has changed. Basically, we note the change |
748 | * then notify the upper layer protocol unless further mode changes | | 776 | * then notify the upper layer protocol unless further mode changes |
749 | * are pending. | | 777 | * are pending. |
750 | * Note that if encryption gets disabled when it has been requested, | | 778 | * Note that if encryption gets disabled when it has been requested, |
751 | * we will attempt to enable it again.. (its a feature not a bug :) | | 779 | * we will attempt to enable it again.. (its a feature not a bug :) |
752 | */ | | 780 | */ |
753 | static void | | 781 | static void |
754 | hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m) | | 782 | hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m) |
755 | { | | 783 | { |
756 | hci_encryption_change_ep ep; | | 784 | hci_encryption_change_ep ep; |
757 | struct hci_link *link; | | 785 | struct hci_link *link; |
758 | int err; | | 786 | int err; |
759 | | | 787 | |
760 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 788 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 789 | return; |
| | | 790 | |
761 | m_copydata(m, 0, sizeof(ep), &ep); | | 791 | m_copydata(m, 0, sizeof(ep), &ep); |
762 | m_adj(m, sizeof(ep)); | | 792 | m_adj(m, sizeof(ep)); |
763 | | | 793 | |
764 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); | | 794 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); |
765 | | | 795 | |
766 | DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n", | | 796 | DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n", |
767 | ep.con_handle, ep.status, ep.encryption_enable); | | 797 | ep.con_handle, ep.status, ep.encryption_enable); |
768 | | | 798 | |
769 | link = hci_link_lookup_handle(unit, ep.con_handle); | | 799 | link = hci_link_lookup_handle(unit, ep.con_handle); |
770 | if (link == NULL || link->hl_type != HCI_LINK_ACL) | | 800 | if (link == NULL || link->hl_type != HCI_LINK_ACL) |
771 | return; | | 801 | return; |
772 | | | 802 | |
773 | if (ep.status == 0) { | | 803 | if (ep.status == 0) { |
| @@ -791,27 +821,29 @@ hci_event_encryption_change(struct hci_u | | | @@ -791,27 +821,29 @@ hci_event_encryption_change(struct hci_u |
791 | * Change Connection Link Key Complete | | 821 | * Change Connection Link Key Complete |
792 | * | | 822 | * |
793 | * Link keys are handled in userland but if we are waiting to secure | | 823 | * Link keys are handled in userland but if we are waiting to secure |
794 | * this link, we should notify the upper protocols. A SECURE request | | 824 | * this link, we should notify the upper protocols. A SECURE request |
795 | * only needs a single key change, so we can cancel the request. | | 825 | * only needs a single key change, so we can cancel the request. |
796 | */ | | 826 | */ |
797 | static void | | 827 | static void |
798 | hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m) | | 828 | hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m) |
799 | { | | 829 | { |
800 | hci_change_con_link_key_compl_ep ep; | | 830 | hci_change_con_link_key_compl_ep ep; |
801 | struct hci_link *link; | | 831 | struct hci_link *link; |
802 | int err; | | 832 | int err; |
803 | | | 833 | |
804 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 834 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 835 | return; |
| | | 836 | |
805 | m_copydata(m, 0, sizeof(ep), &ep); | | 837 | m_copydata(m, 0, sizeof(ep), &ep); |
806 | m_adj(m, sizeof(ep)); | | 838 | m_adj(m, sizeof(ep)); |
807 | | | 839 | |
808 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); | | 840 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); |
809 | | | 841 | |
810 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); | | 842 | DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status); |
811 | | | 843 | |
812 | link = hci_link_lookup_handle(unit, ep.con_handle); | | 844 | link = hci_link_lookup_handle(unit, ep.con_handle); |
813 | if (link == NULL || link->hl_type != HCI_LINK_ACL) | | 845 | if (link == NULL || link->hl_type != HCI_LINK_ACL) |
814 | return; | | 846 | return; |
815 | | | 847 | |
816 | link->hl_flags &= ~HCI_LINK_SECURE_REQ; | | 848 | link->hl_flags &= ~HCI_LINK_SECURE_REQ; |
817 | | | 849 | |
| @@ -831,76 +863,82 @@ hci_event_change_con_link_key_compl(stru | | | @@ -831,76 +863,82 @@ hci_event_change_con_link_key_compl(stru |
831 | | | 863 | |
832 | /* | | 864 | /* |
833 | * Read Clock Offset Complete | | 865 | * Read Clock Offset Complete |
834 | * | | 866 | * |
835 | * We keep a note of the clock offset of remote devices when a | | 867 | * We keep a note of the clock offset of remote devices when a |
836 | * link is made, in order to facilitate reconnections to the device | | 868 | * link is made, in order to facilitate reconnections to the device |
837 | */ | | 869 | */ |
838 | static void | | 870 | static void |
839 | hci_event_read_clock_offset_compl(struct hci_unit *unit, struct mbuf *m) | | 871 | hci_event_read_clock_offset_compl(struct hci_unit *unit, struct mbuf *m) |
840 | { | | 872 | { |
841 | hci_read_clock_offset_compl_ep ep; | | 873 | hci_read_clock_offset_compl_ep ep; |
842 | struct hci_link *link; | | 874 | struct hci_link *link; |
843 | | | 875 | |
844 | KASSERT(m->m_pkthdr.len >= sizeof(ep)); | | 876 | if (m->m_pkthdr.len < sizeof(ep)) |
| | | 877 | return; |
| | | 878 | |
845 | m_copydata(m, 0, sizeof(ep), &ep); | | 879 | m_copydata(m, 0, sizeof(ep), &ep); |
846 | m_adj(m, sizeof(ep)); | | 880 | m_adj(m, sizeof(ep)); |
847 | | | 881 | |
848 | DPRINTFN(1, "handle #%d, offset=%u, status=0x%x\n", | | 882 | DPRINTFN(1, "handle #%d, offset=%u, status=0x%x\n", |
849 | le16toh(ep.con_handle), le16toh(ep.clock_offset), ep.status); | | 883 | le16toh(ep.con_handle), le16toh(ep.clock_offset), ep.status); |
850 | | | 884 | |
851 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); | | 885 | ep.con_handle = HCI_CON_HANDLE(le16toh(ep.con_handle)); |
852 | link = hci_link_lookup_handle(unit, ep.con_handle); | | 886 | link = hci_link_lookup_handle(unit, ep.con_handle); |
853 | if (link == NULL || link->hl_type != HCI_LINK_ACL) | | 887 | if (link == NULL || link->hl_type != HCI_LINK_ACL) |
854 | return; | | 888 | return; |
855 | | | 889 | |
856 | if (ep.status == 0) | | 890 | if (ep.status == 0) |
857 | link->hl_clock = ep.clock_offset; | | 891 | link->hl_clock = ep.clock_offset; |
858 | } | | 892 | } |
859 | | | 893 | |
860 | /* | | 894 | /* |
861 | * process results of read_bdaddr command_complete event | | 895 | * process results of read_bdaddr command_complete event |
862 | */ | | 896 | */ |
863 | static void | | 897 | static void |
864 | hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m) | | 898 | hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m) |
865 | { | | 899 | { |
866 | hci_read_bdaddr_rp rp; | | 900 | hci_read_bdaddr_rp rp; |
867 | | | 901 | |
868 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 902 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 903 | return; |
| | | 904 | |
869 | m_copydata(m, 0, sizeof(rp), &rp); | | 905 | m_copydata(m, 0, sizeof(rp), &rp); |
870 | m_adj(m, sizeof(rp)); | | 906 | m_adj(m, sizeof(rp)); |
871 | | | 907 | |
872 | if (rp.status > 0) | | 908 | if (rp.status > 0) |
873 | return; | | 909 | return; |
874 | | | 910 | |
875 | if ((unit->hci_flags & BTF_INIT_BDADDR) == 0) | | 911 | if ((unit->hci_flags & BTF_INIT_BDADDR) == 0) |
876 | return; | | 912 | return; |
877 | | | 913 | |
878 | bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr); | | 914 | bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr); |
879 | | | 915 | |
880 | unit->hci_flags &= ~BTF_INIT_BDADDR; | | 916 | unit->hci_flags &= ~BTF_INIT_BDADDR; |
881 | | | 917 | |
882 | cv_broadcast(&unit->hci_init); | | 918 | cv_broadcast(&unit->hci_init); |
883 | } | | 919 | } |
884 | | | 920 | |
885 | /* | | 921 | /* |
886 | * process results of read_buffer_size command_complete event | | 922 | * process results of read_buffer_size command_complete event |
887 | */ | | 923 | */ |
888 | static void | | 924 | static void |
889 | hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m) | | 925 | hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m) |
890 | { | | 926 | { |
891 | hci_read_buffer_size_rp rp; | | 927 | hci_read_buffer_size_rp rp; |
892 | | | 928 | |
893 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 929 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 930 | return; |
| | | 931 | |
894 | m_copydata(m, 0, sizeof(rp), &rp); | | 932 | m_copydata(m, 0, sizeof(rp), &rp); |
895 | m_adj(m, sizeof(rp)); | | 933 | m_adj(m, sizeof(rp)); |
896 | | | 934 | |
897 | if (rp.status > 0) | | 935 | if (rp.status > 0) |
898 | return; | | 936 | return; |
899 | | | 937 | |
900 | if ((unit->hci_flags & BTF_INIT_BUFFER_SIZE) == 0) | | 938 | if ((unit->hci_flags & BTF_INIT_BUFFER_SIZE) == 0) |
901 | return; | | 939 | return; |
902 | | | 940 | |
903 | unit->hci_max_acl_size = le16toh(rp.max_acl_size); | | 941 | unit->hci_max_acl_size = le16toh(rp.max_acl_size); |
904 | unit->hci_num_acl_pkts = le16toh(rp.num_acl_pkts); | | 942 | unit->hci_num_acl_pkts = le16toh(rp.num_acl_pkts); |
905 | unit->hci_max_acl_pkts = le16toh(rp.num_acl_pkts); | | 943 | unit->hci_max_acl_pkts = le16toh(rp.num_acl_pkts); |
906 | unit->hci_max_sco_size = rp.max_sco_size; | | 944 | unit->hci_max_sco_size = rp.max_sco_size; |
| @@ -910,27 +948,29 @@ hci_cmd_read_buffer_size(struct hci_unit | | | @@ -910,27 +948,29 @@ hci_cmd_read_buffer_size(struct hci_unit |
910 | unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE; | | 948 | unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE; |
911 | | | 949 | |
912 | cv_broadcast(&unit->hci_init); | | 950 | cv_broadcast(&unit->hci_init); |
913 | } | | 951 | } |
914 | | | 952 | |
915 | /* | | 953 | /* |
916 | * process results of read_local_features command_complete event | | 954 | * process results of read_local_features command_complete event |
917 | */ | | 955 | */ |
918 | static void | | 956 | static void |
919 | hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m) | | 957 | hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m) |
920 | { | | 958 | { |
921 | hci_read_local_features_rp rp; | | 959 | hci_read_local_features_rp rp; |
922 | | | 960 | |
923 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 961 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 962 | return; |
| | | 963 | |
924 | m_copydata(m, 0, sizeof(rp), &rp); | | 964 | m_copydata(m, 0, sizeof(rp), &rp); |
925 | m_adj(m, sizeof(rp)); | | 965 | m_adj(m, sizeof(rp)); |
926 | | | 966 | |
927 | if (rp.status > 0) | | 967 | if (rp.status > 0) |
928 | return; | | 968 | return; |
929 | | | 969 | |
930 | if ((unit->hci_flags & BTF_INIT_FEATURES) == 0) | | 970 | if ((unit->hci_flags & BTF_INIT_FEATURES) == 0) |
931 | return; | | 971 | return; |
932 | | | 972 | |
933 | memcpy(unit->hci_feat0, rp.features, HCI_FEATURES_SIZE); | | 973 | memcpy(unit->hci_feat0, rp.features, HCI_FEATURES_SIZE); |
934 | | | 974 | |
935 | unit->hci_lmp_mask = 0; | | 975 | unit->hci_lmp_mask = 0; |
936 | | | 976 | |
| @@ -1019,27 +1059,29 @@ hci_cmd_read_local_features(struct hci_u | | | @@ -1019,27 +1059,29 @@ hci_cmd_read_local_features(struct hci_u |
1019 | | | 1059 | |
1020 | unit->hci_flags &= ~BTF_INIT_FEATURES; | | 1060 | unit->hci_flags &= ~BTF_INIT_FEATURES; |
1021 | cv_broadcast(&unit->hci_init); | | 1061 | cv_broadcast(&unit->hci_init); |
1022 | } | | 1062 | } |
1023 | | | 1063 | |
1024 | /* | | 1064 | /* |
1025 | * process results of read_local_extended_features command_complete event | | 1065 | * process results of read_local_extended_features command_complete event |
1026 | */ | | 1066 | */ |
1027 | static void | | 1067 | static void |
1028 | hci_cmd_read_local_extended_features(struct hci_unit *unit, struct mbuf *m) | | 1068 | hci_cmd_read_local_extended_features(struct hci_unit *unit, struct mbuf *m) |
1029 | { | | 1069 | { |
1030 | hci_read_local_extended_features_rp rp; | | 1070 | hci_read_local_extended_features_rp rp; |
1031 | | | 1071 | |
1032 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 1072 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 1073 | return; |
| | | 1074 | |
1033 | m_copydata(m, 0, sizeof(rp), &rp); | | 1075 | m_copydata(m, 0, sizeof(rp), &rp); |
1034 | m_adj(m, sizeof(rp)); | | 1076 | m_adj(m, sizeof(rp)); |
1035 | | | 1077 | |
1036 | if (rp.status > 0) | | 1078 | if (rp.status > 0) |
1037 | return; | | 1079 | return; |
1038 | | | 1080 | |
1039 | if ((unit->hci_flags & BTF_INIT_FEATURES) == 0) | | 1081 | if ((unit->hci_flags & BTF_INIT_FEATURES) == 0) |
1040 | return; | | 1082 | return; |
1041 | | | 1083 | |
1042 | DPRINTFN(1, "%s: page %d of %d\n", device_xname(unit->hci_dev), | | 1084 | DPRINTFN(1, "%s: page %d of %d\n", device_xname(unit->hci_dev), |
1043 | rp.page, rp.max_page); | | 1085 | rp.page, rp.max_page); |
1044 | | | 1086 | |
1045 | switch (rp.page) { | | 1087 | switch (rp.page) { |
| @@ -1066,54 +1108,58 @@ hci_cmd_read_local_extended_features(str | | | @@ -1066,54 +1108,58 @@ hci_cmd_read_local_extended_features(str |
1066 | cv_broadcast(&unit->hci_init); | | 1108 | cv_broadcast(&unit->hci_init); |
1067 | } | | 1109 | } |
1068 | | | 1110 | |
1069 | /* | | 1111 | /* |
1070 | * process results of read_local_ver command_complete event | | 1112 | * process results of read_local_ver command_complete event |
1071 | * | | 1113 | * |
1072 | * reading local supported commands is only supported from 1.2 spec | | 1114 | * reading local supported commands is only supported from 1.2 spec |
1073 | */ | | 1115 | */ |
1074 | static void | | 1116 | static void |
1075 | hci_cmd_read_local_ver(struct hci_unit *unit, struct mbuf *m) | | 1117 | hci_cmd_read_local_ver(struct hci_unit *unit, struct mbuf *m) |
1076 | { | | 1118 | { |
1077 | hci_read_local_ver_rp rp; | | 1119 | hci_read_local_ver_rp rp; |
1078 | | | 1120 | |
1079 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 1121 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 1122 | return; |
| | | 1123 | |
1080 | m_copydata(m, 0, sizeof(rp), &rp); | | 1124 | m_copydata(m, 0, sizeof(rp), &rp); |
1081 | m_adj(m, sizeof(rp)); | | 1125 | m_adj(m, sizeof(rp)); |
1082 | | | 1126 | |
1083 | if (rp.status != 0) | | 1127 | if (rp.status != 0) |
1084 | return; | | 1128 | return; |
1085 | | | 1129 | |
1086 | if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0) | | 1130 | if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0) |
1087 | return; | | 1131 | return; |
1088 | | | 1132 | |
1089 | if (rp.hci_version < HCI_SPEC_V12) { | | 1133 | if (rp.hci_version < HCI_SPEC_V12) { |
1090 | unit->hci_flags &= ~BTF_INIT_COMMANDS; | | 1134 | unit->hci_flags &= ~BTF_INIT_COMMANDS; |
1091 | cv_broadcast(&unit->hci_init); | | 1135 | cv_broadcast(&unit->hci_init); |
1092 | return; | | 1136 | return; |
1093 | } | | 1137 | } |
1094 | | | 1138 | |
1095 | hci_send_cmd(unit, HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0); | | 1139 | hci_send_cmd(unit, HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0); |
1096 | } | | 1140 | } |
1097 | | | 1141 | |
1098 | /* | | 1142 | /* |
1099 | * process results of read_local_commands command_complete event | | 1143 | * process results of read_local_commands command_complete event |
1100 | */ | | 1144 | */ |
1101 | static void | | 1145 | static void |
1102 | hci_cmd_read_local_commands(struct hci_unit *unit, struct mbuf *m) | | 1146 | hci_cmd_read_local_commands(struct hci_unit *unit, struct mbuf *m) |
1103 | { | | 1147 | { |
1104 | hci_read_local_commands_rp rp; | | 1148 | hci_read_local_commands_rp rp; |
1105 | | | 1149 | |
1106 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 1150 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 1151 | return; |
| | | 1152 | |
1107 | m_copydata(m, 0, sizeof(rp), &rp); | | 1153 | m_copydata(m, 0, sizeof(rp), &rp); |
1108 | m_adj(m, sizeof(rp)); | | 1154 | m_adj(m, sizeof(rp)); |
1109 | | | 1155 | |
1110 | if (rp.status != 0) | | 1156 | if (rp.status != 0) |
1111 | return; | | 1157 | return; |
1112 | | | 1158 | |
1113 | if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0) | | 1159 | if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0) |
1114 | return; | | 1160 | return; |
1115 | | | 1161 | |
1116 | unit->hci_flags &= ~BTF_INIT_COMMANDS; | | 1162 | unit->hci_flags &= ~BTF_INIT_COMMANDS; |
1117 | memcpy(unit->hci_cmds, rp.commands, HCI_COMMANDS_SIZE); | | 1163 | memcpy(unit->hci_cmds, rp.commands, HCI_COMMANDS_SIZE); |
1118 | | | 1164 | |
1119 | cv_broadcast(&unit->hci_init); | | 1165 | cv_broadcast(&unit->hci_init); |
| @@ -1122,27 +1168,29 @@ hci_cmd_read_local_commands(struct hci_u | | | @@ -1122,27 +1168,29 @@ hci_cmd_read_local_commands(struct hci_u |
1122 | /* | | 1168 | /* |
1123 | * process results of reset command_complete event | | 1169 | * process results of reset command_complete event |
1124 | * | | 1170 | * |
1125 | * This has killed all the connections, so close down anything we have left, | | 1171 | * This has killed all the connections, so close down anything we have left, |
1126 | * and reinitialise the unit. | | 1172 | * and reinitialise the unit. |
1127 | */ | | 1173 | */ |
1128 | static void | | 1174 | static void |
1129 | hci_cmd_reset(struct hci_unit *unit, struct mbuf *m) | | 1175 | hci_cmd_reset(struct hci_unit *unit, struct mbuf *m) |
1130 | { | | 1176 | { |
1131 | hci_reset_rp rp; | | 1177 | hci_reset_rp rp; |
1132 | struct hci_link *link, *next; | | 1178 | struct hci_link *link, *next; |
1133 | int acl; | | 1179 | int acl; |
1134 | | | 1180 | |
1135 | KASSERT(m->m_pkthdr.len >= sizeof(rp)); | | 1181 | if (m->m_pkthdr.len < sizeof(rp)) |
| | | 1182 | return; |
| | | 1183 | |
1136 | m_copydata(m, 0, sizeof(rp), &rp); | | 1184 | m_copydata(m, 0, sizeof(rp), &rp); |
1137 | m_adj(m, sizeof(rp)); | | 1185 | m_adj(m, sizeof(rp)); |
1138 | | | 1186 | |
1139 | if (rp.status != 0) | | 1187 | if (rp.status != 0) |
1140 | return; | | 1188 | return; |
1141 | | | 1189 | |
1142 | /* | | 1190 | /* |
1143 | * release SCO links first, since they may be holding | | 1191 | * release SCO links first, since they may be holding |
1144 | * an ACL link reference. | | 1192 | * an ACL link reference. |
1145 | */ | | 1193 | */ |
1146 | for (acl = 0 ; acl < 2 ; acl++) { | | 1194 | for (acl = 0 ; acl < 2 ; acl++) { |
1147 | next = TAILQ_FIRST(&unit->hci_links); | | 1195 | next = TAILQ_FIRST(&unit->hci_links); |
1148 | while ((link = next) != NULL) { | | 1196 | while ((link = next) != NULL) { |