Netgraph port from FreeBSD - initial porting work
[dragonfly.git] / sys / netgraph7 / bluetooth / hci / ng_hci_cmds.c
blob289e01f0eb0df8ca915cbe8e13e91187b955549f
1 /*
2 * ng_hci_cmds.c
3 */
5 /*-
6 * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
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.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
30 * $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/hci/ng_hci_cmds.c,v 1.7 2005/01/07 01:45:43 imp Exp $
32 * $DragonFly: src/sys/netgraph7/bluetooth/hci/ng_hci_cmds.c,v 1.2 2008/06/26 23:05:40 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/endian.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/queue.h>
42 #include "ng_message.h"
43 #include "netgraph.h"
44 #include "bluetooth/include/ng_bluetooth.h"
45 #include "bluetooth/include/ng_hci.h"
46 #include "bluetooth/hci/ng_hci_var.h"
47 #include "bluetooth/hci/ng_hci_cmds.h"
48 #include "bluetooth/hci/ng_hci_evnt.h"
49 #include "bluetooth/hci/ng_hci_ulpi.h"
50 #include "bluetooth/hci/ng_hci_misc.h"
52 /******************************************************************************
53 ******************************************************************************
54 ** HCI commands processing module
55 ******************************************************************************
56 ******************************************************************************/
58 #undef min
59 #define min(a, b) ((a) < (b))? (a) : (b)
61 static int complete_command (ng_hci_unit_p, int, struct mbuf **);
63 static int process_link_control_params
64 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
65 static int process_link_policy_params
66 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
67 static int process_hc_baseband_params
68 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
69 static int process_info_params
70 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
71 static int process_status_params
72 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
73 static int process_testing_params
74 (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
76 static int process_link_control_status
77 (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
78 static int process_link_policy_status
79 (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
82 * Send HCI command to the driver.
85 int
86 ng_hci_send_command(ng_hci_unit_p unit)
88 struct mbuf *m0 = NULL, *m = NULL;
89 int free, error = 0;
91 /* Check if other command is pending */
92 if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
93 return (0);
95 /* Check if unit can accept our command */
96 NG_HCI_BUFF_CMD_GET(unit->buffer, free);
97 if (free == 0)
98 return (0);
100 /* Check if driver hook is still ok */
101 if (unit->drv == NULL || NG_HOOK_NOT_VALID(unit->drv)) {
102 NG_HCI_WARN(
103 "%s: %s - hook \"%s\" is not connected or valid\n",
104 __func__, NG_NODE_NAME(unit->node), NG_HCI_HOOK_DRV);
106 NG_BT_MBUFQ_DRAIN(&unit->cmdq);
108 return (ENOTCONN);
112 * Get first command from queue, give it to RAW hook then
113 * make copy of it and send it to the driver
116 m0 = NG_BT_MBUFQ_FIRST(&unit->cmdq);
117 if (m0 == NULL)
118 return (0);
120 ng_hci_mtap(unit, m0);
122 m = m_dup(m0, MB_DONTWAIT);
123 if (m != NULL)
124 NG_SEND_DATA_ONLY(error, unit->drv, m);
125 else
126 error = ENOBUFS;
128 if (error != 0)
129 NG_HCI_ERR(
130 "%s: %s - could not send HCI command, error=%d\n",
131 __func__, NG_NODE_NAME(unit->node), error);
134 * Even if we were not able to send command we still pretend
135 * that everything is OK and let timeout handle that.
138 NG_HCI_BUFF_CMD_USE(unit->buffer, 1);
139 NG_HCI_STAT_CMD_SENT(unit->stat);
140 NG_HCI_STAT_BYTES_SENT(unit->stat, m0->m_pkthdr.len);
143 * Note: ng_hci_command_timeout() will set
144 * NG_HCI_UNIT_COMMAND_PENDING flag
147 ng_hci_command_timeout(unit);
149 return (0);
150 } /* ng_hci_send_command */
153 * Process HCI Command_Compete event. Complete HCI command, and do post
154 * processing on the command parameters (cp) and command return parameters
155 * (e) if required (for example adjust state).
159 ng_hci_process_command_complete(ng_hci_unit_p unit, struct mbuf *e)
161 ng_hci_command_compl_ep *ep = NULL;
162 struct mbuf *cp = NULL;
163 int error = 0;
165 /* Get event packet and update command buffer info */
166 NG_HCI_M_PULLUP(e, sizeof(*ep));
167 if (e == NULL)
168 return (ENOBUFS); /* XXX this is bad */
170 ep = mtod(e, ng_hci_command_compl_ep *);
171 NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
173 /* Check for special NOOP command */
174 if (ep->opcode == 0x0000) {
175 NG_FREE_M(e);
176 goto out;
179 /* Try to match first command item in the queue */
180 error = complete_command(unit, ep->opcode, &cp);
181 if (error != 0) {
182 NG_FREE_M(e);
183 goto out;
187 * Perform post processing on command parameters and return parameters
188 * do it only if status is OK (status == 0). Status is the first byte
189 * of any command return parameters.
192 ep->opcode = le16toh(ep->opcode);
193 m_adj(e, sizeof(*ep));
195 if (*mtod(e, u_int8_t *) == 0) { /* XXX m_pullup here? */
196 switch (NG_HCI_OGF(ep->opcode)) {
197 case NG_HCI_OGF_LINK_CONTROL:
198 error = process_link_control_params(unit,
199 NG_HCI_OCF(ep->opcode), cp, e);
200 break;
202 case NG_HCI_OGF_LINK_POLICY:
203 error = process_link_policy_params(unit,
204 NG_HCI_OCF(ep->opcode), cp, e);
205 break;
207 case NG_HCI_OGF_HC_BASEBAND:
208 error = process_hc_baseband_params(unit,
209 NG_HCI_OCF(ep->opcode), cp, e);
210 break;
212 case NG_HCI_OGF_INFO:
213 error = process_info_params(unit,
214 NG_HCI_OCF(ep->opcode), cp, e);
215 break;
217 case NG_HCI_OGF_STATUS:
218 error = process_status_params(unit,
219 NG_HCI_OCF(ep->opcode), cp, e);
220 break;
222 case NG_HCI_OGF_TESTING:
223 error = process_testing_params(unit,
224 NG_HCI_OCF(ep->opcode), cp, e);
225 break;
227 case NG_HCI_OGF_BT_LOGO:
228 case NG_HCI_OGF_VENDOR:
229 NG_FREE_M(cp);
230 NG_FREE_M(e);
231 break;
233 default:
234 NG_FREE_M(cp);
235 NG_FREE_M(e);
236 error = EINVAL;
237 break;
239 } else {
240 NG_HCI_ERR(
241 "%s: %s - HCI command failed, OGF=%#x, OCF=%#x, status=%#x\n",
242 __func__, NG_NODE_NAME(unit->node),
243 NG_HCI_OGF(ep->opcode), NG_HCI_OCF(ep->opcode),
244 *mtod(e, u_int8_t *));
246 NG_FREE_M(cp);
247 NG_FREE_M(e);
249 out:
250 ng_hci_send_command(unit);
252 return (error);
253 } /* ng_hci_process_command_complete */
256 * Process HCI Command_Status event. Check the status (mst) and do post
257 * processing (if required).
261 ng_hci_process_command_status(ng_hci_unit_p unit, struct mbuf *e)
263 ng_hci_command_status_ep *ep = NULL;
264 struct mbuf *cp = NULL;
265 int error = 0;
267 /* Update command buffer info */
268 NG_HCI_M_PULLUP(e, sizeof(*ep));
269 if (e == NULL)
270 return (ENOBUFS); /* XXX this is bad */
272 ep = mtod(e, ng_hci_command_status_ep *);
273 NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts);
275 /* Check for special NOOP command */
276 if (ep->opcode == 0x0000)
277 goto out;
279 /* Try to match first command item in the queue */
280 error = complete_command(unit, ep->opcode, &cp);
281 if (error != 0)
282 goto out;
285 * Perform post processing on HCI Command_Status event
288 ep->opcode = le16toh(ep->opcode);
290 switch (NG_HCI_OGF(ep->opcode)) {
291 case NG_HCI_OGF_LINK_CONTROL:
292 error = process_link_control_status(unit, ep, cp);
293 break;
295 case NG_HCI_OGF_LINK_POLICY:
296 error = process_link_policy_status(unit, ep, cp);
297 break;
299 case NG_HCI_OGF_BT_LOGO:
300 case NG_HCI_OGF_VENDOR:
301 NG_FREE_M(cp);
302 break;
304 case NG_HCI_OGF_HC_BASEBAND:
305 case NG_HCI_OGF_INFO:
306 case NG_HCI_OGF_STATUS:
307 case NG_HCI_OGF_TESTING:
308 default:
309 NG_FREE_M(cp);
310 error = EINVAL;
311 break;
313 out:
314 NG_FREE_M(e);
315 ng_hci_send_command(unit);
317 return (error);
318 } /* ng_hci_process_command_status */
321 * Complete queued HCI command.
324 static int
325 complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
327 struct mbuf *m = NULL;
329 /* Check unit state */
330 if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) {
331 NG_HCI_ALERT(
332 "%s: %s - no pending command, state=%#x\n",
333 __func__, NG_NODE_NAME(unit->node), unit->state);
335 return (EINVAL);
338 /* Get first command in the queue */
339 m = NG_BT_MBUFQ_FIRST(&unit->cmdq);
340 if (m == NULL) {
341 NG_HCI_ALERT(
342 "%s: %s - empty command queue?!\n", __func__, NG_NODE_NAME(unit->node));
344 return (EINVAL);
348 * Match command opcode, if does not match - do nothing and
349 * let timeout handle that.
352 if (mtod(m, ng_hci_cmd_pkt_t *)->opcode != opcode) {
353 NG_HCI_ALERT(
354 "%s: %s - command queue is out of sync\n", __func__, NG_NODE_NAME(unit->node));
356 return (EINVAL);
360 * Now we can remove command timeout, dequeue completed command
361 * and return command parameters. ng_hci_command_untimeout will
362 * drop NG_HCI_UNIT_COMMAND_PENDING flag.
363 * Note: if ng_hci_command_untimeout() fails (returns non-zero)
364 * then timeout aready happened and timeout message went info node
365 * queue. In this case we ignore command completion and pretend
366 * there is a timeout.
369 if (ng_hci_command_untimeout(unit) != 0)
370 return (ETIMEDOUT);
372 NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp);
373 m_adj(*cp, sizeof(ng_hci_cmd_pkt_t));
375 return (0);
376 } /* complete_command */
379 * Process HCI command timeout
382 void
383 ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
385 ng_hci_unit_p unit = NULL;
386 struct mbuf *m = NULL;
387 u_int16_t opcode;
389 if (NG_NODE_NOT_VALID(node)) {
390 printf("%s: Netgraph node is not valid\n", __func__);
391 return;
394 unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
396 if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
397 unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
399 NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
400 if (m == NULL) {
401 NG_HCI_ALERT(
402 "%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node));
404 return;
407 opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode);
408 NG_FREE_M(m);
410 NG_HCI_ERR(
411 "%s: %s - unable to complete HCI command OGF=%#x, OCF=%#x. Timeout\n",
412 __func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode),
413 NG_HCI_OCF(opcode));
415 /* Try to send more commands */
416 NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
417 ng_hci_send_command(unit);
418 } else
419 NG_HCI_ALERT(
420 "%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node));
421 } /* ng_hci_process_command_timeout */
424 * Process link command return parameters
427 static int
428 process_link_control_params(ng_hci_unit_p unit, u_int16_t ocf,
429 struct mbuf *mcp, struct mbuf *mrp)
431 int error = 0;
433 switch (ocf) {
434 case NG_HCI_OCF_INQUIRY_CANCEL:
435 case NG_HCI_OCF_PERIODIC_INQUIRY:
436 case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
437 case NG_HCI_OCF_LINK_KEY_REP:
438 case NG_HCI_OCF_LINK_KEY_NEG_REP:
439 case NG_HCI_OCF_PIN_CODE_REP:
440 case NG_HCI_OCF_PIN_CODE_NEG_REP:
441 /* These do not need post processing */
442 break;
444 case NG_HCI_OCF_INQUIRY:
445 case NG_HCI_OCF_CREATE_CON:
446 case NG_HCI_OCF_DISCON:
447 case NG_HCI_OCF_ADD_SCO_CON:
448 case NG_HCI_OCF_ACCEPT_CON:
449 case NG_HCI_OCF_REJECT_CON:
450 case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
451 case NG_HCI_OCF_AUTH_REQ:
452 case NG_HCI_OCF_SET_CON_ENCRYPTION:
453 case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
454 case NG_HCI_OCF_MASTER_LINK_KEY:
455 case NG_HCI_OCF_REMOTE_NAME_REQ:
456 case NG_HCI_OCF_READ_REMOTE_FEATURES:
457 case NG_HCI_OCF_READ_REMOTE_VER_INFO:
458 case NG_HCI_OCF_READ_CLOCK_OFFSET:
459 default:
462 * None of these command was supposed to generate
463 * Command_Complete event. Instead Command_Status event
464 * should have been generated and then appropriate event
465 * should have been sent to indicate the final result.
468 error = EINVAL;
469 break;
472 NG_FREE_M(mcp);
473 NG_FREE_M(mrp);
475 return (error);
476 } /* process_link_control_params */
479 * Process link policy command return parameters
482 static int
483 process_link_policy_params(ng_hci_unit_p unit, u_int16_t ocf,
484 struct mbuf *mcp, struct mbuf *mrp)
486 int error = 0;
488 switch (ocf){
489 case NG_HCI_OCF_ROLE_DISCOVERY: {
490 ng_hci_role_discovery_rp *rp = NULL;
491 ng_hci_unit_con_t *con = NULL;
492 u_int16_t h;
494 NG_HCI_M_PULLUP(mrp, sizeof(*rp));
495 if (mrp != NULL) {
496 rp = mtod(mrp, ng_hci_role_discovery_rp *);
498 h = NG_HCI_CON_HANDLE(le16toh(rp->con_handle));
499 con = ng_hci_con_by_handle(unit, h);
500 if (con == NULL) {
501 NG_HCI_ALERT(
502 "%s: %s - invalid connection handle=%d\n",
503 __func__, NG_NODE_NAME(unit->node), h);
504 error = ENOENT;
505 } else if (con->link_type != NG_HCI_LINK_ACL) {
506 NG_HCI_ALERT(
507 "%s: %s - invalid link type=%d\n", __func__, NG_NODE_NAME(unit->node),
508 con->link_type);
509 error = EINVAL;
510 } else
511 con->role = rp->role;
512 } else
513 error = ENOBUFS;
514 } break;
516 case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
517 case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
518 /* These do not need post processing */
519 break;
521 case NG_HCI_OCF_HOLD_MODE:
522 case NG_HCI_OCF_SNIFF_MODE:
523 case NG_HCI_OCF_EXIT_SNIFF_MODE:
524 case NG_HCI_OCF_PARK_MODE:
525 case NG_HCI_OCF_EXIT_PARK_MODE:
526 case NG_HCI_OCF_QOS_SETUP:
527 case NG_HCI_OCF_SWITCH_ROLE:
528 default:
531 * None of these command was supposed to generate
532 * Command_Complete event. Instead Command_Status event
533 * should have been generated and then appropriate event
534 * should have been sent to indicate the final result.
537 error = EINVAL;
538 break;
541 NG_FREE_M(mcp);
542 NG_FREE_M(mrp);
544 return (error);
545 } /* process_link_policy_params */
548 * Process HC and baseband command return parameters
552 process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf,
553 struct mbuf *mcp, struct mbuf *mrp)
555 int error = 0;
557 switch (ocf) {
558 case NG_HCI_OCF_SET_EVENT_MASK:
559 case NG_HCI_OCF_SET_EVENT_FILTER:
560 case NG_HCI_OCF_FLUSH: /* XXX Do we need to handle that? */
561 case NG_HCI_OCF_READ_PIN_TYPE:
562 case NG_HCI_OCF_WRITE_PIN_TYPE:
563 case NG_HCI_OCF_CREATE_NEW_UNIT_KEY:
564 case NG_HCI_OCF_WRITE_STORED_LINK_KEY:
565 case NG_HCI_OCF_WRITE_CON_ACCEPT_TIMO:
566 case NG_HCI_OCF_WRITE_PAGE_TIMO:
567 case NG_HCI_OCF_READ_SCAN_ENABLE:
568 case NG_HCI_OCF_WRITE_SCAN_ENABLE:
569 case NG_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY:
570 case NG_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY:
571 case NG_HCI_OCF_READ_AUTH_ENABLE:
572 case NG_HCI_OCF_WRITE_AUTH_ENABLE:
573 case NG_HCI_OCF_READ_ENCRYPTION_MODE:
574 case NG_HCI_OCF_WRITE_ENCRYPTION_MODE:
575 case NG_HCI_OCF_WRITE_VOICE_SETTINGS:
576 case NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS:
577 case NG_HCI_OCF_WRITE_NUM_BROADCAST_RETRANS:
578 case NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY:
579 case NG_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY:
580 case NG_HCI_OCF_READ_SCO_FLOW_CONTROL:
581 case NG_HCI_OCF_WRITE_SCO_FLOW_CONTROL:
582 case NG_HCI_OCF_H2HC_FLOW_CONTROL: /* XXX Not supported this time */
583 case NG_HCI_OCF_HOST_BUFFER_SIZE:
584 case NG_HCI_OCF_READ_IAC_LAP:
585 case NG_HCI_OCF_WRITE_IAC_LAP:
586 case NG_HCI_OCF_READ_PAGE_SCAN_PERIOD:
587 case NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD:
588 case NG_HCI_OCF_READ_PAGE_SCAN:
589 case NG_HCI_OCF_WRITE_PAGE_SCAN:
590 case NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO:
591 case NG_HCI_OCF_WRITE_LINK_SUPERVISION_TIMO:
592 case NG_HCI_OCF_READ_SUPPORTED_IAC_NUM:
593 case NG_HCI_OCF_READ_STORED_LINK_KEY:
594 case NG_HCI_OCF_DELETE_STORED_LINK_KEY:
595 case NG_HCI_OCF_READ_CON_ACCEPT_TIMO:
596 case NG_HCI_OCF_READ_PAGE_TIMO:
597 case NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY:
598 case NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY:
599 case NG_HCI_OCF_READ_VOICE_SETTINGS:
600 case NG_HCI_OCF_READ_AUTO_FLUSH_TIMO:
601 case NG_HCI_OCF_WRITE_AUTO_FLUSH_TIMO:
602 case NG_HCI_OCF_READ_XMIT_LEVEL:
603 case NG_HCI_OCF_HOST_NUM_COMPL_PKTS: /* XXX Can get here? */
604 case NG_HCI_OCF_CHANGE_LOCAL_NAME:
605 case NG_HCI_OCF_READ_LOCAL_NAME:
606 case NG_HCI_OCF_READ_UNIT_CLASS:
607 case NG_HCI_OCF_WRITE_UNIT_CLASS:
608 /* These do not need post processing */
609 break;
611 case NG_HCI_OCF_RESET: {
612 ng_hci_unit_con_p con = NULL;
613 int size;
616 * XXX
618 * After RESET command unit goes into standby mode
619 * and all operational state is lost. Host controller
620 * will revert to default values for all parameters.
622 * For now we shall terminate all connections and drop
623 * inited bit. After RESET unit must be re-initialized.
626 while (!LIST_EMPTY(&unit->con_list)) {
627 con = LIST_FIRST(&unit->con_list);
629 /* Remove all timeouts (if any) */
630 if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
631 ng_hci_con_untimeout(con);
633 /* Connection terminated by local host */
634 ng_hci_lp_discon_ind(con, 0x16);
635 ng_hci_free_con(con);
638 NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size);
639 NG_HCI_BUFF_ACL_FREE(unit->buffer, size);
641 NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size);
642 NG_HCI_BUFF_SCO_FREE(unit->buffer, size);
644 unit->state &= ~NG_HCI_UNIT_INITED;
645 } break;
647 default:
648 error = EINVAL;
649 break;
652 NG_FREE_M(mcp);
653 NG_FREE_M(mrp);
655 return (error);
656 } /* process_hc_baseband_params */
659 * Process info command return parameters
662 static int
663 process_info_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
664 struct mbuf *mrp)
666 int error = 0, len;
668 switch (ocf) {
669 case NG_HCI_OCF_READ_LOCAL_VER:
670 case NG_HCI_OCF_READ_COUNTRY_CODE:
671 break;
673 case NG_HCI_OCF_READ_LOCAL_FEATURES:
674 m_adj(mrp, sizeof(u_int8_t));
675 len = min(mrp->m_pkthdr.len, sizeof(unit->features));
676 m_copydata(mrp, 0, len, (caddr_t) unit->features);
677 break;
679 case NG_HCI_OCF_READ_BUFFER_SIZE: {
680 ng_hci_read_buffer_size_rp *rp = NULL;
682 /* Do not update buffer descriptor if node was initialized */
683 if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
684 break;
686 NG_HCI_M_PULLUP(mrp, sizeof(*rp));
687 if (mrp != NULL) {
688 rp = mtod(mrp, ng_hci_read_buffer_size_rp *);
690 NG_HCI_BUFF_ACL_SET(
691 unit->buffer,
692 le16toh(rp->num_acl_pkt), /* number */
693 le16toh(rp->max_acl_size), /* size */
694 le16toh(rp->num_acl_pkt) /* free */
697 NG_HCI_BUFF_SCO_SET(
698 unit->buffer,
699 le16toh(rp->num_sco_pkt), /* number */
700 rp->max_sco_size, /* size */
701 le16toh(rp->num_sco_pkt) /* free */
704 /* Let upper layers know */
705 ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
706 ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
707 } else
708 error = ENOBUFS;
709 } break;
711 case NG_HCI_OCF_READ_BDADDR:
712 /* Do not update BD_ADDR if node was initialized */
713 if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY)
714 break;
716 m_adj(mrp, sizeof(u_int8_t));
717 len = min(mrp->m_pkthdr.len, sizeof(unit->bdaddr));
718 m_copydata(mrp, 0, len, (caddr_t) &unit->bdaddr);
720 /* Let upper layers know */
721 ng_hci_node_is_up(unit->node, unit->acl, NULL, 0);
722 ng_hci_node_is_up(unit->node, unit->sco, NULL, 0);
723 break;
725 default:
726 error = EINVAL;
727 break;
730 NG_FREE_M(mcp);
731 NG_FREE_M(mrp);
733 return (error);
734 } /* process_info_params */
737 * Process status command return parameters
740 static int
741 process_status_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
742 struct mbuf *mrp)
744 int error = 0;
746 switch (ocf) {
747 case NG_HCI_OCF_READ_FAILED_CONTACT_CNTR:
748 case NG_HCI_OCF_RESET_FAILED_CONTACT_CNTR:
749 case NG_HCI_OCF_GET_LINK_QUALITY:
750 case NG_HCI_OCF_READ_RSSI:
751 /* These do not need post processing */
752 break;
754 default:
755 error = EINVAL;
756 break;
759 NG_FREE_M(mcp);
760 NG_FREE_M(mrp);
762 return (error);
763 } /* process_status_params */
766 * Process testing command return parameters
770 process_testing_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp,
771 struct mbuf *mrp)
773 int error = 0;
775 switch (ocf) {
778 * XXX FIXME
779 * We do not support these features at this time. However,
780 * HCI node could support this and do something smart. At least
781 * node can change unit state.
784 case NG_HCI_OCF_READ_LOOPBACK_MODE:
785 case NG_HCI_OCF_WRITE_LOOPBACK_MODE:
786 case NG_HCI_OCF_ENABLE_UNIT_UNDER_TEST:
787 break;
789 default:
790 error = EINVAL;
791 break;
794 NG_FREE_M(mcp);
795 NG_FREE_M(mrp);
797 return (error);
798 } /* process_testing_params */
801 * Process link control command status
804 static int
805 process_link_control_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
806 struct mbuf *mcp)
808 int error = 0;
810 switch (NG_HCI_OCF(ep->opcode)) {
811 case NG_HCI_OCF_INQUIRY:
812 case NG_HCI_OCF_DISCON: /* XXX */
813 case NG_HCI_OCF_REJECT_CON: /* XXX */
814 case NG_HCI_OCF_CHANGE_CON_PKT_TYPE:
815 case NG_HCI_OCF_AUTH_REQ:
816 case NG_HCI_OCF_SET_CON_ENCRYPTION:
817 case NG_HCI_OCF_CHANGE_CON_LINK_KEY:
818 case NG_HCI_OCF_MASTER_LINK_KEY:
819 case NG_HCI_OCF_REMOTE_NAME_REQ:
820 case NG_HCI_OCF_READ_REMOTE_FEATURES:
821 case NG_HCI_OCF_READ_REMOTE_VER_INFO:
822 case NG_HCI_OCF_READ_CLOCK_OFFSET:
823 /* These do not need post processing */
824 break;
826 case NG_HCI_OCF_CREATE_CON:
827 break;
829 case NG_HCI_OCF_ADD_SCO_CON:
830 break;
832 case NG_HCI_OCF_ACCEPT_CON:
833 break;
835 case NG_HCI_OCF_INQUIRY_CANCEL:
836 case NG_HCI_OCF_PERIODIC_INQUIRY:
837 case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY:
838 case NG_HCI_OCF_LINK_KEY_REP:
839 case NG_HCI_OCF_LINK_KEY_NEG_REP:
840 case NG_HCI_OCF_PIN_CODE_REP:
841 case NG_HCI_OCF_PIN_CODE_NEG_REP:
842 default:
845 * None of these command was supposed to generate
846 * Command_Status event. Instead Command_Complete event
847 * should have been sent.
850 error = EINVAL;
851 break;
854 NG_FREE_M(mcp);
856 return (error);
857 } /* process_link_control_status */
860 * Process link policy command status
863 static int
864 process_link_policy_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep,
865 struct mbuf *mcp)
867 int error = 0;
869 switch (NG_HCI_OCF(ep->opcode)) {
870 case NG_HCI_OCF_HOLD_MODE:
871 case NG_HCI_OCF_SNIFF_MODE:
872 case NG_HCI_OCF_EXIT_SNIFF_MODE:
873 case NG_HCI_OCF_PARK_MODE:
874 case NG_HCI_OCF_EXIT_PARK_MODE:
875 case NG_HCI_OCF_SWITCH_ROLE:
876 /* These do not need post processing */
877 break;
879 case NG_HCI_OCF_QOS_SETUP:
880 break;
882 case NG_HCI_OCF_ROLE_DISCOVERY:
883 case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS:
884 case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS:
885 default:
888 * None of these command was supposed to generate
889 * Command_Status event. Instead Command_Complete event
890 * should have been sent.
893 error = EINVAL;
894 break;
897 NG_FREE_M(mcp);
899 return (error);
900 } /* process_link_policy_status */