Example #1
0
const char *
ukbd_parse_desc(struct ukbd_softc *sc)
{
	struct hid_data *d;
	struct hid_item h;
	int size;
	void *desc;
	int imod;

	uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
	imod = 0;
	sc->sc_nkeycode = 0;
	d = hid_start_parse(desc, size, hid_input);
	while (hid_get_item(d, &h)) {
		/*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n",
		  h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
		if (h.kind != hid_input || (h.flags & HIO_CONST) ||
		    HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
		    h.report_ID != sc->sc_hdev.sc_report_id)
			continue;
		DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
			 "cnt=%d\n", imod,
			 h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
		if (h.flags & HIO_VARIABLE) {
			if (h.loc.size != 1)
				return ("bad modifier size");
			/* Single item */
			if (imod < MAXMOD) {
				sc->sc_modloc[imod] = h.loc;
				sc->sc_mods[imod].mask = 1 << imod;
				sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
				imod++;
			} else
				return ("too many modifier keys");
		} else {
			/* Array */
			if (h.loc.size != 8)
				return ("key code size != 8");
			if (h.loc.count > MAXKEYCODE)
				return ("too many key codes");
			if (h.loc.pos % 8 != 0)
				return ("key codes not on byte boundary");
			if (sc->sc_nkeycode != 0)
				return ("multiple key code arrays\n");
			sc->sc_keycodeloc = h.loc;
			sc->sc_nkeycode = h.loc.count;
		}
	}
	sc->sc_nmod = imod;
	hid_end_parse(d);

	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);

	return (NULL);
}
Example #2
0
int
ums_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	/*
	 * Some (older) Griffin PowerMate knobs may masquerade as a
	 * mouse, avoid treating them as such, they have only one axis.
	 */
	if (uha->uiaa->uiaa_vendor == USB_VENDOR_GRIFFIN &&
	    uha->uiaa->uiaa_product == USB_PRODUCT_GRIFFIN_POWERMATE)
		return UMATCH_NONE;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) &&
	    !hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER)) &&
	    !hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_DIGITIZERS, 0x0002)))
		return UMATCH_NONE;

	return UMATCH_IFACECLASS;
}
static const char *
btkbd_parse_desc(struct btkbd_softc *sc, int id, const void *desc, int dlen)
{
	struct hid_data *d;
	struct hid_item h;
	int imod;

	imod = 0;
	sc->sc_nkeycode = 0;
	d = hid_start_parse(desc, dlen, hid_input);
	while (hid_get_item(d, &h)) {
		if (h.kind != hid_input || (h.flags & HIO_CONST) ||
		    HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
		    h.report_ID != id)
			continue;

		if (h.flags & HIO_VARIABLE) {
			if (h.loc.size != 1)
				return ("bad modifier size");

			/* Single item */
			if (imod < MAXMOD) {
				sc->sc_modloc[imod] = h.loc;
				sc->sc_mods[imod].mask = 1 << imod;
				sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
				imod++;
			} else
				return ("too many modifier keys");
		} else {
			/* Array */
			if (h.loc.size != 8)
				return ("key code size != 8");

			if (h.loc.count > MAXKEYCODE)
				return ("too many key codes");

			if (h.loc.pos % 8 != 0)
				return ("key codes not on byte boundary");

			if (sc->sc_nkeycode != 0)
				return ("multiple key code arrays\n");

			sc->sc_keycodeloc = h.loc;
			sc->sc_nkeycode = h.loc.count;
		}
	}
	sc->sc_nmod = imod;
	hid_end_parse(d);

	hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
		   id, hid_output, &sc->sc_numloc, NULL);

	hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
		   id, hid_output, &sc->sc_capsloc, NULL);

	hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
		   id, hid_output, &sc->sc_scroloc, NULL);

	return (NULL);
}
Example #4
0
int
cc_match(struct hid_appcol *ha)
{
	struct hid_interface *hi;
	struct hid_report *hr;
	struct hid_field *hf;
	unsigned int u, up;

	hi = hid_appcol_get_parser_private(ha);
	assert(hi != NULL);

	if (config_cc_attach(hi) <= 0)
		return (HID_MATCH_NONE);

	u = hid_appcol_get_usage(ha);
	if (u != HID_USAGE2(HUP_CONSUMER, HUG_CONSUMER_CONTROL))
		return (HID_MATCH_NONE);

	hr = NULL;
	while ((hr = hid_appcol_get_next_report(ha, hr)) != NULL) {
		hf = NULL;
		while ((hf = hid_report_get_next_field(hr, hf, HID_INPUT)) !=
		    NULL) {
			up = hid_field_get_usage_page(hf);
			if (up == HUP_CONSUMER)
				return (HID_MATCH_GENERAL);
		}
	}

	return (HID_MATCH_NONE);
}
Example #5
0
File: uts.c Project: ryo/netbsd-src
Static int
uts_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCH_SCREEN)) &&
	    !hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, HUD_FINGER)))
		return UMATCH_NONE;

	return UMATCH_IFACECLASS;
}
static int
btkbd_match(device_t self, cfdata_t cfdata, void *aux)
{
	struct bthidev_attach_args *ba = aux;

	if (hid_is_collection(ba->ba_desc, ba->ba_dlen, ba->ba_id,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
		return 1;

	return 0;
}
Example #7
0
static int
btms_match(device_t parent, cfdata_t match, void *aux)
{
	struct bthidev_attach_args *ba = aux;

	if (hid_is_collection(ba->ba_desc, ba->ba_dlen, ba->ba_id,
			    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
		return 1;

	return 0;
}
Example #8
0
int
ums_match(struct device *parent, void *match, void *aux)
{
    struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
    int size;
    void *desc;

    uhidev_get_report_desc(uha->parent, &desc, &size);

    if (hid_is_collection(desc, size, uha->reportid,
                          HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
        return (UMATCH_IFACECLASS);

    if (hid_is_collection(desc, size, uha->reportid,
                          HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)))
        return (UMATCH_IFACECLASS);

    if (hid_is_collection(desc, size, uha->reportid,
                          HID_USAGE2(HUP_DIGITIZERS, HUD_PEN)))
        return (UMATCH_IFACECLASS);

    return (UMATCH_NONE);
}
Example #9
0
int
ukbd_match(device_t parent, cfdata_t match, void *aux)
{
	struct uhidev_attach_arg *uha = aux;
	int size;
	void *desc;

	uhidev_get_report_desc(uha->parent, &desc, &size);
	if (!hid_is_collection(desc, size, uha->reportid,
			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
		return (UMATCH_NONE);

	return (UMATCH_IFACECLASS);
}
Example #10
0
int
mouse_match(struct hid_appcol *ha)
{
	struct hid_interface *hi;
	unsigned int u;

	hi = hid_appcol_get_parser_private(ha);
	assert(hi != NULL);

	if (config_mouse_attach(hi) <= 0)
		return (HID_MATCH_NONE);

	u = hid_appcol_get_usage(ha);
	if (u == HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
		return (HID_MATCH_GENERAL);

	return (HID_MATCH_NONE);
}
Example #11
0
void
ums_attach(struct device *parent, struct device *self, void *aux)
{
	struct ums_softc *sc = (struct ums_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	u_int32_t flags, quirks;
	int i, wheel, twheel;

	sc->sc_hdev.sc_intr = ums_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
	if (quirks & UQ_MS_REVZ)
		sc->flags |= UMS_REVZ;
	if (quirks & UQ_SPUR_BUT_UP)
		sc->flags |= UMS_SPUR_BUT_UP;
	if (quirks & UQ_MS_LEADING_BYTE)
		sc->flags |= UMS_LEADINGBYTE;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
	       uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		printf("\n%s: mouse has no X report\n",
		       sc->sc_hdev.sc_dev.dv_xname);
		return;
	}
	if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
		printf("\n%s: X report 0x%04x not supported\n",
		       sc->sc_hdev.sc_dev.dv_xname, flags);
		return;
	}

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
	       uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		printf("\n%s: mouse has no Y report\n",
		       sc->sc_hdev.sc_dev.dv_xname);
		return;
	}
	if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
		printf("\n%s: Y report 0x%04x not supported\n",
		       sc->sc_hdev.sc_dev.dv_xname, flags);
		return;
	}

	/*
	 * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
	 * in that order.
	 */

	wheel = hid_locate(desc, size,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
	    uha->reportid, hid_input, &sc->sc_loc_z, &flags);
	if (wheel == 0)
		twheel = hid_locate(desc, size,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
		    uha->reportid, hid_input, &sc->sc_loc_z, &flags);
	else
		twheel = 0;

	if (wheel || twheel) {
		if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
			DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
				sc->sc_hdev.sc_dev.dv_xname, flags));
			sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
			/* Wheels need the Z axis reversed. */
			sc->flags ^= UMS_REVZ;
		}
		/*
		 * We might have both a wheel and Z direction; in this case,
		 * report the Z direction on the W axis.
		*/
		if (hid_locate(desc, size,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
		    uha->reportid, hid_input, &sc->sc_loc_w, &flags)) {
			if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
				DPRINTF(("\n%s: Z report 0x%04x not supported\n",
					sc->sc_hdev.sc_dev.dv_xname, flags));
				/* Bad Z coord, ignore it */
				sc->sc_loc_w.size = 0;
			}
			else
				sc->flags |= UMS_W;
		}
	} else if (hid_locate(desc, size,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
	    uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
		if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
			DPRINTF(("\n%s: Z report 0x%04x not supported\n",
				sc->sc_hdev.sc_dev.dv_xname, flags));
			sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
		}
	}

	/*
	 * The Microsoft Wireless Intellimouse 2.0 reports its wheel
	 * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
	 * us to know that the byte after the wheel is the tilt axis.
	 * There are no other HID axis descriptors other than X, Y and
	 * TWHEEL, so we report TWHEEL on the W axis.
	 */
	if (twheel) {
		sc->sc_loc_w = sc->sc_loc_z;
		sc->sc_loc_w.pos = sc->sc_loc_w.pos + 8;
		sc->flags |= UMS_W | UMS_LEADINGBYTE;
		/* Wheels need their axis reversed. */
		sc->flags ^= UMS_REVW;
	}

	/* figure out the number of buttons */
	for (i = 1; i <= MAX_BUTTONS; i++)
		if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
		    uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
			break;
	sc->nbuttons = i - 1;

	/*
	 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
	 * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
	 * all of its other button positions are all off. It also reports that
	 * it has two addional buttons and a tilt wheel.
	 */
	if (quirks & UQ_MS_BAD_CLASS) {
		/* UMS_LEADINGBYTE cleared on purpose */
		sc->flags = UMS_Z | UMS_SPUR_BUT_UP;
		sc->nbuttons = 3;
		/* XXX change sc_hdev isize to 5? */
		/* 1st byte of descriptor report contains garbage */
		sc->sc_loc_x.pos = 16;
		sc->sc_loc_y.pos = 24;
		sc->sc_loc_z.pos = 32;
		sc->sc_loc_btn[0].pos = 8;
		sc->sc_loc_btn[1].pos = 9;
		sc->sc_loc_btn[2].pos = 10;
	}

	/*
	 * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has
	 * five Report IDs: 19, 23, 24, 17, 18 (in the order they appear in
	 * report descriptor), it seems that report 17 contains the necessary
	 * mouse information (3-buttons, X, Y, wheel) so we specify it
	 * manually.
	 */
	if (uaa->vendor == USB_VENDOR_MICROSOFT &&
	    uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) {
		sc->flags = UMS_Z;
		sc->nbuttons = 3;
		/* XXX change sc_hdev isize to 5? */
		sc->sc_loc_x.pos = 8;
		sc->sc_loc_y.pos = 16;
		sc->sc_loc_z.pos = 24;
		sc->sc_loc_btn[0].pos = 0;
		sc->sc_loc_btn[1].pos = 1;
		sc->sc_loc_btn[2].pos = 2;
	}

	printf(": %d button%s",
	    sc->nbuttons, sc->nbuttons <= 1 ? "" : "s");
	switch (sc->flags & (UMS_Z | UMS_W)) {
	case UMS_Z:
		printf(", Z dir");
		break;
	case UMS_W:
		printf(", W dir");
		break;
	case UMS_Z | UMS_W:
		printf(", Z and W dir");
		break;
	}
	printf("\n");

#ifdef USB_DEBUG
	DPRINTF(("ums_attach: sc=%p\n", sc));
	DPRINTF(("ums_attach: X\t%d/%d\n",
	     sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("ums_attach: Y\t%d/%d\n",
	    sc->sc_loc_y.pos, sc->sc_loc_y.size));
	if (sc->flags & UMS_Z)
		DPRINTF(("ums_attach: Z\t%d/%d\n",
		    sc->sc_loc_z.pos, sc->sc_loc_z.size));
	if (sc->flags & UMS_W)
		DPRINTF(("ums_attach: W\t%d/%d\n",
		    sc->sc_loc_w.pos, sc->sc_loc_w.size));
	for (i = 1; i <= sc->nbuttons; i++) {
		DPRINTF(("ums_attach: B%d\t%d/%d\n",
		    i, sc->sc_loc_btn[i - 1].pos, sc->sc_loc_btn[i - 1].size));
	}
#endif

	a.accessops = &ums_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
Example #12
0
static void
btms_attach(device_t parent, device_t self, void *aux)
{
	struct btms_softc *sc = device_private(self);
	struct bthidev_attach_args *ba = aux;
	struct wsmousedev_attach_args wsma;
	struct hid_location *zloc;
	uint32_t flags, quirks;
	int i, hl;

	ba->ba_input = btms_input;

	quirks = btms_lookup_quirk_flags(ba->ba_vendor, ba->ba_product);

	/* control the horizontal */
	hl = hid_locate(ba->ba_desc,
			ba->ba_dlen,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
			ba->ba_id,
			hid_input,
			&sc->sc_loc_x,
			&flags);

	if (hl == 0 || NOTMOUSE(flags)) {
		aprint_error("X report 0x%04x not supported\n", flags);
		return;
	}

	/* control the vertical */
	hl = hid_locate(ba->ba_desc,
			ba->ba_dlen,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
			ba->ba_id,
			hid_input,
			&sc->sc_loc_y,
			&flags);

	if (hl == 0 || NOTMOUSE(flags)) {
		aprint_error("Y report 0x%04x not supported\n", flags);
		return;
	}

	/* Try the wheel first as the Z activator since it's tradition. */
	hl = hid_locate(ba->ba_desc,
			ba->ba_dlen,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
			ba->ba_id,
			hid_input,
			&sc->sc_loc_z,
			&flags);

	zloc = &sc->sc_loc_z;
	if (hl) {
		if (NOTMOUSE(flags)) {
			aprint_error("Wheel report 0x%04x ignored\n", flags);

			/* ignore Bad Z coord */
			sc->sc_loc_z.size = 0;
		} else {
			sc->sc_flags |= BTMS_HASZ;
			/* Wheels need the Z axis reversed. */
			sc->sc_flags ^= BTMS_REVZ;
			/* Put Z on the W coordinate */
			zloc = &sc->sc_loc_w;
		}
	}

	hl = hid_locate(ba->ba_desc,
			ba->ba_dlen,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
			ba->ba_id,
			hid_input,
			zloc,
			&flags);

	/*
	 * The horizontal component of the scrollball can also be given by
	 * Application Control Pan in the Consumer page, so if we didnt see
	 * any Z then check that.
	 */
	if (!hl) {
		hl = hid_locate(ba->ba_desc,
				ba->ba_dlen,
				HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN),
				ba->ba_id,
				hid_input,
				zloc,
				&flags);
	}

	if (hl) {
		if (NOTMOUSE(flags))
			zloc->size = 0;	/* ignore Z */
		else {
			if (sc->sc_flags & BTMS_HASZ)
				sc->sc_flags |= BTMS_HASW;
			else
				sc->sc_flags |= BTMS_HASZ;
		}
	}

	for (i = 1 ; i <= MAX_BUTTONS ; i++) {
		hl = hid_locate(ba->ba_desc,
				ba->ba_dlen,
				HID_USAGE2(HUP_BUTTON, i),
				ba->ba_id,
				hid_input,
				&sc->sc_loc_button[i - 1],
				NULL);

		if (hl == 0)
			break;
	}
	sc->sc_num_buttons = i - 1;

	if (ISSET(quirks, BTMS_QUIRK_ELECOM))
		btms_fixup_elecom(ba, sc);

	aprint_normal(": %d button%s%s%s%s.\n",
			sc->sc_num_buttons,
			sc->sc_num_buttons == 1 ? "" : "s",
			sc->sc_flags & BTMS_HASW ? ", W" : "",
			sc->sc_flags & BTMS_HASZ ? " and Z dir" : "",
			sc->sc_flags & BTMS_HASW ? "s" : "");
#ifdef BTMS_DEBUG
	if (btms_debug)
		btms_print_device(sc);
#endif

	wsma.accessops = &btms_wsmouse_accessops;
	wsma.accesscookie = sc;

	sc->sc_wsmouse = config_found(self, &wsma, wsmousedevprint);

	pmf_device_register(self, NULL, NULL);
}
Example #13
0
int
main (int argc, char **argv)
{
    char *device_file;
    int fd = -1;
    int report_id;
    report_desc_t report_desc;
    struct hid_data *data;
    hid_item_t item;
    boolean is_keyboard = FALSE;
    boolean is_keypad = FALSE;
    boolean is_mouse = FALSE;
    boolean is_joystick = FALSE;

    if (! hfp_init(argc, argv))
        goto end;

    device_file = getenv("HAL_PROP_HIDDEV_DEVICE");
    if (! device_file)
        goto end;

    fd = open(device_file, O_RDONLY);
    if (fd < 0)
        goto end;

    /* give a meaningful process title for ps(1) */
    setproctitle("%s", device_file);

#ifdef HAVE_LIBUSB20
    report_id = hid_get_report_id(fd);
    if (report_id == -1)
#else
    if (ioctl(fd, USB_GET_REPORT_ID, &report_id) < 0)
#endif
        goto end;

    hid_init(NULL);

    report_desc = hid_get_report_desc(fd);
    if (! report_desc)
        goto end;

    for (data = hid_start_parse(report_desc, ~0, report_id); hid_get_item(data, &item);)
        if (item.kind == hid_collection)
        {
            if (item.collection == HID_COLLECTION_APPLICATION)
            {
                const char *page;
                char *full_page;
                int i;

                page = hid_usage_page(HID_PAGE(item.usage));

                full_page = hfp_strdup_printf("%s Page", page);
                for (i = 0; full_page[i] != 0; i++)
                    if (full_page[i] == '_')
                        full_page[i] = ' ';

                libhal_device_property_strlist_append(hfp_ctx, hfp_udi, "hiddev.application_pages", full_page, &hfp_error);
                hfp_free(full_page);
            }

            switch (item.usage)
            {
            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE):
                is_mouse = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_JOYSTICK):
            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_GAME_PAD):
                is_joystick = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD):
                is_keyboard = TRUE;
                break;

            case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYPAD):
                is_keypad = TRUE;
                break;
            }
        }
    hid_end_parse(data);

    hid_dispose_report_desc(report_desc);

    if (is_keyboard || is_mouse || is_joystick || is_keypad)
    {
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input", &hfp_error);
        libhal_device_set_property_string(hfp_ctx, hfp_udi, "info.category", "input", &hfp_error);
        libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device", device_file, &hfp_error);
    }
    if (is_keyboard)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keyboard", &hfp_error);
    if (is_keypad)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keypad", &hfp_error);
    if (is_keyboard || is_keypad)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.keys", &hfp_error);
    if (is_mouse)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.mouse", &hfp_error);
    if (is_joystick)
        libhal_device_add_capability(hfp_ctx, hfp_udi, "input.joystick", &hfp_error);

