コード例 #1
0
ファイル: bthidev.c プロジェクト: Tommmster/netbsd-avr32
static void
bthidev_attach(device_t parent, device_t self, void *aux)
{
	struct bthidev_softc *sc = device_private(self);
	prop_dictionary_t dict = aux;
	prop_object_t obj;
	device_t dev;
	struct bthidev_attach_args bha;
	struct bthidev *hidev;
	struct hid_data *d;
	struct hid_item h;
	const void *desc;
	int locs[BTHIDBUSCF_NLOCS];
	int maxid, rep, dlen;

	/*
	 * Init softc
	 */
	sc->sc_dev = self;
	LIST_INIT(&sc->sc_list);
	callout_init(&sc->sc_reconnect, 0);
	callout_setfunc(&sc->sc_reconnect, bthidev_timeout, sc);
	sc->sc_state = BTHID_CLOSED;
	sc->sc_flags = BTHID_CONNECTING;
	sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
	sc->sc_intpsm = L2CAP_PSM_HID_INTR;

	sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0);

	/*
	 * extract config from proplist
	 */
	obj = prop_dictionary_get(dict, BTDEVladdr);
	bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVraddr);
	bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVmode);
	if (prop_object_type(obj) == PROP_TYPE_STRING) {
		if (prop_string_equals_cstring(obj, BTDEVauth))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH);
		else if (prop_string_equals_cstring(obj, BTDEVencrypt))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT);
		else if (prop_string_equals_cstring(obj, BTDEVsecure))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE);
		else  {
			aprint_error(" unknown %s\n", BTDEVmode);
			return;
		}

		aprint_verbose(" %s %s", BTDEVmode,
					 prop_string_cstring_nocopy(obj));
	}

	obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_ctlpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_ctlpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVcontrolpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVinterruptpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_intpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_intpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVinterruptpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVdescriptor);
	if (prop_object_type(obj) == PROP_TYPE_DATA) {
		dlen = prop_data_size(obj);
		desc = prop_data_data_nocopy(obj);
	} else {
		aprint_error(" no %s\n", BTHIDEVdescriptor);
		return;
	}

	obj = prop_dictionary_get(dict, BTHIDEVreconnect);
	if (prop_object_type(obj) == PROP_TYPE_BOOL
	    && !prop_bool_true(obj))
		sc->sc_flags |= BTHID_RECONNECT;

	/*
	 * Parse the descriptor and attach child devices, one per report.
	 */
	maxid = -1;
	h.report_ID = 0;
	d = hid_start_parse(desc, dlen, hid_none);
	while (hid_get_item(d, &h)) {
		if (h.report_ID > maxid)
			maxid = h.report_ID;
	}
	hid_end_parse(d);

	if (maxid < 0) {
		aprint_error(" no reports found\n");
		return;
	}

	aprint_normal("\n");

	for (rep = 0 ; rep <= maxid ; rep++) {
		if (hid_report_size(desc, dlen, hid_feature, rep) == 0
		    && hid_report_size(desc, dlen, hid_input, rep) == 0
		    && hid_report_size(desc, dlen, hid_output, rep) == 0)
			continue;

		bha.ba_desc = desc;
		bha.ba_dlen = dlen;
		bha.ba_input = bthidev_null;
		bha.ba_feature = bthidev_null;
		bha.ba_output = bthidev_output;
		bha.ba_id = rep;

		locs[BTHIDBUSCF_REPORTID] = rep;

		dev = config_found_sm_loc(self, "bthidbus",
					locs, &bha, bthidev_print, config_stdsubmatch);
		if (dev != NULL) {
			hidev = device_private(dev);
			hidev->sc_dev = dev;
			hidev->sc_parent = self;
			hidev->sc_id = rep;
			hidev->sc_input = bha.ba_input;
			hidev->sc_feature = bha.ba_feature;
			LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next);
		}
	}

	/*
	 * start bluetooth connections
	 */
	mutex_enter(bt_lock);
	if ((sc->sc_flags & BTHID_RECONNECT) == 0)
		bthidev_listen(sc);

	if (sc->sc_flags & BTHID_CONNECTING)
		bthidev_connect(sc);
	mutex_exit(bt_lock);
}
コード例 #2
0
ファイル: bthidev.c プロジェクト: appleorange1/bitrig
void
bthidev_attach(struct device *parent, struct device *self, void *aux)
{
	struct bthidev_softc *sc = (struct bthidev_softc *)self;
	struct btdev_attach_args *bda = (struct btdev_attach_args *)aux;
	struct bthidev_attach_args bha;
	struct bthidev *hidev;
	struct hid_data *d;
	struct hid_item h;
	int maxid, rep;

	/*
	 * Init softc
	 */
	LIST_INIT(&sc->sc_list);
	timeout_set(&sc->sc_reconnect, bthidev_timeout, sc);
	sc->sc_state = BTHID_CLOSED;
	sc->sc_flags = BTHID_CONNECTING;
	sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
	sc->sc_intpsm = L2CAP_PSM_HID_INTR;

	sc->sc_mode = 0;

	/*
	 * copy in our configuration info
	 */
	bdaddr_copy(&sc->sc_laddr, &bda->bd_laddr);
	bdaddr_copy(&sc->sc_raddr, &bda->bd_raddr);

	if (bda->bd_mode != BTDEV_MODE_NONE) {
		if (bda->bd_mode == BTDEV_MODE_AUTH) {
			sc->sc_mode = L2CAP_LM_AUTH;
			printf(" auth");
		} else if (bda->bd_mode == BTDEV_MODE_ENCRYPT) {
			sc->sc_mode = L2CAP_LM_ENCRYPT;
			printf(" encrypt");
		} else if (bda->bd_mode == BTDEV_MODE_SECURE) {
			sc->sc_mode = L2CAP_LM_SECURE;
			printf(" secure");
		} else {
			printf(" unknown link-mode: %d\n", bda->bd_mode);
			return;
		}
	}

	if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_ctl))
		sc->sc_ctlpsm = bda->bd_hid.hid_ctl;

	if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_int))
		sc->sc_intpsm = bda->bd_hid.hid_int;

	if (bda->bd_hid.hid_flags & BTHID_INITIATE)
		sc->sc_flags |= BTHID_RECONNECT;

	if (bda->bd_hid.hid_desc == NULL ||
	    bda->bd_hid.hid_dlen == 0 ||
	    bda->bd_hid.hid_dlen > MAX_DESCRIPTOR_LEN) {
		printf(": no descriptor\n");
		return;
	}
	sc->sc_dlen = bda->bd_hid.hid_dlen;
	sc->sc_desc = malloc(bda->bd_hid.hid_dlen, M_BTHIDEV,
	    M_WAITOK | M_CANFAIL);
	if (sc->sc_desc == NULL) {
		printf(": no memory\n");
		return;
	}
	if (copyin(bda->bd_hid.hid_desc, sc->sc_desc, bda->bd_hid.hid_dlen)) {
		free(sc->sc_desc, M_BTHIDEV);
		printf(": no descriptor");
		return;
	}

	/*
	 * Parse the descriptor and attach child devices, one per report.
	 */
	maxid = -1;
	h.report_ID = 0;
	d = hid_start_parse(sc->sc_desc, sc->sc_dlen, hid_none);
	while (hid_get_item(d, &h)) {
		if (h.report_ID > maxid)
			maxid = h.report_ID;
	}
	hid_end_parse(d);

	if (maxid < 0) {
		printf(": no reports found\n");
		return;
	}

	printf("\n");

	for (rep = 0 ; rep <= maxid ; rep++) {
		if (hid_report_size(sc->sc_desc, sc->sc_dlen, hid_feature, rep) == 0
		    && hid_report_size(sc->sc_desc, sc->sc_dlen, hid_input, rep) == 0
		    && hid_report_size(sc->sc_desc, sc->sc_dlen, hid_output, rep) == 0)
			continue;

		bha.ba_desc = sc->sc_desc;
		bha.ba_dlen = sc->sc_dlen;
		bha.ba_input = bthidev_null;
		bha.ba_feature = bthidev_null;
		bha.ba_output = bthidev_output;
		bha.ba_id = rep;

		hidev = (struct bthidev *)config_found_sm(self, &bha,
		    bthidev_print, bthidevsubmatch);
		if (hidev != NULL) {
			hidev->sc_parent = &sc->sc_btdev;
			hidev->sc_id = rep;
			hidev->sc_input = bha.ba_input;
			hidev->sc_feature = bha.ba_feature;
			LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next);
		}
	}

	/*
	 * start bluetooth connections
	 */
	mutex_enter(&bt_lock);
	if ((sc->sc_flags & BTHID_RECONNECT) == 0)
		bthidev_listen(sc);

	if (sc->sc_flags & BTHID_CONNECTING)
		bthidev_connect(sc);
	mutex_exit(&bt_lock);
}