FreeBSD kernel netgraph code
ng_hci_ulpi.c
Go to the documentation of this file.
1/*
2 * ng_hci_ulpi.c
3 */
4
5/*-
6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
7 *
8 * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: ng_hci_ulpi.c,v 1.7 2003/09/08 18:57:51 max Exp $
33 * $FreeBSD$
34 */
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/endian.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>
42#include <sys/queue.h>
43#include <netgraph/ng_message.h>
44#include <netgraph/netgraph.h>
52
53/******************************************************************************
54 ******************************************************************************
55 ** Upper Layer Protocol Interface module
56 ******************************************************************************
57 ******************************************************************************/
58
62
63/*
64 * Process LP_ConnectReq event from the upper layer protocol
65 */
66
67int
69{
70 int link_type;
71
72 if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
74"%s: %s - unit is not ready, state=%#x\n",
75 __func__, NG_NODE_NAME(unit->node), unit->state);
76
77 NG_FREE_ITEM(item);
78
79 return (ENXIO);
80 }
81
82 if (NGI_MSG(item)->header.arglen != sizeof(ng_hci_lp_con_req_ep)) {
84"%s: %s - invalid LP_ConnectReq message size=%d\n",
85 __func__, NG_NODE_NAME(unit->node),
86 NGI_MSG(item)->header.arglen);
87
88 NG_FREE_ITEM(item);
89
90 return (EMSGSIZE);
91 }
92 link_type = ((ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data))->link_type;
93 switch(link_type){
94 case NG_HCI_LINK_ACL:
95 return (ng_hci_lp_acl_con_req(unit, item, hook));
96 case NG_HCI_LINK_SCO:
97 if (hook != unit->sco ) {
99 "%s: %s - LP_ConnectReq for SCO connection came from wrong hook=%p\n",
100 __func__, NG_NODE_NAME(unit->node), hook);
101
102 NG_FREE_ITEM(item);
103
104 return (EINVAL);
105 }
106
107 return (ng_hci_lp_sco_con_req(unit, item, hook));
110 return (ng_hci_lp_le_con_req(unit, item, hook, link_type));
111 default:
112 panic("%s: link_type invalid.", __func__);
113 }
114
115 return (EINVAL);
116} /* ng_hci_lp_con_req */
117
118/*
119 * Request to create new ACL connection
120 */
121
122static int
124{
125 struct acl_con_req {
126 ng_hci_cmd_pkt_t hdr;
127 ng_hci_create_con_cp cp;
128 } __attribute__ ((packed)) *req = NULL;
129 ng_hci_lp_con_req_ep *ep = NULL;
130 ng_hci_unit_con_p con = NULL;
131 ng_hci_neighbor_t *n = NULL;
132 struct mbuf *m = NULL;
133 int error = 0;
134
135 ep = (ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data);
136
137 /*
138 * Only one ACL connection can exist between each pair of units.
139 * So try to find ACL connection descriptor (in any state) that
140 * has requested remote BD_ADDR.
141 *
142 * Two cases:
143 *
144 * 1) We do not have connection to the remote unit. This is simple.
145 * Just create new connection descriptor and send HCI command to
146 * create new connection.
147 *
148 * 2) We do have connection descriptor. We need to check connection
149 * state:
150 *
151 * 2.1) NG_HCI_CON_W4_LP_CON_RSP means that we are in the middle of
152 * accepting connection from the remote unit. This is a race
153 * condition. We will ignore this message.
154 *
155 * 2.2) NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already
156 * requested connection or we just accepted it. In any case
157 * all we need to do here is set appropriate notification bit
158 * and wait.
159 *
160 * 2.3) NG_HCI_CON_OPEN means connection is open. Just reply back
161 * and let upper layer know that we have connection already.
162 */
163
165 if (con != NULL) {
166 switch (con->state) {
167 case NG_HCI_CON_W4_LP_CON_RSP: /* XXX */
168 error = EALREADY;
169 break;
170
172 if (hook == unit->acl)
174 else
176 break;
177
178 case NG_HCI_CON_OPEN: {
179 struct ng_mesg *msg = NULL;
180 ng_hci_lp_con_cfm_ep *cfm = NULL;
181
182 if (hook != NULL && NG_HOOK_IS_VALID(hook)) {
183 NGI_GET_MSG(item, msg);
184 NG_FREE_MSG(msg);
185
187 NGM_HCI_LP_CON_CFM, sizeof(*cfm),
188 M_NOWAIT);
189 if (msg != NULL) {
190 cfm = (ng_hci_lp_con_cfm_ep *)msg->data;
191 cfm->status = 0;
192 cfm->link_type = con->link_type;
193 cfm->con_handle = con->con_handle;
194 bcopy(&con->bdaddr, &cfm->bdaddr,
195 sizeof(cfm->bdaddr));
196
197 /*
198 * This will forward item back to
199 * sender and set item to NULL
200 */
201
202 _NGI_MSG(item) = msg;
203 NG_FWD_ITEM_HOOK(error, item, hook);
204 } else
205 error = ENOMEM;
206 } else
208"%s: %s - Source hook is not valid, hook=%p\n",
209 __func__, NG_NODE_NAME(unit->node),
210 hook);
211 } break;
212
213 default:
214 panic(
215"%s: %s - Invalid connection state=%d\n",
216 __func__, NG_NODE_NAME(unit->node), con->state);
217 break;
218 }
219
220 goto out;
221 }
222
223 /*
224 * If we got here then we need to create new ACL connection descriptor
225 * and submit HCI command. First create new connection desriptor, set
226 * bdaddr and notification flags.
227 */
228
229 con = ng_hci_new_con(unit, NG_HCI_LINK_ACL);
230 if (con == NULL) {
231 error = ENOMEM;
232 goto out;
233 }
234
235 bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
236
237 /*
238 * Create HCI command
239 */
240
241 MGETHDR(m, M_NOWAIT, MT_DATA);
242 if (m == NULL) {
243 ng_hci_free_con(con);
244 error = ENOBUFS;
245 goto out;
246 }
247
248 m->m_pkthdr.len = m->m_len = sizeof(*req);
249 req = mtod(m, struct acl_con_req *);
250 req->hdr.type = NG_HCI_CMD_PKT;
251 req->hdr.length = sizeof(req->cp);
252 req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
254
255 bcopy(&ep->bdaddr, &req->cp.bdaddr, sizeof(req->cp.bdaddr));
256
257 req->cp.pkt_type = (NG_HCI_PKT_DM1|NG_HCI_PKT_DH1);
258 if (unit->features[0] & NG_HCI_LMP_3SLOT)
259 req->cp.pkt_type |= (NG_HCI_PKT_DM3|NG_HCI_PKT_DH3);
260 if (unit->features[0] & NG_HCI_LMP_5SLOT)
261 req->cp.pkt_type |= (NG_HCI_PKT_DM5|NG_HCI_PKT_DH5);
262
263 req->cp.pkt_type &= unit->packet_mask;
264 if ((req->cp.pkt_type & (NG_HCI_PKT_DM1|NG_HCI_PKT_DH1|
267 req->cp.pkt_type = (NG_HCI_PKT_DM1|NG_HCI_PKT_DH1);
268
269 req->cp.pkt_type = htole16(req->cp.pkt_type);
270
271 if ((unit->features[0] & NG_HCI_LMP_SWITCH) && unit->role_switch)
272 req->cp.accept_role_switch = 1;
273 else
274 req->cp.accept_role_switch = 0;
275
276 /*
277 * We may speed up connect by specifying valid parameters.
278 * So check the neighbor cache.
279 */
280
282 if (n == NULL) {
283 req->cp.page_scan_rep_mode = 0;
284 req->cp.page_scan_mode = 0;
285 req->cp.clock_offset = 0;
286 } else {
287 req->cp.page_scan_rep_mode = n->page_scan_rep_mode;
288 req->cp.page_scan_mode = n->page_scan_mode;
289 req->cp.clock_offset = htole16(n->clock_offset);
290 }
291
292 /*
293 * Adust connection state
294 */
295
296 if (hook == unit->acl)
298 else
300
303
304 /*
305 * Queue and send HCI command
306 */
307
308 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
309 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
310 error = ng_hci_send_command(unit);
311out:
312 if (item != NULL)
313 NG_FREE_ITEM(item);
314
315 return (error);
316} /* ng_hci_lp_acl_con_req */
317
318/*
319 * Request to create new SCO connection
320 */
321
322static int
324{
325 struct sco_con_req {
326 ng_hci_cmd_pkt_t hdr;
327 ng_hci_add_sco_con_cp cp;
328 } __attribute__ ((packed)) *req = NULL;
329 ng_hci_lp_con_req_ep *ep = NULL;
330 ng_hci_unit_con_p acl_con = NULL, sco_con = NULL;
331 struct mbuf *m = NULL;
332 int error = 0;
333
334 ep = (ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data);
335
336 /*
337 * SCO connection without ACL link
338 *
339 * If upper layer requests SCO connection and there is no open ACL
340 * connection to the desired remote unit, we will reject the request.
341 */
342
343 LIST_FOREACH(acl_con, &unit->con_list, next)
344 if (acl_con->link_type == NG_HCI_LINK_ACL &&
345 acl_con->state == NG_HCI_CON_OPEN &&
346 bcmp(&acl_con->bdaddr, &ep->bdaddr, sizeof(bdaddr_t)) == 0)
347 break;
348
349 if (acl_con == NULL) {
351"%s: %s - No open ACL connection to bdaddr=%x:%x:%x:%x:%x:%x\n",
352 __func__, NG_NODE_NAME(unit->node),
353 ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
354 ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
355
356 error = ENOENT;
357 goto out;
358 }
359
360 /*
361 * Multiple SCO connections can exist between the same pair of units.
362 * We assume that multiple SCO connections have to be opened one after
363 * another.
364 *
365 * Try to find SCO connection descriptor that matches the following:
366 *
367 * 1) sco_con->link_type == NG_HCI_LINK_SCO
368 *
369 * 2) sco_con->state == NG_HCI_CON_W4_LP_CON_RSP ||
370 * sco_con->state == NG_HCI_CON_W4_CONN_COMPLETE
371 *
372 * 3) sco_con->bdaddr == ep->bdaddr
373 *
374 * Two cases:
375 *
376 * 1) We do not have connection descriptor. This is simple. Just
377 * create new connection and submit Add_SCO_Connection command.
378 *
379 * 2) We do have connection descriptor. We need to check the state.
380 *
381 * 2.1) NG_HCI_CON_W4_LP_CON_RSP means we in the middle of accepting
382 * connection from the remote unit. This is a race condition and
383 * we will ignore the request.
384 *
385 * 2.2) NG_HCI_CON_W4_CONN_COMPLETE means upper layer already requested
386 * connection or we just accepted it.
387 */
388
389 LIST_FOREACH(sco_con, &unit->con_list, next)
390 if (sco_con->link_type == NG_HCI_LINK_SCO &&
391 (sco_con->state == NG_HCI_CON_W4_LP_CON_RSP ||
392 sco_con->state == NG_HCI_CON_W4_CONN_COMPLETE) &&
393 bcmp(&sco_con->bdaddr, &ep->bdaddr, sizeof(bdaddr_t)) == 0)
394 break;
395
396 if (sco_con != NULL) {
397 switch (sco_con->state) {
398 case NG_HCI_CON_W4_LP_CON_RSP: /* XXX */
399 error = EALREADY;
400 break;
401
403 sco_con->flags |= NG_HCI_CON_NOTIFY_SCO;
404 break;
405
406 default:
407 panic(
408"%s: %s - Invalid connection state=%d\n",
409 __func__, NG_NODE_NAME(unit->node),
410 sco_con->state);
411 break;
412 }
413
414 goto out;
415 }
416
417 /*
418 * If we got here then we need to create new SCO connection descriptor
419 * and submit HCI command.
420 */
421
422 sco_con = ng_hci_new_con(unit, NG_HCI_LINK_SCO);
423 if (sco_con == NULL) {
424 error = ENOMEM;
425 goto out;
426 }
427
428 bcopy(&ep->bdaddr, &sco_con->bdaddr, sizeof(sco_con->bdaddr));
429
430 /*
431 * Create HCI command
432 */
433
434 MGETHDR(m, M_NOWAIT, MT_DATA);
435 if (m == NULL) {
436 ng_hci_free_con(sco_con);
437 error = ENOBUFS;
438 goto out;
439 }
440
441 m->m_pkthdr.len = m->m_len = sizeof(*req);
442 req = mtod(m, struct sco_con_req *);
443 req->hdr.type = NG_HCI_CMD_PKT;
444 req->hdr.length = sizeof(req->cp);
445 req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
447
448 req->cp.con_handle = htole16(acl_con->con_handle);
449
450 req->cp.pkt_type = NG_HCI_PKT_HV1;
451 if (unit->features[1] & NG_HCI_LMP_HV2_PKT)
452 req->cp.pkt_type |= NG_HCI_PKT_HV2;
453 if (unit->features[1] & NG_HCI_LMP_HV3_PKT)
454 req->cp.pkt_type |= NG_HCI_PKT_HV3;
455
456 req->cp.pkt_type &= unit->packet_mask;
457 if ((req->cp.pkt_type & (NG_HCI_PKT_HV1|
459 NG_HCI_PKT_HV3)) == 0)
460 req->cp.pkt_type = NG_HCI_PKT_HV1;
461
462 req->cp.pkt_type = htole16(req->cp.pkt_type);
463
464 /*
465 * Adust connection state
466 */
467
468 sco_con->flags |= NG_HCI_CON_NOTIFY_SCO;
469
470 sco_con->state = NG_HCI_CON_W4_CONN_COMPLETE;
471 ng_hci_con_timeout(sco_con);
472
473 /*
474 * Queue and send HCI command
475 */
476
477 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
478 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
479 error = ng_hci_send_command(unit);
480out:
481 NG_FREE_ITEM(item);
482
483 return (error);
484} /* ng_hci_lp_sco_con_req */
485
486static int
487ng_hci_lp_le_con_req(ng_hci_unit_p unit, item_p item, hook_p hook, int link_type)
488{
489 struct acl_con_req {
490 ng_hci_cmd_pkt_t hdr;
491 ng_hci_le_create_connection_cp cp;
492 } __attribute__ ((packed)) *req = NULL;
493 ng_hci_lp_con_req_ep *ep = NULL;
494 ng_hci_unit_con_p con = NULL;
495 struct mbuf *m = NULL;
496 int error = 0;
497
498 ep = (ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data);
499 if((link_type != NG_HCI_LINK_LE_PUBLIC)&&
500 (link_type != NG_HCI_LINK_LE_RANDOM)){
501 printf("%s: Link type %d Cannot be here \n", __func__,
502 link_type);
503 }
504 /*
505 * Only one ACL connection can exist between each pair of units.
506 * So try to find ACL connection descriptor (in any state) that
507 * has requested remote BD_ADDR.
508 *
509 * Two cases:
510 *
511 * 1) We do not have connection to the remote unit. This is simple.
512 * Just create new connection descriptor and send HCI command to
513 * create new connection.
514 *
515 * 2) We do have connection descriptor. We need to check connection
516 * state:
517 *
518 * 2.1) NG_HCI_CON_W4_LP_CON_RSP means that we are in the middle of
519 * accepting connection from the remote unit. This is a race
520 * condition. We will ignore this message.
521 *
522 * 2.2) NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already
523 * requested connection or we just accepted it. In any case
524 * all we need to do here is set appropriate notification bit
525 * and wait.
526 *
527 * 2.3) NG_HCI_CON_OPEN means connection is open. Just reply back
528 * and let upper layer know that we have connection already.
529 */
530
531 con = ng_hci_con_by_bdaddr(unit, &ep->bdaddr, link_type);
532 if (con != NULL) {
533 switch (con->state) {
534 case NG_HCI_CON_W4_LP_CON_RSP: /* XXX */
535 error = EALREADY;
536 break;
537
539 if (hook != unit->sco)
541 else
543 break;
544
545 case NG_HCI_CON_OPEN: {
546 struct ng_mesg *msg = NULL;
547 ng_hci_lp_con_cfm_ep *cfm = NULL;
548
549 if (hook != NULL && NG_HOOK_IS_VALID(hook)) {
550 NGI_GET_MSG(item, msg);
551 NG_FREE_MSG(msg);
552
554 NGM_HCI_LP_CON_CFM, sizeof(*cfm),
555 M_NOWAIT);
556 if (msg != NULL) {
557 cfm = (ng_hci_lp_con_cfm_ep *)msg->data;
558 cfm->status = 0;
559 cfm->link_type = con->link_type;
560 cfm->con_handle = con->con_handle;
561 bcopy(&con->bdaddr, &cfm->bdaddr,
562 sizeof(cfm->bdaddr));
563
564 /*
565 * This will forward item back to
566 * sender and set item to NULL
567 */
568
569 _NGI_MSG(item) = msg;
570 NG_FWD_ITEM_HOOK(error, item, hook);
571 } else
572 error = ENOMEM;
573 } else
575"%s: %s - Source hook is not valid, hook=%p\n",
576 __func__, NG_NODE_NAME(unit->node),
577 hook);
578 } break;
579
580 default:
581 panic(
582"%s: %s - Invalid connection state=%d\n",
583 __func__, NG_NODE_NAME(unit->node), con->state);
584 break;
585 }
586
587 goto out;
588 }
589
590 /*
591 * If we got here then we need to create new ACL connection descriptor
592 * and submit HCI command. First create new connection desriptor, set
593 * bdaddr and notification flags.
594 */
595
596 con = ng_hci_new_con(unit, link_type);
597 if (con == NULL) {
598 error = ENOMEM;
599 goto out;
600 }
601
602 bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
603
604 /*
605 * Create HCI command
606 */
607
608 MGETHDR(m, M_NOWAIT, MT_DATA);
609 if (m == NULL) {
610 ng_hci_free_con(con);
611 error = ENOBUFS;
612 goto out;
613 }
614
615 m->m_pkthdr.len = m->m_len = sizeof(*req);
616 req = mtod(m, struct acl_con_req *);
617 req->hdr.type = NG_HCI_CMD_PKT;
618 req->hdr.length = sizeof(req->cp);
619 req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LE,
621
622 bcopy(&ep->bdaddr, &req->cp.peer_addr, sizeof(req->cp.peer_addr));
623 req->cp.own_address_type = 0;
624 req->cp.peer_addr_type = (link_type == NG_HCI_LINK_LE_RANDOM)? 1:0;
625 req->cp.scan_interval = htole16(4);
626 req->cp.scan_window = htole16(4);
627 req->cp.filter_policy = 0;
628 req->cp.conn_interval_min = htole16(0xf);
629 req->cp.conn_interval_max = htole16(0xf);
630 req->cp.conn_latency = htole16(0);
631 req->cp.supervision_timeout = htole16(0xc80);
632 req->cp.min_ce_length = htole16(1);
633 req->cp.max_ce_length = htole16(1);
634 /*
635 * Adust connection state
636 */
637
638 if (hook != unit->sco)
640 else
642
645
646 /*
647 * Queue and send HCI command
648 */
649
650 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
651 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
652 error = ng_hci_send_command(unit);
653out:
654 if (item != NULL)
655 NG_FREE_ITEM(item);
656
657 return (error);
658} /* ng_hci_lp_acl_con_req */
659
660/*
661 * Process LP_DisconnectReq event from the upper layer protocol
662 */
663
664int
666{
667 struct discon_req {
668 ng_hci_cmd_pkt_t hdr;
669 ng_hci_discon_cp cp;
670 } __attribute__ ((packed)) *req = NULL;
671 ng_hci_lp_discon_req_ep *ep = NULL;
672 ng_hci_unit_con_p con = NULL;
673 struct mbuf *m = NULL;
674 int error = 0;
675
676 /* Check if unit is ready */
677 if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
679"%s: %s - unit is not ready, state=%#x\n",
680 __func__, NG_NODE_NAME(unit->node), unit->state);
681
682 error = ENXIO;
683 goto out;
684 }
685
686 if (NGI_MSG(item)->header.arglen != sizeof(*ep)) {
688"%s: %s - invalid LP_DisconnectReq message size=%d\n",
689 __func__, NG_NODE_NAME(unit->node),
690 NGI_MSG(item)->header.arglen);
691
692 error = EMSGSIZE;
693 goto out;
694 }
695
696 ep = (ng_hci_lp_discon_req_ep *)(NGI_MSG(item)->data);
697
698 con = ng_hci_con_by_handle(unit, ep->con_handle);
699 if (con == NULL) {
701"%s: %s - invalid connection handle=%d\n",
702 __func__, NG_NODE_NAME(unit->node), ep->con_handle);
703
704 error = ENOENT;
705 goto out;
706 }
707
708 if (con->state != NG_HCI_CON_OPEN) {
710"%s: %s - invalid connection state=%d, handle=%d\n",
711 __func__, NG_NODE_NAME(unit->node), con->state,
712 ep->con_handle);
713
714 error = EINVAL;
715 goto out;
716 }
717
718 /*
719 * Create HCI command
720 */
721
722 MGETHDR(m, M_NOWAIT, MT_DATA);
723 if (m == NULL) {
724 error = ENOBUFS;
725 goto out;
726 }
727
728 m->m_pkthdr.len = m->m_len = sizeof(*req);
729 req = mtod(m, struct discon_req *);
730 req->hdr.type = NG_HCI_CMD_PKT;
731 req->hdr.length = sizeof(req->cp);
732 req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
734
735 req->cp.con_handle = htole16(ep->con_handle);
736 req->cp.reason = ep->reason;
737
738 /*
739 * Queue and send HCI command
740 */
741
742 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
743 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
744 error = ng_hci_send_command(unit);
745out:
746 NG_FREE_ITEM(item);
747
748 return (error);
749} /* ng_hci_lp_discon_req */
750
751/*
752 * Send LP_ConnectCfm event to the upper layer protocol
753 */
754
755int
757{
758 ng_hci_unit_p unit = con->unit;
759 struct ng_mesg *msg = NULL;
760 ng_hci_lp_con_cfm_ep *ep = NULL;
761 int error;
762
763 /*
764 * Check who wants to be notified. For ACL links both ACL and SCO
765 * upstream hooks will be notified (if required). For SCO links
766 * only SCO upstream hook will receive notification
767 */
768
769 if (con->link_type != NG_HCI_LINK_SCO &&
771 if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
773 sizeof(*ep), M_NOWAIT);
774 if (msg != NULL) {
775 ep = (ng_hci_lp_con_cfm_ep *) msg->data;
776 ep->status = status;
777 ep->link_type = con->link_type;
778 ep->con_handle = con->con_handle;
779 bcopy(&con->bdaddr, &ep->bdaddr,
780 sizeof(ep->bdaddr));
781
782 NG_SEND_MSG_HOOK(error, unit->node, msg,
783 unit->acl, 0);
784 }
785 } else
787"%s: %s - ACL hook not valid, hook=%p\n",
788 __func__, NG_NODE_NAME(unit->node), unit->acl);
789
790 con->flags &= ~NG_HCI_CON_NOTIFY_ACL;
791 }
792
793 if (con->flags & NG_HCI_CON_NOTIFY_SCO) {
794 if (unit->sco != NULL && NG_HOOK_IS_VALID(unit->sco)) {
796 sizeof(*ep), M_NOWAIT);
797 if (msg != NULL) {
798 ep = (ng_hci_lp_con_cfm_ep *) msg->data;
799 ep->status = status;
800 ep->link_type = con->link_type;
801 ep->con_handle = con->con_handle;
802 bcopy(&con->bdaddr, &ep->bdaddr,
803 sizeof(ep->bdaddr));
804
805 NG_SEND_MSG_HOOK(error, unit->node, msg,
806 unit->sco, 0);
807 }
808 } else
810"%s: %s - SCO hook not valid, hook=%p\n",
811 __func__, NG_NODE_NAME(unit->node), unit->acl);
812
813 con->flags &= ~NG_HCI_CON_NOTIFY_SCO;
814 }
815
816 return (0);
817} /* ng_hci_lp_con_cfm */
818
819int
821{
822 ng_hci_unit_p unit = con->unit;
823 struct ng_mesg *msg = NULL;
824 ng_hci_lp_enc_change_ep *ep = NULL;
825 int error;
826
827 if (con->link_type != NG_HCI_LINK_SCO) {
828 if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
830 sizeof(*ep), M_NOWAIT);
831 if (msg != NULL) {
832 ep = (ng_hci_lp_enc_change_ep *) msg->data;
833 ep->status = status;
834 ep->link_type = con->link_type;
835 ep->con_handle = con->con_handle;
836
837 NG_SEND_MSG_HOOK(error, unit->node, msg,
838 unit->acl, 0);
839 }
840 } else
842"%s: %s - ACL hook not valid, hook=%p\n",
843 __func__, NG_NODE_NAME(unit->node), unit->acl);
844 }
845 return (0);
846} /* ng_hci_lp_con_cfm */
847
848/*
849 * Send LP_ConnectInd event to the upper layer protocol
850 */
851
852int
854{
855 ng_hci_unit_p unit = con->unit;
856 struct ng_mesg *msg = NULL;
857 ng_hci_lp_con_ind_ep *ep = NULL;
858 hook_p hook = NULL;
859 int error = 0;
860
861 /*
862 * Connection_Request event is generated for specific link type.
863 * Use link_type to select upstream hook.
864 */
865
866 if (con->link_type != NG_HCI_LINK_SCO)
867 hook = unit->acl;
868 else
869 hook = unit->sco;
870
871 if (hook != NULL && NG_HOOK_IS_VALID(hook)) {
873 sizeof(*ep), M_NOWAIT);
874 if (msg == NULL)
875 return (ENOMEM);
876
877 ep = (ng_hci_lp_con_ind_ep *)(msg->data);
878 ep->link_type = con->link_type;
879 bcopy(uclass, ep->uclass, sizeof(ep->uclass));
880 bcopy(&con->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));
881
882 NG_SEND_MSG_HOOK(error, unit->node, msg, hook, 0);
883 } else {
885"%s: %s - Upstream hook is not connected or not valid, hook=%p\n",
886 __func__, NG_NODE_NAME(unit->node), hook);
887
888 error = ENOTCONN;
889 }
890
891 return (error);
892} /* ng_hci_lp_con_ind */
893
894/*
895 * Process LP_ConnectRsp event from the upper layer protocol
896 */
897
898int
900{
901 struct con_rsp_req {
902 ng_hci_cmd_pkt_t hdr;
903 union {
904 ng_hci_accept_con_cp acc;
905 ng_hci_reject_con_cp rej;
906 } __attribute__ ((packed)) cp;
907 } __attribute__ ((packed)) *req = NULL;
908 ng_hci_lp_con_rsp_ep *ep = NULL;
909 ng_hci_unit_con_p con = NULL;
910 struct mbuf *m = NULL;
911 int error = 0;
912
913 /* Check if unit is ready */
914 if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
916"%s: %s - unit is not ready, state=%#x\n",
917 __func__, NG_NODE_NAME(unit->node), unit->state);
918
919 error = ENXIO;
920 goto out;
921 }
922
923 if (NGI_MSG(item)->header.arglen != sizeof(*ep)) {
925"%s: %s - invalid LP_ConnectRsp message size=%d\n",
926 __func__, NG_NODE_NAME(unit->node),
927 NGI_MSG(item)->header.arglen);
928
929 error = EMSGSIZE;
930 goto out;
931 }
932
933 ep = (ng_hci_lp_con_rsp_ep *)(NGI_MSG(item)->data);
934
935 /*
936 * Here we have to deal with race. Upper layers might send conflicting
937 * requests. One might send Accept and other Reject. We will not try
938 * to solve all the problems, so first request will always win.
939 *
940 * Try to find connection that matches the following:
941 *
942 * 1) con->link_type == ep->link_type
943 *
944 * 2) con->state == NG_HCI_CON_W4_LP_CON_RSP ||
945 * con->state == NG_HCI_CON_W4_CONN_COMPLETE
946 *
947 * 3) con->bdaddr == ep->bdaddr
948 *
949 * Two cases:
950 *
951 * 1) We do not have connection descriptor. Could be bogus request or
952 * we have rejected connection already.
953 *
954 * 2) We do have connection descriptor. Then we need to check state:
955 *
956 * 2.1) NG_HCI_CON_W4_LP_CON_RSP means upper layer has requested
957 * connection and it is a first response from the upper layer.
958 * if "status == 0" (Accept) then we will send Accept_Connection
959 * command and change connection state to W4_CONN_COMPLETE, else
960 * send reject and delete connection.
961 *
962 * 2.2) NG_HCI_CON_W4_CONN_COMPLETE means that we already accepted
963 * connection. If "status == 0" we just need to link request
964 * and wait, else ignore Reject request.
965 */
966
967 LIST_FOREACH(con, &unit->con_list, next)
968 if (con->link_type == ep->link_type &&
971 bcmp(&con->bdaddr, &ep->bdaddr, sizeof(bdaddr_t)) == 0)
972 break;
973
974 if (con == NULL) {
975 /* Reject for non-existing connection is fine */
976 error = (ep->status == 0)? ENOENT : 0;
977 goto out;
978 }
979
980 /*
981 * Remove connection timeout and check connection state.
982 * Note: if ng_hci_con_untimeout() fails (returns non-zero value) then
983 * timeout already happened and event went into node's queue.
984 */
985
986 if ((error = ng_hci_con_untimeout(con)) != 0)
987 goto out;
988
989 switch (con->state) {
991
992 /*
993 * Create HCI command
994 */
995
996 MGETHDR(m, M_NOWAIT, MT_DATA);
997 if (m == NULL) {
998 error = ENOBUFS;
999 goto out;
1000 }
1001
1002 req = mtod(m, struct con_rsp_req *);
1003 req->hdr.type = NG_HCI_CMD_PKT;
1004
1005 if (ep->status == 0) {
1006 req->hdr.length = sizeof(req->cp.acc);
1007 req->hdr.opcode = htole16(NG_HCI_OPCODE(
1010
1011 bcopy(&ep->bdaddr, &req->cp.acc.bdaddr,
1012 sizeof(req->cp.acc.bdaddr));
1013
1014 /*
1015 * We are accepting connection, so if we support role
1016 * switch and role switch was enabled then set role to
1017 * NG_HCI_ROLE_MASTER and let LM peform role switch.
1018 * Otherwise we remain slave. In this case LM WILL NOT
1019 * perform role switch.
1020 */
1021
1022 if ((unit->features[0] & NG_HCI_LMP_SWITCH) &&
1023 unit->role_switch)
1024 req->cp.acc.role = NG_HCI_ROLE_MASTER;
1025 else
1026 req->cp.acc.role = NG_HCI_ROLE_SLAVE;
1027
1028 /*
1029 * Adjust connection state
1030 */
1031
1032 if (hook == unit->acl)
1034 else
1036
1038 ng_hci_con_timeout(con);
1039 } else {
1040 req->hdr.length = sizeof(req->cp.rej);
1041 req->hdr.opcode = htole16(NG_HCI_OPCODE(
1044
1045 bcopy(&ep->bdaddr, &req->cp.rej.bdaddr,
1046 sizeof(req->cp.rej.bdaddr));
1047
1048 req->cp.rej.reason = ep->status;
1049
1050 /*
1051 * Free connection descritor
1052 * Item will be deleted just before return.
1053 */
1054
1055 ng_hci_free_con(con);
1056 }
1057
1058 m->m_pkthdr.len = m->m_len = sizeof(req->hdr) + req->hdr.length;
1059
1060 /* Queue and send HCI command */
1061 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
1062 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
1063 error = ng_hci_send_command(unit);
1064 break;
1065
1067 if (ep->status == 0) {
1068 if (hook == unit->acl)
1070 else
1072 } else
1073 error = EPERM;
1074 break;
1075
1076 default:
1077 panic(
1078"%s: %s - Invalid connection state=%d\n",
1079 __func__, NG_NODE_NAME(unit->node), con->state);
1080 break;
1081 }
1082out:
1083 NG_FREE_ITEM(item);
1084
1085 return (error);
1086} /* ng_hci_lp_con_rsp */
1087
1088/*
1089 * Send LP_DisconnectInd to the upper layer protocol
1090 */
1091
1092int
1094{
1095 ng_hci_unit_p unit = con->unit;
1096 struct ng_mesg *msg = NULL;
1097 ng_hci_lp_discon_ind_ep *ep = NULL;
1098 int error = 0;
1099
1100 /*
1101 * Disconnect_Complete event is generated for specific connection
1102 * handle. For ACL connection handles both ACL and SCO upstream
1103 * hooks will receive notification. For SCO connection handles
1104 * only SCO upstream hook will receive notification.
1105 */
1106
1107 if (con->link_type != NG_HCI_LINK_SCO) {
1108 if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
1110 NGM_HCI_LP_DISCON_IND, sizeof(*ep), M_NOWAIT);
1111 if (msg == NULL)
1112 return (ENOMEM);
1113
1114 ep = (ng_hci_lp_discon_ind_ep *) msg->data;
1115 ep->reason = reason;
1116 ep->link_type = con->link_type;
1117 ep->con_handle = con->con_handle;
1118
1119 NG_SEND_MSG_HOOK(error,unit->node,msg,unit->acl,0);
1120 } else
1122"%s: %s - ACL hook is not connected or not valid, hook=%p\n",
1123 __func__, NG_NODE_NAME(unit->node), unit->acl);
1124 }
1125
1126 if (unit->sco != NULL && NG_HOOK_IS_VALID(unit->sco)) {
1128 sizeof(*ep), M_NOWAIT);
1129 if (msg == NULL)
1130 return (ENOMEM);
1131
1132 ep = (ng_hci_lp_discon_ind_ep *) msg->data;
1133 ep->reason = reason;
1134 ep->link_type = con->link_type;
1135 ep->con_handle = con->con_handle;
1136
1137 NG_SEND_MSG_HOOK(error, unit->node, msg, unit->sco, 0);
1138 } else
1140"%s: %s - SCO hook is not connected or not valid, hook=%p\n",
1141 __func__, NG_NODE_NAME(unit->node), unit->sco);
1142
1143 return (0);
1144} /* ng_hci_lp_discon_ind */
1145
1146/*
1147 * Process LP_QoSReq action from the upper layer protocol
1148 */
1149
1150int
1152{
1153 struct qos_setup_req {
1154 ng_hci_cmd_pkt_t hdr;
1155 ng_hci_qos_setup_cp cp;
1156 } __attribute__ ((packed)) *req = NULL;
1157 ng_hci_lp_qos_req_ep *ep = NULL;
1158 ng_hci_unit_con_p con = NULL;
1159 struct mbuf *m = NULL;
1160 int error = 0;
1161
1162 /* Check if unit is ready */
1163 if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
1165"%s: %s - unit is not ready, state=%#x\n",
1166 __func__, NG_NODE_NAME(unit->node), unit->state);
1167
1168 error = ENXIO;
1169 goto out;
1170 }
1171
1172 if (NGI_MSG(item)->header.arglen != sizeof(*ep)) {
1174"%s: %s - invalid LP_QoSSetupReq message size=%d\n",
1175 __func__, NG_NODE_NAME(unit->node),
1176 NGI_MSG(item)->header.arglen);
1177
1178 error = EMSGSIZE;
1179 goto out;
1180 }
1181
1182 ep = (ng_hci_lp_qos_req_ep *)(NGI_MSG(item)->data);
1183
1184 con = ng_hci_con_by_handle(unit, ep->con_handle);
1185 if (con == NULL) {
1186 NG_HCI_ERR(
1187"%s: %s - invalid connection handle=%d\n",
1188 __func__, NG_NODE_NAME(unit->node), ep->con_handle);
1189
1190 error = EINVAL;
1191 goto out;
1192 }
1193
1194 if (con->link_type != NG_HCI_LINK_ACL) {
1195 NG_HCI_ERR("%s: %s - invalid link type=%d\n",
1196 __func__, NG_NODE_NAME(unit->node), con->link_type);
1197
1198 error = EINVAL;
1199 goto out;
1200 }
1201
1202 if (con->state != NG_HCI_CON_OPEN) {
1203 NG_HCI_ERR(
1204"%s: %s - invalid connection state=%d, handle=%d\n",
1205 __func__, NG_NODE_NAME(unit->node), con->state,
1206 con->con_handle);
1207
1208 error = EINVAL;
1209 goto out;
1210 }
1211
1212 /*
1213 * Create HCI command
1214 */
1215
1216 MGETHDR(m, M_NOWAIT, MT_DATA);
1217 if (m == NULL) {
1218 error = ENOBUFS;
1219 goto out;
1220 }
1221
1222 m->m_pkthdr.len = m->m_len = sizeof(*req);
1223 req = mtod(m, struct qos_setup_req *);
1224 req->hdr.type = NG_HCI_CMD_PKT;
1225 req->hdr.length = sizeof(req->cp);
1226 req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_POLICY,
1228
1229 req->cp.con_handle = htole16(ep->con_handle);
1230 req->cp.flags = ep->flags;
1231 req->cp.service_type = ep->service_type;
1232 req->cp.token_rate = htole32(ep->token_rate);
1233 req->cp.peak_bandwidth = htole32(ep->peak_bandwidth);
1234 req->cp.latency = htole32(ep->latency);
1235 req->cp.delay_variation = htole32(ep->delay_variation);
1236
1237 /*
1238 * Adjust connection state
1239 */
1240
1241 if (hook == unit->acl)
1243 else
1245
1246 /*
1247 * Queue and send HCI command
1248 */
1249
1250 NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
1251 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
1252 error = ng_hci_send_command(unit);
1253out:
1254 NG_FREE_ITEM(item);
1255
1256 return (error);
1257} /* ng_hci_lp_qos_req */
1258
1259/*
1260 * Send LP_QoSCfm event to the upper layer protocol
1261 */
1262
1263int
1265{
1266 ng_hci_unit_p unit = con->unit;
1267 struct ng_mesg *msg = NULL;
1268 ng_hci_lp_qos_cfm_ep *ep = NULL;
1269 int error;
1270
1271 if (con->flags & NG_HCI_CON_NOTIFY_ACL) {
1272 if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
1274 sizeof(*ep), M_NOWAIT);
1275 if (msg != NULL) {
1276 ep = (ng_hci_lp_qos_cfm_ep *) msg->data;
1277 ep->status = status;
1278 ep->con_handle = con->con_handle;
1279
1280 NG_SEND_MSG_HOOK(error, unit->node, msg,
1281 unit->acl, 0);
1282 }
1283 } else
1285"%s: %s - ACL hook not valid, hook=%p\n",
1286 __func__, NG_NODE_NAME(unit->node), unit->acl);
1287
1288 con->flags &= ~NG_HCI_CON_NOTIFY_ACL;
1289 }
1290
1291 if (con->flags & NG_HCI_CON_NOTIFY_SCO) {
1292 if (unit->sco != NULL && NG_HOOK_IS_VALID(unit->sco)) {
1294 sizeof(*ep), M_NOWAIT);
1295 if (msg != NULL) {
1296 ep = (ng_hci_lp_qos_cfm_ep *) msg->data;
1297 ep->status = status;
1298 ep->con_handle = con->con_handle;
1299
1300 NG_SEND_MSG_HOOK(error, unit->node, msg,
1301 unit->sco, 0);
1302 }
1303 } else
1305"%s: %s - SCO hook not valid, hook=%p\n",
1306 __func__, NG_NODE_NAME(unit->node), unit->sco);
1307
1308 con->flags &= ~NG_HCI_CON_NOTIFY_SCO;
1309 }
1310
1311 return (0);
1312} /* ng_hci_lp_qos_cfm */
1313
1314/*
1315 * Send LP_QoSViolationInd event to the upper layer protocol
1316 */
1317
1318int
1320{
1321 ng_hci_unit_p unit = con->unit;
1322 struct ng_mesg *msg = NULL;
1323 ng_hci_lp_qos_ind_ep *ep = NULL;
1324 int error;
1325
1326 /*
1327 * QoS Violation can only be generated for ACL connection handles.
1328 * Both ACL and SCO upstream hooks will receive notification.
1329 */
1330
1331 if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
1333 sizeof(*ep), M_NOWAIT);
1334 if (msg == NULL)
1335 return (ENOMEM);
1336
1337 ep = (ng_hci_lp_qos_ind_ep *) msg->data;
1338 ep->con_handle = con->con_handle;
1339
1340 NG_SEND_MSG_HOOK(error, unit->node, msg, unit->acl, 0);
1341 } else
1343"%s: %s - ACL hook is not connected or not valid, hook=%p\n",
1344 __func__, NG_NODE_NAME(unit->node), unit->acl);
1345
1346 if (unit->sco != NULL && NG_HOOK_IS_VALID(unit->sco)) {
1348 sizeof(*ep), M_NOWAIT);
1349 if (msg == NULL)
1350 return (ENOMEM);
1351
1352 ep = (ng_hci_lp_qos_ind_ep *) msg->data;
1353 ep->con_handle = con->con_handle;
1354
1355 NG_SEND_MSG_HOOK(error, unit->node, msg, unit->sco, 0);
1356 } else
1358"%s: %s - SCO hook is not connected or not valid, hook=%p\n",
1359 __func__, NG_NODE_NAME(unit->node), unit->sco);
1360
1361 return (0);
1362} /* ng_hci_lp_qos_ind */
1363
1364/*
1365 * Process connection timeout
1366 */
1367
1368void
1369ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
1370{
1371 ng_hci_unit_p unit = NULL;
1372 ng_hci_unit_con_p con = NULL;
1373
1374 if (NG_NODE_NOT_VALID(node)) {
1375 printf("%s: Netgraph node is not valid\n", __func__);
1376 return;
1377 }
1378
1379 unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
1380 con = ng_hci_con_by_handle(unit, con_handle);
1381
1382 if (con == NULL) {
1384"%s: %s - could not find connection, handle=%d\n",
1385 __func__, NG_NODE_NAME(node), con_handle);
1386 return;
1387 }
1388
1389 if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) {
1391"%s: %s - no pending connection timeout, handle=%d, state=%d, flags=%#x\n",
1392 __func__, NG_NODE_NAME(node), con_handle, con->state,
1393 con->flags);
1394 return;
1395 }
1396
1397 con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
1398
1399 /*
1400 * We expect to receive connection timeout in one of the following
1401 * states:
1402 *
1403 * 1) NG_HCI_CON_W4_LP_CON_RSP means that upper layer has not responded
1404 * to our LP_CON_IND. Do nothing and destroy connection. Remote peer
1405 * most likely already gave up on us.
1406 *
1407 * 2) NG_HCI_CON_W4_CONN_COMPLETE means upper layer requested connection
1408 * (or we in the process of accepting it) and baseband has timedout
1409 * on us. Inform upper layers and send LP_CON_CFM.
1410 */
1411
1412 switch (con->state) {
1414 break;
1415
1417 ng_hci_lp_con_cfm(con, 0xee);
1418 break;
1419
1420 default:
1421 panic(
1422"%s: %s - Invalid connection state=%d\n",
1423 __func__, NG_NODE_NAME(node), con->state);
1424 break;
1425 }
1426
1427 ng_hci_free_con(con);
1428} /* ng_hci_process_con_timeout */
#define NGI_MSG(i)
Definition: netgraph.h:834
#define _NGI_MSG(i)
Definition: netgraph.h:693
#define NG_NODE_NOT_VALID(node)
Definition: netgraph.h:611
#define NG_FWD_ITEM_HOOK(error, item, hook)
Definition: netgraph.h:898
#define NG_NODE_NAME(node)
Definition: netgraph.h:603
#define NG_FREE_ITEM(item)
Definition: netgraph.h:847
#define NG_FREE_MSG(msg)
Definition: netgraph.h:938
#define NG_HOOK_IS_VALID(hook)
Definition: netgraph.h:338
#define NGI_GET_MSG(i, m)
Definition: netgraph.h:858
#define NG_NODE_PRIVATE(node)
Definition: netgraph.h:609
#define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr)
Definition: netgraph.h:958
#define NG_BT_MBUFQ_ENQUEUE(q, i)
Definition: ng_bluetooth.h:99
#define NG_HCI_CON_OPEN
Definition: ng_hci.h:568
#define NG_HCI_OCF_DISCON
Definition: ng_hci.h:734
#define NG_HCI_PKT_DM1
Definition: ng_hci.h:128
#define NG_HCI_OGF_LE
Definition: ng_hci.h:1528
#define NG_HCI_OCF_ACCEPT_CON
Definition: ng_hci.h:748
#define NG_HCI_LMP_5SLOT
Definition: ng_hci.h:94
#define NGM_HCI_LP_QOS_IND
Definition: ng_hci.h:535
#define NG_HCI_PKT_HV1
Definition: ng_hci.h:130
#define NG_HCI_PKT_HV3
Definition: ng_hci.h:132
#define NG_HCI_CMD_PKT
Definition: ng_hci.h:408
#define NG_HCI_PKT_DH1
Definition: ng_hci.h:129
#define NGM_HCI_LP_CON_IND
Definition: ng_hci.h:492
#define NG_HCI_OCF_REJECT_CON
Definition: ng_hci.h:755
#define NG_HCI_CON_W4_LP_CON_RSP
Definition: ng_hci.h:566
#define NG_HCI_LINK_LE_RANDOM
Definition: ng_hci.h:123
#define NG_HCI_LMP_3SLOT
Definition: ng_hci.h:93
#define NG_HCI_OGF_LINK_POLICY
Definition: ng_hci.h:870
#define NG_HCI_LMP_SWITCH
Definition: ng_hci.h:98
#define NG_HCI_PKT_DM3
Definition: ng_hci.h:134
#define NG_HCI_OCF_ADD_SCO_CON
Definition: ng_hci.h:741
#define NG_HCI_OCF_CREATE_CON
Definition: ng_hci.h:723
#define NG_HCI_OCF_LE_CREATE_CONNECTION
Definition: ng_hci.h:1617
#define NGM_HCI_COOKIE
Definition: ng_hci.h:60
#define NGM_HCI_LP_CON_CFM
Definition: ng_hci.h:483
#define NG_HCI_UNIT_READY
Definition: ng_hci.h:561
#define NGM_HCI_LP_ENC_CHG
Definition: ng_hci.h:540
#define NG_HCI_LINK_ACL
Definition: ng_hci.h:121
#define NG_HCI_OGF_LINK_CONTROL
Definition: ng_hci.h:694
#define NG_HCI_LMP_HV3_PKT
Definition: ng_hci.h:107
#define NG_HCI_PKT_DM5
Definition: ng_hci.h:137
#define NG_HCI_PKT_HV2
Definition: ng_hci.h:131
#define NGM_HCI_LP_DISCON_IND
Definition: ng_hci.h:508
#define NG_HCI_UNIT_COMMAND_PENDING
Definition: ng_hci.h:562
#define NGM_HCI_LP_QOS_CFM
Definition: ng_hci.h:528
#define NG_HCI_ROLE_MASTER
Definition: ng_hci.h:188
#define NG_HCI_LMP_HV2_PKT
Definition: ng_hci.h:106
#define NG_HCI_PKT_DH3
Definition: ng_hci.h:135
#define NG_HCI_ROLE_SLAVE
Definition: ng_hci.h:189
#define NG_HCI_OCF_QOS_SETUP
Definition: ng_hci.h:910
#define NG_HCI_CON_W4_CONN_COMPLETE
Definition: ng_hci.h:567
#define NG_HCI_PKT_DH5
Definition: ng_hci.h:138
#define NG_HCI_LINK_SCO
Definition: ng_hci.h:120
#define NG_HCI_LINK_LE_PUBLIC
Definition: ng_hci.h:122
#define NG_HCI_OPCODE(gf, cf)
Definition: ng_hci.h:380
int ng_hci_send_command(ng_hci_unit_p unit)
Definition: ng_hci_cmds.c:91
int ng_hci_con_timeout(ng_hci_unit_con_p con)
Definition: ng_hci_misc.c:408
ng_hci_unit_con_p ng_hci_con_by_handle(ng_hci_unit_p unit, int con_handle)
Definition: ng_hci_misc.c:335
ng_hci_unit_con_p ng_hci_new_con(ng_hci_unit_p unit, int link_type)
Definition: ng_hci_misc.c:258
ng_hci_unit_con_p ng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type)
Definition: ng_hci_misc.c:351
int ng_hci_con_untimeout(ng_hci_unit_con_p con)
Definition: ng_hci_misc.c:429
void ng_hci_free_con(ng_hci_unit_con_p con)
Definition: ng_hci_misc.c:310
ng_hci_neighbor_p ng_hci_get_neighbor(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type)
Definition: ng_hci_misc.c:219
int ng_hci_lp_qos_req(ng_hci_unit_p unit, item_p item, hook_p hook)
Definition: ng_hci_ulpi.c:1151
static int ng_hci_lp_sco_con_req(ng_hci_unit_p, item_p, hook_p)
Definition: ng_hci_ulpi.c:323
static int ng_hci_lp_acl_con_req(ng_hci_unit_p, item_p, hook_p)
Definition: ng_hci_ulpi.c:123
int ng_hci_lp_con_ind(ng_hci_unit_con_p con, u_int8_t *uclass)
Definition: ng_hci_ulpi.c:853
int ng_hci_lp_discon_ind(ng_hci_unit_con_p con, int reason)
Definition: ng_hci_ulpi.c:1093
int ng_hci_lp_con_cfm(ng_hci_unit_con_p con, int status)
Definition: ng_hci_ulpi.c:756
void ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
Definition: ng_hci_ulpi.c:1369
int ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
Definition: ng_hci_ulpi.c:899
int ng_hci_lp_enc_change(ng_hci_unit_con_p con, int status)
Definition: ng_hci_ulpi.c:820
int ng_hci_lp_qos_ind(ng_hci_unit_con_p con)
Definition: ng_hci_ulpi.c:1319
int ng_hci_lp_discon_req(ng_hci_unit_p unit, item_p item, hook_p hook)
Definition: ng_hci_ulpi.c:665
static int ng_hci_lp_le_con_req(ng_hci_unit_p, item_p, hook_p, int)
Definition: ng_hci_ulpi.c:487
int ng_hci_lp_qos_cfm(ng_hci_unit_con_p con, int status)
Definition: ng_hci_ulpi.c:1264
int ng_hci_lp_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
Definition: ng_hci_ulpi.c:68
#define NG_HCI_CON_NOTIFY_ACL
Definition: ng_hci_var.h:179
#define NG_HCI_ERR
Definition: ng_hci_var.h:48
#define NG_HCI_INFO
Definition: ng_hci_var.h:50
#define NG_HCI_CON_NOTIFY_SCO
Definition: ng_hci_var.h:180
#define NG_HCI_ALERT
Definition: ng_hci_var.h:47
#define NG_HCI_CON_TIMEOUT_PENDING
Definition: ng_hci_var.h:178
#define NG_HCI_WARN
Definition: ng_hci_var.h:49
ng_hci_unit_t * ng_hci_unit_p
Definition: ng_hci_var.h:167
#define NG_MKMESSAGE(msg, cookie, cmdid, len, how)
Definition: ng_message.h:378
uint8_t status
Definition: ng_ubt_intel.c:0
struct ubt_hci_evhdr header
Definition: ng_ubt_var.h:0
struct ubt_softc __attribute__
u_int8_t link_type
Definition: ng_hci.h:486
bdaddr_t bdaddr
Definition: ng_hci.h:488
u_int16_t con_handle
Definition: ng_hci.h:487
u_int8_t status
Definition: ng_hci.h:485
bdaddr_t bdaddr
Definition: ng_hci.h:496
u_int8_t uclass[NG_HCI_CLASS_SIZE]
Definition: ng_hci.h:495
u_int8_t link_type
Definition: ng_hci.h:494
bdaddr_t bdaddr
Definition: ng_hci.h:467
u_int8_t link_type
Definition: ng_hci.h:503
u_int8_t status
Definition: ng_hci.h:502
bdaddr_t bdaddr
Definition: ng_hci.h:504
u_int16_t con_handle
Definition: ng_hci.h:512
u_int16_t con_handle
Definition: ng_hci.h:478
u_int16_t con_handle
Definition: ng_hci.h:531
u_int16_t status
Definition: ng_hci.h:530
u_int16_t con_handle
Definition: ng_hci.h:537
u_int32_t token_rate
Definition: ng_hci.h:521
u_int8_t flags
Definition: ng_hci.h:519
u_int32_t latency
Definition: ng_hci.h:523
u_int16_t con_handle
Definition: ng_hci.h:518
u_int32_t peak_bandwidth
Definition: ng_hci.h:522
u_int8_t service_type
Definition: ng_hci.h:520
u_int32_t delay_variation
Definition: ng_hci.h:524
u_int16_t clock_offset
Definition: ng_hci_var.h:214
u_int8_t page_scan_rep_mode
Definition: ng_hci_var.h:212
u_int8_t page_scan_mode
Definition: ng_hci_var.h:213
u_int16_t con_handle
Definition: ng_hci_var.h:183
u_int16_t flags
Definition: ng_hci_var.h:177
u_int8_t link_type
Definition: ng_hci_var.h:185
bdaddr_t bdaddr
Definition: ng_hci_var.h:182
u_int16_t state
Definition: ng_hci_var.h:176
ng_hci_unit_p unit
Definition: ng_hci_var.h:174
ng_hci_node_role_switch_ep role_switch
Definition: ng_hci_var.h:140
ng_bt_mbufq_t cmdq
Definition: ng_hci_var.h:156
ng_hci_node_state_ep state
Definition: ng_hci_var.h:132
node_p node
Definition: ng_hci_var.h:129
hook_p acl
Definition: ng_hci_var.h:160
ng_hci_node_packet_mask_ep packet_mask
Definition: ng_hci_var.h:139
u_int8_t features[NG_HCI_FEATURES_SIZE]
Definition: ng_hci_var.h:135
hook_p sco
Definition: ng_hci_var.h:161
char data[]
Definition: ng_message.h:69