end:
    return 0;
}
Example #14
0
int
hidms_setup(struct device *self, struct hidms *ms, uint32_t quirks,
    int id, void *desc, int dlen)
{
	struct hid_item h;
	struct hid_data *d;
	uint32_t flags;
	int i, wheel, twheel;

	ms->sc_device = self;
	ms->sc_rawmode = 1;

	ms->sc_flags = quirks;

	if (!hid_locate(desc, dlen, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), id,
	    hid_input, &ms->sc_loc_x, &flags)) {
		printf("\n%s: mouse has no X report\n", self->dv_xname);
		return ENXIO;
	}
	switch(flags & MOUSE_FLAGS_MASK) {
	case 0:
		ms->sc_flags |= HIDMS_ABSX;
		break;
	case HIO_RELATIVE:
		break;
	default:
		printf("\n%s: X report 0x%04x not supported\n",
		    self->dv_xname, flags);
		return ENXIO;
	}

	if (!hid_locate(desc, dlen, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), id,
	    hid_input, &ms->sc_loc_y, &flags)) {
		printf("\n%s: mouse has no Y report\n", self->dv_xname);
		return ENXIO;
	}
	switch(flags & MOUSE_FLAGS_MASK) {
	case 0:
		ms->sc_flags |= HIDMS_ABSY;
		break;
	case HIO_RELATIVE:
		break;
	default:
		printf("\n%s: Y report 0x%04x not supported\n",
		    self->dv_xname, flags);
		return ENXIO;
	}

	/*
	 * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
	 * in that order.
	 */

	wheel = hid_locate(desc, dlen,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), id,
	    hid_input, &ms->sc_loc_z, &flags);
	if (wheel == 0)
		twheel = hid_locate(desc, dlen,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), id,
		    hid_input, &ms->sc_loc_z, &flags);
	else
		twheel = 0;

	if (wheel || twheel) {
		if (NOTMOUSE(flags)) {
			DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
			    self->dv_xname, flags));
			ms->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			ms->sc_flags |= HIDMS_Z;
			/* Wheels need the Z axis reversed. */
			ms->sc_flags ^= HIDMS_REVZ;
		}
		/*
		 * We might have both a wheel and Z direction; in this case,
		 * report the Z direction on the W axis.
		 *
		 * Otherwise, check for a W direction as an AC Pan input used
		 * on some newer mice.
		 */
		if (hid_locate(desc, dlen,
		    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), id,
		    hid_input, &ms->sc_loc_w, &flags)) {
			if (NOTMOUSE(flags)) {
				DPRINTF(("\n%s: Z report 0x%04x not supported\n",
				    self->dv_xname, flags));
				/* Bad Z coord, ignore it */
				ms->sc_loc_w.size = 0;
			}
			else
				ms->sc_flags |= HIDMS_W;
		} else if (hid_locate(desc, dlen,
		    HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN), id, hid_input,
		    &ms->sc_loc_w, &flags)) {
			ms->sc_flags |= HIDMS_W;
		}
	} else if (hid_locate(desc, dlen,
	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), id,
	    hid_input, &ms->sc_loc_z, &flags)) {
		if (NOTMOUSE(flags)) {
			DPRINTF(("\n%s: Z report 0x%04x not supported\n",
			    self->dv_xname, flags));
			ms->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
		} else {
			ms->sc_flags |= HIDMS_Z;
		}
	}

	/*
	 * The Microsoft Wireless Intellimouse 2.0 reports its wheel
	 * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
	 * us to know that the byte after the wheel is the tilt axis.
	 * There are no other HID axis descriptors other than X, Y and
	 * TWHEEL, so we report TWHEEL on the W axis.
	 */
	if (twheel) {
		ms->sc_loc_w = ms->sc_loc_z;
		ms->sc_loc_w.pos = ms->sc_loc_w.pos + 8;
		ms->sc_flags |= HIDMS_W | HIDMS_LEADINGBYTE;
		/* Wheels need their axis reversed. */
		ms->sc_flags ^= HIDMS_REVW;
	}

	/* figure out the number of buttons */
	for (i = 1; i <= MAX_BUTTONS; i++)
		if (!hid_locate(desc, dlen, HID_USAGE2(HUP_BUTTON, i), id,
		    hid_input, &ms->sc_loc_btn[i - 1], NULL))
			break;
	ms->sc_num_buttons = i - 1;

	if (hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS,
	    HUD_TIP_SWITCH), id, hid_input,
	    &ms->sc_loc_btn[ms->sc_num_buttons], NULL)){
		ms->sc_flags |= HIDMS_TIP;
		ms->sc_num_buttons++;
	}

	if (hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS,
	    HUD_ERASER), id, hid_input,
	    &ms->sc_loc_btn[ms->sc_num_buttons], NULL)){
		ms->sc_flags |= HIDMS_ERASER;
		ms->sc_num_buttons++;
	}

	if (hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS,
	    HUD_BARREL_SWITCH), id, hid_input,
	    &ms->sc_loc_btn[ms->sc_num_buttons], NULL)){
		ms->sc_flags |= HIDMS_BARREL;
		ms->sc_num_buttons++;
	}

	/*
	 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
	 * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
	 * all of its other button positions are all off. It also reports that
	 * it has two addional buttons and a tilt wheel.
	 */
	if (ms->sc_flags & HIDMS_MS_BAD_CLASS) {
		/* HIDMS_LEADINGBYTE cleared on purpose */
		ms->sc_flags = HIDMS_Z | HIDMS_SPUR_BUT_UP;
		ms->sc_num_buttons = 3;
		/* XXX change sc_hdev isize to 5? */
		/* 1st byte of descriptor report contains garbage */
		ms->sc_loc_x.pos = 16;
		ms->sc_loc_y.pos = 24;
		ms->sc_loc_z.pos = 32;
		ms->sc_loc_btn[0].pos = 8;
		ms->sc_loc_btn[1].pos = 9;
		ms->sc_loc_btn[2].pos = 10;
	}
	/* Parse descriptors to get touch panel bounds */
	d = hid_start_parse(desc, dlen, hid_input);
	while (hid_get_item(d, &h)) {
		if (h.kind != hid_input ||
		    HID_GET_USAGE_PAGE(h.usage) != HUP_GENERIC_DESKTOP)
			continue;
		DPRINTF(("hidms: usage=0x%x range %d..%d\n",
			h.usage, h.logical_minimum, h.logical_maximum));
		switch (HID_GET_USAGE(h.usage)) {
		case HUG_X:
			if (ms->sc_flags & HIDMS_ABSX) {
				ms->sc_tsscale.minx = h.logical_minimum;
				ms->sc_tsscale.maxx = h.logical_maximum;
			}
			break;
		case HUG_Y:
			if (ms->sc_flags & HIDMS_ABSY) {
				ms->sc_tsscale.miny = h.logical_minimum;
				ms->sc_tsscale.maxy = h.logical_maximum;
			}
			break;
		}
	}
	hid_end_parse(d);
	return 0;
}
Example #15
0
void
ums_attach(device_t parent, device_t self, void *aux)
{
	struct ums_softc *sc = device_private(self);
	struct uhidev_attach_arg *uha = aux;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	uint32_t flags, quirks;
	int i, hl;
	struct hid_location *zloc;
	bool isdigitizer;

	aprint_naive("\n");

	sc->sc_hdev.sc_dev = self;
	sc->sc_hdev.sc_intr = ums_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
	if (quirks & UQ_MS_REVZ)
		sc->flags |= UMS_REVZ;
	if (quirks & UQ_SPUR_BUT_UP)
		sc->flags |= UMS_SPUR_BUT_UP;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	isdigitizer = hid_is_collection(desc, size, uha->reportid,
	    HID_USAGE2(HUP_DIGITIZERS, 0x0002));

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
	       uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		aprint_error("\n%s: mouse has no X report\n",
		       device_xname(sc->sc_hdev.sc_dev));
		return;
	}
	switch (flags & MOUSE_FLAGS_MASK) {
	case 0:
		sc->flags |= UMS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error("\n%s: X report 0x%04x not supported\n",
		       device_xname(sc->sc_hdev.sc_dev), flags);
		return;
	}

	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
	       uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		aprint_error("\n%s: mouse has no Y report\n",
		       device_xname(sc->sc_hdev.sc_dev));
		return;
	}
	switch (flags & MOUSE_FLAGS_MASK) {
	case 0:
		sc->flags |= UMS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error("\n%s: Y report 0x%04x not supported\n",
		       device_xname(sc->sc_hdev.sc_dev), flags);
		return;
	}

	/* Try the wheel first as the Z activator since it's tradition. */
	hl = hid_locate(desc,
			size,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
			uha->reportid,
			hid_input,
			&sc->sc_loc_z,
			&flags);

	zloc = &sc->sc_loc_z;
	if (hl) {
		if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
			aprint_verbose("\n%s: Wheel report 0x%04x not "
			    "supported\n", device_xname(sc->sc_hdev.sc_dev),
			    flags);
			sc->sc_loc_z.size = 0;	/* Bad Z coord, ignore it */
		} else {
			sc->flags |= UMS_Z;
			/* Wheels need the Z axis reversed. */
			sc->flags ^= UMS_REVZ;
			/* Put Z on the W coordinate */
			zloc = &sc->sc_loc_w;
		}
	}

	hl = hid_locate(desc,
			size,
			HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
			uha->reportid,
			hid_input,
			zloc,
			&flags);

	/*
	 * The horizontal component of the scrollball can also be given by
	 * Application Control Pan in the Consumer page, so if we didnt see
	 * any Z then check that.
	 */
	if (!hl) {
		hl = hid_locate(desc,
				size,
				HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN),
				uha->reportid,
				hid_input,
				zloc,
				&flags);
	}

	if (hl) {
		if ((flags & MOUSE_FLAGS_MASK) != HIO_RELATIVE) {
			aprint_verbose("\n%s: Z report 0x%04x not supported\n",
			       device_xname(sc->sc_hdev.sc_dev), flags);
			zloc->size = 0;	/* Bad Z coord, ignore it */
		} else {
			if (sc->flags & UMS_Z)
				sc->flags |= UMS_W;
			else
				sc->flags |= UMS_Z;
		}
	}

	if (uha->uiaa->uiaa_vendor == USB_VENDOR_MICROSOFT) {
		int fixpos;
		/*
		 * The Microsoft Wireless Laser Mouse 6000 v2.0 and the
		 * Microsoft Comfort Mouse 2.0 report a bad position for
		 * the wheel and wheel tilt controls -- should be in bytes
		 * 3 & 4 of the report. Fix this if necessary.
		 */
		switch (uha->uiaa->uiaa_product) {
		case USB_PRODUCT_MICROSOFT_24GHZ_XCVR10:
		case USB_PRODUCT_MICROSOFT_24GHZ_XCVR20:
			fixpos = 24;
			break;
		case USB_PRODUCT_MICROSOFT_CM6000:
			fixpos = 40;
			break;
		default:
			fixpos = 0;
			break;
		}
		if (fixpos) {
			if ((sc->flags & UMS_Z) && sc->sc_loc_z.pos == 0)
				sc->sc_loc_z.pos = fixpos;
			if ((sc->flags & UMS_W) && sc->sc_loc_w.pos == 0)
				sc->sc_loc_w.pos = sc->sc_loc_z.pos + 8;
		}
	}

	/* figure out the number of buttons */
	for (i = 1; i <= MAX_BUTTONS; i++)
		if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
		    uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
			break;

	if (isdigitizer) {
		for (size_t j = 0; j < __arraycount(digbut); j++) {
			if (hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS,
			    digbut[j].feature), uha->reportid, hid_input,
			    &sc->sc_loc_btn[i - 1], 0)) {
				if (i <= MAX_BUTTONS) {
					i++;
					sc->flags |= digbut[j].flag;
				} else
					aprint_error_dev(self,
					    "ran out of buttons\n");
			}
		}
	}
	sc->nbuttons = i - 1;

	aprint_normal(": %d button%s%s%s%s%s%s%s%s%s\n",
	    sc->nbuttons, sc->nbuttons == 1 ? "" : "s",
	    sc->flags & UMS_W ? ", W" : "",
	    sc->flags & UMS_Z ? " and Z dir" : "",
	    sc->flags & UMS_W ? "s" : "",
	    isdigitizer ? " digitizer"  : "",
	    sc->flags & UMS_TIP_SWITCH ? ", tip" : "",
	    sc->flags & UMS_SEC_TIP_SWITCH ? ", sec tip" : "",
	    sc->flags & UMS_BARREL_SWITCH ? ", barrel" : "",
	    sc->flags & UMS_ERASER ? ", eraser" : "");

