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); }
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); }
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); }
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); }
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; }
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; }
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); }
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; }