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); }
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; }
void utwitch_attach(struct device *parent, struct device *self, void *aux) { struct utwitch_softc *sc = (struct utwitch_softc *)self; struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; struct usbd_device *dev = uha->parent->sc_udev; int size, repid, err; void *desc; sc->sc_udev = dev; sc->sc_hdev.sc_intr = utwitch_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; sc->sc_ilen = hid_report_size(desc, size, hid_input, repid); sc->sc_olen = hid_report_size(desc, size, hid_output, repid); sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); err = uhidev_open(&sc->sc_hdev); if (err) { printf("utwitch_open: uhidev_open %d\n", err); return; } sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK); printf("\n"); /* attach sensor */ strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); /* add BBU sensor */ sc->sc_sensor_val.type = SENSOR_INTEGER; sensor_attach(&sc->sc_sensordev, &sc->sc_sensor_val); strlcpy(sc->sc_sensor_val.desc, "BBU", sizeof(sc->sc_sensor_val.desc)); /* add BBU delta sensor */ sc->sc_sensor_delta.type = SENSOR_INTEGER; sensor_attach(&sc->sc_sensordev, &sc->sc_sensor_delta); strlcpy(sc->sc_sensor_delta.desc, "mBBU/sec", sizeof(sc->sc_sensor_delta.desc)); sc->sc_sensortask = sensor_task_register(sc, utwitch_refresh, UPDATE_TICK); if (sc->sc_sensortask == NULL) { printf(", unable to register update task\n"); return; } sensordev_install(&sc->sc_sensordev); DPRINTF(("utwitch_attach: complete\n")); /* init device */ /* XXX */ utwitch_set_mode(sc, 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); }
int ums_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; 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_NONE); return (UMATCH_IFACECLASS); }
void ums_attach(struct device *parent, struct device *self, void *aux) { struct ums_softc *sc = (struct ums_softc *)self; struct hidms *ms = &sc->sc_ms; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; struct usb_attach_arg *uaa = uha->uaa; int size, repid; void *desc; u_int32_t quirks; sc->sc_hdev.sc_intr = ums_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_udev = uaa->device; sc->sc_hdev.sc_report_id = uha->reportid; quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); if (hidms_setup(self, ms, quirks, uha->reportid, desc, size) != 0) return; /* * 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) { ms->sc_flags = HIDMS_Z; ms->sc_num_buttons = 3; /* XXX change sc_hdev isize to 5? */ ms->sc_loc_x.pos = 8; ms->sc_loc_y.pos = 16; ms->sc_loc_z.pos = 24; ms->sc_loc_btn[0].pos = 0; ms->sc_loc_btn[1].pos = 1; ms->sc_loc_btn[2].pos = 2; } hidms_attach(ms, &ums_accessops); }
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; }
void uhid_attach(struct device *parent, struct device *self, void *aux) { struct uhid_softc *sc = (struct uhid_softc *)self; struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; int size, repid; void *desc; sc->sc_hdev.sc_intr = uhid_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); printf(": input=%d, output=%d, feature=%d\n", sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize); }
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); }
void uoakv_attach(struct device *parent, struct device *self, void *aux) { struct uoakv_softc *sc = (struct uoakv_softc *)self; struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; struct usbd_device *dev = uha->parent->sc_udev; struct uoak_softc *scc = &sc->sc_uoak_softc; int i, err, size, repid; void *desc; sc->sc_hdev.sc_intr = uoakv_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; scc->sc_parent = sc; scc->sc_udev = dev; scc->sc_hdev = &sc->sc_hdev; scc->sc_methods = &uoakv_methods; scc->sc_sensordev = &sc->sc_sensordev; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; scc->sc_ilen = hid_report_size(desc, size, hid_input, repid); scc->sc_olen = hid_report_size(desc, size, hid_output, repid); scc->sc_flen = hid_report_size(desc, size, hid_feature, repid); /* device initialize */ (void)uoak_led_ctrl(scc, OAK_TARGET_RAM, OAK_LED_ON); err = uoak_set_sample_rate(scc, OAK_TARGET_RAM, UOAKV_SAMPLE_RATE); if (err) { printf("%s: could not set sampling rate. exit\n", sc->sc_hdev.sc_dev.dv_xname); return; } /* query and print device setting */ uoak_get_devinfo(scc); uoak_print_devinfo(scc); DPRINTF((" config in RAM\n")); uoak_get_setting(scc, OAK_TARGET_RAM); uoak_print_setting(scc, OAK_TARGET_RAM); #ifdef UOAKV_DEBUG DPRINTF((" config in FRASH\n")); uoak_get_setting(scc, OAK_TARGET_FLASH); uoak_print_setting(scc, OAK_TARGET_FLASH); #endif /* attach sensor */ strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); for (i = 0; i < OAK_V_MAXSENSORS; i++) uoak_sensor_attach(scc, &sc->sc_sensor[i].v, SENSOR_VOLTS_DC); /* start sensor */ sc->sc_sensortask = sensor_task_register(sc, uoakv_refresh, UOAKV_REFRESH_PERIOD); if (sc->sc_sensortask == NULL) { printf(", unable to register update task\n"); return; } sensordev_install(&sc->sc_sensordev); err = uhidev_open(&sc->sc_hdev); if (err) { printf("%s: could not open interrupt pipe, quit\n", sc->sc_hdev.sc_dev.dv_xname); return; } scc->sc_ibuf = malloc(scc->sc_ilen, M_USBDEV, M_WAITOK); DPRINTF(("uoakv_attach: complete\n")); }
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 uyurex_attach(device_t parent, device_t self, void *aux) { struct uyurex_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; usbd_device_handle dev = uha->parent->sc_udev; int size, repid, err; void *desc; sc->sc_udev = dev; sc->sc_hdev.sc_dev = self; sc->sc_hdev.sc_intr = uyurex_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; uhidev_get_report_desc(uha->parent, &desc, &size); repid = uha->reportid; sc->sc_ilen = hid_report_size(desc, size, hid_input, repid); sc->sc_olen = hid_report_size(desc, size, hid_output, repid); sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); aprint_normal("\n"); aprint_naive("\n"); err = uhidev_open(&sc->sc_hdev); if (err) { aprint_error_dev(self, "uyurex_open: uhidev_open %d\n", err); return; } sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_hdev.sc_dev); /* attach sensor */ sc->sc_sme = sysmon_envsys_create(); /* error handling? XXX */ sc->sc_sme->sme_name = device_xname(self); /* add BBU sensor */ sc->sc_sensor_val.units = ENVSYS_INTEGER; sc->sc_sensor_val.state = ENVSYS_SINVALID; sc->sc_sensor_val.flags = ENVSYS_FMONCRITICAL; /* abuse XXX */ strlcpy(sc->sc_sensor_val.desc, "BBU", sizeof(sc->sc_sensor_val.desc)); sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_val); /* add BBU delta sensor */ sc->sc_sensor_delta.units = ENVSYS_INTEGER; sc->sc_sensor_delta.state = ENVSYS_SINVALID; strlcpy(sc->sc_sensor_delta.desc, "mBBU/sec", sizeof(sc->sc_sensor_delta.desc)); sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_delta); sc->sc_sme->sme_cookie = sc; sc->sc_sme->sme_refresh = uyurex_refresh; sc->sc_sme->sme_events_timeout = UPDATE_TICK; sc->sc_sme->sme_flags = SME_INIT_REFRESH; if (sysmon_envsys_register(sc->sc_sme)) { aprint_error_dev(self, "unable to register with sysmon\n"); sysmon_envsys_destroy(sc->sc_sme); } callout_init(&sc->sc_deltach, 0); callout_reset(&sc->sc_deltach, UPDATE_TICK * hz, uyurex_delta, sc); DPRINTF(("uyurex_attach: complete\n")); /* init device */ /* XXX */ uyurex_set_mode(sc, 0); }
void uslhcom_attach(struct device *parent, struct device *self, void *aux) { struct uslhcom_softc *sc = (struct uslhcom_softc *)self; struct uhidev_attach_arg *uha = aux; struct usbd_device *dev = uha->parent->sc_udev; struct ucom_attach_args uca; struct uslhcom_version_info version; int err, repid, size, rsize; void *desc; sc->sc_udev = dev; sc->sc_lsr = sc->sc_msr = 0; sc->sc_hdev.sc_intr = uslhcom_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; sc->sc_hdev.sc_isize = sc->sc_hdev.sc_osize = sc->sc_hdev.sc_fsize = 0; uhidev_get_report_desc(uha->parent, &desc, &size); for (repid = 0; repid < uha->parent->sc_nrepid; repid++) { rsize = hid_report_size(desc, size, hid_input, repid); if (sc->sc_hdev.sc_isize < rsize) sc->sc_hdev.sc_isize = rsize; rsize = hid_report_size(desc, size, hid_output, repid); if (sc->sc_hdev.sc_osize < rsize) sc->sc_hdev.sc_osize = rsize; rsize = hid_report_size(desc, size, hid_feature, repid); if (sc->sc_hdev.sc_fsize < rsize) sc->sc_hdev.sc_fsize = rsize; } printf("\n"); err = uhidev_open(&sc->sc_hdev); if (err) { DPRINTF(("uslhcom_attach: uhidev_open %d\n", err)); return; } DPRINTF(("uslhcom_attach: sc %p opipe %p ipipe %p report_id %d\n", sc, sc->sc_hdev.sc_parent->sc_opipe, sc->sc_hdev.sc_parent->sc_ipipe, uha->reportid)); DPRINTF(("uslhcom_attach: isize %d osize %d fsize %d\n", sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize)); uslhcom_uart_endis(sc, UART_DISABLE); uslhcom_get_version(sc, &version); printf("%s: pid %#x rev %#x\n", sc->sc_hdev.sc_dev.dv_xname, version.product_id, version.product_revision); /* setup ucom layer */ uca.portno = UCOM_UNK_PORTNO; uca.bulkin = uca.bulkout = -1; uca.ibufsize = uca.ibufsizepad = 0; uca.obufsize = sc->sc_hdev.sc_osize; uca.opkthdrlen = USLHCOM_TX_HEADER_SIZE; uca.uhidev = sc->sc_hdev.sc_parent; uca.device = uha->uaa->device; uca.iface = uha->uaa->iface; uca.methods = &uslhcom_methods; uca.arg = sc; uca.info = NULL; sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); }
int uhidev_ioctl(struct uhidev *sc, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct usb_ctl_report_desc *rd; struct usb_ctl_report *re; int size, extra; usbd_status err; void *desc; switch (cmd) { case USB_GET_REPORT_DESC: uhidev_get_report_desc(sc->sc_parent, &desc, &size); rd = (struct usb_ctl_report_desc *)addr; size = min(size, sizeof rd->ucrd_data); rd->ucrd_size = size; memcpy(rd->ucrd_data, desc, size); break; case USB_GET_REPORT: re = (struct usb_ctl_report *)addr; switch (re->ucr_report) { case UHID_INPUT_REPORT: size = sc->sc_isize; break; case UHID_OUTPUT_REPORT: size = sc->sc_osize; break; case UHID_FEATURE_REPORT: size = sc->sc_fsize; break; default: return EINVAL; } extra = sc->sc_report_id != 0; err = uhidev_get_report(sc, re->ucr_report, re->ucr_data, size + extra); if (extra) memcpy(re->ucr_data, re->ucr_data + 1, size); if (err) return EIO; break; case USB_SET_REPORT: re = (struct usb_ctl_report *)addr; switch (re->ucr_report) { case UHID_INPUT_REPORT: size = sc->sc_isize; break; case UHID_OUTPUT_REPORT: size = sc->sc_osize; break; case UHID_FEATURE_REPORT: size = sc->sc_fsize; break; default: return EINVAL; } err = uhidev_set_report(sc, re->ucr_report, re->ucr_data, size); if (err) return EIO; break; case USB_GET_REPORT_ID: *(int *)addr = sc->sc_report_id; break; default: return -1; } return 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); }
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; }