#ifdef UMS_DEBUG
	DPRINTF(("ums_attach: sc=%p\n", sc));
	DPRINTF(("ums_attach: X\t%d/%d\n",
		 sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("ums_attach: Y\t%d/%d\n",
		 sc->sc_loc_y.pos, sc->sc_loc_y.size));
	if (sc->flags & UMS_Z)
		DPRINTF(("ums_attach: Z\t%d/%d\n",
			 sc->sc_loc_z.pos, sc->sc_loc_z.size));
	if (sc->flags & UMS_W)
		DPRINTF(("ums_attach: W\t%d/%d\n",
			 sc->sc_loc_w.pos, sc->sc_loc_w.size));
	for (i = 1; i <= sc->nbuttons; i++) {
		DPRINTF(("ums_attach: B%d\t%d/%d\n",
			 i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size));
	}
#endif

	a.accessops = &ums_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);

	return;
}
Example #16
0
void
ukbd_attach(struct device *parent, struct device *self, void *aux)
{
	struct ukbd_softc *sc = (struct ukbd_softc *)self;
	struct hidkbd *kbd = &sc->sc_kbd;
	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
	struct usb_hid_descriptor *hid;
	u_int32_t qflags;
	int dlen, repid;
	void *desc;
	kbd_t layout = (kbd_t)-1;

	sc->sc_hdev.sc_intr = ukbd_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_udev = uha->uaa->device;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &dlen);
	repid = uha->reportid;
	sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid);
	sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid);
	sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid);

	qflags = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
	if (hidkbd_attach(self, kbd, 1, qflags, repid, desc, dlen) != 0)
		return;

	if (uha->uaa->vendor == USB_VENDOR_APPLE) {
		int iso = 0;

		if ((uha->uaa->product == USB_PRODUCT_APPLE_FOUNTAIN_ISO) ||
 		    (uha->uaa->product == USB_PRODUCT_APPLE_GEYSER_ISO))
 		    	iso = 1;

		if (hid_locate(desc, dlen, HID_USAGE2(HUP_APPLE, HUG_FN_KEY),
		    uha->reportid, hid_input, &sc->sc_apple_fn, &qflags)) {
			if (qflags & HIO_VARIABLE) {
				if (iso)
					sc->sc_munge = ukbd_apple_iso_munge;
				else
					sc->sc_munge = ukbd_apple_munge;
			}
		}
	}

	if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
	    uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) {
		/* ignore country code on purpose */
	} else {
		hid = usbd_get_hid_descriptor(uha->uaa->iface);

		if (hid->bCountryCode <= HCC_MAX)
			layout = ukbd_countrylayout[hid->bCountryCode];
#ifdef DIAGNOSTIC
		if (hid->bCountryCode != 0)
			printf(", country code %d", hid->bCountryCode);
#endif
	}
	if (layout == (kbd_t)-1) {
#ifdef UKBD_LAYOUT
		layout = UKBD_LAYOUT;
#else
		layout = KB_US | KB_DEFAULT;
#endif
	}

	printf("\n");

