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