void ng_hci_unit_clean(ng_hci_unit_p unit, int reason) { int size; /* Drain command queue */ if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) ng_hci_command_untimeout(unit); NG_BT_MBUFQ_DRAIN(&unit->cmdq); NG_HCI_BUFF_CMD_SET(unit->buffer, 1); /* Clean up connection list */ while (!LIST_EMPTY(&unit->con_list)) { ng_hci_unit_con_p con = LIST_FIRST(&unit->con_list); /* Remove all timeouts (if any) */ if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) ng_hci_con_untimeout(con); /* * Notify upper layer protocol and destroy connection * descriptor. Do not really care about the result. */ ng_hci_lp_discon_ind(con, reason); ng_hci_free_con(con); } NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size); NG_HCI_BUFF_ACL_FREE(unit->buffer, size); NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size); NG_HCI_BUFF_SCO_FREE(unit->buffer, size); /* Clean up neighbors list */ ng_hci_flush_neighbor_cache(unit); } /* ng_hci_unit_clean */
int ng_hci_process_command_complete(ng_hci_unit_p unit, struct mbuf *e) { ng_hci_command_compl_ep *ep = NULL; struct mbuf *cp = NULL; int error = 0; /* Get event packet and update command buffer info */ NG_HCI_M_PULLUP(e, sizeof(*ep)); if (e == NULL) return (ENOBUFS); /* XXX this is bad */ ep = mtod(e, ng_hci_command_compl_ep *); NG_HCI_BUFF_CMD_SET(unit->buffer, ep->num_cmd_pkts); /* Check for special NOOP command */ if (ep->opcode == 0x0000) { NG_FREE_M(e); goto out; } /* Try to match first command item in the queue */ error = complete_command(unit, ep->opcode, &cp); if (error != 0) { NG_FREE_M(e); goto out; } /* * Perform post processing on command parameters and return parameters * do it only if status is OK (status == 0). Status is the first byte * of any command return parameters. */ ep->opcode = le16toh(ep->opcode); m_adj(e, sizeof(*ep)); if (*mtod(e, u_int8_t *) == 0) { /* XXX m_pullup here? */ switch (NG_HCI_OGF(ep->opcode)) { case NG_HCI_OGF_LINK_CONTROL: error = process_link_control_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_LINK_POLICY: error = process_link_policy_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_HC_BASEBAND: error = process_hc_baseband_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_INFO: error = process_info_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_STATUS: error = process_status_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_TESTING: error = process_testing_params(unit, NG_HCI_OCF(ep->opcode), cp, e); break; case NG_HCI_OGF_BT_LOGO: case NG_HCI_OGF_VENDOR: NG_FREE_M(cp); NG_FREE_M(e); break; default: NG_FREE_M(cp); NG_FREE_M(e); error = EINVAL; break; } } else {