#ifdef __loongson__
	if (uha->uaa->vendor == USB_VENDOR_CYPRESS &&
	    uha->uaa->product == USB_PRODUCT_CYPRESS_LPRDK)
		sc->sc_munge = ukbd_gdium_munge;
#endif

	if (kbd->sc_console_keyboard) {
		extern struct wskbd_mapdata ukbd_keymapdata;

		DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
		ukbd_keymapdata.layout = layout;
		wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
		ukbd_enable(sc, 1);
	}

	/* Flash the leds; no real purpose, just shows we're alive. */
	ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM |
		          WSKBD_LED_CAPS | WSKBD_LED_COMPOSE);
	usbd_delay_ms(sc->sc_hdev.sc_udev, 400);
	ukbd_set_leds(sc, 0);

	hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops);
}
Example #17
0
File: uts.c Project: ryo/netbsd-src
Static void
uts_attach(device_t parent, device_t self, void *aux)
{
	struct uts_softc *sc = device_private(self);
	struct uhidev_attach_arg *uha = aux;
	struct wsmousedev_attach_args a;
	int size;
	void *desc;
	uint32_t flags;
	struct hid_data * d;
	struct hid_item item;

	aprint_naive("\n");

	sc->sc_hdev.sc_dev = self;
	sc->sc_hdev.sc_intr = uts_intr;
	sc->sc_hdev.sc_parent = uha->parent;
	sc->sc_hdev.sc_report_id = uha->reportid;

	uhidev_get_report_desc(uha->parent, &desc, &size);

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* requires HID usage Generic_Desktop:X */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
		uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no X report\n");
		return;
	}
	switch (flags & TSCREEN_FLAGS_MASK) {
	case 0:
		sc->flags |= UTS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "X report 0x%04x not supported\n", flags);
		return;
	}

	/* requires HID usage Generic_Desktop:Y */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
		uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no Y report\n");
		return;
	}
	switch (flags & TSCREEN_FLAGS_MASK) {
	case 0:
		sc->flags |= UTS_ABS;
		break;
	case HIO_RELATIVE:
		break;
	default:
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "Y report 0x%04x not supported\n", flags);
		return;
	}

	/* requires HID usage Digitizer:Tip_Switch */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
	    uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no tip switch report\n");
		return;
	}

	/* requires HID usage Digitizer:In_Range */
	if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE),
		uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
		aprint_error_dev(sc->sc_hdev.sc_dev,
		    "touchscreen has no range report\n");
		return;
	}

	/* multi-touch support would need HUD_CONTACTID and HUD_CONTACTMAX */

