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