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;
	}
}
Exemple #2
0
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;
}
Exemple #3
0
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;
	}
}
Exemple #4
0
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;
	}
}
Exemple #6
0
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;
	}
}
Exemple #9
0
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;
	}
}