1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright 2013, Michael Terrell <vashisnotatree@gmail.com> 5 * Copyright 2018, Johannes Lundberg <johalun0@gmail.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/module.h> 34 #include <sys/kernel.h> 35 #include <sys/systm.h> 36 37 #include <sys/conf.h> 38 #include <sys/bus.h> 39 #include <sys/lock.h> 40 #include <sys/mutex.h> 41 #include <sys/syslog.h> 42 #include <sys/fcntl.h> 43 44 #include <dev/usb/usb.h> 45 #include <dev/usb/usbdi.h> 46 #include <dev/usb/usbdi_util.h> 47 48 #include <dev/usb/usbhid.h> 49 #include <dev/usb/usb_ioctl.h> 50 51 #include "usb_rdesc.h" 52 53 #define UHID_SNES_IFQ_MAX_LEN 8 54 55 #define UREQ_GET_PORT_STATUS 0x01 56 #define UREQ_SOFT_RESET 0x02 57 58 #define UP 0x7f00 59 #define DOWN 0x7fff 60 #define LEFT 0x00ff 61 #define RIGHT 0xff7f 62 #define X 0x1f 63 #define Y 0x8f 64 #define A 0x2f 65 #define B 0x4f 66 #define SELECT 0x10 67 #define START 0x20 68 #define LEFT_T 0x01 69 #define RIGHT_T 0x02 70 71 static const uint8_t uhid_snes_report_descr[] = { UHID_SNES_REPORT_DESCR() }; 72 #define SNES_DEV(v,p,i) { USB_VPI(v,p,i) } 73 74 static const STRUCT_USB_HOST_ID snes_devs[] = { 75 SNES_DEV(0x0810, 0xe501, 0), /* GeeekPi K-0161 */ 76 SNES_DEV(0x0079, 0x0011, 0) /* Dragonrise */ 77 }; 78 79 enum { 80 UHID_SNES_INTR_DT_RD, 81 UHID_SNES_STATUS_DT_RD, 82 UHID_SNES_N_TRANSFER 83 }; 84 85 struct uhid_snes_softc { 86 device_t sc_dev; 87 struct usb_device *sc_usb_device; 88 struct mtx sc_mutex; 89 struct usb_callout sc_watchdog; 90 uint8_t sc_iface_num; 91 struct usb_xfer *sc_transfer[UHID_SNES_N_TRANSFER]; 92 struct usb_fifo_sc sc_fifo; 93 struct usb_fifo_sc sc_fifo_no_reset; 94 int sc_fflags; 95 struct usb_fifo *sc_fifo_open[2]; 96 uint8_t sc_zero_length_packets; 97 uint8_t sc_previous_status; 98 uint8_t sc_iid; 99 uint8_t sc_oid; 100 uint8_t sc_fid; 101 uint8_t sc_iface_index; 102 103 uint32_t sc_isize; 104 uint32_t sc_osize; 105 uint32_t sc_fsize; 106 107 void *sc_repdesc_ptr; 108 109 uint16_t sc_repdesc_size; 110 111 struct usb_device *sc_udev; 112 #define UHID_FLAG_IMMED 0x01 /* set if read should be immediate */ 113 114 }; 115 116 static device_probe_t uhid_snes_probe; 117 static device_attach_t uhid_snes_attach; 118 static device_detach_t uhid_snes_detach; 119 120 static usb_fifo_open_t uhid_snes_open; 121 static usb_fifo_close_t uhid_snes_close; 122 static usb_fifo_ioctl_t uhid_snes_ioctl; 123 static usb_fifo_cmd_t uhid_snes_start_read; 124 static usb_fifo_cmd_t uhid_snes_stop_read; 125 126 static void uhid_snes_reset(struct uhid_snes_softc *); 127 static void uhid_snes_watchdog(void *); 128 129 static usb_callback_t uhid_snes_read_callback; 130 static usb_callback_t uhid_snes_status_callback; 131 132 static struct usb_fifo_methods uhid_snes_fifo_methods = { 133 .f_open = &uhid_snes_open, 134 .f_close = &uhid_snes_close, 135 .f_ioctl = &uhid_snes_ioctl, 136 .f_start_read = &uhid_snes_start_read, 137 .f_stop_read = &uhid_snes_stop_read, 138 .basename[0] = "uhid_snes" 139 }; 140 141 static const struct usb_config uhid_snes_config[UHID_SNES_N_TRANSFER] = { 142 [UHID_SNES_INTR_DT_RD] = { 143 .callback = &uhid_snes_read_callback, 144 .bufsize = sizeof(struct usb_device_request) +1, 145 .flags = {.short_xfer_ok = 1, .short_frames_ok = 1, 146 .pipe_bof =1, .proxy_buffer =1}, 147 .type = UE_INTERRUPT, 148 .endpoint = 0x81, 149 .direction = UE_DIR_IN 150 }, 151 [UHID_SNES_STATUS_DT_RD] = { 152 .callback = &uhid_snes_status_callback, 153 .bufsize = sizeof(struct usb_device_request) + 1, 154 .timeout = 1000, 155 .type = UE_CONTROL, 156 .endpoint = 0x00, 157 .direction = UE_DIR_ANY 158 } 159 }; 160 161 static int 162 uhid_get_report(struct uhid_snes_softc *sc, uint8_t type, 163 uint8_t id, void *kern_data, void *user_data, uint16_t len) 164 { 165 int err; 166 uint8_t free_data = 0; 167 168 if (kern_data == NULL) { 169 kern_data = malloc(len, M_USBDEV, M_WAITOK); 170 free_data = 1; 171 } 172 err = usbd_req_get_report(sc->sc_udev, NULL, kern_data, 173 len, sc->sc_iface_index, type, id); 174 if (err) { 175 err = ENXIO; 176 goto done; 177 } 178 if (user_data) { 179 /* dummy buffer */ 180 err = copyout(kern_data, user_data, len); 181 if (err) { 182 goto done; 183 } 184 } 185 done: 186 if (free_data) { 187 free(kern_data, M_USBDEV); 188 } 189 return (err); 190 } 191 192 static int 193 uhid_set_report(struct uhid_snes_softc *sc, uint8_t type, 194 uint8_t id, void *kern_data, void *user_data, uint16_t len) 195 { 196 int err; 197 uint8_t free_data = 0; 198 199 if (kern_data == NULL) { 200 kern_data = malloc(len, M_USBDEV, M_WAITOK); 201 free_data = 1; 202 err = copyin(user_data, kern_data, len); 203 if (err) { 204 goto done; 205 } 206 } 207 err = usbd_req_set_report(sc->sc_udev, NULL, kern_data, 208 len, sc->sc_iface_index, type, id); 209 if (err) { 210 err = ENXIO; 211 goto done; 212 } 213 done: 214 if (free_data) { 215 free(kern_data, M_USBDEV); 216 } 217 return (err); 218 } 219 220 static int 221 uhid_snes_open(struct usb_fifo *fifo, int fflags) 222 { 223 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 224 int error; 225 226 if (sc->sc_fflags & fflags) { 227 uhid_snes_reset(sc); 228 return (EBUSY); 229 } 230 231 mtx_lock(&sc->sc_mutex); 232 usbd_xfer_set_stall(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 233 mtx_unlock(&sc->sc_mutex); 234 235 error = usb_fifo_alloc_buffer(fifo, 236 usbd_xfer_max_len(sc->sc_transfer[UHID_SNES_INTR_DT_RD]), 237 UHID_SNES_IFQ_MAX_LEN); 238 if (error) 239 return (ENOMEM); 240 241 sc->sc_fifo_open[USB_FIFO_RX] = fifo; 242 243 return (0); 244 } 245 246 static void 247 uhid_snes_reset(struct uhid_snes_softc *sc) 248 { 249 struct usb_device_request req; 250 int error; 251 252 req.bRequest = UREQ_SOFT_RESET; 253 USETW(req.wValue, 0); 254 USETW(req.wIndex, sc->sc_iface_num); 255 USETW(req.wLength, 0); 256 257 mtx_lock(&sc->sc_mutex); 258 259 error = usbd_do_request_flags(sc->sc_usb_device, &sc->sc_mutex, 260 &req, NULL, 0, NULL, 2 * USB_MS_HZ); 261 262 if (error) { 263 usbd_do_request_flags(sc->sc_usb_device, &sc->sc_mutex, 264 &req, NULL, 0, NULL, 2 * USB_MS_HZ); 265 } 266 267 mtx_unlock(&sc->sc_mutex); 268 } 269 270 static void 271 uhid_snes_close(struct usb_fifo *fifo, int fflags) 272 { 273 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 274 275 sc->sc_fflags &= ~(fflags & FREAD); 276 usb_fifo_free_buffer(fifo); 277 } 278 279 static int 280 uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags) 281 { 282 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 283 struct usb_gen_descriptor *ugd; 284 #ifdef COMPAT_FREEBSD32 285 struct usb_gen_descriptor local_ugd; 286 struct usb_gen_descriptor32 *ugd32 = NULL; 287 #endif 288 uint32_t size; 289 int error = 0; 290 uint8_t id; 291 292 ugd = data; 293 #ifdef COMPAT_FREEBSD32 294 switch (cmd) { 295 case USB_GET_REPORT_DESC32: 296 case USB_GET_REPORT32: 297 case USB_SET_REPORT32: 298 ugd32 = data; 299 ugd = &local_ugd; 300 usb_gen_descriptor_from32(ugd, ugd32); 301 cmd = _IOC_NEWTYPE(cmd, struct usb_gen_descriptor); 302 break; 303 } 304 #endif 305 306 switch (cmd) { 307 case USB_GET_REPORT_DESC: 308 if (sc->sc_repdesc_size > ugd->ugd_maxlen) { 309 size = ugd->ugd_maxlen; 310 } else { 311 size = sc->sc_repdesc_size; 312 } 313 314 ugd->ugd_actlen = size; 315 if (ugd->ugd_data == NULL) 316 break; /* descriptor length only*/ 317 error = copyout(sc->sc_repdesc_ptr, ugd->ugd_data, size); 318 break; 319 320 case USB_SET_IMMED: 321 if (!(fflags & FREAD)) { 322 error = EPERM; 323 break; 324 } 325 326 if (*(int *)data) { 327 /* do a test read */ 328 error = uhid_get_report(sc, UHID_INPUT_REPORT, 329 sc->sc_iid, NULL, NULL, sc->sc_isize); 330 if (error) { 331 break; 332 } 333 mtx_lock(&sc->sc_mutex); 334 sc->sc_fflags |= UHID_FLAG_IMMED; 335 mtx_unlock(&sc->sc_mutex); 336 } else { 337 mtx_lock(&sc->sc_mutex); 338 sc->sc_fflags &= ~UHID_FLAG_IMMED; 339 mtx_unlock(&sc->sc_mutex); 340 } 341 break; 342 343 case USB_GET_REPORT: 344 if (!(fflags & FREAD)) { 345 error = EPERM; 346 break; 347 } 348 switch (ugd->ugd_report_type) { 349 case UHID_INPUT_REPORT: 350 size = sc->sc_isize; 351 id = sc->sc_iid; 352 break; 353 case UHID_OUTPUT_REPORT: 354 size = sc->sc_osize; 355 id = sc->sc_oid; 356 break; 357 case UHID_FEATURE_REPORT: 358 size = sc->sc_fsize; 359 id = sc->sc_fid; 360 break; 361 default: 362 return (EINVAL); 363 } 364 if (id != 0) 365 copyin(ugd->ugd_data, &id, 1); 366 error = uhid_get_report(sc, ugd->ugd_report_type, id, 367 NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); 368 break; 369 370 case USB_SET_REPORT: 371 if (!(fflags & FWRITE)) { 372 error = EPERM; 373 break; 374 } 375 switch (ugd->ugd_report_type) { 376 case UHID_INPUT_REPORT: 377 size = sc->sc_isize; 378 id = sc->sc_iid; 379 break; 380 case UHID_OUTPUT_REPORT: 381 size = sc->sc_osize; 382 id = sc->sc_oid; 383 break; 384 case UHID_FEATURE_REPORT: 385 size = sc->sc_fsize; 386 id = sc->sc_fid; 387 break; 388 default: 389 return (EINVAL); 390 } 391 if (id != 0) 392 copyin(ugd->ugd_data, &id, 1); 393 error = uhid_set_report(sc, ugd->ugd_report_type, id, 394 NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); 395 break; 396 397 case USB_GET_REPORT_ID: 398 /* XXX: we only support reportid 0? */ 399 *(int *)data = 0; 400 break; 401 402 default: 403 error = EINVAL; 404 break; 405 } 406 407 #ifdef COMPAT_FREEBSD32 408 if (ugd32 != NULL) 409 update_usb_gen_descriptor32(ugd32, ugd); 410 #endif 411 return (error); 412 } 413 414 static void 415 uhid_snes_watchdog(void *arg) 416 { 417 struct uhid_snes_softc *sc = arg; 418 419 mtx_assert(&sc->sc_mutex, MA_OWNED); 420 421 if (sc->sc_fflags == 0) 422 usbd_transfer_start(sc->sc_transfer[UHID_SNES_STATUS_DT_RD]); 423 424 usb_callout_reset(&sc->sc_watchdog, hz, &uhid_snes_watchdog, sc); 425 } 426 427 static void 428 uhid_snes_start_read(struct usb_fifo *fifo) 429 { 430 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 431 432 usbd_transfer_start(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 433 } 434 435 static void 436 uhid_snes_stop_read(struct usb_fifo *fifo) 437 { 438 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 439 440 usbd_transfer_stop(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 441 } 442 443 static void 444 uhid_snes_read_callback(struct usb_xfer *transfer, usb_error_t error) 445 { 446 struct uhid_snes_softc *sc = usbd_xfer_softc(transfer); 447 struct usb_fifo *fifo = sc->sc_fifo_open[USB_FIFO_RX]; 448 struct usb_page_cache *pc; 449 int actual, max; 450 451 usbd_xfer_status(transfer, &actual, NULL, NULL, NULL); 452 if (fifo == NULL) 453 return; 454 455 switch (USB_GET_STATE(transfer)) { 456 case USB_ST_TRANSFERRED: 457 if (actual == 0) { 458 if (sc->sc_zero_length_packets == 4) 459 /* Throttle transfers. */ 460 usbd_xfer_set_interval(transfer, 500); 461 else 462 sc->sc_zero_length_packets++; 463 464 } else { 465 /* disable throttling. */ 466 usbd_xfer_set_interval(transfer, 0); 467 sc->sc_zero_length_packets = 0; 468 } 469 pc = usbd_xfer_get_frame(transfer, 0); 470 usb_fifo_put_data(fifo, pc, 0, actual, 1); 471 /* Fall through */ 472 setup: 473 case USB_ST_SETUP: 474 if (usb_fifo_put_bytes_max(fifo) != 0) { 475 max = usbd_xfer_max_len(transfer); 476 usbd_xfer_set_frame_len(transfer, 0, max); 477 usbd_transfer_submit(transfer); 478 } 479 break; 480 481 default: 482 /*disable throttling. */ 483 usbd_xfer_set_interval(transfer, 0); 484 sc->sc_zero_length_packets = 0; 485 486 if (error != USB_ERR_CANCELLED) { 487 /* Issue a clear-stall request. */ 488 usbd_xfer_set_stall(transfer); 489 goto setup; 490 } 491 break; 492 } 493 } 494 495 static void 496 uhid_snes_status_callback(struct usb_xfer *transfer, usb_error_t error) 497 { 498 struct uhid_snes_softc *sc = usbd_xfer_softc(transfer); 499 struct usb_device_request req; 500 struct usb_page_cache *pc; 501 uint8_t current_status, new_status; 502 503 switch (USB_GET_STATE(transfer)) { 504 case USB_ST_SETUP: 505 req.bmRequestType = UT_READ_CLASS_INTERFACE; 506 req.bRequest = UREQ_GET_PORT_STATUS; 507 USETW(req.wValue, 0); 508 req.wIndex[0] = sc->sc_iface_num; 509 req.wIndex[1] = 0; 510 USETW(req.wLength, 1); 511 512 pc = usbd_xfer_get_frame(transfer, 0); 513 usbd_copy_in(pc, 0, &req, sizeof(req)); 514 usbd_xfer_set_frame_len(transfer, 0, sizeof(req)); 515 usbd_xfer_set_frame_len(transfer, 1, 1); 516 usbd_xfer_set_frames(transfer, 2); 517 usbd_transfer_submit(transfer); 518 break; 519 520 case USB_ST_TRANSFERRED: 521 pc = usbd_xfer_get_frame(transfer, 1); 522 usbd_copy_out(pc, 0, ¤t_status, 1); 523 new_status = current_status & ~sc->sc_previous_status; 524 sc->sc_previous_status = current_status; 525 break; 526 527 default: 528 break; 529 } 530 531 } 532 533 static int 534 uhid_snes_probe(device_t dev) 535 { 536 struct usb_attach_arg *uaa = device_get_ivars(dev); 537 538 if (uaa->usb_mode != USB_MODE_HOST) 539 return (ENXIO); 540 541 return (usbd_lookup_id_by_uaa(snes_devs, sizeof(snes_devs), uaa)); 542 } 543 544 static int 545 uhid_snes_attach(device_t dev) 546 { 547 struct usb_attach_arg *uaa = device_get_ivars(dev); 548 struct uhid_snes_softc *sc = device_get_softc(dev); 549 struct usb_interface_descriptor *idesc; 550 struct usb_config_descriptor *cdesc; 551 uint8_t alt_index, iface_index = uaa->info.bIfaceIndex; 552 int error,unit = device_get_unit(dev); 553 554 sc->sc_dev = dev; 555 sc->sc_usb_device = uaa->device; 556 device_set_usb_desc(dev); 557 mtx_init(&sc->sc_mutex, "uhid_snes", NULL, MTX_DEF | MTX_RECURSE); 558 usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mutex, 0); 559 560 idesc = usbd_get_interface_descriptor(uaa->iface); 561 alt_index = -1; 562 for(;;) { 563 if (idesc == NULL) 564 break; 565 566 if ((idesc->bDescriptorType == UDESC_INTERFACE) && 567 (idesc->bLength >= sizeof(*idesc))) { 568 if (idesc->bInterfaceNumber != uaa->info.bIfaceNum) { 569 break; 570 } else { 571 alt_index++; 572 if (idesc->bInterfaceClass == UICLASS_HID) 573 goto found; 574 } 575 } 576 577 cdesc = usbd_get_config_descriptor(uaa->device); 578 idesc = (void *)usb_desc_foreach(cdesc, (void *)idesc); 579 goto found; 580 } 581 goto detach; 582 583 found: 584 if (alt_index) { 585 error = usbd_set_alt_interface_index(uaa->device, iface_index, alt_index); 586 if (error) 587 goto detach; 588 } 589 590 sc->sc_iface_num = idesc->bInterfaceNumber; 591 592 error = usbd_transfer_setup(uaa->device, &iface_index, 593 sc->sc_transfer, uhid_snes_config, UHID_SNES_N_TRANSFER, sc, 594 &sc->sc_mutex); 595 596 if (error) 597 goto detach; 598 599 error = usb_fifo_attach(uaa->device, sc, &sc->sc_mutex, 600 &uhid_snes_fifo_methods, &sc->sc_fifo, unit, -1, 601 iface_index, UID_ROOT, GID_OPERATOR, 0644); 602 sc->sc_repdesc_size = sizeof(uhid_snes_report_descr); 603 sc->sc_repdesc_ptr = __DECONST(void*, &uhid_snes_report_descr); 604 605 if (error) 606 goto detach; 607 608 mtx_lock(&sc->sc_mutex); 609 uhid_snes_watchdog(sc); 610 mtx_unlock(&sc->sc_mutex); 611 return (0); 612 613 detach: 614 uhid_snes_detach(dev); 615 return (ENOMEM); 616 } 617 618 static int 619 uhid_snes_detach(device_t dev) 620 { 621 struct uhid_snes_softc *sc = device_get_softc(dev); 622 623 usb_fifo_detach(&sc->sc_fifo); 624 usb_fifo_detach(&sc->sc_fifo_no_reset); 625 626 mtx_lock(&sc->sc_mutex); 627 usb_callout_stop(&sc->sc_watchdog); 628 mtx_unlock(&sc->sc_mutex); 629 630 usbd_transfer_unsetup(sc->sc_transfer, UHID_SNES_N_TRANSFER); 631 usb_callout_drain(&sc->sc_watchdog); 632 mtx_destroy(&sc->sc_mutex); 633 634 return (0); 635 } 636 637 static device_method_t uhid_snes_methods[] = { 638 DEVMETHOD(device_probe, uhid_snes_probe), 639 DEVMETHOD(device_attach, uhid_snes_attach), 640 DEVMETHOD(device_detach, uhid_snes_detach), 641 DEVMETHOD_END 642 }; 643 644 static driver_t uhid_snes_driver = { 645 "uhid_snes", 646 uhid_snes_methods, 647 sizeof(struct uhid_snes_softc) 648 }; 649 650 static devclass_t uhid_snes_devclass; 651 652 DRIVER_MODULE(uhid_snes, uhub, uhid_snes_driver, uhid_snes_devclass, NULL, 0); 653 MODULE_DEPEND(uhid_snes, usb, 1, 1, 1); 654 USB_PNP_HOST_INFO(snes_devs); 655