Esempio n. 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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
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);
}
Esempio n. 4
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);
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
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);
}
Esempio n. 8
0
File: uts.c Progetto: 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;
}