Exemple #1
0
/*
 * return appropriate mode for HID descriptor
 */
const char *
hid_mode(prop_data_t desc)
{
	report_desc_t r;
	hid_data_t d;
	struct hid_item h;
	const char *mode;

	hid_init(NULL);

	mode = BTDEVauth;	/* default */

	r = hid_use_report_desc(prop_data_data_nocopy(desc),
				prop_data_size(desc));
	if (r == NULL)
		err(EXIT_FAILURE, "hid_use_report_desc");

	d = hid_start_parse(r, ~0, -1);
	while (hid_get_item(d, &h) > 0) {
		if (h.kind == hid_collection
		    && HID_PAGE(h.usage) == HUP_GENERIC_DESKTOP
		    && HID_USAGE(h.usage) == HUG_KEYBOARD)
			mode = BTDEVencrypt;
	}

	hid_end_parse(d);
	hid_dispose_report_desc(r);

	return mode;
}
Exemple #2
0
report_desc_t
hid_get_report_desc(int fd)
{
	struct usb_gen_descriptor ugd;
	report_desc_t rep;
	void *data;

	memset(&ugd, 0, sizeof(ugd));

	/* get actual length first */
	ugd.ugd_data = hid_pass_ptr(NULL);
	ugd.ugd_maxlen = 65535;
	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
#ifdef HID_COMPAT7
		/* could not read descriptor */
		/* try FreeBSD 7 compat code */
		return (hid_get_report_desc_compat7(fd));
#else
		return (NULL);
#endif
	}

	/*
	 * NOTE: The kernel will return a failure if 
	 * "ugd_actlen" is zero.
	 */
	data = malloc(ugd.ugd_actlen);
	if (data == NULL)
		return (NULL);

	/* fetch actual descriptor */
	ugd.ugd_data = hid_pass_ptr(data);
	ugd.ugd_maxlen = ugd.ugd_actlen;
	if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
		/* could not read descriptor */
		free(data);
		return (NULL);
	}

	/* sanity check */
	if (ugd.ugd_actlen < 1) {
		/* invalid report descriptor */
		free(data);
		return (NULL);
	}

	/* check END_COLLECTION */
	if (((unsigned char *)data)[ugd.ugd_actlen -1] != 0xC0) {
		/* invalid end byte */
		free(data);
		return (NULL);
	}

	rep = hid_use_report_desc(data, ugd.ugd_actlen);

	free(data);

	return (rep);
}
report_desc_t
hid_get_report_desc_compat7(int fd)
{
	struct usb_ctl_report_desc rep;

	rep.ucrd_size = 0;
	if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0)
		return (NULL);

	return (hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size));
}
Exemple #4
0
static int32_t
hid_sdp_query(bdaddr_t const *local, struct hid_device *hd, int32_t *error)
{
	void	*ss = NULL;
	uint8_t	*hid_descriptor = NULL;
	int32_t	 i, control_psm = -1, interrupt_psm = -1,
		 reconnect_initiate = -1,
		 normally_connectable = 0, battery_power = 0,
		 hid_descriptor_length = -1;

	if (local == NULL)
		local = NG_HCI_BDADDR_ANY;
	if (hd == NULL)
		hid_sdp_query_exit(EINVAL);

	for (i = 0; i < nvalues; i ++) {
		values[i].flags = SDP_ATTR_INVALID;
		values[i].attr = 0;
		values[i].vlen = sizeof(buffer[i]);
		values[i].value = buffer[i];
	}

	if ((ss = sdp_open(local, &hd->bdaddr)) == NULL)
		hid_sdp_query_exit(ENOMEM);
	if (sdp_error(ss) != 0)
		hid_sdp_query_exit(sdp_error(ss));
	if (sdp_search(ss, 1, &service, nattrs, attrs, nvalues, values) != 0)
                hid_sdp_query_exit(sdp_error(ss));

        sdp_close(ss);
        ss = NULL;

	for (i = 0; i < nvalues; i ++) {
		if (values[i].flags != SDP_ATTR_OK)
			continue;

		switch (values[i].attr) {
		case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
			control_psm = hid_sdp_parse_protocol_descriptor_list(&values[i]);
			break;

		case SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS:
			interrupt_psm = hid_sdp_parse_protocol_descriptor_list(&values[i]);
			break;

		case 0x0205: /* HIDReconnectInitiate */
			reconnect_initiate = hid_sdp_parse_boolean(&values[i]);
			break;

		case 0x0206: /* HIDDescriptorList */
			if (hid_sdp_parse_hid_descriptor(&values[i]) == 0) {
				hid_descriptor = values[i].value;
				hid_descriptor_length = values[i].vlen;
			}
			break;

		case 0x0209: /* HIDBatteryPower */
			battery_power = hid_sdp_parse_boolean(&values[i]);
			break;

		case 0x020d: /* HIDNormallyConnectable */
			normally_connectable = hid_sdp_parse_boolean(&values[i]);
			break;
		}
	}

	if (control_psm == -1 || interrupt_psm == -1 ||
	    reconnect_initiate == -1 ||
	    hid_descriptor == NULL || hid_descriptor_length == -1)
		hid_sdp_query_exit(ENOATTR);

	hd->control_psm = control_psm;
	hd->interrupt_psm = interrupt_psm;
	hd->reconnect_initiate = reconnect_initiate? 1 : 0;
	hd->battery_power = battery_power? 1 : 0;
	hd->normally_connectable = normally_connectable? 1 : 0;
	hd->desc = hid_use_report_desc(hid_descriptor, hid_descriptor_length);
	if (hd->desc == NULL)
		hid_sdp_query_exit(ENOMEM);

	return (0);
}