Index: sys/dev/usb/input/ums.c =================================================================== --- sys/dev/usb/input/ums.c +++ sys/dev/usb/input/ums.c @@ -118,6 +118,9 @@ #define UMS_FLAG_SBU 0x0010 /* spurious button up events */ #define UMS_FLAG_REVZ 0x0020 /* Z-axis is reversed */ #define UMS_FLAG_W_AXIS 0x0040 +#define UMS_FLAG_X_ABS 0x0100 +#define UMS_FLAG_Y_ABS 0x0200 +#define UMS_FLAG_Z_ABS 0x0400 uint8_t sc_iid_w; uint8_t sc_iid_x; @@ -225,13 +228,15 @@ int32_t buttons_reported = 0; #endif int32_t dw = 0; - int32_t dx = 0; - int32_t dy = 0; - int32_t dz = 0; + int32_t dx = sc->sc_status.dx; + int32_t dy = sc->sc_status.dy; + int32_t dz = sc->sc_status.dz; int32_t dt = 0; uint8_t i; uint8_t id; int len; + int changed = 0; + uint32_t abs_flags = 0; usbd_xfer_status(xfer, &len, NULL, NULL, NULL); @@ -273,17 +278,35 @@ } repeat: + abs_flags |= info->sc_flags & (UMS_FLAG_X_ABS | UMS_FLAG_Y_ABS | UMS_FLAG_Z_ABS); + if ((info->sc_flags & UMS_FLAG_W_AXIS) && - (id == info->sc_iid_w)) + (id == info->sc_iid_w)) { dw += hid_get_data(buf, len, &info->sc_loc_w); + changed += dw != 0; + } if ((info->sc_flags & UMS_FLAG_X_AXIS) && - (id == info->sc_iid_x)) - dx += hid_get_data(buf, len, &info->sc_loc_x); + (id == info->sc_iid_x)) { + + if (info->sc_flags & UMS_FLAG_X_ABS) + dx = hid_get_data(buf, len, &info->sc_loc_x); + else + dx += hid_get_data(buf, len, &info->sc_loc_x); + + changed += dx != sc->sc_status.dx; + } if ((info->sc_flags & UMS_FLAG_Y_AXIS) && - (id == info->sc_iid_y)) - dy = -hid_get_data(buf, len, &info->sc_loc_y); + (id == info->sc_iid_y)) { + + if (info->sc_flags & UMS_FLAG_Y_ABS) + dy = -hid_get_data(buf, len, &info->sc_loc_y); + else + dy -= hid_get_data(buf, len, &info->sc_loc_y); + + changed += dy != sc->sc_status.dy; + } if ((info->sc_flags & UMS_FLAG_Z_AXIS) && (id == info->sc_iid_z)) { @@ -291,7 +314,13 @@ temp = hid_get_data(buf, len, &info->sc_loc_z); if (info->sc_flags & UMS_FLAG_REVZ) temp = -temp; - dz -= temp; + + if (info->sc_flags & UMS_FLAG_Z_ABS) + dz = -temp; + else + dz -= temp; + + changed += dz != sc->sc_status.dz; } if ((info->sc_flags & UMS_FLAG_T_AXIS) && @@ -299,6 +328,7 @@ dt -= hid_get_data(buf, len, &info->sc_loc_t); /* T-axis is translated into button presses */ buttons_found |= (1UL << 5) | (1UL << 6); + changed += dt != 0; } for (i = 0; i < info->sc_buttons; i++) { @@ -322,9 +352,12 @@ #endif /* keep old button value(s) for non-detected buttons */ buttons |= sc->sc_status.button & ~buttons_found; + changed += buttons != sc->sc_status.button; - if (dx || dy || dz || dt || dw || - (buttons != sc->sc_status.button)) { + if (changed) { + int32_t old_dx = sc->sc_status.dx; + int32_t old_dy = sc->sc_status.dy; + int32_t old_dz = sc->sc_status.dz; DPRINTFN(6, "x:%d y:%d z:%d t:%d w:%d buttons:0x%08x\n", dx, dy, dz, dt, dw, buttons); @@ -339,14 +372,21 @@ } sc->sc_status.button = buttons; - sc->sc_status.dx += dx; - sc->sc_status.dy += dy; - sc->sc_status.dz += dz; + sc->sc_status.dx = dx; + sc->sc_status.dy = dy; + sc->sc_status.dz = dz; /* * sc->sc_status.dt += dt; * no way to export this yet */ + if (!(abs_flags & UMS_FLAG_X_ABS)) + dx -= old_dx; + if (!(abs_flags & UMS_FLAG_Y_ABS)) + dy -= old_dy; + if (!(abs_flags & UMS_FLAG_Z_ABS)) + dz -= old_dz; + /* * The Qtronix keyboard has a built in PS/2 * port for a mouse. The firmware once in a @@ -367,7 +407,10 @@ usb_callout_stop(&sc->sc_callout); - ums_put_queue(sc, dx, dy, dz, dt, buttons); + /* sysmouse does not support absolute positioning */ + if (!(abs_flags & (UMS_FLAG_X_ABS | UMS_FLAG_Y_ABS | UMS_FLAG_Z_ABS))) + ums_put_queue(sc, dx, dy, dz, dt, buttons); + #ifdef EVDEV_SUPPORT ums_evdev_push(sc, dx, dy, dz, dt, buttons_reported); @@ -470,14 +513,20 @@ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), hid_input, index, &info->sc_loc_x, &flags, &info->sc_iid_x)) { - if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { + switch (flags & MOUSE_FLAGS_MASK) { + case 0: + info->sc_flags |= UMS_FLAG_X_ABS; + case MOUSE_FLAGS: info->sc_flags |= UMS_FLAG_X_AXIS; } } if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), hid_input, index, &info->sc_loc_y, &flags, &info->sc_iid_y)) { - if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { + switch (flags & MOUSE_FLAGS_MASK) { + case 0: + info->sc_flags |= UMS_FLAG_Y_ABS; + case MOUSE_FLAGS: info->sc_flags |= UMS_FLAG_Y_AXIS; } } @@ -488,7 +537,11 @@ hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), hid_input, index, &info->sc_loc_z, &flags, &info->sc_iid_z)) { - if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { + + switch (flags & MOUSE_FLAGS_MASK) { + case 0: + info->sc_flags |= UMS_FLAG_Z_ABS; + case MOUSE_FLAGS: info->sc_flags |= UMS_FLAG_Z_AXIS; } /* @@ -507,7 +560,10 @@ HUG_Z), hid_input, index, &info->sc_loc_z, &flags, &info->sc_iid_z)) { - if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { + switch (flags & MOUSE_FLAGS_MASK) { + case 0: + info->sc_flags |= UMS_FLAG_Z_ABS; + case MOUSE_FLAGS: info->sc_flags |= UMS_FLAG_Z_AXIS; } } @@ -563,13 +619,14 @@ return; /* announce information about the mouse */ - device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates ID=%u\n", + device_printf(dev, "%d buttons and [%s%s%s%s%s]%s coordinates ID=%u\n", (info->sc_buttons), (info->sc_flags & UMS_FLAG_X_AXIS) ? "X" : "", (info->sc_flags & UMS_FLAG_Y_AXIS) ? "Y" : "", (info->sc_flags & UMS_FLAG_Z_AXIS) ? "Z" : "", (info->sc_flags & UMS_FLAG_T_AXIS) ? "T" : "", (info->sc_flags & UMS_FLAG_W_AXIS) ? "W" : "", + (info->sc_flags & (UMS_FLAG_X_ABS | UMS_FLAG_Y_ABS | UMS_FLAG_Z_ABS)) ? " (absolute)" : "", info->sc_iid_x); } @@ -713,6 +770,8 @@ goto detach; #ifdef EVDEV_SUPPORT + info = &sc->sc_info[0]; + sc->sc_evdev = evdev_alloc(); evdev_set_name(sc->sc_evdev, device_get_desc(dev)); evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev)); @@ -722,19 +781,31 @@ evdev_set_methods(sc->sc_evdev, sc, &ums_evdev_methods); evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER); evdev_support_event(sc->sc_evdev, EV_SYN); + if (info->sc_flags & (UMS_FLAG_X_ABS | UMS_FLAG_Y_ABS | UMS_FLAG_Z_ABS)) + evdev_support_event(sc->sc_evdev, EV_ABS); evdev_support_event(sc->sc_evdev, EV_REL); evdev_support_event(sc->sc_evdev, EV_KEY); - info = &sc->sc_info[0]; - - if (info->sc_flags & UMS_FLAG_X_AXIS) - evdev_support_rel(sc->sc_evdev, REL_X); + if (info->sc_flags & UMS_FLAG_X_AXIS) { + if (info->sc_flags & UMS_FLAG_X_ABS) + evdev_support_abs(sc->sc_evdev, ABS_X, 0, 0, 0x7fff, 0, 0, 0); + else + evdev_support_rel(sc->sc_evdev, REL_X); + } - if (info->sc_flags & UMS_FLAG_Y_AXIS) - evdev_support_rel(sc->sc_evdev, REL_Y); + if (info->sc_flags & UMS_FLAG_Y_AXIS) { + if (info->sc_flags & UMS_FLAG_Y_ABS) + evdev_support_abs(sc->sc_evdev, ABS_Y, 0, 0, 0x7fff, 0, 0, 0); + else + evdev_support_rel(sc->sc_evdev, REL_Y); + } - if (info->sc_flags & UMS_FLAG_Z_AXIS) - evdev_support_rel(sc->sc_evdev, REL_WHEEL); + if (info->sc_flags & UMS_FLAG_Z_AXIS) { + if (info->sc_flags & UMS_FLAG_Z_ABS) + evdev_support_abs(sc->sc_evdev, ABS_Z, 0, 0, 0x7fff, 0, 0, 0); + else + evdev_support_rel(sc->sc_evdev, REL_Z); + } if (info->sc_flags & UMS_FLAG_T_AXIS) evdev_support_rel(sc->sc_evdev, REL_HWHEEL); @@ -925,9 +996,21 @@ { if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { /* Push evdev event */ - evdev_push_rel(sc->sc_evdev, REL_X, dx); - evdev_push_rel(sc->sc_evdev, REL_Y, -dy); - evdev_push_rel(sc->sc_evdev, REL_WHEEL, -dz); + if (sc->sc_info[0].sc_flags & UMS_FLAG_X_ABS) + evdev_push_event(sc->sc_evdev, EV_ABS, ABS_X, dx); + else + evdev_push_rel(sc->sc_evdev, REL_X, dx); + + if (sc->sc_info[0].sc_flags & UMS_FLAG_Y_ABS) + evdev_push_event(sc->sc_evdev, EV_ABS, ABS_Y, -dy); + else + evdev_push_rel(sc->sc_evdev, REL_Y, -dy); + + if (sc->sc_info[0].sc_flags & UMS_FLAG_Z_ABS) + evdev_push_event(sc->sc_evdev, EV_ABS, ABS_WHEEL, -dx); + else + evdev_push_rel(sc->sc_evdev, REL_WHEEL, -dz); + evdev_push_rel(sc->sc_evdev, REL_HWHEEL, dt); evdev_push_mouse_btn(sc->sc_evdev, (buttons & ~MOUSE_STDBUTTONS) |