1107120Sjulian/* 2107120Sjulian * ng_hci_cmds.c 3139823Simp */ 4139823Simp 5139823Simp/*- 6107120Sjulian * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com> 7107120Sjulian * All rights reserved. 8107120Sjulian * 9107120Sjulian * Redistribution and use in source and binary forms, with or without 10107120Sjulian * modification, are permitted provided that the following conditions 11107120Sjulian * are met: 12107120Sjulian * 1. Redistributions of source code must retain the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer. 14107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 15107120Sjulian * notice, this list of conditions and the following disclaimer in the 16107120Sjulian * documentation and/or other materials provided with the distribution. 17107120Sjulian * 18107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28107120Sjulian * SUCH DAMAGE. 29107120Sjulian * 30121054Semax * $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $ 31107120Sjulian * $FreeBSD: stable/11/sys/netgraph/bluetooth/hci/ng_hci_cmds.c 361165 2020-05-18 08:57:55Z hselasky $ 32107120Sjulian */ 33107120Sjulian 34107120Sjulian#include <sys/param.h> 35107120Sjulian#include <sys/systm.h> 36107120Sjulian#include <sys/kernel.h> 37107120Sjulian#include <sys/endian.h> 38107120Sjulian#include <sys/malloc.h> 39107120Sjulian#include <sys/mbuf.h> 40107120Sjulian#include <sys/queue.h> 41107120Sjulian#include <netgraph/ng_message.h> 42107120Sjulian#include <netgraph/netgraph.h> 43128688Semax#include <netgraph/bluetooth/include/ng_bluetooth.h> 44128688Semax#include <netgraph/bluetooth/include/ng_hci.h> 45128688Semax#include <netgraph/bluetooth/hci/ng_hci_var.h> 46128688Semax#include <netgraph/bluetooth/hci/ng_hci_cmds.h> 47128688Semax#include <netgraph/bluetooth/hci/ng_hci_evnt.h> 48128688Semax#include <netgraph/bluetooth/hci/ng_hci_ulpi.h> 49128688Semax#include <netgraph/bluetooth/hci/ng_hci_misc.h> 50107120Sjulian 51107120Sjulian/****************************************************************************** 52107120Sjulian ****************************************************************************** 53107120Sjulian ** HCI commands processing module 54107120Sjulian ****************************************************************************** 55107120Sjulian ******************************************************************************/ 56107120Sjulian 57107120Sjulian#undef min 58107120Sjulian#define min(a, b) ((a) < (b))? (a) : (b) 59107120Sjulian 60107120Sjulianstatic int complete_command (ng_hci_unit_p, int, struct mbuf **); 61107120Sjulian 62107120Sjulianstatic int process_link_control_params 63107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 64107120Sjulianstatic int process_link_policy_params 65107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 66107120Sjulianstatic int process_hc_baseband_params 67107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 68107120Sjulianstatic int process_info_params 69107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 70107120Sjulianstatic int process_status_params 71107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 72107120Sjulianstatic int process_testing_params 73107120Sjulian (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 74281198Stakawatastatic int process_le_params 75281198Stakawata (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *); 76107120Sjulian 77107120Sjulianstatic int process_link_control_status 78107120Sjulian (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *); 79107120Sjulianstatic int process_link_policy_status 80107120Sjulian (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *); 81281198Stakawatastatic int process_le_status 82281198Stakawata (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *); 83107120Sjulian 84107120Sjulian/* 85107120Sjulian * Send HCI command to the driver. 86107120Sjulian */ 87107120Sjulian 88107120Sjulianint 89107120Sjulianng_hci_send_command(ng_hci_unit_p unit) 90107120Sjulian{ 91107120Sjulian struct mbuf *m0 = NULL, *m = NULL; 92107120Sjulian int free, error = 0; 93107120Sjulian 94107120Sjulian /* Check if other command is pending */ 95107120Sjulian if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) 96107120Sjulian return (0); 97107120Sjulian 98107120Sjulian /* Check if unit can accept our command */ 99107120Sjulian NG_HCI_BUFF_CMD_GET(unit->buffer, free); 100107120Sjulian if (free == 0) 101107120Sjulian return (0); 102107120Sjulian 103107120Sjulian /* Check if driver hook is still ok */ 104107120Sjulian if (unit->drv == NULL || NG_HOOK_NOT_VALID(unit->drv)) { 105107120Sjulian NG_HCI_WARN( 106107120Sjulian"%s: %s - hook \"%s\" is not connected or valid\n", 107107120Sjulian __func__, NG_NODE_NAME(unit->node), NG_HCI_HOOK_DRV); 108107120Sjulian 109107120Sjulian NG_BT_MBUFQ_DRAIN(&unit->cmdq); 110107120Sjulian 111107120Sjulian return (ENOTCONN); 112107120Sjulian } 113107120Sjulian 114107120Sjulian /* 115107120Sjulian * Get first command from queue, give it to RAW hook then 116107120Sjulian * make copy of it and send it to the driver 117107120Sjulian */ 118107120Sjulian 119107120Sjulian m0 = NG_BT_MBUFQ_FIRST(&unit->cmdq); 120107120Sjulian if (m0 == NULL) 121107120Sjulian return (0); 122107120Sjulian 123107120Sjulian ng_hci_mtap(unit, m0); 124107120Sjulian 125243882Sglebius m = m_dup(m0, M_NOWAIT); 126107120Sjulian if (m != NULL) 127107120Sjulian NG_SEND_DATA_ONLY(error, unit->drv, m); 128107120Sjulian else 129107120Sjulian error = ENOBUFS; 130107120Sjulian 131107120Sjulian if (error != 0) 132107120Sjulian NG_HCI_ERR( 133107120Sjulian"%s: %s - could not send HCI command, error=%d\n", 134107120Sjulian __func__, NG_NODE_NAME(unit->node), error); 135107120Sjulian 136107120Sjulian /* 137107120Sjulian * Even if we were not able to send command we still pretend 138107120Sjulian * that everything is OK and let timeout handle that. 139107120Sjulian */ 140107120Sjulian 141107120Sjulian NG_HCI_BUFF_CMD_USE(unit->buffer, 1); 142107120Sjulian NG_HCI_STAT_CMD_SENT(unit->stat); 143107120Sjulian NG_HCI_STAT_BYTES_SENT(unit->stat, m0->m_pkthdr.len); 144107120Sjulian 145107120Sjulian /* 146107120Sjulian * Note: ng_hci_command_timeout() will set 147107120Sjulian * NG_HCI_UNIT_COMMAND_PENDING flag 148107120Sjulian */ 149107120Sjulian 150107120Sjulian ng_hci_command_timeout(unit); 151107120Sjulian 152107120Sjulian return (0); 153107120Sjulian} /* ng_hci_send_command */ 154107120Sjulian 155107120Sjulian/* 156107120Sjulian * Process HCI Command_Compete event. Complete HCI command, and do post 157107120Sjulian * processing on the command parameters (cp) and command return parameters 158107120Sjulian * (e) if required (for example adjust state). 159107120Sjulian */ 160107120Sjulian 161107120Sjulianint 162107120Sjulianng_hci_process_command_complete(ng_hci_unit_p unit, struct mbuf *e) 163107120Sjulian{ 164107120Sjulian ng_hci_command_compl_ep *ep = NULL; 165107120Sjulian struct mbuf *cp = NULL; 166107120Sjulian int error = 0; 167107120Sjulian 168107120Sjulian /* Get event packet and update command buffer info */ 169107120Sjulian NG_HCI_M_PULLUP(e, sizeof(*ep)); 170107120Sjulian if (e == NULL) 171107120Sjulian return (ENOBUFS); /* XXX this is bad */ 172107120Sjulian 173107120Sjulian ep = mtod(e, ng_hci_command_compl_ep *); 174107120Sjulian NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts); 175107120Sjulian 176107120Sjulian /* Check for special NOOP command */ 177107120Sjulian if (ep->opcode == 0x0000) { 178107120Sjulian NG_FREE_M(e); 179107120Sjulian goto out; 180107120Sjulian } 181107120Sjulian 182107120Sjulian /* Try to match first command item in the queue */ 183107120Sjulian error = complete_command(unit, ep->opcode, &cp); 184107120Sjulian if (error != 0) { 185107120Sjulian NG_FREE_M(e); 186107120Sjulian goto out; 187107120Sjulian } 188107120Sjulian 189107120Sjulian /* 190107120Sjulian * Perform post processing on command parameters and return parameters 191107120Sjulian * do it only if status is OK (status == 0). Status is the first byte 192107120Sjulian * of any command return parameters. 193107120Sjulian */ 194107120Sjulian 195107120Sjulian ep->opcode = le16toh(ep->opcode); 196107120Sjulian m_adj(e, sizeof(*ep)); 197107120Sjulian 198107120Sjulian if (*mtod(e, u_int8_t *) == 0) { /* XXX m_pullup here? */ 199107120Sjulian switch (NG_HCI_OGF(ep->opcode)) { 200107120Sjulian case NG_HCI_OGF_LINK_CONTROL: 201107120Sjulian error = process_link_control_params(unit, 202107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 203107120Sjulian break; 204107120Sjulian 205107120Sjulian case NG_HCI_OGF_LINK_POLICY: 206107120Sjulian error = process_link_policy_params(unit, 207107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 208107120Sjulian break; 209107120Sjulian 210107120Sjulian case NG_HCI_OGF_HC_BASEBAND: 211107120Sjulian error = process_hc_baseband_params(unit, 212107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 213107120Sjulian break; 214107120Sjulian 215107120Sjulian case NG_HCI_OGF_INFO: 216107120Sjulian error = process_info_params(unit, 217107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 218107120Sjulian break; 219107120Sjulian 220107120Sjulian case NG_HCI_OGF_STATUS: 221107120Sjulian error = process_status_params(unit, 222107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 223107120Sjulian break; 224107120Sjulian 225107120Sjulian case NG_HCI_OGF_TESTING: 226107120Sjulian error = process_testing_params(unit, 227107120Sjulian NG_HCI_OCF(ep->opcode), cp, e); 228107120Sjulian break; 229281198Stakawata case NG_HCI_OGF_LE: 230281198Stakawata error = process_le_params(unit, 231281198Stakawata NG_HCI_OCF(ep->opcode), cp, e); 232281198Stakawata break; 233107120Sjulian case NG_HCI_OGF_BT_LOGO: 234107120Sjulian case NG_HCI_OGF_VENDOR: 235107120Sjulian NG_FREE_M(cp); 236107120Sjulian NG_FREE_M(e); 237107120Sjulian break; 238107120Sjulian 239107120Sjulian default: 240107120Sjulian NG_FREE_M(cp); 241107120Sjulian NG_FREE_M(e); 242107120Sjulian error = EINVAL; 243107120Sjulian break; 244107120Sjulian } 245107120Sjulian } else { 246107120Sjulian NG_HCI_ERR( 247107120Sjulian"%s: %s - HCI command failed, OGF=%#x, OCF=%#x, status=%#x\n", 248107120Sjulian __func__, NG_NODE_NAME(unit->node), 249107120Sjulian NG_HCI_OGF(ep->opcode), NG_HCI_OCF(ep->opcode), 250107120Sjulian *mtod(e, u_int8_t *)); 251107120Sjulian 252107120Sjulian NG_FREE_M(cp); 253107120Sjulian NG_FREE_M(e); 254107120Sjulian } 255107120Sjulianout: 256107120Sjulian ng_hci_send_command(unit); 257107120Sjulian 258107120Sjulian return (error); 259107120Sjulian} /* ng_hci_process_command_complete */ 260107120Sjulian 261107120Sjulian/* 262107120Sjulian * Process HCI Command_Status event. Check the status (mst) and do post 263107120Sjulian * processing (if required). 264107120Sjulian */ 265107120Sjulian 266107120Sjulianint 267107120Sjulianng_hci_process_command_status(ng_hci_unit_p unit, struct mbuf *e) 268107120Sjulian{ 269107120Sjulian ng_hci_command_status_ep *ep = NULL; 270107120Sjulian struct mbuf *cp = NULL; 271107120Sjulian int error = 0; 272107120Sjulian 273107120Sjulian /* Update command buffer info */ 274107120Sjulian NG_HCI_M_PULLUP(e, sizeof(*ep)); 275107120Sjulian if (e == NULL) 276107120Sjulian return (ENOBUFS); /* XXX this is bad */ 277107120Sjulian 278107120Sjulian ep = mtod(e, ng_hci_command_status_ep *); 279107120Sjulian NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts); 280107120Sjulian 281107120Sjulian /* Check for special NOOP command */ 282107120Sjulian if (ep->opcode == 0x0000) 283107120Sjulian goto out; 284107120Sjulian 285107120Sjulian /* Try to match first command item in the queue */ 286107120Sjulian error = complete_command(unit, ep->opcode, &cp); 287107120Sjulian if (error != 0) 288107120Sjulian goto out; 289107120Sjulian 290107120Sjulian /* 291107120Sjulian * Perform post processing on HCI Command_Status event 292107120Sjulian */ 293107120Sjulian 294107120Sjulian ep->opcode = le16toh(ep->opcode); 295107120Sjulian 296107120Sjulian switch (NG_HCI_OGF(ep->opcode)) { 297107120Sjulian case NG_HCI_OGF_LINK_CONTROL: 298107120Sjulian error = process_link_control_status(unit, ep, cp); 299107120Sjulian break; 300107120Sjulian 301107120Sjulian case NG_HCI_OGF_LINK_POLICY: 302107120Sjulian error = process_link_policy_status(unit, ep, cp); 303107120Sjulian break; 304281198Stakawata case NG_HCI_OGF_LE: 305281198Stakawata error = process_le_status(unit, ep, cp); 306281198Stakawata break; 307107120Sjulian case NG_HCI_OGF_BT_LOGO: 308107120Sjulian case NG_HCI_OGF_VENDOR: 309107120Sjulian NG_FREE_M(cp); 310107120Sjulian break; 311107120Sjulian 312107120Sjulian case NG_HCI_OGF_HC_BASEBAND: 313107120Sjulian case NG_HCI_OGF_INFO: 314107120Sjulian case NG_HCI_OGF_STATUS: 315107120Sjulian case NG_HCI_OGF_TESTING: 316107120Sjulian default: 317107120Sjulian NG_FREE_M(cp); 318107120Sjulian error = EINVAL; 319107120Sjulian break; 320107120Sjulian } 321107120Sjulianout: 322107120Sjulian NG_FREE_M(e); 323107120Sjulian ng_hci_send_command(unit); 324107120Sjulian 325107120Sjulian return (error); 326107120Sjulian} /* ng_hci_process_command_status */ 327107120Sjulian 328107120Sjulian/* 329107120Sjulian * Complete queued HCI command. 330107120Sjulian */ 331107120Sjulian 332107120Sjulianstatic int 333107120Sjuliancomplete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp) 334107120Sjulian{ 335107120Sjulian struct mbuf *m = NULL; 336107120Sjulian 337107120Sjulian /* Check unit state */ 338107120Sjulian if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) { 339107120Sjulian NG_HCI_ALERT( 340107120Sjulian"%s: %s - no pending command, state=%#x\n", 341107120Sjulian __func__, NG_NODE_NAME(unit->node), unit->state); 342107120Sjulian 343107120Sjulian return (EINVAL); 344107120Sjulian } 345107120Sjulian 346107120Sjulian /* Get first command in the queue */ 347107120Sjulian m = NG_BT_MBUFQ_FIRST(&unit->cmdq); 348107120Sjulian if (m == NULL) { 349107120Sjulian NG_HCI_ALERT( 350107120Sjulian"%s: %s - empty command queue?!\n", __func__, NG_NODE_NAME(unit->node)); 351107120Sjulian 352107120Sjulian return (EINVAL); 353107120Sjulian } 354107120Sjulian 355107120Sjulian /* 356107120Sjulian * Match command opcode, if does not match - do nothing and 357107120Sjulian * let timeout handle that. 358107120Sjulian */ 359107120Sjulian 360107120Sjulian if (mtod(m, ng_hci_cmd_pkt_t *)->opcode != opcode) { 361107120Sjulian NG_HCI_ALERT( 362107120Sjulian"%s: %s - command queue is out of sync\n", __func__, NG_NODE_NAME(unit->node)); 363107120Sjulian 364107120Sjulian return (EINVAL); 365107120Sjulian } 366107120Sjulian 367107120Sjulian /* 368107120Sjulian * Now we can remove command timeout, dequeue completed command 369121054Semax * and return command parameters. ng_hci_command_untimeout will 370121054Semax * drop NG_HCI_UNIT_COMMAND_PENDING flag. 371121054Semax * Note: if ng_hci_command_untimeout() fails (returns non-zero) 372298813Spfg * then timeout already happened and timeout message went info node 373121054Semax * queue. In this case we ignore command completion and pretend 374121054Semax * there is a timeout. 375107120Sjulian */ 376107120Sjulian 377121054Semax if (ng_hci_command_untimeout(unit) != 0) 378121054Semax return (ETIMEDOUT); 379121054Semax 380107120Sjulian NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp); 381107120Sjulian m_adj(*cp, sizeof(ng_hci_cmd_pkt_t)); 382107120Sjulian 383107120Sjulian return (0); 384107120Sjulian} /* complete_command */ 385107120Sjulian 386107120Sjulian/* 387107120Sjulian * Process HCI command timeout 388107120Sjulian */ 389107120Sjulian 390107120Sjulianvoid 391107120Sjulianng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) 392107120Sjulian{ 393121054Semax ng_hci_unit_p unit = NULL; 394107120Sjulian struct mbuf *m = NULL; 395107120Sjulian u_int16_t opcode; 396107120Sjulian 397121054Semax if (NG_NODE_NOT_VALID(node)) { 398121054Semax printf("%s: Netgraph node is not valid\n", __func__); 399121054Semax return; 400121054Semax } 401121054Semax 402121054Semax unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node); 403121054Semax 404107120Sjulian if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) { 405121054Semax unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; 406121054Semax 407107120Sjulian NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m); 408107120Sjulian if (m == NULL) { 409121054Semax NG_HCI_ALERT( 410121054Semax"%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node)); 411107120Sjulian 412107120Sjulian return; 413107120Sjulian } 414107120Sjulian 415107120Sjulian opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode); 416107120Sjulian NG_FREE_M(m); 417107120Sjulian 418107120Sjulian NG_HCI_ERR( 419107120Sjulian"%s: %s - unable to complete HCI command OGF=%#x, OCF=%#x. Timeout\n", 420107120Sjulian __func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode), 421107120Sjulian NG_HCI_OCF(opcode)); 422107120Sjulian 423121054Semax /* Try to send more commands */ 424107120Sjulian NG_HCI_BUFF_CMD_SET(unit->buffer, 1); 425107120Sjulian ng_hci_send_command(unit); 426107120Sjulian } else 427121054Semax NG_HCI_ALERT( 428121054Semax"%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node)); 429107120Sjulian} /* ng_hci_process_command_timeout */ 430107120Sjulian 431107120Sjulian/* 432107120Sjulian * Process link command return parameters 433107120Sjulian */ 434107120Sjulian 435107120Sjulianstatic int 436107120Sjulianprocess_link_control_params(ng_hci_unit_p unit, u_int16_t ocf, 437107120Sjulian struct mbuf *mcp, struct mbuf *mrp) 438107120Sjulian{ 439107120Sjulian int error = 0; 440107120Sjulian 441107120Sjulian switch (ocf) { 442107120Sjulian case NG_HCI_OCF_INQUIRY_CANCEL: 443107120Sjulian case NG_HCI_OCF_PERIODIC_INQUIRY: 444107120Sjulian case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY: 445107120Sjulian case NG_HCI_OCF_LINK_KEY_REP: 446107120Sjulian case NG_HCI_OCF_LINK_KEY_NEG_REP: 447107120Sjulian case NG_HCI_OCF_PIN_CODE_REP: 448107120Sjulian case NG_HCI_OCF_PIN_CODE_NEG_REP: 449107120Sjulian /* These do not need post processing */ 450107120Sjulian break; 451107120Sjulian 452107120Sjulian case NG_HCI_OCF_INQUIRY: 453107120Sjulian case NG_HCI_OCF_CREATE_CON: 454107120Sjulian case NG_HCI_OCF_DISCON: 455107120Sjulian case NG_HCI_OCF_ADD_SCO_CON: 456107120Sjulian case NG_HCI_OCF_ACCEPT_CON: 457107120Sjulian case NG_HCI_OCF_REJECT_CON: 458107120Sjulian case NG_HCI_OCF_CHANGE_CON_PKT_TYPE: 459107120Sjulian case NG_HCI_OCF_AUTH_REQ: 460107120Sjulian case NG_HCI_OCF_SET_CON_ENCRYPTION: 461107120Sjulian case NG_HCI_OCF_CHANGE_CON_LINK_KEY: 462107120Sjulian case NG_HCI_OCF_MASTER_LINK_KEY: 463107120Sjulian case NG_HCI_OCF_REMOTE_NAME_REQ: 464107120Sjulian case NG_HCI_OCF_READ_REMOTE_FEATURES: 465107120Sjulian case NG_HCI_OCF_READ_REMOTE_VER_INFO: 466107120Sjulian case NG_HCI_OCF_READ_CLOCK_OFFSET: 467107120Sjulian default: 468107120Sjulian 469107120Sjulian /* 470107120Sjulian * None of these command was supposed to generate 471107120Sjulian * Command_Complete event. Instead Command_Status event 472107120Sjulian * should have been generated and then appropriate event 473107120Sjulian * should have been sent to indicate the final result. 474107120Sjulian */ 475107120Sjulian 476107120Sjulian error = EINVAL; 477107120Sjulian break; 478107120Sjulian } 479107120Sjulian 480107120Sjulian NG_FREE_M(mcp); 481107120Sjulian NG_FREE_M(mrp); 482107120Sjulian 483107120Sjulian return (error); 484107120Sjulian} /* process_link_control_params */ 485107120Sjulian 486107120Sjulian/* 487107120Sjulian * Process link policy command return parameters 488107120Sjulian */ 489107120Sjulian 490107120Sjulianstatic int 491107120Sjulianprocess_link_policy_params(ng_hci_unit_p unit, u_int16_t ocf, 492107120Sjulian struct mbuf *mcp, struct mbuf *mrp) 493107120Sjulian{ 494107120Sjulian int error = 0; 495107120Sjulian 496107120Sjulian switch (ocf){ 497107120Sjulian case NG_HCI_OCF_ROLE_DISCOVERY: { 498107120Sjulian ng_hci_role_discovery_rp *rp = NULL; 499107120Sjulian ng_hci_unit_con_t *con = NULL; 500107120Sjulian u_int16_t h; 501107120Sjulian 502107120Sjulian NG_HCI_M_PULLUP(mrp, sizeof(*rp)); 503107120Sjulian if (mrp != NULL) { 504107120Sjulian rp = mtod(mrp, ng_hci_role_discovery_rp *); 505107120Sjulian 506107120Sjulian h = NG_HCI_CON_HANDLE(le16toh(rp->con_handle)); 507107120Sjulian con = ng_hci_con_by_handle(unit, h); 508107120Sjulian if (con == NULL) { 509107120Sjulian NG_HCI_ALERT( 510107120Sjulian"%s: %s - invalid connection handle=%d\n", 511107120Sjulian __func__, NG_NODE_NAME(unit->node), h); 512107120Sjulian error = ENOENT; 513107120Sjulian } else if (con->link_type != NG_HCI_LINK_ACL) { 514107120Sjulian NG_HCI_ALERT( 515107120Sjulian"%s: %s - invalid link type=%d\n", __func__, NG_NODE_NAME(unit->node), 516107120Sjulian con->link_type); 517107120Sjulian error = EINVAL; 518107120Sjulian } else 519107120Sjulian con->role = rp->role; 520107120Sjulian } else 521107120Sjulian error = ENOBUFS; 522107120Sjulian } break; 523107120Sjulian 524107120Sjulian case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS: 525107120Sjulian case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS: 526107120Sjulian /* These do not need post processing */ 527107120Sjulian break; 528107120Sjulian 529107120Sjulian case NG_HCI_OCF_HOLD_MODE: 530107120Sjulian case NG_HCI_OCF_SNIFF_MODE: 531107120Sjulian case NG_HCI_OCF_EXIT_SNIFF_MODE: 532107120Sjulian case NG_HCI_OCF_PARK_MODE: 533107120Sjulian case NG_HCI_OCF_EXIT_PARK_MODE: 534107120Sjulian case NG_HCI_OCF_QOS_SETUP: 535107120Sjulian case NG_HCI_OCF_SWITCH_ROLE: 536107120Sjulian default: 537107120Sjulian 538107120Sjulian /* 539107120Sjulian * None of these command was supposed to generate 540107120Sjulian * Command_Complete event. Instead Command_Status event 541107120Sjulian * should have been generated and then appropriate event 542107120Sjulian * should have been sent to indicate the final result. 543107120Sjulian */ 544107120Sjulian 545107120Sjulian error = EINVAL; 546107120Sjulian break; 547107120Sjulian } 548107120Sjulian 549107120Sjulian NG_FREE_M(mcp); 550107120Sjulian NG_FREE_M(mrp); 551107120Sjulian 552107120Sjulian return (error); 553107120Sjulian} /* process_link_policy_params */ 554107120Sjulian 555107120Sjulian/* 556107120Sjulian * Process HC and baseband command return parameters 557107120Sjulian */ 558107120Sjulian 559107120Sjulianint 560107120Sjulianprocess_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf, 561107120Sjulian struct mbuf *mcp, struct mbuf *mrp) 562107120Sjulian{ 563107120Sjulian int error = 0; 564107120Sjulian 565107120Sjulian switch (ocf) { 566107120Sjulian case NG_HCI_OCF_SET_EVENT_MASK: 567107120Sjulian case NG_HCI_OCF_SET_EVENT_FILTER: 568107120Sjulian case NG_HCI_OCF_FLUSH: /* XXX Do we need to handle that? */ 569107120Sjulian case NG_HCI_OCF_READ_PIN_TYPE: 570107120Sjulian case NG_HCI_OCF_WRITE_PIN_TYPE: 571107120Sjulian case NG_HCI_OCF_CREATE_NEW_UNIT_KEY: 572107120Sjulian case NG_HCI_OCF_WRITE_STORED_LINK_KEY: 573107120Sjulian case NG_HCI_OCF_WRITE_CON_ACCEPT_TIMO: 574107120Sjulian case NG_HCI_OCF_WRITE_PAGE_TIMO: 575107120Sjulian case NG_HCI_OCF_READ_SCAN_ENABLE: 576107120Sjulian case NG_HCI_OCF_WRITE_SCAN_ENABLE: 577107120Sjulian case NG_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY: 578107120Sjulian case NG_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY: 579107120Sjulian case NG_HCI_OCF_READ_AUTH_ENABLE: 580107120Sjulian case NG_HCI_OCF_WRITE_AUTH_ENABLE: 581107120Sjulian case NG_HCI_OCF_READ_ENCRYPTION_MODE: 582107120Sjulian case NG_HCI_OCF_WRITE_ENCRYPTION_MODE: 583107120Sjulian case NG_HCI_OCF_WRITE_VOICE_SETTINGS: 584107120Sjulian case NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS: 585107120Sjulian case NG_HCI_OCF_WRITE_NUM_BROADCAST_RETRANS: 586107120Sjulian case NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY: 587107120Sjulian case NG_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY: 588107120Sjulian case NG_HCI_OCF_READ_SCO_FLOW_CONTROL: 589107120Sjulian case NG_HCI_OCF_WRITE_SCO_FLOW_CONTROL: 590107120Sjulian case NG_HCI_OCF_H2HC_FLOW_CONTROL: /* XXX Not supported this time */ 591107120Sjulian case NG_HCI_OCF_HOST_BUFFER_SIZE: 592107120Sjulian case NG_HCI_OCF_READ_IAC_LAP: 593107120Sjulian case NG_HCI_OCF_WRITE_IAC_LAP: 594107120Sjulian case NG_HCI_OCF_READ_PAGE_SCAN_PERIOD: 595107120Sjulian case NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD: 596107120Sjulian case NG_HCI_OCF_READ_PAGE_SCAN: 597107120Sjulian case NG_HCI_OCF_WRITE_PAGE_SCAN: 598107120Sjulian case NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO: 599107120Sjulian case NG_HCI_OCF_WRITE_LINK_SUPERVISION_TIMO: 600107120Sjulian case NG_HCI_OCF_READ_SUPPORTED_IAC_NUM: 601107120Sjulian case NG_HCI_OCF_READ_STORED_LINK_KEY: 602107120Sjulian case NG_HCI_OCF_DELETE_STORED_LINK_KEY: 603107120Sjulian case NG_HCI_OCF_READ_CON_ACCEPT_TIMO: 604107120Sjulian case NG_HCI_OCF_READ_PAGE_TIMO: 605107120Sjulian case NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY: 606107120Sjulian case NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY: 607107120Sjulian case NG_HCI_OCF_READ_VOICE_SETTINGS: 608107120Sjulian case NG_HCI_OCF_READ_AUTO_FLUSH_TIMO: 609107120Sjulian case NG_HCI_OCF_WRITE_AUTO_FLUSH_TIMO: 610107120Sjulian case NG_HCI_OCF_READ_XMIT_LEVEL: 611107120Sjulian case NG_HCI_OCF_HOST_NUM_COMPL_PKTS: /* XXX Can get here? */ 612107120Sjulian case NG_HCI_OCF_CHANGE_LOCAL_NAME: 613107120Sjulian case NG_HCI_OCF_READ_LOCAL_NAME: 614107120Sjulian case NG_HCI_OCF_READ_UNIT_CLASS: 615107120Sjulian case NG_HCI_OCF_WRITE_UNIT_CLASS: 616281198Stakawata case NG_HCI_OCF_READ_LE_HOST_SUPPORTED: 617281198Stakawata case NG_HCI_OCF_WRITE_LE_HOST_SUPPORTED: 618107120Sjulian /* These do not need post processing */ 619107120Sjulian break; 620107120Sjulian 621107120Sjulian case NG_HCI_OCF_RESET: { 622107120Sjulian ng_hci_unit_con_p con = NULL; 623107120Sjulian int size; 624107120Sjulian 625107120Sjulian /* 626107120Sjulian * XXX 627107120Sjulian * 628107120Sjulian * After RESET command unit goes into standby mode 629107120Sjulian * and all operational state is lost. Host controller 630107120Sjulian * will revert to default values for all parameters. 631107120Sjulian * 632107120Sjulian * For now we shall terminate all connections and drop 633107120Sjulian * inited bit. After RESET unit must be re-initialized. 634107120Sjulian */ 635107120Sjulian 636107120Sjulian while (!LIST_EMPTY(&unit->con_list)) { 637107120Sjulian con = LIST_FIRST(&unit->con_list); 638107120Sjulian 639121054Semax /* Remove all timeouts (if any) */ 640121054Semax if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) 641121054Semax ng_hci_con_untimeout(con); 642121054Semax 643107120Sjulian /* Connection terminated by local host */ 644107120Sjulian ng_hci_lp_discon_ind(con, 0x16); 645107120Sjulian ng_hci_free_con(con); 646107120Sjulian } 647107120Sjulian 648107120Sjulian NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size); 649107120Sjulian NG_HCI_BUFF_ACL_FREE(unit->buffer, size); 650107120Sjulian 651107120Sjulian NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size); 652107120Sjulian NG_HCI_BUFF_SCO_FREE(unit->buffer, size); 653107120Sjulian 654107120Sjulian unit->state &= ~NG_HCI_UNIT_INITED; 655107120Sjulian } break; 656107120Sjulian 657107120Sjulian default: 658107120Sjulian error = EINVAL; 659107120Sjulian break; 660107120Sjulian } 661107120Sjulian 662107120Sjulian NG_FREE_M(mcp); 663107120Sjulian NG_FREE_M(mrp); 664107120Sjulian 665107120Sjulian return (error); 666107120Sjulian} /* process_hc_baseband_params */ 667107120Sjulian 668107120Sjulian/* 669107120Sjulian * Process info command return parameters 670107120Sjulian */ 671107120Sjulian 672107120Sjulianstatic int 673107120Sjulianprocess_info_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp, 674107120Sjulian struct mbuf *mrp) 675107120Sjulian{ 676107120Sjulian int error = 0, len; 677107120Sjulian 678107120Sjulian switch (ocf) { 679107120Sjulian case NG_HCI_OCF_READ_LOCAL_VER: 680107120Sjulian case NG_HCI_OCF_READ_COUNTRY_CODE: 681107120Sjulian break; 682107120Sjulian 683107120Sjulian case NG_HCI_OCF_READ_LOCAL_FEATURES: 684107120Sjulian m_adj(mrp, sizeof(u_int8_t)); 685107120Sjulian len = min(mrp->m_pkthdr.len, sizeof(unit->features)); 686107120Sjulian m_copydata(mrp, 0, len, (caddr_t) unit->features); 687107120Sjulian break; 688107120Sjulian 689107120Sjulian case NG_HCI_OCF_READ_BUFFER_SIZE: { 690107120Sjulian ng_hci_read_buffer_size_rp *rp = NULL; 691107120Sjulian 692107120Sjulian /* Do not update buffer descriptor if node was initialized */ 693107120Sjulian if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY) 694107120Sjulian break; 695107120Sjulian 696107120Sjulian NG_HCI_M_PULLUP(mrp, sizeof(*rp)); 697107120Sjulian if (mrp != NULL) { 698107120Sjulian rp = mtod(mrp, ng_hci_read_buffer_size_rp *); 699107120Sjulian 700107120Sjulian NG_HCI_BUFF_ACL_SET( 701107120Sjulian unit->buffer, 702107120Sjulian le16toh(rp->num_acl_pkt), /* number */ 703107120Sjulian le16toh(rp->max_acl_size), /* size */ 704107120Sjulian le16toh(rp->num_acl_pkt) /* free */ 705107120Sjulian ); 706107120Sjulian 707107120Sjulian NG_HCI_BUFF_SCO_SET( 708107120Sjulian unit->buffer, 709107120Sjulian le16toh(rp->num_sco_pkt), /* number */ 710107120Sjulian rp->max_sco_size, /* size */ 711107120Sjulian le16toh(rp->num_sco_pkt) /* free */ 712107120Sjulian ); 713107120Sjulian 714107120Sjulian /* Let upper layers know */ 715107120Sjulian ng_hci_node_is_up(unit->node, unit->acl, NULL, 0); 716107120Sjulian ng_hci_node_is_up(unit->node, unit->sco, NULL, 0); 717107120Sjulian } else 718107120Sjulian error = ENOBUFS; 719107120Sjulian } break; 720107120Sjulian 721107120Sjulian case NG_HCI_OCF_READ_BDADDR: 722107120Sjulian /* Do not update BD_ADDR if node was initialized */ 723107120Sjulian if ((unit->state & NG_HCI_UNIT_READY) == NG_HCI_UNIT_READY) 724107120Sjulian break; 725107120Sjulian 726107120Sjulian m_adj(mrp, sizeof(u_int8_t)); 727107120Sjulian len = min(mrp->m_pkthdr.len, sizeof(unit->bdaddr)); 728107120Sjulian m_copydata(mrp, 0, len, (caddr_t) &unit->bdaddr); 729107120Sjulian 730107120Sjulian /* Let upper layers know */ 731107120Sjulian ng_hci_node_is_up(unit->node, unit->acl, NULL, 0); 732107120Sjulian ng_hci_node_is_up(unit->node, unit->sco, NULL, 0); 733107120Sjulian break; 734107120Sjulian 735107120Sjulian default: 736107120Sjulian error = EINVAL; 737107120Sjulian break; 738107120Sjulian } 739107120Sjulian 740107120Sjulian NG_FREE_M(mcp); 741107120Sjulian NG_FREE_M(mrp); 742107120Sjulian 743107120Sjulian return (error); 744107120Sjulian} /* process_info_params */ 745107120Sjulian 746107120Sjulian/* 747107120Sjulian * Process status command return parameters 748107120Sjulian */ 749107120Sjulian 750107120Sjulianstatic int 751107120Sjulianprocess_status_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp, 752107120Sjulian struct mbuf *mrp) 753107120Sjulian{ 754107120Sjulian int error = 0; 755107120Sjulian 756107120Sjulian switch (ocf) { 757107120Sjulian case NG_HCI_OCF_READ_FAILED_CONTACT_CNTR: 758107120Sjulian case NG_HCI_OCF_RESET_FAILED_CONTACT_CNTR: 759107120Sjulian case NG_HCI_OCF_GET_LINK_QUALITY: 760107120Sjulian case NG_HCI_OCF_READ_RSSI: 761107120Sjulian /* These do not need post processing */ 762107120Sjulian break; 763107120Sjulian 764107120Sjulian default: 765107120Sjulian error = EINVAL; 766107120Sjulian break; 767107120Sjulian } 768107120Sjulian 769107120Sjulian NG_FREE_M(mcp); 770107120Sjulian NG_FREE_M(mrp); 771107120Sjulian 772107120Sjulian return (error); 773107120Sjulian} /* process_status_params */ 774107120Sjulian 775107120Sjulian/* 776107120Sjulian * Process testing command return parameters 777107120Sjulian */ 778107120Sjulian 779107120Sjulianint 780107120Sjulianprocess_testing_params(ng_hci_unit_p unit, u_int16_t ocf, struct mbuf *mcp, 781107120Sjulian struct mbuf *mrp) 782107120Sjulian{ 783107120Sjulian int error = 0; 784107120Sjulian 785107120Sjulian switch (ocf) { 786107120Sjulian 787107120Sjulian /* 788107120Sjulian * XXX FIXME 789107120Sjulian * We do not support these features at this time. However, 790107120Sjulian * HCI node could support this and do something smart. At least 791107120Sjulian * node can change unit state. 792107120Sjulian */ 793107120Sjulian 794107120Sjulian case NG_HCI_OCF_READ_LOOPBACK_MODE: 795107120Sjulian case NG_HCI_OCF_WRITE_LOOPBACK_MODE: 796107120Sjulian case NG_HCI_OCF_ENABLE_UNIT_UNDER_TEST: 797107120Sjulian break; 798107120Sjulian 799107120Sjulian default: 800107120Sjulian error = EINVAL; 801107120Sjulian break; 802107120Sjulian } 803107120Sjulian 804107120Sjulian NG_FREE_M(mcp); 805107120Sjulian NG_FREE_M(mrp); 806107120Sjulian 807107120Sjulian return (error); 808107120Sjulian} /* process_testing_params */ 809107120Sjulian 810281198Stakawata/* 811281198Stakawata * Process LE command return parameters 812281198Stakawata */ 813281198Stakawata 814281198Stakawatastatic int 815281198Stakawataprocess_le_params(ng_hci_unit_p unit, u_int16_t ocf, 816281198Stakawata struct mbuf *mcp, struct mbuf *mrp) 817281198Stakawata{ 818281198Stakawata int error = 0; 819281198Stakawata 820281198Stakawata switch (ocf){ 821281198Stakawata case NG_HCI_OCF_LE_SET_EVENT_MASK: 822281198Stakawata case NG_HCI_OCF_LE_READ_BUFFER_SIZE: 823281198Stakawata case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES: 824281198Stakawata case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS: 825281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS: 826281198Stakawata case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER: 827281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISING_DATA: 828281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA: 829281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE: 830281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS: 831281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_ENABLE: 832281198Stakawata case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL: 833281198Stakawata case NG_HCI_OCF_LE_CLEAR_WHITE_LIST: 834281198Stakawata case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE: 835281198Stakawata case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST: 836281198Stakawata case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST: 837281198Stakawata case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION: 838281198Stakawata case NG_HCI_OCF_LE_READ_CHANNEL_MAP: 839281198Stakawata case NG_HCI_OCF_LE_ENCRYPT: 840281198Stakawata case NG_HCI_OCF_LE_RAND: 841281198Stakawata case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY: 842281198Stakawata case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY: 843361165Shselasky case NG_HCI_OCF_LE_READ_SUPPORTED_STATES: 844281198Stakawata case NG_HCI_OCF_LE_RECEIVER_TEST: 845281198Stakawata case NG_HCI_OCF_LE_TRANSMITTER_TEST: 846281198Stakawata case NG_HCI_OCF_LE_TEST_END: 847281198Stakawata 848281198Stakawata /* These do not need post processing */ 849281198Stakawata break; 850281198Stakawata case NG_HCI_OCF_LE_CREATE_CONNECTION: 851281198Stakawata case NG_HCI_OCF_LE_CONNECTION_UPDATE: 852281198Stakawata case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES: 853281198Stakawata case NG_HCI_OCF_LE_START_ENCRYPTION: 854281198Stakawata 855281198Stakawata 856281198Stakawata default: 857281198Stakawata /* 858281198Stakawata * None of these command was supposed to generate 859281198Stakawata * Command_Complete event. Instead Command_Status event 860281198Stakawata * should have been generated and then appropriate event 861281198Stakawata * should have been sent to indicate the final result. 862281198Stakawata */ 863281198Stakawata 864281198Stakawata error = EINVAL; 865281198Stakawata break; 866281198Stakawata } 867281198Stakawata 868281198Stakawata NG_FREE_M(mcp); 869281198Stakawata NG_FREE_M(mrp); 870281198Stakawata 871281198Stakawata return (error); 872281198Stakawata 873281198Stakawata} 874281198Stakawata 875281198Stakawata 876281198Stakawata 877281198Stakawatastatic int 878281198Stakawataprocess_le_status(ng_hci_unit_p unit,ng_hci_command_status_ep *ep, 879281198Stakawata struct mbuf *mcp) 880281198Stakawata{ 881281198Stakawata int error = 0; 882281198Stakawata 883281198Stakawata switch (NG_HCI_OCF(ep->opcode)){ 884281198Stakawata case NG_HCI_OCF_LE_CREATE_CONNECTION: 885281198Stakawata case NG_HCI_OCF_LE_CONNECTION_UPDATE: 886281198Stakawata case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES: 887281198Stakawata case NG_HCI_OCF_LE_START_ENCRYPTION: 888281198Stakawata 889281198Stakawata /* These do not need post processing */ 890281198Stakawata break; 891281198Stakawata 892281198Stakawata case NG_HCI_OCF_LE_SET_EVENT_MASK: 893281198Stakawata case NG_HCI_OCF_LE_READ_BUFFER_SIZE: 894281198Stakawata case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES: 895281198Stakawata case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS: 896281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS: 897281198Stakawata case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER: 898281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISING_DATA: 899281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA: 900281198Stakawata case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE: 901281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS: 902281198Stakawata case NG_HCI_OCF_LE_SET_SCAN_ENABLE: 903281198Stakawata case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL: 904281198Stakawata case NG_HCI_OCF_LE_CLEAR_WHITE_LIST: 905281198Stakawata case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE: 906281198Stakawata case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST: 907281198Stakawata case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST: 908281198Stakawata case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION: 909281198Stakawata case NG_HCI_OCF_LE_READ_CHANNEL_MAP: 910281198Stakawata case NG_HCI_OCF_LE_ENCRYPT: 911281198Stakawata case NG_HCI_OCF_LE_RAND: 912281198Stakawata case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY: 913281198Stakawata case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY: 914361165Shselasky case NG_HCI_OCF_LE_READ_SUPPORTED_STATES: 915281198Stakawata case NG_HCI_OCF_LE_RECEIVER_TEST: 916281198Stakawata case NG_HCI_OCF_LE_TRANSMITTER_TEST: 917281198Stakawata case NG_HCI_OCF_LE_TEST_END: 918281198Stakawata 919281198Stakawata 920281198Stakawata default: 921281198Stakawata /* 922281198Stakawata * None of these command was supposed to generate 923281198Stakawata * Command_Stutus event. Command Complete instead. 924281198Stakawata */ 925281198Stakawata 926281198Stakawata error = EINVAL; 927281198Stakawata break; 928281198Stakawata } 929281198Stakawata 930281198Stakawata NG_FREE_M(mcp); 931281198Stakawata 932281198Stakawata return (error); 933281198Stakawata 934281198Stakawata} 935281198Stakawata 936107120Sjulian/* 937107120Sjulian * Process link control command status 938107120Sjulian */ 939107120Sjulian 940107120Sjulianstatic int 941107120Sjulianprocess_link_control_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep, 942107120Sjulian struct mbuf *mcp) 943107120Sjulian{ 944107120Sjulian int error = 0; 945107120Sjulian 946107120Sjulian switch (NG_HCI_OCF(ep->opcode)) { 947107120Sjulian case NG_HCI_OCF_INQUIRY: 948107120Sjulian case NG_HCI_OCF_DISCON: /* XXX */ 949107120Sjulian case NG_HCI_OCF_REJECT_CON: /* XXX */ 950107120Sjulian case NG_HCI_OCF_CHANGE_CON_PKT_TYPE: 951107120Sjulian case NG_HCI_OCF_AUTH_REQ: 952107120Sjulian case NG_HCI_OCF_SET_CON_ENCRYPTION: 953107120Sjulian case NG_HCI_OCF_CHANGE_CON_LINK_KEY: 954107120Sjulian case NG_HCI_OCF_MASTER_LINK_KEY: 955107120Sjulian case NG_HCI_OCF_REMOTE_NAME_REQ: 956107120Sjulian case NG_HCI_OCF_READ_REMOTE_FEATURES: 957107120Sjulian case NG_HCI_OCF_READ_REMOTE_VER_INFO: 958107120Sjulian case NG_HCI_OCF_READ_CLOCK_OFFSET: 959107120Sjulian /* These do not need post processing */ 960107120Sjulian break; 961107120Sjulian 962107120Sjulian case NG_HCI_OCF_CREATE_CON: 963107120Sjulian break; 964107120Sjulian 965107120Sjulian case NG_HCI_OCF_ADD_SCO_CON: 966107120Sjulian break; 967107120Sjulian 968107120Sjulian case NG_HCI_OCF_ACCEPT_CON: 969107120Sjulian break; 970107120Sjulian 971107120Sjulian case NG_HCI_OCF_INQUIRY_CANCEL: 972107120Sjulian case NG_HCI_OCF_PERIODIC_INQUIRY: 973107120Sjulian case NG_HCI_OCF_EXIT_PERIODIC_INQUIRY: 974107120Sjulian case NG_HCI_OCF_LINK_KEY_REP: 975107120Sjulian case NG_HCI_OCF_LINK_KEY_NEG_REP: 976107120Sjulian case NG_HCI_OCF_PIN_CODE_REP: 977107120Sjulian case NG_HCI_OCF_PIN_CODE_NEG_REP: 978107120Sjulian default: 979107120Sjulian 980107120Sjulian /* 981107120Sjulian * None of these command was supposed to generate 982107120Sjulian * Command_Status event. Instead Command_Complete event 983107120Sjulian * should have been sent. 984107120Sjulian */ 985107120Sjulian 986107120Sjulian error = EINVAL; 987107120Sjulian break; 988107120Sjulian } 989107120Sjulian 990107120Sjulian NG_FREE_M(mcp); 991107120Sjulian 992107120Sjulian return (error); 993107120Sjulian} /* process_link_control_status */ 994107120Sjulian 995107120Sjulian/* 996107120Sjulian * Process link policy command status 997107120Sjulian */ 998107120Sjulian 999107120Sjulianstatic int 1000107120Sjulianprocess_link_policy_status(ng_hci_unit_p unit, ng_hci_command_status_ep *ep, 1001107120Sjulian struct mbuf *mcp) 1002107120Sjulian{ 1003107120Sjulian int error = 0; 1004107120Sjulian 1005107120Sjulian switch (NG_HCI_OCF(ep->opcode)) { 1006107120Sjulian case NG_HCI_OCF_HOLD_MODE: 1007107120Sjulian case NG_HCI_OCF_SNIFF_MODE: 1008107120Sjulian case NG_HCI_OCF_EXIT_SNIFF_MODE: 1009107120Sjulian case NG_HCI_OCF_PARK_MODE: 1010107120Sjulian case NG_HCI_OCF_EXIT_PARK_MODE: 1011107120Sjulian case NG_HCI_OCF_SWITCH_ROLE: 1012107120Sjulian /* These do not need post processing */ 1013107120Sjulian break; 1014107120Sjulian 1015107120Sjulian case NG_HCI_OCF_QOS_SETUP: 1016107120Sjulian break; 1017107120Sjulian 1018107120Sjulian case NG_HCI_OCF_ROLE_DISCOVERY: 1019107120Sjulian case NG_HCI_OCF_READ_LINK_POLICY_SETTINGS: 1020107120Sjulian case NG_HCI_OCF_WRITE_LINK_POLICY_SETTINGS: 1021107120Sjulian default: 1022107120Sjulian 1023107120Sjulian /* 1024107120Sjulian * None of these command was supposed to generate 1025107120Sjulian * Command_Status event. Instead Command_Complete event 1026107120Sjulian * should have been sent. 1027107120Sjulian */ 1028107120Sjulian 1029107120Sjulian error = EINVAL; 1030107120Sjulian break; 1031107120Sjulian } 1032107120Sjulian 1033107120Sjulian NG_FREE_M(mcp); 1034107120Sjulian 1035107120Sjulian return (error); 1036107120Sjulian} /* process_link_policy_status */ 1037107120Sjulian 1038