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