Annotation of sys/netbt/hci_event.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hci_event.c,v 1.5 2007/06/19 08:12:35 uwe Exp $ */
2: /* $NetBSD: hci_event.c,v 1.6 2007/04/21 06:15:23 plunky Exp $ */
3:
4: /*-
5: * Copyright (c) 2005 Iain Hibbert.
6: * Copyright (c) 2006 Itronix Inc.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of Itronix Inc. may not be used to endorse
18: * or promote products derived from this software without specific
19: * prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28: * ON ANY THEORY OF LIABILITY, WHETHER IN
29: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31: * POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: #include <sys/cdefs.h>
35:
36: #include <sys/param.h>
37: #include <sys/kernel.h>
38: #include <sys/malloc.h>
39: #include <sys/mbuf.h>
40: #include <sys/proc.h>
41: #include <sys/systm.h>
42:
43: #include <netbt/bluetooth.h>
44: #include <netbt/hci.h>
45: #include <netbt/sco.h>
46:
47: static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *);
48: static void hci_event_command_status(struct hci_unit *, struct mbuf *);
49: static void hci_event_command_compl(struct hci_unit *, struct mbuf *);
50: static void hci_event_con_compl(struct hci_unit *, struct mbuf *);
51: static void hci_event_discon_compl(struct hci_unit *, struct mbuf *);
52: static void hci_event_con_req(struct hci_unit *, struct mbuf *);
53: static void hci_event_num_compl_pkts(struct hci_unit *, struct mbuf *);
54: static void hci_event_auth_compl(struct hci_unit *, struct mbuf *);
55: static void hci_event_encryption_change(struct hci_unit *, struct mbuf *);
56: static void hci_event_change_con_link_key_compl(struct hci_unit *, struct mbuf *);
57: static void hci_cmd_read_bdaddr(struct hci_unit *, struct mbuf *);
58: static void hci_cmd_read_buffer_size(struct hci_unit *, struct mbuf *);
59: static void hci_cmd_read_local_features(struct hci_unit *, struct mbuf *);
60: static void hci_cmd_reset(struct hci_unit *, struct mbuf *);
61:
62: #ifdef BLUETOOTH_DEBUG
63: int bluetooth_debug = 0;
64:
65: static const char *hci_eventnames[] = {
66: /* 0x00 */ "NULL",
67: /* 0x01 */ "INQUIRY COMPLETE",
68: /* 0x02 */ "INQUIRY RESULT",
69: /* 0x03 */ "CONN COMPLETE",
70: /* 0x04 */ "CONN REQ",
71: /* 0x05 */ "DISCONN COMPLETE",
72: /* 0x06 */ "AUTH COMPLETE",
73: /* 0x07 */ "REMOTE NAME REQ COMPLETE",
74: /* 0x08 */ "ENCRYPTION CHANGE",
75: /* 0x09 */ "CHANGE CONN LINK KEY COMPLETE",
76: /* 0x0a */ "MASTER LINK KEY COMPLETE",
77: /* 0x0b */ "READ REMOTE FEATURES COMPLETE",
78: /* 0x0c */ "READ REMOTE VERSION INFO COMPLETE",
79: /* 0x0d */ "QoS SETUP COMPLETE",
80: /* 0x0e */ "COMMAND COMPLETE",
81: /* 0x0f */ "COMMAND STATUS",
82: /* 0x10 */ "HARDWARE ERROR",
83: /* 0x11 */ "FLUSH OCCUR",
84: /* 0x12 */ "ROLE CHANGE",
85: /* 0x13 */ "NUM COMPLETED PACKETS",
86: /* 0x14 */ "MODE CHANGE",
87: /* 0x15 */ "RETURN LINK KEYS",
88: /* 0x16 */ "PIN CODE REQ",
89: /* 0x17 */ "LINK KEY REQ",
90: /* 0x18 */ "LINK KEY NOTIFICATION",
91: /* 0x19 */ "LOOPBACK COMMAND",
92: /* 0x1a */ "DATA BUFFER OVERFLOW",
93: /* 0x1b */ "MAX SLOT CHANGE",
94: /* 0x1c */ "READ CLOCK OFFSET COMPLETE",
95: /* 0x1d */ "CONN PKT TYPE CHANGED",
96: /* 0x1e */ "QOS VIOLATION",
97: /* 0x1f */ "PAGE SCAN MODE CHANGE",
98: /* 0x20 */ "PAGE SCAN REP MODE CHANGE",
99: /* 0x21 */ "FLOW SPECIFICATION COMPLETE",
100: /* 0x22 */ "RSSI RESULT",
101: /* 0x23 */ "READ REMOTE EXT FEATURES"
102: };
103:
104: static const char *
105: hci_eventstr(unsigned int event)
106: {
107:
108: if (event < (sizeof(hci_eventnames) / sizeof(*hci_eventnames)))
109: return hci_eventnames[event];
110:
111: switch (event) {
112: case HCI_EVENT_SCO_CON_COMPL: /* 0x2c */
113: return "SCO CON COMPLETE";
114:
115: case HCI_EVENT_SCO_CON_CHANGED: /* 0x2d */
116: return "SCO CON CHANGED";
117:
118: case HCI_EVENT_BT_LOGO: /* 0xfe */
119: return "BT_LOGO";
120:
121: case HCI_EVENT_VENDOR: /* 0xff */
122: return "VENDOR";
123: }
124:
125: return "UNRECOGNISED";
126: }
127: #endif /* BLUETOOTH_DEBUG */
128:
129: /*
130: * process HCI Events
131: *
132: * We will free the mbuf at the end, no need for any sub
133: * functions to handle that. We kind of assume that the
134: * device sends us valid events.
135: * XXX "kind of"? This needs to be fixed.
136: */
137: void
138: hci_event(struct mbuf *m, struct hci_unit *unit)
139: {
140: hci_event_hdr_t hdr;
141:
142: KASSERT(m->m_flags & M_PKTHDR);
143:
144: KASSERT(m->m_pkthdr.len >= sizeof(hdr));
145: m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
146: m_adj(m, sizeof(hdr));
147:
148: KASSERT(hdr.type == HCI_EVENT_PKT);
149:
150: DPRINTFN(1, "(%s) event %s\n", unit->hci_devname, hci_eventstr(hdr.event));
151:
152: switch(hdr.event) {
153: case HCI_EVENT_COMMAND_STATUS:
154: hci_event_command_status(unit, m);
155: break;
156:
157: case HCI_EVENT_COMMAND_COMPL:
158: hci_event_command_compl(unit, m);
159: break;
160:
161: case HCI_EVENT_NUM_COMPL_PKTS:
162: hci_event_num_compl_pkts(unit, m);
163: break;
164:
165: case HCI_EVENT_INQUIRY_RESULT:
166: hci_event_inquiry_result(unit, m);
167: break;
168:
169: case HCI_EVENT_CON_COMPL:
170: hci_event_con_compl(unit, m);
171: break;
172:
173: case HCI_EVENT_DISCON_COMPL:
174: hci_event_discon_compl(unit, m);
175: break;
176:
177: case HCI_EVENT_CON_REQ:
178: hci_event_con_req(unit, m);
179: break;
180:
181: case HCI_EVENT_AUTH_COMPL:
182: hci_event_auth_compl(unit, m);
183: break;
184:
185: case HCI_EVENT_ENCRYPTION_CHANGE:
186: hci_event_encryption_change(unit, m);
187: break;
188:
189: case HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL:
190: hci_event_change_con_link_key_compl(unit, m);
191: break;
192:
193: case HCI_EVENT_SCO_CON_COMPL:
194: case HCI_EVENT_INQUIRY_COMPL:
195: case HCI_EVENT_REMOTE_NAME_REQ_COMPL:
196: case HCI_EVENT_MASTER_LINK_KEY_COMPL:
197: case HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
198: case HCI_EVENT_READ_REMOTE_VER_INFO_COMPL:
199: case HCI_EVENT_QOS_SETUP_COMPL:
200: case HCI_EVENT_HARDWARE_ERROR:
201: case HCI_EVENT_FLUSH_OCCUR:
202: case HCI_EVENT_ROLE_CHANGE:
203: case HCI_EVENT_MODE_CHANGE:
204: case HCI_EVENT_RETURN_LINK_KEYS:
205: case HCI_EVENT_PIN_CODE_REQ:
206: case HCI_EVENT_LINK_KEY_REQ:
207: case HCI_EVENT_LINK_KEY_NOTIFICATION:
208: case HCI_EVENT_LOOPBACK_COMMAND:
209: case HCI_EVENT_DATA_BUFFER_OVERFLOW:
210: case HCI_EVENT_MAX_SLOT_CHANGE:
211: case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
212: case HCI_EVENT_CON_PKT_TYPE_CHANGED:
213: case HCI_EVENT_QOS_VIOLATION:
214: case HCI_EVENT_PAGE_SCAN_MODE_CHANGE:
215: case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
216: case HCI_EVENT_FLOW_SPECIFICATION_COMPL:
217: case HCI_EVENT_RSSI_RESULT:
218: case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES:
219: case HCI_EVENT_SCO_CON_CHANGED:
220: case HCI_EVENT_BT_LOGO:
221: case HCI_EVENT_VENDOR:
222: break;
223:
224: default:
225: UNKNOWN(hdr.event);
226: break;
227: }
228:
229: m_freem(m);
230: }
231:
232: /*
233: * Command Status
234: *
235: * Update our record of num_cmd_pkts then post-process any pending commands
236: * and optionally restart cmd output on the unit.
237: */
238: static void
239: hci_event_command_status(struct hci_unit *unit, struct mbuf *m)
240: {
241: hci_command_status_ep ep;
242: struct hci_link *link;
243:
244: KASSERT(m->m_pkthdr.len >= sizeof(ep));
245: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
246: m_adj(m, sizeof(ep));
247:
248: DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n",
249: unit->hci_devname,
250: HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
251: ep.status,
252: ep.num_cmd_pkts);
253:
254: unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
255:
256: /*
257: * post processing of pending commands
258: */
259: switch(letoh16(ep.opcode)) {
260: case HCI_CMD_CREATE_CON:
261: switch (ep.status) {
262: case 0x12: /* Invalid HCI command parameters */
263: DPRINTF("(%s) Invalid HCI command parameters\n",
264: unit->hci_devname);
265: while ((link = hci_link_lookup_state(unit,
266: HCI_LINK_ACL, HCI_LINK_WAIT_CONNECT)) != NULL)
267: hci_link_free(link, ECONNABORTED);
268: break;
269: }
270: break;
271: default:
272: break;
273: }
274:
275: while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
276: IF_DEQUEUE(&unit->hci_cmdwait, m);
277: hci_output_cmd(unit, m);
278: }
279: }
280:
281: /*
282: * Command Complete
283: *
284: * Update our record of num_cmd_pkts then handle the completed command,
285: * and optionally restart cmd output on the unit.
286: */
287: static void
288: hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
289: {
290: hci_command_compl_ep ep;
291:
292: KASSERT(m->m_pkthdr.len >= sizeof(ep));
293: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
294: m_adj(m, sizeof(ep));
295:
296: DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n",
297: unit->hci_devname,
298: HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
299: ep.num_cmd_pkts);
300:
301: unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
302:
303: /*
304: * post processing of completed commands
305: */
306: switch(letoh16(ep.opcode)) {
307: case HCI_CMD_READ_BDADDR:
308: hci_cmd_read_bdaddr(unit, m);
309: break;
310:
311: case HCI_CMD_READ_BUFFER_SIZE:
312: hci_cmd_read_buffer_size(unit, m);
313: break;
314:
315: case HCI_CMD_READ_LOCAL_FEATURES:
316: hci_cmd_read_local_features(unit, m);
317: break;
318:
319: case HCI_CMD_RESET:
320: hci_cmd_reset(unit, m);
321: break;
322:
323: default:
324: break;
325: }
326:
327: while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
328: IF_DEQUEUE(&unit->hci_cmdwait, m);
329: hci_output_cmd(unit, m);
330: }
331: }
332:
333: /*
334: * Number of Completed Packets
335: *
336: * This is sent periodically by the Controller telling us how many
337: * buffers are now freed up and which handle was using them. From
338: * this we determine which type of buffer it was and add the qty
339: * back into the relevant packet counter, then restart output on
340: * links that have halted.
341: */
342: static void
343: hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m)
344: {
345: hci_num_compl_pkts_ep ep;
346: struct hci_link *link, *next;
347: uint16_t handle, num;
348: int num_acl = 0, num_sco = 0;
349:
350: KASSERT(m->m_pkthdr.len >= sizeof(ep));
351: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
352: m_adj(m, sizeof(ep));
353:
354: while (ep.num_con_handles--) {
355: m_copydata(m, 0, sizeof(handle), (caddr_t)&handle);
356: m_adj(m, sizeof(handle));
357: handle = letoh16(handle);
358:
359: m_copydata(m, 0, sizeof(num), (caddr_t)&num);
360: m_adj(m, sizeof(num));
361: num = letoh16(num);
362:
363: link = hci_link_lookup_handle(unit, handle);
364: if (link) {
365: if (link->hl_type == HCI_LINK_ACL) {
366: num_acl += num;
367: hci_acl_complete(link, num);
368: } else {
369: num_sco += num;
370: hci_sco_complete(link, num);
371: }
372: } else {
373: /* XXX need to issue Read_Buffer_Size or Reset? */
374: printf("%s: unknown handle %d! "
375: "(losing track of %d packet buffer%s)\n",
376: unit->hci_devname, handle,
377: num, (num == 1 ? "" : "s"));
378: }
379: }
380:
381: /*
382: * Move up any queued packets. When a link has sent data, it will move
383: * to the back of the queue - technically then if a link had something
384: * to send and there were still buffers available it could get started
385: * twice but it seemed more important to to handle higher loads fairly
386: * than worry about wasting cycles when we are not busy.
387: */
388:
389: unit->hci_num_acl_pkts += num_acl;
390: unit->hci_num_sco_pkts += num_sco;
391:
392: link = TAILQ_FIRST(&unit->hci_links);
393: while (link && (unit->hci_num_acl_pkts > 0 || unit->hci_num_sco_pkts > 0)) {
394: next = TAILQ_NEXT(link, hl_next);
395:
396: if (link->hl_type == HCI_LINK_ACL) {
397: if (unit->hci_num_acl_pkts > 0 && link->hl_txqlen > 0)
398: hci_acl_start(link);
399: } else {
400: if (unit->hci_num_sco_pkts > 0 && link->hl_txqlen > 0)
401: hci_sco_start(link);
402: }
403:
404: link = next;
405: }
406: }
407:
408: /*
409: * Inquiry Result
410: *
411: * keep a note of devices seen, so we know which unit to use
412: * on outgoing connections
413: */
414: static void
415: hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m)
416: {
417: hci_inquiry_result_ep ep;
418: struct hci_memo *memo;
419: bdaddr_t bdaddr;
420:
421: KASSERT(m->m_pkthdr.len >= sizeof(ep));
422: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
423: m_adj(m, sizeof(ep));
424:
425: DPRINTFN(1, "%d response%s\n", ep.num_responses,
426: (ep.num_responses == 1 ? "" : "s"));
427:
428: while(ep.num_responses--) {
429: m_copydata(m, 0, sizeof(bdaddr_t), (caddr_t)&bdaddr);
430:
431: DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
432: bdaddr.b[5], bdaddr.b[4], bdaddr.b[3],
433: bdaddr.b[2], bdaddr.b[1], bdaddr.b[0]);
434:
435: memo = hci_memo_find(unit, &bdaddr);
436: if (memo == NULL) {
437: memo = malloc(sizeof(struct hci_memo),
438: M_BLUETOOTH, M_NOWAIT);
439: if (memo == NULL) {
440: DPRINTFN(0, "out of memo memory!\n");
441: break;
442: }
443: bzero(memo, sizeof *memo);
444:
445: LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
446: }
447:
448: microtime(&memo->time);
449: m_copydata(m, 0, sizeof(hci_inquiry_response),
450: (caddr_t)&memo->response);
451: m_adj(m, sizeof(hci_inquiry_response));
452:
453: memo->response.clock_offset =
454: letoh16(memo->response.clock_offset);
455: }
456: }
457:
458: /*
459: * Connection Complete
460: *
461: * Sent to us when a connection is made. If there is no link
462: * structure already allocated for this, we must have changed
463: * our mind, so just disconnect.
464: */
465: static void
466: hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
467: {
468: hci_con_compl_ep ep;
469: hci_write_link_policy_settings_cp cp;
470: struct hci_link *link;
471: int err;
472:
473: KASSERT(m->m_pkthdr.len >= sizeof(ep));
474: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
475: m_adj(m, sizeof(ep));
476:
477: DPRINTFN(1, "(%s) %s connection complete for "
478: "%02x:%02x:%02x:%02x:%02x:%02x status %#x\n",
479: unit->hci_devname,
480: (ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"),
481: ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
482: ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
483: ep.status);
484:
485: link = hci_link_lookup_bdaddr(unit, &ep.bdaddr, ep.link_type);
486:
487: if (ep.status) {
488: if (link != NULL) {
489: switch (ep.status) {
490: case 0x04: /* "Page Timeout" */
491: err = EHOSTDOWN;
492: break;
493:
494: case 0x08: /* "Connection Timed Out" */
495: case 0x10: /* "Connection Accept Timeout Exceeded" */
496: err = ETIMEDOUT;
497: break;
498:
499: case 0x16: /* "Connection Terminated by Local Host" */
500: err = 0;
501: break;
502:
503: default:
504: err = ECONNREFUSED;
505: break;
506: }
507:
508: hci_link_free(link, err);
509: }
510:
511: return;
512: }
513:
514: if (link == NULL) {
515: hci_discon_cp dp;
516:
517: dp.con_handle = ep.con_handle;
518: dp.reason = 0x13; /* "Remote User Terminated Connection" */
519:
520: hci_send_cmd(unit, HCI_CMD_DISCONNECT, &dp, sizeof(dp));
521: return;
522: }
523:
524: /* XXX could check auth_enable here */
525:
526: if (ep.encryption_mode)
527: link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
528:
529: link->hl_state = HCI_LINK_OPEN;
530: link->hl_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
531:
532: if (ep.link_type == HCI_LINK_ACL) {
533: cp.con_handle = ep.con_handle;
534: cp.settings = htole16(unit->hci_link_policy);
535: err = hci_send_cmd(unit, HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
536: &cp, sizeof(cp));
537: if (err)
538: printf("%s: Warning, could not write link policy\n",
539: unit->hci_devname);
540:
541: err = hci_acl_setmode(link);
542: if (err == EINPROGRESS)
543: return;
544:
545: hci_acl_linkmode(link);
546: } else {
547: (*link->hl_sco->sp_proto->connected)(link->hl_sco->sp_upper);
548: }
549: }
550:
551: /*
552: * Disconnection Complete
553: *
554: * This is sent in response to a disconnection request, but also if
555: * the remote device goes out of range.
556: */
557: static void
558: hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m)
559: {
560: hci_discon_compl_ep ep;
561: struct hci_link *link;
562:
563: KASSERT(m->m_pkthdr.len >= sizeof(ep));
564: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
565: m_adj(m, sizeof(ep));
566:
567: ep.con_handle = letoh16(ep.con_handle);
568:
569: DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
570:
571: link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle));
572: if (link)
573: hci_link_free(link, ENOENT); /* XXX NetBSD used ENOLINK here */
574: }
575:
576: /*
577: * Connect Request
578: *
579: * We check upstream for appropriate listeners and accept connections
580: * that are wanted.
581: */
582: static void
583: hci_event_con_req(struct hci_unit *unit, struct mbuf *m)
584: {
585: hci_con_req_ep ep;
586: hci_accept_con_cp ap;
587: hci_reject_con_cp rp;
588: struct hci_link *link;
589:
590: KASSERT(m->m_pkthdr.len >= sizeof(ep));
591: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
592: m_adj(m, sizeof(ep));
593:
594: DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
595: "class %2.2x%2.2x%2.2x type %s\n",
596: ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
597: ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
598: ep.uclass[0], ep.uclass[1], ep.uclass[2],
599: ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO");
600:
601: if (ep.link_type == HCI_LINK_ACL)
602: link = hci_acl_newconn(unit, &ep.bdaddr);
603: else
604: link = hci_sco_newconn(unit, &ep.bdaddr);
605:
606: if (link == NULL) {
607: memset(&rp, 0, sizeof(rp));
608: bdaddr_copy(&rp.bdaddr, &ep.bdaddr);
609: rp.reason = 0x0f; /* Unacceptable BD_ADDR */
610:
611: hci_send_cmd(unit, HCI_CMD_REJECT_CON, &rp, sizeof(rp));
612: } else {
613: memset(&ap, 0, sizeof(ap));
614: bdaddr_copy(&ap.bdaddr, &ep.bdaddr);
615: if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
616: ap.role = HCI_ROLE_MASTER;
617: else
618: ap.role = HCI_ROLE_SLAVE;
619:
620: hci_send_cmd(unit, HCI_CMD_ACCEPT_CON, &ap, sizeof(ap));
621: }
622: }
623:
624: /*
625: * Auth Complete
626: *
627: * Authentication has been completed on an ACL link. We can notify the
628: * upper layer protocols unless further mode changes are pending.
629: */
630: static void
631: hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m)
632: {
633: hci_auth_compl_ep ep;
634: struct hci_link *link;
635: int err;
636:
637: KASSERT(m->m_pkthdr.len >= sizeof(ep));
638: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
639: m_adj(m, sizeof(ep));
640:
641: ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
642:
643: DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
644:
645: link = hci_link_lookup_handle(unit, ep.con_handle);
646: if (link == NULL || link->hl_type != HCI_LINK_ACL)
647: return;
648:
649: if (ep.status == 0) {
650: link->hl_flags |= HCI_LINK_AUTH;
651:
652: if (link->hl_state == HCI_LINK_WAIT_AUTH)
653: link->hl_state = HCI_LINK_OPEN;
654:
655: err = hci_acl_setmode(link);
656: if (err == EINPROGRESS)
657: return;
658: }
659:
660: hci_acl_linkmode(link);
661: }
662:
663: /*
664: * Encryption Change
665: *
666: * The encryption status has changed. Basically, we note the change
667: * then notify the upper layer protocol unless further mode changes
668: * are pending.
669: * Note that if encryption gets disabled when it has been requested,
670: * we will attempt to enable it again.. (its a feature not a bug :)
671: */
672: static void
673: hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m)
674: {
675: hci_encryption_change_ep ep;
676: struct hci_link *link;
677: int err;
678:
679: KASSERT(m->m_pkthdr.len >= sizeof(ep));
680: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
681: m_adj(m, sizeof(ep));
682:
683: ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
684:
685: DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n",
686: ep.con_handle, ep.status, ep.encryption_enable);
687:
688: link = hci_link_lookup_handle(unit, ep.con_handle);
689: if (link == NULL || link->hl_type != HCI_LINK_ACL)
690: return;
691:
692: if (ep.status == 0) {
693: if (ep.encryption_enable == 0)
694: link->hl_flags &= ~HCI_LINK_ENCRYPT;
695: else
696: link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
697:
698: if (link->hl_state == HCI_LINK_WAIT_ENCRYPT)
699: link->hl_state = HCI_LINK_OPEN;
700:
701: err = hci_acl_setmode(link);
702: if (err == EINPROGRESS)
703: return;
704: }
705:
706: hci_acl_linkmode(link);
707: }
708:
709: /*
710: * Change Connection Link Key Complete
711: *
712: * Link keys are handled in userland but if we are waiting to secure
713: * this link, we should notify the upper protocols. A SECURE request
714: * only needs a single key change, so we can cancel the request.
715: */
716: static void
717: hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
718: {
719: hci_change_con_link_key_compl_ep ep;
720: struct hci_link *link;
721: int err;
722:
723: KASSERT(m->m_pkthdr.len >= sizeof(ep));
724: m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
725: m_adj(m, sizeof(ep));
726:
727: ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
728:
729: DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
730:
731: link = hci_link_lookup_handle(unit, ep.con_handle);
732: if (link == NULL || link->hl_type != HCI_LINK_ACL)
733: return;
734:
735: link->hl_flags &= ~HCI_LINK_SECURE_REQ;
736:
737: if (ep.status == 0) {
738: link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_SECURE);
739:
740: if (link->hl_state == HCI_LINK_WAIT_SECURE)
741: link->hl_state = HCI_LINK_OPEN;
742:
743: err = hci_acl_setmode(link);
744: if (err == EINPROGRESS)
745: return;
746: }
747:
748: hci_acl_linkmode(link);
749: }
750:
751: /*
752: * process results of read_bdaddr command_complete event
753: */
754: static void
755: hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
756: {
757: hci_read_bdaddr_rp rp;
758: int s;
759:
760: KASSERT(m->m_pkthdr.len >= sizeof(rp));
761: m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
762: m_adj(m, sizeof(rp));
763:
764: if (rp.status > 0)
765: return;
766:
767: if ((unit->hci_flags & BTF_INIT_BDADDR) == 0)
768: return;
769:
770: bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr);
771:
772: s = splraiseipl(unit->hci_ipl);
773: unit->hci_flags &= ~BTF_INIT_BDADDR;
774: splx(s);
775:
776: wakeup(unit);
777: }
778:
779: /*
780: * process results of read_buffer_size command_complete event
781: */
782: static void
783: hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m)
784: {
785: hci_read_buffer_size_rp rp;
786: int s;
787:
788: KASSERT(m->m_pkthdr.len >= sizeof(rp));
789: m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
790: m_adj(m, sizeof(rp));
791:
792: if (rp.status > 0)
793: return;
794:
795: if ((unit->hci_flags & BTF_INIT_BUFFER_SIZE) == 0)
796: return;
797:
798: unit->hci_max_acl_size = letoh16(rp.max_acl_size);
799: unit->hci_num_acl_pkts = letoh16(rp.num_acl_pkts);
800: unit->hci_max_sco_size = rp.max_sco_size;
801: unit->hci_num_sco_pkts = letoh16(rp.num_sco_pkts);
802:
803: s = splraiseipl(unit->hci_ipl);
804: unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
805: splx(s);
806:
807: wakeup(unit);
808: }
809:
810: /*
811: * process results of read_local_features command_complete event
812: */
813: static void
814: hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
815: {
816: hci_read_local_features_rp rp;
817: int s;
818:
819: KASSERT(m->m_pkthdr.len >= sizeof(rp));
820: m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
821: m_adj(m, sizeof(rp));
822:
823: if (rp.status > 0)
824: return;
825:
826: if ((unit->hci_flags & BTF_INIT_FEATURES) == 0)
827: return;
828:
829: unit->hci_lmp_mask = 0;
830:
831: if (rp.features[0] & HCI_LMP_ROLE_SWITCH)
832: unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
CVSweb