#ifdef UTS_DEBUG
	DPRINTF(("uts_attach: sc=%p\n", sc));
	DPRINTF(("uts_attach: X\t%d/%d\n",
		sc->sc_loc_x.pos, sc->sc_loc_x.size));
	DPRINTF(("uts_attach: Y\t%d/%d\n",
		sc->sc_loc_y.pos, sc->sc_loc_y.size));
	DPRINTF(("uts_attach: Z\t%d/%d\n",
		sc->sc_loc_z.pos, sc->sc_loc_z.size));
#endif

	a.accessops = &uts_accessops;
	a.accesscookie = sc;

	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);

	/* calibrate the touchscreen */
	memset(&sc->sc_calibcoords, 0, sizeof(sc->sc_calibcoords));
	sc->sc_calibcoords.maxx = 4095;
	sc->sc_calibcoords.maxy = 4095;
	sc->sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET;
	d = hid_start_parse(desc, size, hid_input);
	while (hid_get_item(d, &item)) {
		if (item.kind != hid_input
		    || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
		    || item.report_ID != sc->sc_hdev.sc_report_id)
			continue;
		if (HID_GET_USAGE(item.usage) == HUG_X) {
			sc->sc_calibcoords.minx = item.logical_minimum;
			sc->sc_calibcoords.maxx = item.logical_maximum;
		}
		if (HID_GET_USAGE(item.usage) == HUG_Y) {
			sc->sc_calibcoords.miny = item.logical_minimum;
			sc->sc_calibcoords.maxy = item.logical_maximum;
		}
	}
	hid_end_parse(d);

	tpcalib_init(&sc->sc_tpcalib);
	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
	    (void *)&sc->sc_calibcoords, 0, 0);

	return;
}
Example #18
0
void
mouse_recv(struct hid_appcol *ha, struct hid_report *hr)
{
	struct hid_interface *hi;
	struct hid_field *hf;
	struct mouse_dev *md;
	struct mouse_info mi;
	unsigned int usage, up;
	int has_wheel, has_twheel, has_fake_twheel, has_z, flags;
	int b, btn, dx, dy, dw, dt, df, dz, i;

	hi = hid_appcol_get_parser_private(ha);
	assert(hi != NULL);
	md = hid_appcol_get_private(ha);
	assert(md != NULL);

	dx = dy = dw = dt = df = dz = 0;
	has_wheel = has_twheel = has_fake_twheel = has_z = 0;
	btn = 0;
	hf = NULL;
	while ((hf = hid_report_get_next_field(hr, hf, HID_INPUT)) != NULL) {
		flags = hid_field_get_flags(hf);
		if (flags & HIO_CONST || (flags & HIO_VARIABLE) == 0)
			continue;
		for (i = 0; i < hf->hf_count; i++) {
			usage = HID_USAGE(hf->hf_usage[i]);
			up = HID_PAGE(hf->hf_usage[i]);
			if (up == HUP_BUTTON) {
				if (usage < BUTTON_MAX && hf->hf_value[i]) {
					b = usage - 1;
					if (b == 1)
						b = 2;
					else if (b == 2)
						b = 1;
					btn |= (1 << b);
				}
				continue;
			}

			switch (hf->hf_usage[i]) {
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X):
				dx = hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y):
				dy = hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL):
				/*
				 * HUG_WHEEL is the most common place for
				 * mouse wheel.
				 */
				has_wheel = 1;
				dw = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL):
				/*
				 * Some older Microsoft mouse (e.g. Microsoft
				 * Wireless Intellimouse 2.0) used
				 * HUG_TWHEEL(0x48) to report its wheel. Note
				 * that HUG_TWHEEL seems to be a temporary thing
				 * at the time. (The name TWHEEL is also a
				 * non-standard name) Later new HID usage spec
				 * defined 0x48 as usage "Resolution Multiplier"
				 * and newer M$ mouse stopped using 0x48 for
				 * mouse wheel.
				 */
				has_fake_twheel = 1;
				df = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z):
				/* Some mouse use HUG_Z to report its wheel. */
				has_z = 1;
				dz = -hf->hf_value[i];
				break;
			case HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN):
				/* Tilt wheel. */
				has_twheel = 1;
				dt = -hf->hf_value[i];
				break;
			}
		}
	}

	if (verbose > 1)
		PRINT1("mouse received data: dx(%d) dy(%d) dw(%d) dt(%d) "
		    "btn(%#x)\n", dx, dy, dw, dt, btn);

	/*
	 * There is no way to report tilt wheel to the kernel, for now
	 * translate them to button #8 and #9.
	 */
	if (has_twheel) {
		if (dt > 0)
			btn |= (1 << 8);
		else if (dt < 0)
			btn |= (1 << 9);
	}

	/* Push the data to console device. (and sysmouse) */
	mi.operation = MOUSE_ACTION;
	mi.u.data.x = dx;
	mi.u.data.y = dy;
	mi.u.data.buttons = btn;
	if (has_wheel)
		mi.u.data.z = dw;
	else if (has_fake_twheel)
		mi.u.data.z = df;
	else if (has_z)
		mi.u.data.z = dz;
	else
		mi.u.data.z = 0;

	if (ioctl(md->cons_fd, CONS_MOUSECTL, &mi) < 0)
		syslog(LOG_ERR, "%s[%d] could not submit mouse data:"
		    " ioctl failed: %m", basename(hi->dev), hi->ndx);
}