2 * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
37 #include <dev/usb/usb.h>
38 #include <dev/usb/usbdi.h>
44 static int umouse_debug
= 0;
45 #define DPRINTF(params) if (umouse_debug) printf params
46 #define WPRINTF(params) printf params
48 /* USB endpoint context (1-15) for reporting mouse data events*/
49 #define UMOUSE_INTR_ENDPT 1
51 #define UMOUSE_REPORT_DESC_TYPE 0x22
53 #define UMOUSE_GET_REPORT 0x01
54 #define UMOUSE_GET_IDLE 0x02
55 #define UMOUSE_GET_PROTOCOL 0x03
56 #define UMOUSE_SET_REPORT 0x09
57 #define UMOUSE_SET_IDLE 0x0A
58 #define UMOUSE_SET_PROTOCOL 0x0B
60 #define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
71 static const char *umouse_desc_strings
[] = {
79 struct umouse_hid_descriptor
{
81 uint8_t bDescriptorType
;
84 uint8_t bNumDescriptors
;
85 uint8_t bReportDescriptorType
;
86 uint8_t wItemLength
[2];
89 struct umouse_config_desc
{
90 struct usb_config_descriptor confd
;
91 struct usb_interface_descriptor ifcd
;
92 struct umouse_hid_descriptor hidd
;
93 struct usb_endpoint_descriptor endpd
;
94 struct usb_endpoint_ss_comp_descriptor sscompd
;
97 #define MOUSE_MAX_X 0x8000
98 #define MOUSE_MAX_Y 0x8000
100 static const uint8_t umouse_report_desc
[] = {
101 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
102 0x09, 0x02, /* USAGE (Mouse) */
103 0xa1, 0x01, /* COLLECTION (Application) */
104 0x09, 0x01, /* USAGE (Pointer) */
105 0xa1, 0x00, /* COLLECTION (Physical) */
106 0x05, 0x09, /* USAGE_PAGE (Button) */
107 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
108 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */
109 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
110 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
111 0x75, 0x01, /* REPORT_SIZE (1) */
112 0x95, 0x03, /* REPORT_COUNT (3) */
113 0x81, 0x02, /* INPUT (Data,Var,Abs); 3 buttons */
114 0x75, 0x05, /* REPORT_SIZE (5) */
115 0x95, 0x01, /* REPORT_COUNT (1) */
116 0x81, 0x03, /* INPUT (Cnst,Var,Abs); padding */
117 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
118 0x09, 0x30, /* USAGE (X) */
119 0x09, 0x31, /* USAGE (Y) */
120 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */
121 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (0x7fff) */
122 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
123 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (0x7fff) */
124 0x75, 0x10, /* REPORT_SIZE (16) */
125 0x95, 0x02, /* REPORT_COUNT (2) */
126 0x81, 0x02, /* INPUT (Data,Var,Abs) */
127 0x05, 0x01, /* USAGE Page (Generic Desktop) */
128 0x09, 0x38, /* USAGE (Wheel) */
129 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */
130 0x45, 0x00, /* PHYSICAL_MAXIMUM (0) */
131 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */
132 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */
133 0x75, 0x08, /* REPORT_SIZE (8) */
134 0x95, 0x01, /* REPORT_COUNT (1) */
135 0x81, 0x06, /* INPUT (Data,Var,Rel) */
136 0xc0, /* END_COLLECTION */
137 0xc0 /* END_COLLECTION */
140 struct umouse_report
{
141 uint8_t buttons
; /* bits: 0 left, 1 right, 2 middle */
142 int16_t x
; /* x position */
143 int16_t y
; /* y position */
144 int8_t z
; /* z wheel position */
148 #define MSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
150 static struct usb_device_descriptor umouse_dev_desc
= {
151 .bLength
= sizeof(umouse_dev_desc
),
152 .bDescriptorType
= UDESC_DEVICE
,
153 MSETW(.bcdUSB
, UD_USB_3_0
),
154 .bMaxPacketSize
= 8, /* max packet size */
155 MSETW(.idVendor
, 0xFB5D), /* vendor */
156 MSETW(.idProduct
, 0x0001), /* product */
157 MSETW(.bcdDevice
, 0), /* device version */
158 .iManufacturer
= UMSTR_MANUFACTURER
,
159 .iProduct
= UMSTR_PRODUCT
,
160 .iSerialNumber
= UMSTR_SERIAL
,
161 .bNumConfigurations
= 1,
164 static struct umouse_config_desc umouse_confd
= {
166 .bLength
= sizeof(umouse_confd
.confd
),
167 .bDescriptorType
= UDESC_CONFIG
,
168 .wTotalLength
[0] = sizeof(umouse_confd
),
170 .bConfigurationValue
= 1,
171 .iConfiguration
= UMSTR_CONFIG
,
172 .bmAttributes
= UC_BUS_POWERED
| UC_REMOTE_WAKEUP
,
176 .bLength
= sizeof(umouse_confd
.ifcd
),
177 .bDescriptorType
= UDESC_INTERFACE
,
179 .bInterfaceClass
= UICLASS_HID
,
180 .bInterfaceSubClass
= UISUBCLASS_BOOT
,
181 .bInterfaceProtocol
= UIPROTO_MOUSE
,
184 .bLength
= sizeof(umouse_confd
.hidd
),
185 .bDescriptorType
= 0x21,
186 .bcdHID
= { 0x01, 0x10 },
188 .bNumDescriptors
= 1,
189 .bReportDescriptorType
= UMOUSE_REPORT_DESC_TYPE
,
190 .wItemLength
= { sizeof(umouse_report_desc
), 0 },
193 .bLength
= sizeof(umouse_confd
.endpd
),
194 .bDescriptorType
= UDESC_ENDPOINT
,
195 .bEndpointAddress
= UE_DIR_IN
| UMOUSE_INTR_ENDPT
,
196 .bmAttributes
= UE_INTERRUPT
,
197 .wMaxPacketSize
[0] = 8,
201 .bLength
= sizeof(umouse_confd
.sscompd
),
202 .bDescriptorType
= UDESC_ENDPOINT_SS_COMP
,
205 MSETW(.wBytesPerInterval
, 0),
210 struct umouse_bos_desc
{
211 struct usb_bos_descriptor bosd
;
212 struct usb_devcap_ss_descriptor usbssd
;
216 struct umouse_bos_desc umouse_bosd
= {
218 .bLength
= sizeof(umouse_bosd
.bosd
),
219 .bDescriptorType
= UDESC_BOS
,
220 HSETW(.wTotalLength
, sizeof(umouse_bosd
)),
224 .bLength
= sizeof(umouse_bosd
.usbssd
),
225 .bDescriptorType
= UDESC_DEVICE_CAPABILITY
,
226 .bDevCapabilityType
= 3,
228 HSETW(.wSpeedsSupported
, 0x08),
229 .bFunctionalitySupport
= 3,
230 .bU1DevExitLat
= 0xa, /* dummy - not used */
231 .wU2DevExitLat
= { 0x20, 0x00 },
236 struct umouse_softc
{
241 struct umouse_report um_report
;
250 pthread_mutex_t ev_mtx
;
252 struct timeval prev_evt
;
256 umouse_event(uint8_t button
, int x
, int y
, void *arg
)
258 struct umouse_softc
*sc
;
259 struct bhyvegc_image
*gc
;
261 gc
= console_get_image();
269 pthread_mutex_lock(&sc
->mtx
);
271 sc
->um_report
.buttons
= 0;
275 sc
->um_report
.buttons
|= 0x01; /* left */
277 sc
->um_report
.buttons
|= 0x04; /* middle */
279 sc
->um_report
.buttons
|= 0x02; /* right */
283 sc
->um_report
.z
= -1;
285 /* scale coords to mouse resolution */
286 sc
->um_report
.x
= MOUSE_MAX_X
* x
/ gc
->width
;
287 sc
->um_report
.y
= MOUSE_MAX_X
* y
/ gc
->height
;
289 pthread_mutex_unlock(&sc
->mtx
);
291 pthread_mutex_lock(&sc
->ev_mtx
);
292 sc
->hci
->hci_intr(sc
->hci
, UE_DIR_IN
| UMOUSE_INTR_ENDPT
);
293 pthread_mutex_unlock(&sc
->ev_mtx
);
297 umouse_init(struct usb_hci
*hci
, char *opt
)
299 struct umouse_softc
*sc
;
301 sc
= calloc(1, sizeof(struct umouse_softc
));
304 sc
->hid
.protocol
= 1; /* REPORT protocol */
305 sc
->opt
= strdup(opt
);
306 pthread_mutex_init(&sc
->mtx
, NULL
);
307 pthread_mutex_init(&sc
->ev_mtx
, NULL
);
309 console_ptr_register(umouse_event
, sc
, 10);
314 #define UREQ(x,y) ((x) | ((y) << 8))
317 umouse_request(void *scarg
, struct usb_data_xfer
*xfer
)
319 struct umouse_softc
*sc
;
320 struct usb_data_xfer_block
*data
;
336 for (i
= 0; i
< xfer
->ndata
; i
++) {
337 xfer
->data
[idx
].bdone
= 0;
338 if (data
== NULL
&& USB_DATA_OK(xfer
,i
)) {
339 data
= &xfer
->data
[idx
];
343 xfer
->data
[idx
].processed
= 1;
344 idx
= (idx
+ 1) % USB_MAX_XFER_BLOCKS
;
347 err
= USB_ERR_NORMAL_COMPLETION
;
351 DPRINTF(("umouse_request: port %d\r\n", sc
->hci
->hci_port
));
355 value
= UGETW(xfer
->ureq
->wValue
);
356 index
= UGETW(xfer
->ureq
->wIndex
);
357 len
= UGETW(xfer
->ureq
->wLength
);
359 DPRINTF(("umouse_request: port %d, type 0x%x, req 0x%x, val 0x%x, "
360 "idx 0x%x, len %u\r\n",
361 sc
->hci
->hci_port
, xfer
->ureq
->bmRequestType
,
362 xfer
->ureq
->bRequest
, value
, index
, len
));
364 switch (UREQ(xfer
->ureq
->bRequest
, xfer
->ureq
->bmRequestType
)) {
365 case UREQ(UR_GET_CONFIG
, UT_READ_DEVICE
):
366 DPRINTF(("umouse: (UR_GET_CONFIG, UT_READ_DEVICE)\r\n"));
370 *udata
= umouse_confd
.confd
.bConfigurationValue
;
371 data
->blen
= len
> 0 ? len
- 1 : 0;
372 eshort
= data
->blen
> 0;
376 case UREQ(UR_GET_DESCRIPTOR
, UT_READ_DEVICE
):
377 DPRINTF(("umouse: (UR_GET_DESCRIPTOR, UT_READ_DEVICE) val %x\r\n",
382 switch (value
>> 8) {
384 DPRINTF(("umouse: (->UDESC_DEVICE) len %u ?= "
385 "sizeof(umouse_dev_desc) %lu\r\n",
386 len
, sizeof(umouse_dev_desc
)));
387 if ((value
& 0xFF) != 0) {
388 err
= USB_ERR_IOERROR
;
391 if (len
> sizeof(umouse_dev_desc
)) {
392 data
->blen
= len
- sizeof(umouse_dev_desc
);
393 len
= sizeof(umouse_dev_desc
);
396 memcpy(data
->buf
, &umouse_dev_desc
, len
);
401 DPRINTF(("umouse: (->UDESC_CONFIG)\r\n"));
402 if ((value
& 0xFF) != 0) {
403 err
= USB_ERR_IOERROR
;
406 if (len
> sizeof(umouse_confd
)) {
407 data
->blen
= len
- sizeof(umouse_confd
);
408 len
= sizeof(umouse_confd
);
412 memcpy(data
->buf
, &umouse_confd
, len
);
417 DPRINTF(("umouse: (->UDESC_STRING)\r\n"));
419 if ((value
& 0xFF) < UMSTR_MAX
)
420 str
= umouse_desc_strings
[value
& 0xFF];
424 if ((value
& 0xFF) == UMSTR_LANG
) {
426 udata
[1] = UDESC_STRING
;
427 data
->blen
= len
- 2;
442 slen
= 2 + strlen(str
) * 2;
444 udata
[1] = UDESC_STRING
;
447 data
->blen
= len
- slen
;
451 for (i
= 2; i
< len
; i
+= 2) {
460 DPRINTF(("umouse: USB3 BOS\r\n"));
461 if (len
> sizeof(umouse_bosd
)) {
462 data
->blen
= len
- sizeof(umouse_bosd
);
463 len
= sizeof(umouse_bosd
);
466 memcpy(udata
, &umouse_bosd
, len
);
471 DPRINTF(("umouse: unknown(%d)->ERROR\r\n", value
>> 8));
472 err
= USB_ERR_IOERROR
;
475 eshort
= data
->blen
> 0;
478 case UREQ(UR_GET_DESCRIPTOR
, UT_READ_INTERFACE
):
479 DPRINTF(("umouse: (UR_GET_DESCRIPTOR, UT_READ_INTERFACE) "
480 "0x%x\r\n", (value
>> 8)));
484 switch (value
>> 8) {
485 case UMOUSE_REPORT_DESC_TYPE
:
486 if (len
> sizeof(umouse_report_desc
)) {
487 data
->blen
= len
- sizeof(umouse_report_desc
);
488 len
= sizeof(umouse_report_desc
);
491 memcpy(data
->buf
, umouse_report_desc
, len
);
495 DPRINTF(("umouse: IO ERROR\r\n"));
496 err
= USB_ERR_IOERROR
;
499 eshort
= data
->blen
> 0;
502 case UREQ(UR_GET_INTERFACE
, UT_READ_INTERFACE
):
503 DPRINTF(("umouse: (UR_GET_INTERFACE, UT_READ_INTERFACE)\r\n"));
505 DPRINTF(("umouse get_interface, invalid index %d\r\n",
507 err
= USB_ERR_IOERROR
;
516 data
->blen
= len
- 1;
518 eshort
= data
->blen
> 0;
522 case UREQ(UR_GET_STATUS
, UT_READ_DEVICE
):
523 DPRINTF(("umouse: (UR_GET_STATUS, UT_READ_DEVICE)\r\n"));
524 if (data
!= NULL
&& len
> 1) {
525 if (sc
->hid
.feature
== UF_DEVICE_REMOTE_WAKEUP
)
526 USETW(udata
, UDS_REMOTE_WAKEUP
);
529 data
->blen
= len
- 2;
533 eshort
= data
->blen
> 0;
536 case UREQ(UR_GET_STATUS
, UT_READ_INTERFACE
):
537 case UREQ(UR_GET_STATUS
, UT_READ_ENDPOINT
):
538 DPRINTF(("umouse: (UR_GET_STATUS, UT_READ_INTERFACE)\r\n"));
539 if (data
!= NULL
&& len
> 1) {
541 data
->blen
= len
- 2;
544 eshort
= data
->blen
> 0;
547 case UREQ(UR_SET_ADDRESS
, UT_WRITE_DEVICE
):
548 /* XXX Controller should've handled this */
549 DPRINTF(("umouse set address %u\r\n", value
));
552 case UREQ(UR_SET_CONFIG
, UT_WRITE_DEVICE
):
553 DPRINTF(("umouse set config %u\r\n", value
));
556 case UREQ(UR_SET_DESCRIPTOR
, UT_WRITE_DEVICE
):
557 DPRINTF(("umouse set descriptor %u\r\n", value
));
561 case UREQ(UR_CLEAR_FEATURE
, UT_WRITE_DEVICE
):
562 DPRINTF(("umouse: (UR_SET_FEATURE, UT_WRITE_DEVICE) %x\r\n", value
));
563 if (value
== UF_DEVICE_REMOTE_WAKEUP
)
567 case UREQ(UR_SET_FEATURE
, UT_WRITE_DEVICE
):
568 DPRINTF(("umouse: (UR_SET_FEATURE, UT_WRITE_DEVICE) %x\r\n", value
));
569 if (value
== UF_DEVICE_REMOTE_WAKEUP
)
570 sc
->hid
.feature
= UF_DEVICE_REMOTE_WAKEUP
;
573 case UREQ(UR_CLEAR_FEATURE
, UT_WRITE_INTERFACE
):
574 case UREQ(UR_CLEAR_FEATURE
, UT_WRITE_ENDPOINT
):
575 case UREQ(UR_SET_FEATURE
, UT_WRITE_INTERFACE
):
576 case UREQ(UR_SET_FEATURE
, UT_WRITE_ENDPOINT
):
577 DPRINTF(("umouse: (UR_CLEAR_FEATURE, UT_WRITE_INTERFACE)\r\n"));
578 err
= USB_ERR_IOERROR
;
581 case UREQ(UR_SET_INTERFACE
, UT_WRITE_INTERFACE
):
582 DPRINTF(("umouse set interface %u\r\n", value
));
585 case UREQ(UR_ISOCH_DELAY
, UT_WRITE_DEVICE
):
586 DPRINTF(("umouse set isoch delay %u\r\n", value
));
589 case UREQ(UR_SET_SEL
, 0):
590 DPRINTF(("umouse set sel\r\n"));
593 case UREQ(UR_SYNCH_FRAME
, UT_WRITE_ENDPOINT
):
594 DPRINTF(("umouse synch frame\r\n"));
597 /* HID device requests */
599 case UREQ(UMOUSE_GET_REPORT
, UT_READ_CLASS_INTERFACE
):
600 DPRINTF(("umouse: (UMOUSE_GET_REPORT, UT_READ_CLASS_INTERFACE) "
601 "0x%x\r\n", (value
>> 8)));
605 if ((value
>> 8) == 0x01 && len
>= sizeof(sc
->um_report
)) {
606 /* TODO read from backend */
608 if (len
> sizeof(sc
->um_report
)) {
609 data
->blen
= len
- sizeof(sc
->um_report
);
610 len
= sizeof(sc
->um_report
);
614 memcpy(data
->buf
, &sc
->um_report
, len
);
617 err
= USB_ERR_IOERROR
;
620 eshort
= data
->blen
> 0;
623 case UREQ(UMOUSE_GET_IDLE
, UT_READ_CLASS_INTERFACE
):
624 if (data
!= NULL
&& len
> 0) {
625 *udata
= sc
->hid
.idle
;
626 data
->blen
= len
- 1;
629 eshort
= data
->blen
> 0;
632 case UREQ(UMOUSE_GET_PROTOCOL
, UT_READ_CLASS_INTERFACE
):
633 if (data
!= NULL
&& len
> 0) {
634 *udata
= sc
->hid
.protocol
;
635 data
->blen
= len
- 1;
638 eshort
= data
->blen
> 0;
641 case UREQ(UMOUSE_SET_REPORT
, UT_WRITE_CLASS_INTERFACE
):
642 DPRINTF(("umouse: (UMOUSE_SET_REPORT, UT_WRITE_CLASS_INTERFACE) ignored\r\n"));
645 case UREQ(UMOUSE_SET_IDLE
, UT_WRITE_CLASS_INTERFACE
):
646 sc
->hid
.idle
= UGETW(xfer
->ureq
->wValue
) >> 8;
647 DPRINTF(("umouse: (UMOUSE_SET_IDLE, UT_WRITE_CLASS_INTERFACE) %x\r\n",
651 case UREQ(UMOUSE_SET_PROTOCOL
, UT_WRITE_CLASS_INTERFACE
):
652 sc
->hid
.protocol
= UGETW(xfer
->ureq
->wValue
) >> 8;
653 DPRINTF(("umouse: (UR_CLEAR_FEATURE, UT_WRITE_CLASS_INTERFACE) %x\r\n",
658 DPRINTF(("**** umouse request unhandled\r\n"));
659 err
= USB_ERR_IOERROR
;
664 if (xfer
->ureq
&& (xfer
->ureq
->bmRequestType
& UT_WRITE
) &&
665 (err
== USB_ERR_NORMAL_COMPLETION
) && (data
!= NULL
))
668 err
= USB_ERR_SHORT_XFER
;
670 DPRINTF(("umouse request error code %d (0=ok), blen %u txlen %u\r\n",
671 err
, (data
? data
->blen
: 0), (data
? data
->bdone
: 0)));
677 umouse_data_handler(void *scarg
, struct usb_data_xfer
*xfer
, int dir
,
680 struct umouse_softc
*sc
;
681 struct usb_data_xfer_block
*data
;
686 DPRINTF(("umouse handle data - DIR=%s|EP=%d, blen %d\r\n",
687 dir
? "IN" : "OUT", epctx
, xfer
->data
[0].blen
));
690 /* find buffer to add data */
692 err
= USB_ERR_NORMAL_COMPLETION
;
694 /* handle xfer at first unprocessed item with buffer */
697 for (i
= 0; i
< xfer
->ndata
; i
++) {
698 data
= &xfer
->data
[idx
];
699 if (data
->buf
!= NULL
&& data
->blen
!= 0) {
705 idx
= (idx
+ 1) % USB_MAX_XFER_BLOCKS
;
714 DPRINTF(("umouse no buffer provided for input\r\n"));
723 pthread_mutex_lock(&sc
->mtx
);
726 err
= USB_ERR_CANCELLED
;
727 USB_DATA_SET_ERRCODE(&xfer
->data
[xfer
->head
], USB_NAK
);
728 pthread_mutex_unlock(&sc
->mtx
);
733 err
= USB_ERR_STALLED
;
734 USB_DATA_SET_ERRCODE(data
, USB_STALL
);
735 pthread_mutex_unlock(&sc
->mtx
);
745 memcpy(udata
, &sc
->um_report
, 6);
746 data
->blen
= len
- 6;
748 err
= USB_ERR_SHORT_XFER
;
752 pthread_mutex_unlock(&sc
->mtx
);
754 USB_DATA_SET_ERRCODE(data
, USB_STALL
);
755 err
= USB_ERR_STALLED
;
763 umouse_reset(void *scarg
)
765 struct umouse_softc
*sc
;
775 umouse_remove(void *scarg
)
782 umouse_stop(void *scarg
)
789 struct usb_devemu ue_mouse
= {
792 .ue_usbspeed
= USB_SPEED_HIGH
,
793 .ue_init
= umouse_init
,
794 .ue_request
= umouse_request
,
795 .ue_data
= umouse_data_handler
,
796 .ue_reset
= umouse_reset
,
797 .ue_remove
= umouse_remove
,
798 .ue_stop
= umouse_stop
800 USB_EMUL_SET(ue_mouse
);