static void hci_link_control(uint16_t ocf, int plen, uint8_t *data) { uint8_t status; const uint16_t ogf = OGF_LINK_CTL; switch (ocf) { case OCF_CREATE_CONN: command_status(ogf, ocf, 0x00); create_connection(data); break; case OCF_ACCEPT_CONN_REQ: command_status(ogf, ocf, 0x00); accept_connection(data); break; case OCF_DISCONNECT: command_status(ogf, ocf, 0x00); disconnect(data); break; default: status = 0x01; command_complete(ogf, ocf, 1, &status); break; } }
static struct stasis_app_command *exec_command_on_condition( struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, app_command_can_exec_cb can_exec_fn) { int retval; struct stasis_app_command *command; command_fn = command_fn ? : noop_cb; command = command_create(command_fn, data); if (!command) { return NULL; } ao2_lock(control->command_queue); if (can_exec_fn && (retval = can_exec_fn(control))) { ao2_unlock(control->command_queue); command_complete(command, retval); return command; } ao2_link_flags(control->command_queue, command, OBJ_NOLOCK); ast_cond_signal(&control->wait_cond); ao2_unlock(control->command_queue); return command; }
static void hci_status_param(uint16_t ocf, int plen, uint8_t *data) { read_local_amp_info_rp ai; const uint16_t ogf = OGF_STATUS_PARAM; switch (ocf) { case OCF_READ_LOCAL_AMP_INFO: memset(&ai, 0, sizeof(ai)); /* BT only */ ai.amp_status = 0x01; ai.max_pdu_size = htobl(L2CAP_DEFAULT_MTU); ai.controller_type = HCI_AMP; ai.max_amp_assoc_length = htobl(HCI_MAX_ACL_SIZE); /* No flushing at all */ ai.max_flush_timeout = 0xFFFFFFFF; ai.best_effort_flush_timeout = 0xFFFFFFFF; command_complete(ogf, ocf, sizeof(ai), &ai); break; default: command_status(ogf, ocf, 0x01); break; } }
void control_flush_queue(struct stasis_app_control *control) { struct ao2_iterator iter; struct stasis_app_command *command; iter = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK); while ((command = ao2_iterator_next(&iter))) { command_complete(command, -1); ao2_ref(command, -1); } ao2_iterator_destroy(&iter); }
static void hci_link_policy(uint16_t ocf, int plen, uint8_t *data) { uint8_t status; const uint16_t ogf = OGF_INFO_PARAM; switch (ocf) { default: status = 0x01; command_complete(ogf, ocf, 1, &status); break; } }
static void hci_le_control(uint16_t ocf, int plen, uint8_t *data) { le_read_buffer_size_rp bs; const uint16_t ogf = OGF_LE_CTL; switch (ocf) { case OCF_LE_READ_BUFFER_SIZE: bs.status = 0; bs.pkt_len = htobs(VHCI_ACL_MTU); bs.max_pkt = htobs(VHCI_ACL_MAX_PKT); command_complete(ogf, ocf, sizeof(bs), &bs); break; default: command_status(ogf, ocf, 0x01); break; } }
static void hci_info_param(uint16_t ocf, int plen, uint8_t *data) { read_local_version_rp lv; read_local_features_rp lf; read_local_ext_features_rp ef; read_buffer_size_rp bs; read_bd_addr_rp ba; uint8_t status; const uint16_t ogf = OGF_INFO_PARAM; switch (ocf) { case OCF_READ_LOCAL_VERSION: lv.status = 0x00; lv.hci_ver = 0x03; lv.hci_rev = htobs(0x0000); lv.lmp_ver = 0x03; lv.manufacturer = htobs(29); lv.lmp_subver = htobs(0x0000); command_complete(ogf, ocf, sizeof(lv), &lv); break; case OCF_READ_LOCAL_FEATURES: lf.status = 0x00; memcpy(lf.features, vdev.features, 8); command_complete(ogf, ocf, sizeof(lf), &lf); break; case OCF_READ_LOCAL_EXT_FEATURES: ef.status = 0x00; if (*data == 0) { ef.page_num = 0; ef.max_page_num = 0; memcpy(ef.features, vdev.features, 8); } else { ef.page_num = *data; ef.max_page_num = 0; memset(ef.features, 0, 8); } command_complete(ogf, ocf, sizeof(ef), &ef); break; case OCF_READ_BUFFER_SIZE: bs.status = 0x00; bs.acl_mtu = htobs(VHCI_ACL_MTU); bs.sco_mtu = 0; bs.acl_max_pkt = htobs(VHCI_ACL_MAX_PKT); bs.sco_max_pkt = htobs(0); command_complete(ogf, ocf, sizeof(bs), &bs); break; case OCF_READ_BD_ADDR: ba.status = 0x00; bacpy(&ba.bdaddr, &vdev.bdaddr); command_complete(ogf, ocf, sizeof(ba), &ba); break; default: status = 0x01; command_complete(ogf, ocf, 1, &status); break; } }
static void hci_host_control(uint16_t ocf, int plen, uint8_t *data) { read_local_name_rp ln; read_class_of_dev_rp cd; read_inquiry_mode_rp im; read_ext_inquiry_response_rp ir; uint8_t status; const uint16_t ogf = OGF_HOST_CTL; switch (ocf) { case OCF_RESET: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_SET_EVENT_FLT: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_CHANGE_LOCAL_NAME: status = 0x00; memcpy(vdev.name, data, sizeof(vdev.name)); command_complete(ogf, ocf, 1, &status); break; case OCF_READ_LOCAL_NAME: ln.status = 0x00; memcpy(ln.name, vdev.name, sizeof(ln.name)); command_complete(ogf, ocf, sizeof(ln), &ln); break; case OCF_WRITE_CONN_ACCEPT_TIMEOUT: case OCF_WRITE_PAGE_TIMEOUT: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_WRITE_SCAN_ENABLE: status = scan_enable(data); command_complete(ogf, ocf, 1, &status); break; case OCF_WRITE_AUTH_ENABLE: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_WRITE_ENCRYPT_MODE: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_CLASS_OF_DEV: cd.status = 0x00; memcpy(cd.dev_class, vdev.dev_class, 3); command_complete(ogf, ocf, sizeof(cd), &cd); break; case OCF_WRITE_CLASS_OF_DEV: status = 0x00; memcpy(vdev.dev_class, data, 3); command_complete(ogf, ocf, 1, &status); break; case OCF_READ_INQUIRY_MODE: im.status = 0x00; im.mode = vdev.inq_mode; command_complete(ogf, ocf, sizeof(im), &im); break; case OCF_WRITE_INQUIRY_MODE: status = 0x00; vdev.inq_mode = data[0]; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_EXT_INQUIRY_RESPONSE: ir.status = 0x00; ir.fec = vdev.eir_fec; memcpy(ir.data, vdev.eir_data, HCI_MAX_EIR_LENGTH); command_complete(ogf, ocf, sizeof(ir), &ir); break; case OCF_WRITE_EXT_INQUIRY_RESPONSE: status = 0x00; vdev.eir_fec = data[0]; memcpy(vdev.eir_data, data + 1, HCI_MAX_EIR_LENGTH); command_complete(ogf, ocf, 1, &status); break; default: status = 0x01; command_complete(ogf, ocf, 1, &status); break; } }
static void hci_host_control(uint16_t ocf, int plen, uint8_t *data) { read_scan_enable_rp se; read_local_name_rp ln; read_class_of_dev_rp cd; read_inquiry_mode_rp im; read_ext_inquiry_response_rp ir; read_simple_pairing_mode_rp pm; read_le_host_supported_rp hs; uint8_t status; const uint16_t ogf = OGF_HOST_CTL; switch (ocf) { case OCF_RESET: status = 0x00; reset_vdev(); command_complete(ogf, ocf, 1, &status); break; case OCF_SET_EVENT_FLT: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_CHANGE_LOCAL_NAME: status = 0x00; memcpy(vdev.name, data, sizeof(vdev.name)); command_complete(ogf, ocf, 1, &status); break; case OCF_READ_LOCAL_NAME: ln.status = 0x00; memcpy(ln.name, vdev.name, sizeof(ln.name)); command_complete(ogf, ocf, sizeof(ln), &ln); break; case OCF_WRITE_CONN_ACCEPT_TIMEOUT: case OCF_WRITE_PAGE_TIMEOUT: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_SCAN_ENABLE: se.status = 0x00; se.enable = vdev.scan_enable; command_complete(ogf, ocf, sizeof(se), &se); break; case OCF_WRITE_SCAN_ENABLE: status = 0x00; vdev.scan_enable = scan_enable(data); command_complete(ogf, ocf, 1, &status); break; case OCF_WRITE_AUTH_ENABLE: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_WRITE_ENCRYPT_MODE: status = 0x00; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_CLASS_OF_DEV: cd.status = 0x00; memcpy(cd.dev_class, vdev.dev_class, 3); command_complete(ogf, ocf, sizeof(cd), &cd); break; case OCF_WRITE_CLASS_OF_DEV: status = 0x00; memcpy(vdev.dev_class, data, 3); command_complete(ogf, ocf, 1, &status); break; case OCF_READ_INQUIRY_MODE: im.status = 0x00; im.mode = vdev.inq_mode; command_complete(ogf, ocf, sizeof(im), &im); break; case OCF_WRITE_INQUIRY_MODE: status = 0x00; vdev.inq_mode = data[0]; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_EXT_INQUIRY_RESPONSE: ir.status = 0x00; ir.fec = vdev.eir_fec; memcpy(ir.data, vdev.eir_data, HCI_MAX_EIR_LENGTH); command_complete(ogf, ocf, sizeof(ir), &ir); break; case OCF_WRITE_EXT_INQUIRY_RESPONSE: status = 0x00; vdev.eir_fec = data[0]; memcpy(vdev.eir_data, data + 1, HCI_MAX_EIR_LENGTH); command_complete(ogf, ocf, 1, &status); break; case OCF_READ_SIMPLE_PAIRING_MODE: pm.status = 0x00; pm.mode = vdev.ssp_mode; command_complete(ogf, ocf, sizeof(pm), &pm); break; case OCF_WRITE_SIMPLE_PAIRING_MODE: status = 0x00; vdev.ssp_mode = data[0]; command_complete(ogf, ocf, 1, &status); break; case OCF_READ_LE_HOST_SUPPORTED: hs.status = 0x00; hs.le = vdev.le_mode; hs.simul = vdev.le_simul; command_complete(ogf, ocf, sizeof(hs), &hs); break; case OCF_WRITE_LE_HOST_SUPPORTED: status = 0x00; vdev.le_mode = data[0]; vdev.le_simul = data[1]; command_complete(ogf, ocf, 1, &status); break; default: command_status(ogf, ocf, 0x01); break; } }