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 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 * 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 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 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 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 781 umouse_remove(void *scarg) 782 { 783 784 return (0); 785 } 786 787 static int 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