xref: /illumos-gate/usr/src/cmd/bhyve/usb_mouse.c (revision 32640292)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 
31 #include <sys/time.h>
32 
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <dev/usb/usb.h>
39 #include <dev/usb/usbdi.h>
40 
41 #include "usb_emul.h"
42 #include "console.h"
43 #include "bhyvegc.h"
44 #include "debug.h"
45 
46 static int umouse_debug = 0;
47 #define	DPRINTF(params) if (umouse_debug) PRINTLN params
48 #define	WPRINTF(params) PRINTLN params
49 
50 /* USB endpoint context (1-15) for reporting mouse data events*/
51 #define	UMOUSE_INTR_ENDPT	1
52 
53 #define UMOUSE_REPORT_DESC_TYPE	0x22
54 
55 #define	UMOUSE_GET_REPORT	0x01
56 #define	UMOUSE_GET_IDLE		0x02
57 #define	UMOUSE_GET_PROTOCOL	0x03
58 #define	UMOUSE_SET_REPORT	0x09
59 #define	UMOUSE_SET_IDLE		0x0A
60 #define	UMOUSE_SET_PROTOCOL	0x0B
61 
62 #define HSETW(ptr, val)   ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
63 
64 enum {
65 	UMSTR_LANG,
66 	UMSTR_MANUFACTURER,
67 	UMSTR_PRODUCT,
68 	UMSTR_SERIAL,
69 	UMSTR_CONFIG,
70 	UMSTR_MAX
71 };
72 
73 static const char *umouse_desc_strings[] = {
74 	"\x09\x04",
75 	"BHYVE",
76 	"HID Tablet",
77 	"01",
78 	"HID Tablet Device",
79 };
80 
81 struct umouse_hid_descriptor {
82 	uint8_t	bLength;
83 	uint8_t	bDescriptorType;
84 	uint8_t	bcdHID[2];
85 	uint8_t	bCountryCode;
86 	uint8_t	bNumDescriptors;
87 	uint8_t	bReportDescriptorType;
88 	uint8_t	wItemLength[2];
89 } __packed;
90 
91 struct umouse_config_desc {
92 	struct usb_config_descriptor		confd;
93 	struct usb_interface_descriptor		ifcd;
94 	struct umouse_hid_descriptor		hidd;
95 	struct usb_endpoint_descriptor		endpd;
96 	struct usb_endpoint_ss_comp_descriptor	sscompd;
97 } __packed;
98 
99 #define MOUSE_MAX_X	0x8000
100 #define MOUSE_MAX_Y	0x8000
101 
102 static const uint8_t umouse_report_desc[] = {
103 	0x05, 0x01,		/* USAGE_PAGE (Generic Desktop)		*/
104 	0x09, 0x02,		/* USAGE (Mouse)			*/
105 	0xa1, 0x01,		/* COLLECTION (Application) 		*/
106 	0x09, 0x01,		/*   USAGE (Pointer)			*/
107 	0xa1, 0x00,		/*   COLLECTION (Physical)		*/
108 	0x05, 0x09,		/*     USAGE_PAGE (Button)		*/
109 	0x19, 0x01,		/*     USAGE_MINIMUM (Button 1)		*/
110 	0x29, 0x03,		/*     USAGE_MAXIMUM (Button 3)		*/
111 	0x15, 0x00,		/*     LOGICAL_MINIMUM (0)		*/
112 	0x25, 0x01,		/*     LOGICAL_MAXIMUM (1)		*/
113 	0x75, 0x01,		/*     REPORT_SIZE (1)			*/
114 	0x95, 0x03,		/*     REPORT_COUNT (3)			*/
115 	0x81, 0x02,		/*     INPUT (Data,Var,Abs); 3 buttons	*/
116 	0x75, 0x05,		/*     REPORT_SIZE (5)			*/
117 	0x95, 0x01,		/*     REPORT_COUNT (1)			*/
118 	0x81, 0x03,		/*     INPUT (Cnst,Var,Abs); padding	*/
119 	0x05, 0x01,		/*     USAGE_PAGE (Generic Desktop)	*/
120 	0x09, 0x30,		/*     USAGE (X)			*/
121 	0x09, 0x31,		/*     USAGE (Y)			*/
122 	0x35, 0x00,		/*     PHYSICAL_MINIMUM (0)		*/
123 	0x46, 0xff, 0x7f,	/*     PHYSICAL_MAXIMUM (0x7fff)	*/
124 	0x15, 0x00,		/*     LOGICAL_MINIMUM (0)		*/
125 	0x26, 0xff, 0x7f,	/*     LOGICAL_MAXIMUM (0x7fff)		*/
126 	0x75, 0x10,		/*     REPORT_SIZE (16)			*/
127 	0x95, 0x02,		/*     REPORT_COUNT (2)			*/
128 	0x81, 0x02,		/*     INPUT (Data,Var,Abs)		*/
129 	0x05, 0x01,		/*     USAGE Page (Generic Desktop)	*/
130 	0x09, 0x38,		/*     USAGE (Wheel)			*/
131 	0x35, 0x00,		/*     PHYSICAL_MINIMUM (0)		*/
132 	0x45, 0x00,		/*     PHYSICAL_MAXIMUM (0)		*/
133 	0x15, 0x81,		/*     LOGICAL_MINIMUM (-127)		*/
134 	0x25, 0x7f,		/*     LOGICAL_MAXIMUM (127)		*/
135 	0x75, 0x08,		/*     REPORT_SIZE (8)			*/
136 	0x95, 0x01,		/*     REPORT_COUNT (1)			*/
137 	0x81, 0x06,		/*     INPUT (Data,Var,Rel)		*/
138 	0xc0,			/*   END_COLLECTION			*/
139 	0xc0			/* END_COLLECTION			*/
140 };
141 
142 struct umouse_report {
143 	uint8_t	buttons;	/* bits: 0 left, 1 right, 2 middle */
144 	int16_t	x;		/* x position */
145 	int16_t	y;		/* y position */
146 	int8_t	z;		/* z wheel position */
147 } __packed;
148 
149 
150 #define	MSETW(ptr, val)	ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
151 
152 static struct usb_device_descriptor umouse_dev_desc = {
153 	.bLength = sizeof(umouse_dev_desc),
154 	.bDescriptorType = UDESC_DEVICE,
155 	MSETW(.bcdUSB, UD_USB_3_0),
156 	.bMaxPacketSize = 8,			/* max packet size */
157 	MSETW(.idVendor, 0xFB5D),		/* vendor */
158 	MSETW(.idProduct, 0x0001),		/* product */
159 	MSETW(.bcdDevice, 0),			/* device version */
160 	.iManufacturer = UMSTR_MANUFACTURER,
161 	.iProduct = UMSTR_PRODUCT,
162 	.iSerialNumber = UMSTR_SERIAL,
163 	.bNumConfigurations = 1,
164 };
165 
166 static struct umouse_config_desc umouse_confd = {
167 	.confd = {
168 		.bLength = sizeof(umouse_confd.confd),
169 		.bDescriptorType = UDESC_CONFIG,
170 		.wTotalLength[0] = sizeof(umouse_confd),
171 		.bNumInterface = 1,
172 		.bConfigurationValue = 1,
173 		.iConfiguration = UMSTR_CONFIG,
174 		.bmAttributes = UC_BUS_POWERED | UC_REMOTE_WAKEUP,
175 		.bMaxPower = 0,
176 	},
177 	.ifcd = {
178 		.bLength = sizeof(umouse_confd.ifcd),
179 		.bDescriptorType = UDESC_INTERFACE,
180 		.bNumEndpoints = 1,
181 		.bInterfaceClass = UICLASS_HID,
182 		.bInterfaceSubClass = UISUBCLASS_BOOT,
183 		.bInterfaceProtocol = UIPROTO_MOUSE,
184 	},
185 	.hidd = {
186 		.bLength = sizeof(umouse_confd.hidd),
187 		.bDescriptorType = 0x21,
188 		.bcdHID = { 0x01, 0x10 },
189 		.bCountryCode = 0,
190 		.bNumDescriptors = 1,
191 		.bReportDescriptorType = UMOUSE_REPORT_DESC_TYPE,
192 		.wItemLength = { sizeof(umouse_report_desc), 0 },
193 	},
194 	.endpd = {
195 		.bLength = sizeof(umouse_confd.endpd),
196 		.bDescriptorType = UDESC_ENDPOINT,
197 		.bEndpointAddress = UE_DIR_IN | UMOUSE_INTR_ENDPT,
198 		.bmAttributes = UE_INTERRUPT,
199 		.wMaxPacketSize[0] = 8,
200 		.bInterval = 0xA,
201 	},
202 	.sscompd = {
203 		.bLength = sizeof(umouse_confd.sscompd),
204 		.bDescriptorType = UDESC_ENDPOINT_SS_COMP,
205 		.bMaxBurst = 0,
206 		.bmAttributes = 0,
207 		MSETW(.wBytesPerInterval, 0),
208 	},
209 };
210 
211 
212 struct umouse_bos_desc {
213 	struct usb_bos_descriptor		bosd;
214 	struct usb_devcap_ss_descriptor		usbssd;
215 } __packed;
216 
217 
218 static struct umouse_bos_desc umouse_bosd = {
219 	.bosd = {
220 		.bLength = sizeof(umouse_bosd.bosd),
221 		.bDescriptorType = UDESC_BOS,
222 		HSETW(.wTotalLength, sizeof(umouse_bosd)),
223 		.bNumDeviceCaps = 1,
224 	},
225 	.usbssd = {
226 		.bLength = sizeof(umouse_bosd.usbssd),
227 		.bDescriptorType = UDESC_DEVICE_CAPABILITY,
228 		.bDevCapabilityType = 3,
229 		.bmAttributes = 0,
230 		HSETW(.wSpeedsSupported, 0x08),
231 		.bFunctionalitySupport = 3,
232 		.bU1DevExitLat = 0xa,   /* dummy - not used */
233 		.wU2DevExitLat = { 0x20, 0x00 },
234 	}
235 };
236 
237 
238 struct umouse_softc {
239 	struct usb_hci *hci;
240 
241 	struct umouse_report um_report;
242 	int	newdata;
243 	struct {
244 		uint8_t	idle;
245 		uint8_t	protocol;
246 		uint8_t	feature;
247 	} hid;
248 
249 	pthread_mutex_t	mtx;
250 	pthread_mutex_t	ev_mtx;
251 	int		polling;
252 	struct timeval	prev_evt;
253 };
254 
255 static void
umouse_event(uint8_t button,int x,int y,void * arg)256 umouse_event(uint8_t button, int x, int y, void *arg)
257 {
258 	struct umouse_softc *sc;
259 	struct bhyvegc_image *gc;
260 
261 	gc = console_get_image();
262 	if (gc == NULL) {
263 		/* not ready */
264 		return;
265 	}
266 
267 	sc = arg;
268 
269 	pthread_mutex_lock(&sc->mtx);
270 
271 	sc->um_report.buttons = 0;
272 	sc->um_report.z = 0;
273 
274 	if (button & 0x01)
275 		sc->um_report.buttons |= 0x01;	/* left */
276 	if (button & 0x02)
277 		sc->um_report.buttons |= 0x04;	/* middle */
278 	if (button & 0x04)
279 		sc->um_report.buttons |= 0x02;	/* right */
280 	if (button & 0x8)
281 		sc->um_report.z = 1;
282 	if (button & 0x10)
283 		sc->um_report.z = -1;
284 
285 	/* scale coords to mouse resolution */
286 	sc->um_report.x = MOUSE_MAX_X * x / gc->width;
287 	sc->um_report.y = MOUSE_MAX_Y * y / gc->height;
288 	sc->newdata = 1;
289 	pthread_mutex_unlock(&sc->mtx);
290 
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);
294 }
295 
296 static void *
umouse_init(struct usb_hci * hci,nvlist_t * nvl)297 umouse_init(struct usb_hci *hci, nvlist_t *nvl)
298 {
299 	struct umouse_softc *sc;
300 
301 	sc = calloc(1, sizeof(struct umouse_softc));
302 	sc->hci = hci;
303 
304 	sc->hid.protocol = 1;	/* REPORT protocol */
305 	pthread_mutex_init(&sc->mtx, NULL);
306 	pthread_mutex_init(&sc->ev_mtx, NULL);
307 
308 	console_ptr_register(umouse_event, sc, 10);
309 
310 	return (sc);
311 }
312 
313 #define	UREQ(x,y)	((x) | ((y) << 8))
314 
315 static int
umouse_request(void * scarg,struct usb_data_xfer * xfer)316 umouse_request(void *scarg, struct usb_data_xfer *xfer)
317 {
318 	struct umouse_softc *sc;
319 	struct usb_data_xfer_block *data;
320 	const char *str;
321 	uint16_t value;
322 	uint16_t index;
323 	uint16_t len;
324 	uint16_t slen;
325 	uint8_t *udata;
326 	int	err;
327 	int	i, idx;
328 	int	eshort;
329 
330 	sc = scarg;
331 
332 	data = NULL;
333 	udata = NULL;
334 	idx = xfer->head;
335 	for (i = 0; i < xfer->ndata; i++) {
336 		xfer->data[idx].bdone = 0;
337 		if (data == NULL && USB_DATA_OK(xfer,i)) {
338 			data = &xfer->data[idx];
339 			udata = data->buf;
340 		}
341 
342 		xfer->data[idx].processed = 1;
343 		idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
344 	}
345 
346 	err = USB_ERR_NORMAL_COMPLETION;
347 	eshort = 0;
348 
349 	if (!xfer->ureq) {
350 		DPRINTF(("umouse_request: port %d", sc->hci->hci_port));
351 		goto done;
352 	}
353 
354 	value = UGETW(xfer->ureq->wValue);
355 	index = UGETW(xfer->ureq->wIndex);
356 	len = UGETW(xfer->ureq->wLength);
357 
358 	DPRINTF(("umouse_request: port %d, type 0x%x, req 0x%x, val 0x%x, "
359 	         "idx 0x%x, len %u",
360 	         sc->hci->hci_port, xfer->ureq->bmRequestType,
361 	         xfer->ureq->bRequest, value, index, len));
362 
363 	switch (UREQ(xfer->ureq->bRequest, xfer->ureq->bmRequestType)) {
364 	case UREQ(UR_GET_CONFIG, UT_READ_DEVICE):
365 		DPRINTF(("umouse: (UR_GET_CONFIG, UT_READ_DEVICE)"));
366 		if (!data)
367 			break;
368 
369 		*udata = umouse_confd.confd.bConfigurationValue;
370 		data->blen = len > 0 ? len - 1 : 0;
371 		eshort = data->blen > 0;
372 		data->bdone += 1;
373 		break;
374 
375 	case UREQ(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
376 		DPRINTF(("umouse: (UR_GET_DESCRIPTOR, UT_READ_DEVICE) val %x",
377 		        value >> 8));
378 		if (!data)
379 			break;
380 
381 		switch (value >> 8) {
382 		case UDESC_DEVICE:
383 			DPRINTF(("umouse: (->UDESC_DEVICE) len %u ?= "
384 			         "sizeof(umouse_dev_desc) %lu",
385 			         len, sizeof(umouse_dev_desc)));
386 			if ((value & 0xFF) != 0) {
387 				err = USB_ERR_STALLED;
388 				goto done;
389 			}
390 			if (len > sizeof(umouse_dev_desc)) {
391 				data->blen = len - sizeof(umouse_dev_desc);
392 				len = sizeof(umouse_dev_desc);
393 			} else
394 				data->blen = 0;
395 			memcpy(data->buf, &umouse_dev_desc, len);
396 			data->bdone += len;
397 			break;
398 
399 		case UDESC_CONFIG:
400 			DPRINTF(("umouse: (->UDESC_CONFIG)"));
401 			if ((value & 0xFF) != 0) {
402 				err = USB_ERR_STALLED;
403 				goto done;
404 			}
405 			if (len > sizeof(umouse_confd)) {
406 				data->blen = len - sizeof(umouse_confd);
407 				len = sizeof(umouse_confd);
408 			} else
409 				data->blen = 0;
410 
411 			memcpy(data->buf, &umouse_confd, len);
412 			data->bdone += len;
413 			break;
414 
415 		case UDESC_STRING:
416 			DPRINTF(("umouse: (->UDESC_STRING)"));
417 			str = NULL;
418 			if ((value & 0xFF) < UMSTR_MAX)
419 				str = umouse_desc_strings[value & 0xFF];
420 			else
421 				goto done;
422 
423 			if ((value & 0xFF) == UMSTR_LANG) {
424 				udata[0] = 4;
425 				udata[1] = UDESC_STRING;
426 				data->blen = len - 2;
427 				len -= 2;
428 				data->bdone += 2;
429 
430 				if (len >= 2) {
431 					udata[2] = str[0];
432 					udata[3] = str[1];
433 					data->blen -= 2;
434 					data->bdone += 2;
435 				} else
436 					data->blen = 0;
437 
438 				goto done;
439 			}
440 
441 			slen = 2 + strlen(str) * 2;
442 			udata[0] = slen;
443 			udata[1] = UDESC_STRING;
444 
445 			if (len > slen) {
446 				data->blen = len - slen;
447 				len = slen;
448 			} else
449 				data->blen = 0;
450 			for (i = 2; i < len; i += 2) {
451 				udata[i] = *str++;
452 				udata[i+1] = '\0';
453 			}
454 			data->bdone += slen;
455 
456 			break;
457 
458 		case UDESC_BOS:
459 			DPRINTF(("umouse: USB3 BOS"));
460 			if (len > sizeof(umouse_bosd)) {
461 				data->blen = len - sizeof(umouse_bosd);
462 				len = sizeof(umouse_bosd);
463 			} else
464 				data->blen = 0;
465 			memcpy(udata, &umouse_bosd, len);
466 			data->bdone += len;
467 			break;
468 
469 		default:
470 			DPRINTF(("umouse: unknown(%d)->ERROR", value >> 8));
471 			err = USB_ERR_STALLED;
472 			goto done;
473 		}
474 		eshort = data->blen > 0;
475 		break;
476 
477 	case UREQ(UR_GET_DESCRIPTOR, UT_READ_INTERFACE):
478 		DPRINTF(("umouse: (UR_GET_DESCRIPTOR, UT_READ_INTERFACE) "
479 		         "0x%x", (value >> 8)));
480 		if (!data)
481 			break;
482 
483 		switch (value >> 8) {
484 		case UMOUSE_REPORT_DESC_TYPE:
485 			if (len > sizeof(umouse_report_desc)) {
486 				data->blen = len - sizeof(umouse_report_desc);
487 				len = sizeof(umouse_report_desc);
488 			} else
489 				data->blen = 0;
490 			memcpy(data->buf, umouse_report_desc, len);
491 			data->bdone += len;
492 			break;
493 		default:
494 			DPRINTF(("umouse: IO ERROR"));
495 			err = USB_ERR_STALLED;
496 			goto done;
497 		}
498 		eshort = data->blen > 0;
499 		break;
500 
501 	case UREQ(UR_GET_INTERFACE, UT_READ_INTERFACE):
502 		DPRINTF(("umouse: (UR_GET_INTERFACE, UT_READ_INTERFACE)"));
503 		if (index != 0) {
504 			DPRINTF(("umouse get_interface, invalid index %d",
505 			        index));
506 			err = USB_ERR_STALLED;
507 			goto done;
508 		}
509 
510 		if (!data)
511 			break;
512 
513 		if (len > 0) {
514 			*udata = 0;
515 			data->blen = len - 1;
516 		}
517 		eshort = data->blen > 0;
518 		data->bdone += 1;
519 		break;
520 
521 	case UREQ(UR_GET_STATUS, UT_READ_DEVICE):
522 		DPRINTF(("umouse: (UR_GET_STATUS, UT_READ_DEVICE)"));
523 		if (data != NULL && len > 1) {
524 			if (sc->hid.feature == UF_DEVICE_REMOTE_WAKEUP)
525 				USETW(udata, UDS_REMOTE_WAKEUP);
526 			else
527 				USETW(udata, 0);
528 			data->blen = len - 2;
529 			data->bdone += 2;
530 		}
531 
532 		eshort = data->blen > 0;
533 		break;
534 
535 	case UREQ(UR_GET_STATUS, UT_READ_INTERFACE):
536 	case UREQ(UR_GET_STATUS, UT_READ_ENDPOINT):
537 		DPRINTF(("umouse: (UR_GET_STATUS, UT_READ_INTERFACE)"));
538 		if (data != NULL && len > 1) {
539 			USETW(udata, 0);
540 			data->blen = len - 2;
541 			data->bdone += 2;
542 		}
543 		eshort = data->blen > 0;
544 		break;
545 
546 	case UREQ(UR_SET_ADDRESS, UT_WRITE_DEVICE):
547 		/* XXX Controller should've handled this */
548 		DPRINTF(("umouse set address %u", value));
549 		break;
550 
551 	case UREQ(UR_SET_CONFIG, UT_WRITE_DEVICE):
552 		DPRINTF(("umouse set config %u", value));
553 		break;
554 
555 	case UREQ(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
556 		DPRINTF(("umouse set descriptor %u", value));
557 		break;
558 
559 
560 	case UREQ(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
561 		DPRINTF(("umouse: (UR_SET_FEATURE, UT_WRITE_DEVICE) %x", value));
562 		if (value == UF_DEVICE_REMOTE_WAKEUP)
563 			sc->hid.feature = 0;
564 		break;
565 
566 	case UREQ(UR_SET_FEATURE, UT_WRITE_DEVICE):
567 		DPRINTF(("umouse: (UR_SET_FEATURE, UT_WRITE_DEVICE) %x", value));
568 		if (value == UF_DEVICE_REMOTE_WAKEUP)
569 			sc->hid.feature = UF_DEVICE_REMOTE_WAKEUP;
570 		break;
571 
572 	case UREQ(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
573 	case UREQ(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
574 	case UREQ(UR_SET_FEATURE, UT_WRITE_INTERFACE):
575 	case UREQ(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
576 		DPRINTF(("umouse: (UR_CLEAR_FEATURE, UT_WRITE_INTERFACE)"));
577 		err = USB_ERR_STALLED;
578 		goto done;
579 
580 	case UREQ(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
581 		DPRINTF(("umouse set interface %u", value));
582 		break;
583 
584 	case UREQ(UR_ISOCH_DELAY, UT_WRITE_DEVICE):
585 		DPRINTF(("umouse set isoch delay %u", value));
586 		break;
587 
588 	case UREQ(UR_SET_SEL, 0):
589 		DPRINTF(("umouse set sel"));
590 		break;
591 
592 	case UREQ(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
593 		DPRINTF(("umouse synch frame"));
594 		break;
595 
596 	/* HID device requests */
597 
598 	case UREQ(UMOUSE_GET_REPORT, UT_READ_CLASS_INTERFACE):
599 		DPRINTF(("umouse: (UMOUSE_GET_REPORT, UT_READ_CLASS_INTERFACE) "
600 		         "0x%x", (value >> 8)));
601 		if (!data)
602 			break;
603 
604 		if ((value >> 8) == 0x01 && len >= sizeof(sc->um_report)) {
605 			/* TODO read from backend */
606 
607 			if (len > sizeof(sc->um_report)) {
608 				data->blen = len - sizeof(sc->um_report);
609 				len = sizeof(sc->um_report);
610 			} else
611 				data->blen = 0;
612 
613 			memcpy(data->buf, &sc->um_report, len);
614 			data->bdone += len;
615 		} else {
616 			err = USB_ERR_STALLED;
617 			goto done;
618 		}
619 		eshort = data->blen > 0;
620 		break;
621 
622 	case UREQ(UMOUSE_GET_IDLE, UT_READ_CLASS_INTERFACE):
623 		if (data != NULL && len > 0) {
624 			*udata = sc->hid.idle;
625 			data->blen = len - 1;
626 			data->bdone += 1;
627 		}
628 		eshort = data->blen > 0;
629 		break;
630 
631 	case UREQ(UMOUSE_GET_PROTOCOL, UT_READ_CLASS_INTERFACE):
632 		if (data != NULL && len > 0) {
633 			*udata = sc->hid.protocol;
634 			data->blen = len - 1;
635 			data->bdone += 1;
636 		}
637 		eshort = data->blen > 0;
638 		break;
639 
640 	case UREQ(UMOUSE_SET_REPORT, UT_WRITE_CLASS_INTERFACE):
641 		DPRINTF(("umouse: (UMOUSE_SET_REPORT, UT_WRITE_CLASS_INTERFACE) ignored"));
642 		break;
643 
644 	case UREQ(UMOUSE_SET_IDLE, UT_WRITE_CLASS_INTERFACE):
645 		sc->hid.idle = UGETW(xfer->ureq->wValue) >> 8;
646 		DPRINTF(("umouse: (UMOUSE_SET_IDLE, UT_WRITE_CLASS_INTERFACE) %x",
647 		        sc->hid.idle));
648 		break;
649 
650 	case UREQ(UMOUSE_SET_PROTOCOL, UT_WRITE_CLASS_INTERFACE):
651 		sc->hid.protocol = UGETW(xfer->ureq->wValue) >> 8;
652 		DPRINTF(("umouse: (UR_CLEAR_FEATURE, UT_WRITE_CLASS_INTERFACE) %x",
653 		        sc->hid.protocol));
654 		break;
655 
656 	default:
657 		DPRINTF(("**** umouse request unhandled"));
658 		err = USB_ERR_STALLED;
659 		break;
660 	}
661 
662 done:
663 /* UT_WRITE is 0, so this is condition is never true. */
664 #ifdef __FreeBSD__
665 	if (xfer->ureq && (xfer->ureq->bmRequestType & UT_WRITE) &&
666 	    (err == USB_ERR_NORMAL_COMPLETION) && (data != NULL))
667 		data->blen = 0;
668 	else if (eshort)
669 		err = USB_ERR_SHORT_XFER;
670 #else
671 	if (eshort)
672 		err = USB_ERR_SHORT_XFER;
673 #endif
674 
675 
676 	DPRINTF(("umouse request error code %d (0=ok), blen %u txlen %u",
677 	        err, (data ? data->blen : 0), (data ? data->bdone : 0)));
678 
679 	return (err);
680 }
681 
682 static int
umouse_data_handler(void * scarg,struct usb_data_xfer * xfer,int dir,int epctx)683 umouse_data_handler(void *scarg, struct usb_data_xfer *xfer, int dir,
684      int epctx)
685 {
686 	struct umouse_softc *sc;
687 	struct usb_data_xfer_block *data;
688 	uint8_t *udata;
689 	int len, i, idx;
690 	int err;
691 
692 	DPRINTF(("umouse handle data - DIR=%s|EP=%d, blen %d",
693 	        dir ? "IN" : "OUT", epctx, xfer->data[0].blen));
694 
695 
696 	/* find buffer to add data */
697 	udata = NULL;
698 	err = USB_ERR_NORMAL_COMPLETION;
699 
700 	/* handle xfer at first unprocessed item with buffer */
701 	data = NULL;
702 	idx = xfer->head;
703 	for (i = 0; i < xfer->ndata; i++) {
704 		data = &xfer->data[idx];
705 		if (data->buf != NULL && data->blen != 0) {
706 			break;
707 		} else {
708 			data->processed = 1;
709 			data = NULL;
710 		}
711 		idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
712 	}
713 	if (!data)
714 		goto done;
715 
716 	udata = data->buf;
717 	len = data->blen;
718 
719 	if (udata == NULL) {
720 		DPRINTF(("umouse no buffer provided for input"));
721 		err = USB_ERR_NOMEM;
722 		goto done;
723 	}
724 
725 	sc = scarg;
726 
727 	if (dir) {
728 
729 		pthread_mutex_lock(&sc->mtx);
730 
731 		if (!sc->newdata) {
732 			err = USB_ERR_CANCELLED;
733 			USB_DATA_SET_ERRCODE(&xfer->data[xfer->head], USB_NAK);
734 			pthread_mutex_unlock(&sc->mtx);
735 			goto done;
736 		}
737 
738 		if (sc->polling) {
739 			err = USB_ERR_STALLED;
740 			USB_DATA_SET_ERRCODE(data, USB_STALL);
741 			pthread_mutex_unlock(&sc->mtx);
742 			goto done;
743 		}
744 		sc->polling = 1;
745 
746 		if (len > 0) {
747 			sc->newdata = 0;
748 
749 			data->processed = 1;
750 			data->bdone += 6;
751 			memcpy(udata, &sc->um_report, 6);
752 			data->blen = len - 6;
753 			if (data->blen > 0)
754 				err = USB_ERR_SHORT_XFER;
755 		}
756 
757 		sc->polling = 0;
758 		pthread_mutex_unlock(&sc->mtx);
759 	} else {
760 		USB_DATA_SET_ERRCODE(data, USB_STALL);
761 		err = USB_ERR_STALLED;
762 	}
763 
764 done:
765 	return (err);
766 }
767 
768 static int
umouse_reset(void * scarg)769 umouse_reset(void *scarg)
770 {
771 	struct umouse_softc *sc;
772 
773 	sc = scarg;
774 
775 	sc->newdata = 0;
776 
777 	return (0);
778 }
779 
780 static int
umouse_remove(void * scarg)781 umouse_remove(void *scarg)
782 {
783 
784 	return (0);
785 }
786 
787 static int
umouse_stop(void * scarg)788 umouse_stop(void *scarg)
789 {
790 
791 	return (0);
792 }
793 
794 
795 static struct usb_devemu ue_mouse = {
796 	.ue_emu =	"tablet",
797 	.ue_usbver =	3,
798 	.ue_usbspeed =	USB_SPEED_HIGH,
799 	.ue_init =	umouse_init,
800 	.ue_request =	umouse_request,
801 	.ue_data =	umouse_data_handler,
802 	.ue_reset =	umouse_reset,
803 	.ue_remove =	umouse_remove,
804 	.ue_stop =	umouse_stop
805 };
806 USB_EMUL_SET(ue_mouse);
807