ums.c (188942) | ums.c (188981) |
---|---|
1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Lennart Augustsson (lennart@augustsson.net) at 7 * Carlstedt Research & Technology. 8 * --- 22 unchanged lines hidden (view full) --- 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Lennart Augustsson (lennart@augustsson.net) at 7 * Carlstedt Research & Technology. 8 * --- 22 unchanged lines hidden (view full) --- 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include <sys/cdefs.h> |
39__FBSDID("$FreeBSD: head/sys/dev/usb/input/ums.c 188942 2009-02-23 18:31:00Z thompsa $"); | 39__FBSDID("$FreeBSD: head/sys/dev/usb/input/ums.c 188981 2009-02-24 03:34:05Z thompsa $"); |
40 41/* 42 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 43 */ 44 45#include "usbdevs.h" 46#include <dev/usb/usb.h> 47#include <dev/usb/usb_mfunc.h> --- 34 unchanged lines hidden (view full) --- 82 83#define UMS_BUF_SIZE 8 /* bytes */ 84#define UMS_IFQ_MAXLEN 50 /* units */ 85#define UMS_BUTTON_MAX 31 /* exclusive, must be less than 32 */ 86#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) 87 88enum { 89 UMS_INTR_DT, | 40 41/* 42 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 43 */ 44 45#include "usbdevs.h" 46#include <dev/usb/usb.h> 47#include <dev/usb/usb_mfunc.h> --- 34 unchanged lines hidden (view full) --- 82 83#define UMS_BUF_SIZE 8 /* bytes */ 84#define UMS_IFQ_MAXLEN 50 /* units */ 85#define UMS_BUTTON_MAX 31 /* exclusive, must be less than 32 */ 86#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) 87 88enum { 89 UMS_INTR_DT, |
90 UMS_INTR_CS, 91 UMS_N_TRANSFER = 2, | 90 UMS_N_TRANSFER, |
92}; 93 94struct ums_softc { 95 struct usb2_fifo_sc sc_fifo; 96 struct mtx sc_mtx; 97 struct usb2_callout sc_callout; 98 struct hid_location sc_loc_w; 99 struct hid_location sc_loc_x; --- 8 unchanged lines hidden (view full) --- 108 struct usb2_xfer *sc_xfer[UMS_N_TRANSFER]; 109 110 uint32_t sc_flags; 111#define UMS_FLAG_X_AXIS 0x0001 112#define UMS_FLAG_Y_AXIS 0x0002 113#define UMS_FLAG_Z_AXIS 0x0004 114#define UMS_FLAG_T_AXIS 0x0008 115#define UMS_FLAG_SBU 0x0010 /* spurious button up events */ | 91}; 92 93struct ums_softc { 94 struct usb2_fifo_sc sc_fifo; 95 struct mtx sc_mtx; 96 struct usb2_callout sc_callout; 97 struct hid_location sc_loc_w; 98 struct hid_location sc_loc_x; --- 8 unchanged lines hidden (view full) --- 107 struct usb2_xfer *sc_xfer[UMS_N_TRANSFER]; 108 109 uint32_t sc_flags; 110#define UMS_FLAG_X_AXIS 0x0001 111#define UMS_FLAG_Y_AXIS 0x0002 112#define UMS_FLAG_Z_AXIS 0x0004 113#define UMS_FLAG_T_AXIS 0x0008 114#define UMS_FLAG_SBU 0x0010 /* spurious button up events */ |
116#define UMS_FLAG_INTR_STALL 0x0020 /* set if transfer error */ 117#define UMS_FLAG_REVZ 0x0040 /* Z-axis is reversed */ 118#define UMS_FLAG_W_AXIS 0x0080 | 115#define UMS_FLAG_REVZ 0x0020 /* Z-axis is reversed */ 116#define UMS_FLAG_W_AXIS 0x0040 |
119 120 uint8_t sc_buttons; 121 uint8_t sc_iid; 122 uint8_t sc_temp[64]; 123}; 124 125static void ums_put_queue_timeout(void *__sc); 126 | 117 118 uint8_t sc_buttons; 119 uint8_t sc_iid; 120 uint8_t sc_temp[64]; 121}; 122 123static void ums_put_queue_timeout(void *__sc); 124 |
127static usb2_callback_t ums_clear_stall_callback; | |
128static usb2_callback_t ums_intr_callback; 129 130static device_probe_t ums_probe; 131static device_attach_t ums_attach; 132static device_detach_t ums_detach; 133 134static usb2_fifo_cmd_t ums_start_read; 135static usb2_fifo_cmd_t ums_stop_read; --- 18 unchanged lines hidden (view full) --- 154 struct ums_softc *sc = __sc; 155 156 mtx_assert(&sc->sc_mtx, MA_OWNED); 157 158 ums_put_queue(sc, 0, 0, 0, 0, 0); 159} 160 161static void | 125static usb2_callback_t ums_intr_callback; 126 127static device_probe_t ums_probe; 128static device_attach_t ums_attach; 129static device_detach_t ums_detach; 130 131static usb2_fifo_cmd_t ums_start_read; 132static usb2_fifo_cmd_t ums_stop_read; --- 18 unchanged lines hidden (view full) --- 151 struct ums_softc *sc = __sc; 152 153 mtx_assert(&sc->sc_mtx, MA_OWNED); 154 155 ums_put_queue(sc, 0, 0, 0, 0, 0); 156} 157 158static void |
162ums_clear_stall_callback(struct usb2_xfer *xfer) 163{ 164 struct ums_softc *sc = xfer->priv_sc; 165 struct usb2_xfer *xfer_other = sc->sc_xfer[UMS_INTR_DT]; 166 167 if (usb2_clear_stall_callback(xfer, xfer_other)) { 168 DPRINTF("stall cleared\n"); 169 sc->sc_flags &= ~UMS_FLAG_INTR_STALL; 170 usb2_transfer_start(xfer_other); 171 } 172} 173 174static void | |
175ums_intr_callback(struct usb2_xfer *xfer) 176{ 177 struct ums_softc *sc = xfer->priv_sc; 178 uint8_t *buf = sc->sc_temp; 179 uint16_t len = xfer->actlen; 180 int32_t buttons = 0; 181 int32_t dw; 182 int32_t dx; --- 6 unchanged lines hidden (view full) --- 189 case USB_ST_TRANSFERRED: 190 DPRINTFN(6, "sc=%p actlen=%d\n", sc, len); 191 192 if (len > sizeof(sc->sc_temp)) { 193 DPRINTFN(6, "truncating large packet to %zu bytes\n", 194 sizeof(sc->sc_temp)); 195 len = sizeof(sc->sc_temp); 196 } | 159ums_intr_callback(struct usb2_xfer *xfer) 160{ 161 struct ums_softc *sc = xfer->priv_sc; 162 uint8_t *buf = sc->sc_temp; 163 uint16_t len = xfer->actlen; 164 int32_t buttons = 0; 165 int32_t dw; 166 int32_t dx; --- 6 unchanged lines hidden (view full) --- 173 case USB_ST_TRANSFERRED: 174 DPRINTFN(6, "sc=%p actlen=%d\n", sc, len); 175 176 if (len > sizeof(sc->sc_temp)) { 177 DPRINTFN(6, "truncating large packet to %zu bytes\n", 178 sizeof(sc->sc_temp)); 179 len = sizeof(sc->sc_temp); 180 } |
197 if (len == 0) { | 181 if (len == 0) |
198 goto tr_setup; | 182 goto tr_setup; |
199 } | 183 |
200 usb2_copy_out(xfer->frbuffers, 0, buf, len); 201 202 DPRINTFN(6, "data = %02x %02x %02x %02x " 203 "%02x %02x %02x %02x\n", 204 (len > 0) ? buf[0] : 0, (len > 1) ? buf[1] : 0, 205 (len > 2) ? buf[2] : 0, (len > 3) ? buf[3] : 0, 206 (len > 4) ? buf[4] : 0, (len > 5) ? buf[5] : 0, 207 (len > 6) ? buf[6] : 0, (len > 7) ? buf[7] : 0); 208 209 /* | 184 usb2_copy_out(xfer->frbuffers, 0, buf, len); 185 186 DPRINTFN(6, "data = %02x %02x %02x %02x " 187 "%02x %02x %02x %02x\n", 188 (len > 0) ? buf[0] : 0, (len > 1) ? buf[1] : 0, 189 (len > 2) ? buf[2] : 0, (len > 3) ? buf[3] : 0, 190 (len > 4) ? buf[4] : 0, (len > 5) ? buf[5] : 0, 191 (len > 6) ? buf[6] : 0, (len > 7) ? buf[7] : 0); 192 193 /* |
210 * The M$ Wireless Intellimouse 2.0 sends 1 extra leading byte 211 * of data compared to most USB mice. This byte frequently 212 * switches from 0x01 (usual state) to 0x02. I assume it is to 213 * allow extra, non-standard, reporting (say battery-life). | 194 * The M$ Wireless Intellimouse 2.0 sends 1 extra 195 * leading byte of data compared to most USB 196 * mice. This byte frequently switches from 0x01 197 * (usual state) to 0x02. I assume it is to allow 198 * extra, non-standard, reporting (say battery-life). |
214 * | 199 * |
215 * However at the same time it generates a left-click message 216 * on the button byte which causes spurious left-click's where 217 * there shouldn't be. This should sort that. Currently it's 218 * the only user of UMS_FLAG_T_AXIS so use it as an 219 * identifier. | 200 * However at the same time it generates a left-click 201 * message on the button byte which causes spurious 202 * left-click's where there shouldn't be. This should 203 * sort that. Currently it's the only user of 204 * UMS_FLAG_T_AXIS so use it as an identifier. |
220 * 221 * | 205 * 206 * |
222 * UPDATE: This problem affects the M$ Wireless Notebook Optical Mouse, 223 * too. However, the leading byte for this mouse is normally 0x11, 224 * and the phantom mouse click occurs when its 0x14. | 207 * UPDATE: This problem affects the M$ Wireless 208 * Notebook Optical Mouse, too. However, the leading 209 * byte for this mouse is normally 0x11, and the 210 * phantom mouse click occurs when its 0x14. |
225 * 226 * We probably should switch to some more official quirk. 227 */ 228 if (sc->sc_iid) { 229 if (sc->sc_flags & UMS_FLAG_T_AXIS) { 230 if (*buf == 0x02) { 231 goto tr_setup; 232 } --- 49 unchanged lines hidden (view full) --- 282 sc->sc_status.dy += dy; 283 sc->sc_status.dz += dz; 284 /* 285 * sc->sc_status.dt += dt; 286 * no way to export this yet 287 */ 288 289 /* | 211 * 212 * We probably should switch to some more official quirk. 213 */ 214 if (sc->sc_iid) { 215 if (sc->sc_flags & UMS_FLAG_T_AXIS) { 216 if (*buf == 0x02) { 217 goto tr_setup; 218 } --- 49 unchanged lines hidden (view full) --- 268 sc->sc_status.dy += dy; 269 sc->sc_status.dz += dz; 270 /* 271 * sc->sc_status.dt += dt; 272 * no way to export this yet 273 */ 274 275 /* |
290 * The Qtronix keyboard has a built in PS/2 port for a mouse. 291 * The firmware once in a while posts a spurious button up 292 * event. This event we ignore by doing a timeout for 50 msecs. 293 * If we receive dx=dy=dz=buttons=0 before we add the event to 294 * the queue. 295 * In any other case we delete the timeout event. | 276 * The Qtronix keyboard has a built in PS/2 277 * port for a mouse. The firmware once in a 278 * while posts a spurious button up 279 * event. This event we ignore by doing a 280 * timeout for 50 msecs. If we receive 281 * dx=dy=dz=buttons=0 before we add the event 282 * to the queue. In any other case we delete 283 * the timeout event. |
296 */ 297 if ((sc->sc_flags & UMS_FLAG_SBU) && 298 (dx == 0) && (dy == 0) && (dz == 0) && (dt == 0) && 299 (dw == 0) && (buttons == 0)) { 300 301 usb2_callout_reset(&sc->sc_callout, hz / 20, 302 &ums_put_queue_timeout, sc); 303 } else { 304 305 usb2_callout_stop(&sc->sc_callout); 306 307 ums_put_queue(sc, dx, dy, dz, dt, buttons); 308 } 309 } 310 case USB_ST_SETUP: 311tr_setup: | 284 */ 285 if ((sc->sc_flags & UMS_FLAG_SBU) && 286 (dx == 0) && (dy == 0) && (dz == 0) && (dt == 0) && 287 (dw == 0) && (buttons == 0)) { 288 289 usb2_callout_reset(&sc->sc_callout, hz / 20, 290 &ums_put_queue_timeout, sc); 291 } else { 292 293 usb2_callout_stop(&sc->sc_callout); 294 295 ums_put_queue(sc, dx, dy, dz, dt, buttons); 296 } 297 } 298 case USB_ST_SETUP: 299tr_setup: |
312 if (sc->sc_flags & UMS_FLAG_INTR_STALL) { 313 usb2_transfer_start(sc->sc_xfer[UMS_INTR_CS]); 314 } else { 315 /* check if we can put more data into the FIFO */ 316 if (usb2_fifo_put_bytes_max( 317 sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { 318 xfer->frlengths[0] = xfer->max_data_length; 319 usb2_start_hardware(xfer); 320 } | 300 /* check if we can put more data into the FIFO */ 301 if (usb2_fifo_put_bytes_max( 302 sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { 303 xfer->frlengths[0] = xfer->max_data_length; 304 usb2_start_hardware(xfer); |
321 } | 305 } |
322 return; | 306 break; |
323 324 default: /* Error */ 325 if (xfer->error != USB_ERR_CANCELLED) { | 307 308 default: /* Error */ 309 if (xfer->error != USB_ERR_CANCELLED) { |
326 /* start clear stall */ 327 sc->sc_flags |= UMS_FLAG_INTR_STALL; 328 usb2_transfer_start(sc->sc_xfer[UMS_INTR_CS]); | 310 /* try clear stall first */ 311 xfer->flags.stall_pipe = 1; 312 goto tr_setup; |
329 } | 313 } |
330 return; | 314 break; |
331 } 332} 333 334static const struct usb2_config ums_config[UMS_N_TRANSFER] = { 335 336 [UMS_INTR_DT] = { 337 .type = UE_INTERRUPT, 338 .endpoint = UE_ADDR_ANY, 339 .direction = UE_DIR_IN, 340 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 341 .mh.bufsize = 0, /* use wMaxPacketSize */ 342 .mh.callback = &ums_intr_callback, 343 }, | 315 } 316} 317 318static const struct usb2_config ums_config[UMS_N_TRANSFER] = { 319 320 [UMS_INTR_DT] = { 321 .type = UE_INTERRUPT, 322 .endpoint = UE_ADDR_ANY, 323 .direction = UE_DIR_IN, 324 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 325 .mh.bufsize = 0, /* use wMaxPacketSize */ 326 .mh.callback = &ums_intr_callback, 327 }, |
344 345 [UMS_INTR_CS] = { 346 .type = UE_CONTROL, 347 .endpoint = 0x00, /* Control pipe */ 348 .direction = UE_DIR_ANY, 349 .mh.bufsize = sizeof(struct usb2_device_request), 350 .mh.callback = &ums_clear_stall_callback, 351 .mh.timeout = 1000, /* 1 second */ 352 .mh.interval = 50, /* 50ms */ 353 }, | |
354}; 355 356static int 357ums_probe(device_t dev) 358{ 359 struct usb2_attach_arg *uaa = device_get_ivars(dev); 360 struct usb2_interface_descriptor *id; 361 void *d_ptr; | 328}; 329 330static int 331ums_probe(device_t dev) 332{ 333 struct usb2_attach_arg *uaa = device_get_ivars(dev); 334 struct usb2_interface_descriptor *id; 335 void *d_ptr; |
362 int32_t error = 0; | 336 int error; |
363 uint16_t d_len; 364 365 DPRINTFN(11, "\n"); 366 | 337 uint16_t d_len; 338 339 DPRINTFN(11, "\n"); 340 |
367 if (uaa->usb2_mode != USB_MODE_HOST) { | 341 if (uaa->usb2_mode != USB_MODE_HOST) |
368 return (ENXIO); | 342 return (ENXIO); |
369 } 370 if (uaa->iface == NULL) { 371 return (ENXIO); 372 } | 343 |
373 id = usb2_get_interface_descriptor(uaa->iface); 374 375 if ((id == NULL) || | 344 id = usb2_get_interface_descriptor(uaa->iface); 345 346 if ((id == NULL) || |
376 (id->bInterfaceClass != UICLASS_HID)) { | 347 (id->bInterfaceClass != UICLASS_HID)) |
377 return (ENXIO); | 348 return (ENXIO); |
378 } 379 error = usb2_req_get_hid_desc 380 (uaa->device, &Giant, | 349 350 error = usb2_req_get_hid_desc(uaa->device, &Giant, |
381 &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); 382 | 351 &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); 352 |
383 if (error) { | 353 if (error) |
384 return (ENXIO); | 354 return (ENXIO); |
385 } | 355 |
386 if (hid_is_collection(d_ptr, d_len, | 356 if (hid_is_collection(d_ptr, d_len, |
387 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) { | 357 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) |
388 error = 0; | 358 error = 0; |
389 } else if ((id->bInterfaceSubClass == UISUBCLASS_BOOT) && 390 (id->bInterfaceProtocol == UIPROTO_MOUSE)) { | 359 else if ((id->bInterfaceSubClass == UISUBCLASS_BOOT) && 360 (id->bInterfaceProtocol == UIPROTO_MOUSE)) |
391 error = 0; | 361 error = 0; |
392 } else { | 362 else |
393 error = ENXIO; | 363 error = ENXIO; |
394 } | |
395 396 free(d_ptr, M_TEMP); 397 return (error); 398} 399 400static int 401ums_attach(device_t dev) 402{ 403 struct usb2_attach_arg *uaa = device_get_ivars(dev); 404 struct ums_softc *sc = device_get_softc(dev); 405 void *d_ptr = NULL; 406 int unit = device_get_unit(dev); | 364 365 free(d_ptr, M_TEMP); 366 return (error); 367} 368 369static int 370ums_attach(device_t dev) 371{ 372 struct usb2_attach_arg *uaa = device_get_ivars(dev); 373 struct ums_softc *sc = device_get_softc(dev); 374 void *d_ptr = NULL; 375 int unit = device_get_unit(dev); |
407 int32_t isize; | 376 int isize; 377 int isizebits; 378 int err; |
408 uint32_t flags; | 379 uint32_t flags; |
409 int32_t err; | |
410 uint16_t d_len; 411 uint8_t i; 412 413 DPRINTFN(11, "sc=%p\n", sc); 414 415 device_set_usb2_desc(dev); 416 417 mtx_init(&sc->sc_mtx, "ums lock", NULL, MTX_DEF | MTX_RECURSE); --- 20 unchanged lines hidden (view full) --- 438 (uaa->device, &Giant, &d_ptr, 439 &d_len, M_TEMP, uaa->info.bIfaceIndex); 440 441 if (err) { 442 device_printf(dev, "error reading report description\n"); 443 goto detach; 444 } 445 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), | 380 uint16_t d_len; 381 uint8_t i; 382 383 DPRINTFN(11, "sc=%p\n", sc); 384 385 device_set_usb2_desc(dev); 386 387 mtx_init(&sc->sc_mtx, "ums lock", NULL, MTX_DEF | MTX_RECURSE); --- 20 unchanged lines hidden (view full) --- 408 (uaa->device, &Giant, &d_ptr, 409 &d_len, M_TEMP, uaa->info.bIfaceIndex); 410 411 if (err) { 412 device_printf(dev, "error reading report description\n"); 413 goto detach; 414 } 415 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), |
446 hid_input, &sc->sc_loc_x, &flags)) { | 416 hid_input, &sc->sc_loc_x, &flags, &sc->sc_iid)) { |
447 448 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 449 sc->sc_flags |= UMS_FLAG_X_AXIS; 450 } 451 } 452 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), | 417 418 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 419 sc->sc_flags |= UMS_FLAG_X_AXIS; 420 } 421 } 422 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), |
453 hid_input, &sc->sc_loc_y, &flags)) { | 423 hid_input, &sc->sc_loc_y, &flags, &sc->sc_iid)) { |
454 455 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 456 sc->sc_flags |= UMS_FLAG_Y_AXIS; 457 } 458 } 459 /* Try the wheel first as the Z activator since it's tradition. */ 460 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, | 424 425 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 426 sc->sc_flags |= UMS_FLAG_Y_AXIS; 427 } 428 } 429 /* Try the wheel first as the Z activator since it's tradition. */ 430 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, |
461 HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags) || | 431 HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid) || |
462 hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, | 432 hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, |
463 HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags)) { | 433 HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid)) { |
464 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 465 sc->sc_flags |= UMS_FLAG_Z_AXIS; 466 } 467 /* 468 * We might have both a wheel and Z direction, if so put 469 * put the Z on the W coordinate. 470 */ 471 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, | 434 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 435 sc->sc_flags |= UMS_FLAG_Z_AXIS; 436 } 437 /* 438 * We might have both a wheel and Z direction, if so put 439 * put the Z on the W coordinate. 440 */ 441 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, |
472 HUG_Z), hid_input, &sc->sc_loc_w, &flags)) { | 442 HUG_Z), hid_input, &sc->sc_loc_w, &flags, &sc->sc_iid)) { |
473 474 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 475 sc->sc_flags |= UMS_FLAG_W_AXIS; 476 } 477 } 478 } else if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, | 443 444 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 445 sc->sc_flags |= UMS_FLAG_W_AXIS; 446 } 447 } 448 } else if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, |
479 HUG_Z), hid_input, &sc->sc_loc_z, &flags)) { | 449 HUG_Z), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid)) { |
480 481 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 482 sc->sc_flags |= UMS_FLAG_Z_AXIS; 483 } 484 } 485 /* 486 * The Microsoft Wireless Intellimouse 2.0 reports it's wheel 487 * using 0x0048, which is HUG_TWHEEL, and seems to expect you 488 * to know that the byte after the wheel is the tilt axis. 489 * There are no other HID axis descriptors other than X,Y and 490 * TWHEEL 491 */ 492 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), | 450 451 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 452 sc->sc_flags |= UMS_FLAG_Z_AXIS; 453 } 454 } 455 /* 456 * The Microsoft Wireless Intellimouse 2.0 reports it's wheel 457 * using 0x0048, which is HUG_TWHEEL, and seems to expect you 458 * to know that the byte after the wheel is the tilt axis. 459 * There are no other HID axis descriptors other than X,Y and 460 * TWHEEL 461 */ 462 if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), |
493 hid_input, &sc->sc_loc_t, &flags)) { | 463 hid_input, &sc->sc_loc_t, &flags, &sc->sc_iid)) { |
494 495 sc->sc_loc_t.pos += 8; 496 497 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 498 sc->sc_flags |= UMS_FLAG_T_AXIS; 499 } 500 } 501 /* figure out the number of buttons */ 502 503 for (i = 0; i < UMS_BUTTON_MAX; i++) { 504 if (!hid_locate(d_ptr, d_len, HID_USAGE2(HUP_BUTTON, (i + 1)), | 464 465 sc->sc_loc_t.pos += 8; 466 467 if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) { 468 sc->sc_flags |= UMS_FLAG_T_AXIS; 469 } 470 } 471 /* figure out the number of buttons */ 472 473 for (i = 0; i < UMS_BUTTON_MAX; i++) { 474 if (!hid_locate(d_ptr, d_len, HID_USAGE2(HUP_BUTTON, (i + 1)), |
505 hid_input, &sc->sc_loc_btn[i], NULL)) { | 475 hid_input, &sc->sc_loc_btn[i], NULL, &sc->sc_iid)) { |
506 break; 507 } 508 } 509 510 sc->sc_buttons = i; 511 | 476 break; 477 } 478 } 479 480 sc->sc_buttons = i; 481 |
512 isize = hid_report_size(d_ptr, d_len, hid_input, &sc->sc_iid); | 482 isize = hid_report_size(d_ptr, d_len, hid_input, NULL); |
513 514 /* 515 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse 516 * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and 517 * all of its other button positions are all off. It also reports that 518 * it has two addional buttons and a tilt wheel. 519 */ 520 if (usb2_test_quirk(uaa, UQ_MS_BAD_CLASS)) { --- 7 unchanged lines hidden (view full) --- 528 /* 1st byte of descriptor report contains garbage */ 529 sc->sc_loc_x.pos = 16; 530 sc->sc_loc_y.pos = 24; 531 sc->sc_loc_z.pos = 32; 532 sc->sc_loc_btn[0].pos = 8; 533 sc->sc_loc_btn[1].pos = 9; 534 sc->sc_loc_btn[2].pos = 10; 535 } | 483 484 /* 485 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse 486 * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and 487 * all of its other button positions are all off. It also reports that 488 * it has two addional buttons and a tilt wheel. 489 */ 490 if (usb2_test_quirk(uaa, UQ_MS_BAD_CLASS)) { --- 7 unchanged lines hidden (view full) --- 498 /* 1st byte of descriptor report contains garbage */ 499 sc->sc_loc_x.pos = 16; 500 sc->sc_loc_y.pos = 24; 501 sc->sc_loc_z.pos = 32; 502 sc->sc_loc_btn[0].pos = 8; 503 sc->sc_loc_btn[1].pos = 9; 504 sc->sc_loc_btn[2].pos = 10; 505 } |
506 |
|
536 /* | 507 /* |
537 * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has 538 * five Report IDs: 19 23 24 17 18 (in the order they appear in report 539 * descriptor), it seems that report id 17 contains the necessary 540 * mouse information(3-buttons,X,Y,wheel) so we specify it manually. | 508 * Some Microsoft devices have incorrectly high location 509 * positions. Correct this: |
541 */ | 510 */ |
542 if ((uaa->info.idVendor == USB_VENDOR_MICROSOFT) && 543 (uaa->info.idProduct == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3)) { 544 sc->sc_flags = (UMS_FLAG_X_AXIS | 545 UMS_FLAG_Y_AXIS | 546 UMS_FLAG_Z_AXIS); 547 sc->sc_buttons = 3; 548 isize = 5; 549 sc->sc_iid = 17; 550 sc->sc_loc_x.pos = 8; 551 sc->sc_loc_y.pos = 16; 552 sc->sc_loc_z.pos = 24; 553 sc->sc_loc_btn[0].pos = 0; 554 sc->sc_loc_btn[1].pos = 1; 555 sc->sc_loc_btn[2].pos = 2; | 511 isizebits = isize * 8; 512 if ((sc->sc_iid != 0) && (isizebits > 8)) { 513 isizebits -= 8; /* remove size of report ID */ 514 sc->sc_loc_w.pos %= isizebits; 515 sc->sc_loc_x.pos %= isizebits; 516 sc->sc_loc_y.pos %= isizebits; 517 sc->sc_loc_z.pos %= isizebits; 518 sc->sc_loc_t.pos %= isizebits; 519 for (i = 0; i != UMS_BUTTON_MAX; i++) 520 sc->sc_loc_btn[i].pos %= isizebits; |
556 } | 521 } |
522 |
|
557 if (usb2_test_quirk(uaa, UQ_MS_REVZ)) { 558 /* Some wheels need the Z axis reversed. */ 559 sc->sc_flags |= UMS_FLAG_REVZ; 560 } 561 if (isize > sc->sc_xfer[UMS_INTR_DT]->max_frame_size) { 562 DPRINTF("WARNING: report size, %d bytes, is larger " 563 "than interrupt size, %d bytes!\n", 564 isize, sc->sc_xfer[UMS_INTR_DT]->max_frame_size); --- 98 unchanged lines hidden (view full) --- 663 usb2_transfer_start(sc->sc_xfer[UMS_INTR_DT]); 664} 665 666static void 667ums_stop_read(struct usb2_fifo *fifo) 668{ 669 struct ums_softc *sc = fifo->priv_sc0; 670 | 523 if (usb2_test_quirk(uaa, UQ_MS_REVZ)) { 524 /* Some wheels need the Z axis reversed. */ 525 sc->sc_flags |= UMS_FLAG_REVZ; 526 } 527 if (isize > sc->sc_xfer[UMS_INTR_DT]->max_frame_size) { 528 DPRINTF("WARNING: report size, %d bytes, is larger " 529 "than interrupt size, %d bytes!\n", 530 isize, sc->sc_xfer[UMS_INTR_DT]->max_frame_size); --- 98 unchanged lines hidden (view full) --- 629 usb2_transfer_start(sc->sc_xfer[UMS_INTR_DT]); 630} 631 632static void 633ums_stop_read(struct usb2_fifo *fifo) 634{ 635 struct ums_softc *sc = fifo->priv_sc0; 636 |
671 usb2_transfer_stop(sc->sc_xfer[UMS_INTR_CS]); | |
672 usb2_transfer_stop(sc->sc_xfer[UMS_INTR_DT]); 673 usb2_callout_stop(&sc->sc_callout); 674} 675 676 677#if ((MOUSE_SYS_PACKETSIZE != 8) || \ 678 (MOUSE_MSC_PACKETSIZE != 5)) 679#error "Software assumptions are not met. Please update code." --- 222 unchanged lines hidden --- | 637 usb2_transfer_stop(sc->sc_xfer[UMS_INTR_DT]); 638 usb2_callout_stop(&sc->sc_callout); 639} 640 641 642#if ((MOUSE_SYS_PACKETSIZE != 8) || \ 643 (MOUSE_MSC_PACKETSIZE != 5)) 644#error "Software assumptions are not met. Please update code." --- 222 unchanged lines hidden --- |