1 /*- 2 * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 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 44 static int umouse_debug = 0; 45 #define DPRINTF(params) if (umouse_debug) printf params 46 #define WPRINTF(params) printf params 47 48 /* USB endpoint context (1-15) for reporting mouse data events*/ 49 #define UMOUSE_INTR_ENDPT 1 50 51 #define UMOUSE_REPORT_DESC_TYPE 0x22 52 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 59 60 #define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) } 61 62 enum { 63 UMSTR_LANG, 64 UMSTR_MANUFACTURER, 65 UMSTR_PRODUCT, 66 UMSTR_SERIAL, 67 UMSTR_CONFIG, 68 UMSTR_MAX 69 }; 70 71 static const char *umouse_desc_strings[] = { 72 "\x04\x09", 73 "BHYVE", 74 "HID Tablet", 75 "01", 76 "HID Tablet Device", 77 }; 78 79 struct umouse_hid_descriptor { 80 uint8_t bLength; 81 uint8_t bDescriptorType; 82 uint8_t bcdHID[2]; 83 uint8_t bCountryCode; 84 uint8_t bNumDescriptors; 85 uint8_t bReportDescriptorType; 86 uint8_t wItemLength[2]; 87 } __packed; 88 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; 95 } __packed; 96 97 #define MOUSE_MAX_X 0x8000 98 #define MOUSE_MAX_Y 0x8000 99 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 */ 138 }; 139 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 */ 145 } __packed; 146 147 148 #define MSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) } 149 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, 162 }; 163 164 static struct umouse_config_desc umouse_confd = { 165 .confd = { 166 .bLength = sizeof(umouse_confd.confd), 167 .bDescriptorType = UDESC_CONFIG, 168 .wTotalLength[0] = sizeof(umouse_confd), 169 .bNumInterface = 1, 170 .bConfigurationValue = 1, 171 .iConfiguration = UMSTR_CONFIG, 172 .bmAttributes = UC_BUS_POWERED | UC_REMOTE_WAKEUP, 173 .bMaxPower = 0, 174 }, 175 .ifcd = { 176 .bLength = sizeof(umouse_confd.ifcd), 177 .bDescriptorType = UDESC_INTERFACE, 178 .bNumEndpoints = 1, 179 .bInterfaceClass = UICLASS_HID, 180 .bInterfaceSubClass = UISUBCLASS_BOOT, 181 .bInterfaceProtocol = UIPROTO_MOUSE, 182 }, 183 .hidd = { 184 .bLength = sizeof(umouse_confd.hidd), 185 .bDescriptorType = 0x21, 186 .bcdHID = { 0x01, 0x10 }, 187 .bCountryCode = 0, 188 .bNumDescriptors = 1, 189 .bReportDescriptorType = UMOUSE_REPORT_DESC_TYPE, 190 .wItemLength = { sizeof(umouse_report_desc), 0 }, 191 }, 192 .endpd = { 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, 198 .bInterval = 0xA, 199 }, 200 .sscompd = { 201 .bLength = sizeof(umouse_confd.sscompd), 202 .bDescriptorType = UDESC_ENDPOINT_SS_COMP, 203 .bMaxBurst = 0, 204 .bmAttributes = 0, 205 MSETW(.wBytesPerInterval, 0), 206 }, 207 }; 208 209 210 struct umouse_bos_desc { 211 struct usb_bos_descriptor bosd; 212 struct usb_devcap_ss_descriptor usbssd; 213 } __packed; 214 215 216 struct umouse_bos_desc umouse_bosd = { 217 .bosd = { 218 .bLength = sizeof(umouse_bosd.bosd), 219 .bDescriptorType = UDESC_BOS, 220 HSETW(.wTotalLength, sizeof(umouse_bosd)), 221 .bNumDeviceCaps = 1, 222 }, 223 .usbssd = { 224 .bLength = sizeof(umouse_bosd.usbssd), 225 .bDescriptorType = UDESC_DEVICE_CAPABILITY, 226 .bDevCapabilityType = 3, 227 .bmAttributes = 0, 228 HSETW(.wSpeedsSupported, 0x08), 229 .bFunctionalitySupport = 3, 230 .bU1DevExitLat = 0xa, /* dummy - not used */ 231 .wU2DevExitLat = { 0x20, 0x00 }, 232 } 233 }; 234 235 236 struct umouse_softc { 237 struct usb_hci *hci; 238 239 char *opt; 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_X * 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, char *opt) 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 sc->opt = strdup(opt); 306 pthread_mutex_init(&sc->mtx, NULL); 307 pthread_mutex_init(&sc->ev_mtx, NULL); 308 309 console_ptr_register(umouse_event, sc, 10); 310 311 return (sc); 312 } 313 314 #define UREQ(x,y) ((x) | ((y) << 8)) 315 316 static int 317 umouse_request(void *scarg, struct usb_data_xfer *xfer) 318 { 319 struct umouse_softc *sc; 320 struct usb_data_xfer_block *data; 321 const char *str; 322 uint16_t value; 323 uint16_t index; 324 uint16_t len; 325 uint16_t slen; 326 uint8_t *udata; 327 int err; 328 int i, idx; 329 int eshort; 330 331 sc = scarg; 332 333 data = NULL; 334 udata = NULL; 335 idx = xfer->head; 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]; 340 udata = data->buf; 341 } 342 343 xfer->data[idx].processed = 1; 344 idx = (idx + 1) % USB_MAX_XFER_BLOCKS; 345 } 346 347 err = USB_ERR_NORMAL_COMPLETION; 348 eshort = 0; 349 350 if (!xfer->ureq) { 351 DPRINTF(("umouse_request: port %d\r\n", sc->hci->hci_port)); 352 goto done; 353 } 354 355 value = UGETW(xfer->ureq->wValue); 356 index = UGETW(xfer->ureq->wIndex); 357 len = UGETW(xfer->ureq->wLength); 358 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)); 363 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")); 367 if (!data) 368 break; 369 370 *udata = umouse_confd.confd.bConfigurationValue; 371 data->blen = len > 0 ? len - 1 : 0; 372 eshort = data->blen > 0; 373 data->bdone += 1; 374 break; 375 376 case UREQ(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 377 DPRINTF(("umouse: (UR_GET_DESCRIPTOR, UT_READ_DEVICE) val %x\r\n", 378 value >> 8)); 379 if (!data) 380 break; 381 382 switch (value >> 8) { 383 case UDESC_DEVICE: 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; 389 goto done; 390 } 391 if (len > sizeof(umouse_dev_desc)) { 392 data->blen = len - sizeof(umouse_dev_desc); 393 len = sizeof(umouse_dev_desc); 394 } else 395 data->blen = 0; 396 memcpy(data->buf, &umouse_dev_desc, len); 397 data->bdone += len; 398 break; 399 400 case UDESC_CONFIG: 401 DPRINTF(("umouse: (->UDESC_CONFIG)\r\n")); 402 if ((value & 0xFF) != 0) { 403 err = USB_ERR_IOERROR; 404 goto done; 405 } 406 if (len > sizeof(umouse_confd)) { 407 data->blen = len - sizeof(umouse_confd); 408 len = sizeof(umouse_confd); 409 } else 410 data->blen = 0; 411 412 memcpy(data->buf, &umouse_confd, len); 413 data->bdone += len; 414 break; 415 416 case UDESC_STRING: 417 DPRINTF(("umouse: (->UDESC_STRING)\r\n")); 418 str = NULL; 419 if ((value & 0xFF) < UMSTR_MAX) 420 str = umouse_desc_strings[value & 0xFF]; 421 else 422 goto done; 423 424 if ((value & 0xFF) == UMSTR_LANG) { 425 udata[0] = 4; 426 udata[1] = UDESC_STRING; 427 data->blen = len - 2; 428 len -= 2; 429 data->bdone += 2; 430 431 if (len >= 2) { 432 udata[2] = str[0]; 433 udata[3] = str[1]; 434 data->blen -= 2; 435 data->bdone += 2; 436 } else 437 data->blen = 0; 438 439 goto done; 440 } 441 442 slen = 2 + strlen(str) * 2; 443 udata[0] = slen; 444 udata[1] = UDESC_STRING; 445 446 if (len > slen) { 447 data->blen = len - slen; 448 len = slen; 449 } else 450 data->blen = 0; 451 for (i = 2; i < len; i += 2) { 452 udata[i] = *str++; 453 udata[i+1] = '\0'; 454 } 455 data->bdone += slen; 456 457 break; 458 459 case UDESC_BOS: 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); 464 } else 465 data->blen = 0; 466 memcpy(udata, &umouse_bosd, len); 467 data->bdone += len; 468 break; 469 470 default: 471 DPRINTF(("umouse: unknown(%d)->ERROR\r\n", value >> 8)); 472 err = USB_ERR_IOERROR; 473 goto done; 474 } 475 eshort = data->blen > 0; 476 break; 477 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))); 481 if (!data) 482 break; 483 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); 489 } else 490 data->blen = 0; 491 memcpy(data->buf, umouse_report_desc, len); 492 data->bdone += len; 493 break; 494 default: 495 DPRINTF(("umouse: IO ERROR\r\n")); 496 err = USB_ERR_IOERROR; 497 goto done; 498 } 499 eshort = data->blen > 0; 500 break; 501 502 case UREQ(UR_GET_INTERFACE, UT_READ_INTERFACE): 503 DPRINTF(("umouse: (UR_GET_INTERFACE, UT_READ_INTERFACE)\r\n")); 504 if (index != 0) { 505 DPRINTF(("umouse get_interface, invalid index %d\r\n", 506 index)); 507 err = USB_ERR_IOERROR; 508 goto done; 509 } 510 511 if (!data) 512 break; 513 514 if (len > 0) { 515 *udata = 0; 516 data->blen = len - 1; 517 } 518 eshort = data->blen > 0; 519 data->bdone += 1; 520 break; 521 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); 527 else 528 USETW(udata, 0); 529 data->blen = len - 2; 530 data->bdone += 2; 531 } 532 533 eshort = data->blen > 0; 534 break; 535 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) { 540 USETW(udata, 0); 541 data->blen = len - 2; 542 data->bdone += 2; 543 } 544 eshort = data->blen > 0; 545 break; 546 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)); 550 break; 551 552 case UREQ(UR_SET_CONFIG, UT_WRITE_DEVICE): 553 DPRINTF(("umouse set config %u\r\n", value)); 554 break; 555 556 case UREQ(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): 557 DPRINTF(("umouse set descriptor %u\r\n", value)); 558 break; 559 560 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) 564 sc->hid.feature = 0; 565 break; 566 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; 571 break; 572 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; 579 goto done; 580 581 case UREQ(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 582 DPRINTF(("umouse set interface %u\r\n", value)); 583 break; 584 585 case UREQ(UR_ISOCH_DELAY, UT_WRITE_DEVICE): 586 DPRINTF(("umouse set isoch delay %u\r\n", value)); 587 break; 588 589 case UREQ(UR_SET_SEL, 0): 590 DPRINTF(("umouse set sel\r\n")); 591 break; 592 593 case UREQ(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): 594 DPRINTF(("umouse synch frame\r\n")); 595 break; 596 597 /* HID device requests */ 598 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))); 602 if (!data) 603 break; 604 605 if ((value >> 8) == 0x01 && len >= sizeof(sc->um_report)) { 606 /* TODO read from backend */ 607 608 if (len > sizeof(sc->um_report)) { 609 data->blen = len - sizeof(sc->um_report); 610 len = sizeof(sc->um_report); 611 } else 612 data->blen = 0; 613 614 memcpy(data->buf, &sc->um_report, len); 615 data->bdone += len; 616 } else { 617 err = USB_ERR_IOERROR; 618 goto done; 619 } 620 eshort = data->blen > 0; 621 break; 622 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; 627 data->bdone += 1; 628 } 629 eshort = data->blen > 0; 630 break; 631 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; 636 data->bdone += 1; 637 } 638 eshort = data->blen > 0; 639 break; 640 641 case UREQ(UMOUSE_SET_REPORT, UT_WRITE_CLASS_INTERFACE): 642 DPRINTF(("umouse: (UMOUSE_SET_REPORT, UT_WRITE_CLASS_INTERFACE) ignored\r\n")); 643 break; 644 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", 648 sc->hid.idle)); 649 break; 650 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", 654 sc->hid.protocol)); 655 break; 656 657 default: 658 DPRINTF(("**** umouse request unhandled\r\n")); 659 err = USB_ERR_IOERROR; 660 break; 661 } 662 663 done: 664 if (xfer->ureq && (xfer->ureq->bmRequestType & UT_WRITE) && 665 (err == USB_ERR_NORMAL_COMPLETION) && (data != NULL)) 666 data->blen = 0; 667 else if (eshort) 668 err = USB_ERR_SHORT_XFER; 669 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))); 672 673 return (err); 674 } 675 676 static int 677 umouse_data_handler(void *scarg, struct usb_data_xfer *xfer, int dir, 678 int epctx) 679 { 680 struct umouse_softc *sc; 681 struct usb_data_xfer_block *data; 682 uint8_t *udata; 683 int len, i, idx; 684 int err; 685 686 DPRINTF(("umouse handle data - DIR=%s|EP=%d, blen %d\r\n", 687 dir ? "IN" : "OUT", epctx, xfer->data[0].blen)); 688 689 690 /* find buffer to add data */ 691 udata = NULL; 692 err = USB_ERR_NORMAL_COMPLETION; 693 694 /* handle xfer at first unprocessed item with buffer */ 695 data = NULL; 696 idx = xfer->head; 697 for (i = 0; i < xfer->ndata; i++) { 698 data = &xfer->data[idx]; 699 if (data->buf != NULL && data->blen != 0) { 700 break; 701 } else { 702 data->processed = 1; 703 data = NULL; 704 } 705 idx = (idx + 1) % USB_MAX_XFER_BLOCKS; 706 } 707 if (!data) 708 goto done; 709 710 udata = data->buf; 711 len = data->blen; 712 713 if (udata == NULL) { 714 DPRINTF(("umouse no buffer provided for input\r\n")); 715 err = USB_ERR_NOMEM; 716 goto done; 717 } 718 719 sc = scarg; 720 721 if (dir) { 722 723 pthread_mutex_lock(&sc->mtx); 724 725 if (!sc->newdata) { 726 err = USB_ERR_CANCELLED; 727 USB_DATA_SET_ERRCODE(&xfer->data[xfer->head], USB_NAK); 728 pthread_mutex_unlock(&sc->mtx); 729 goto done; 730 } 731 732 if (sc->polling) { 733 err = USB_ERR_STALLED; 734 USB_DATA_SET_ERRCODE(data, USB_STALL); 735 pthread_mutex_unlock(&sc->mtx); 736 goto done; 737 } 738 sc->polling = 1; 739 740 if (len > 0) { 741 sc->newdata = 0; 742 743 data->processed = 1; 744 data->bdone += 6; 745 memcpy(udata, &sc->um_report, 6); 746 data->blen = len - 6; 747 if (data->blen > 0) 748 err = USB_ERR_SHORT_XFER; 749 } 750 751 sc->polling = 0; 752 pthread_mutex_unlock(&sc->mtx); 753 } else { 754 USB_DATA_SET_ERRCODE(data, USB_STALL); 755 err = USB_ERR_STALLED; 756 } 757 758 done: 759 return (err); 760 } 761 762 static int 763 umouse_reset(void *scarg) 764 { 765 struct umouse_softc *sc; 766 767 sc = scarg; 768 769 sc->newdata = 0; 770 771 return (0); 772 } 773 774 static int 775 umouse_remove(void *scarg) 776 { 777 778 return (0); 779 } 780 781 static int 782 umouse_stop(void *scarg) 783 { 784 785 return (0); 786 } 787 788 789 struct usb_devemu ue_mouse = { 790 .ue_emu = "tablet", 791 .ue_usbver = 3, 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 799 }; 800 USB_EMUL_SET(ue_mouse); 801