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 73 #define SNES_DEV(v,p,i) { USB_VPI(v,p,i) } 74 75 static const STRUCT_USB_HOST_ID snes_devs[] = { 76 SNES_DEV(0x0810, 0xe501, 0), /* GeeekPi K-0161 */ 77 SNES_DEV(0x0079, 0x0011, 0) /* Dragonrise */ 78 }; 79 80 enum { 81 UHID_SNES_INTR_DT_RD, 82 UHID_SNES_STATUS_DT_RD, 83 UHID_SNES_N_TRANSFER 84 }; 85 86 struct uhid_snes_softc { 87 device_t sc_dev; 88 struct usb_device *sc_usb_device; 89 struct mtx sc_mutex; 90 struct usb_callout sc_watchdog; 91 uint8_t sc_iface_num; 92 struct usb_xfer *sc_transfer[UHID_SNES_N_TRANSFER]; 93 struct usb_fifo_sc sc_fifo; 94 struct usb_fifo_sc sc_fifo_no_reset; 95 int sc_fflags; 96 struct usb_fifo *sc_fifo_open[2]; 97 uint8_t sc_zero_length_packets; 98 uint8_t sc_previous_status; 99 uint8_t sc_iid; 100 uint8_t sc_oid; 101 uint8_t sc_fid; 102 uint8_t sc_iface_index; 103 104 uint32_t sc_isize; 105 uint32_t sc_osize; 106 uint32_t sc_fsize; 107 108 void *sc_repdesc_ptr; 109 110 uint16_t sc_repdesc_size; 111 112 struct usb_device *sc_udev; 113 #define UHID_FLAG_IMMED 0x01 /* set if read should be immediate */ 114 115 }; 116 117 static device_probe_t uhid_snes_probe; 118 static device_attach_t uhid_snes_attach; 119 static device_detach_t uhid_snes_detach; 120 121 static usb_fifo_open_t uhid_snes_open; 122 static usb_fifo_close_t uhid_snes_close; 123 static usb_fifo_ioctl_t uhid_snes_ioctl; 124 static usb_fifo_cmd_t uhid_snes_start_read; 125 static usb_fifo_cmd_t uhid_snes_stop_read; 126 127 static void uhid_snes_reset(struct uhid_snes_softc *); 128 static void uhid_snes_watchdog(void *); 129 130 static usb_callback_t uhid_snes_read_callback; 131 static usb_callback_t uhid_snes_status_callback; 132 133 static struct usb_fifo_methods uhid_snes_fifo_methods = { 134 .f_open = &uhid_snes_open, 135 .f_close = &uhid_snes_close, 136 .f_ioctl = &uhid_snes_ioctl, 137 .f_start_read = &uhid_snes_start_read, 138 .f_stop_read = &uhid_snes_stop_read, 139 .basename[0] = "uhid_snes" 140 }; 141 142 static const struct usb_config uhid_snes_config[UHID_SNES_N_TRANSFER] = { 143 [UHID_SNES_INTR_DT_RD] = { 144 .callback = &uhid_snes_read_callback, 145 .bufsize = sizeof(struct usb_device_request) +1, 146 .flags = {.short_xfer_ok = 1, .short_frames_ok = 1, 147 .pipe_bof =1, .proxy_buffer =1}, 148 .type = UE_INTERRUPT, 149 .endpoint = 0x81, 150 .direction = UE_DIR_IN 151 }, 152 [UHID_SNES_STATUS_DT_RD] = { 153 .callback = &uhid_snes_status_callback, 154 .bufsize = sizeof(struct usb_device_request) + 1, 155 .timeout = 1000, 156 .type = UE_CONTROL, 157 .endpoint = 0x00, 158 .direction = UE_DIR_ANY 159 } 160 }; 161 162 static int 163 uhid_get_report(struct uhid_snes_softc *sc, uint8_t type, 164 uint8_t id, void *kern_data, void *user_data, uint16_t len) 165 { 166 int err; 167 uint8_t free_data = 0; 168 169 if (kern_data == NULL) { 170 kern_data = malloc(len, M_USBDEV, M_WAITOK); 171 if (kern_data == NULL) { 172 err = ENOMEM; 173 goto done; 174 } 175 free_data = 1; 176 } 177 err = usbd_req_get_report(sc->sc_udev, NULL, kern_data, 178 len, sc->sc_iface_index, type, id); 179 if (err) { 180 err = ENXIO; 181 goto done; 182 } 183 if (user_data) { 184 /* dummy buffer */ 185 err = copyout(kern_data, user_data, len); 186 if (err) { 187 goto done; 188 } 189 } 190 done: 191 if (free_data) { 192 free(kern_data, M_USBDEV); 193 } 194 return (err); 195 } 196 197 static int 198 uhid_set_report(struct uhid_snes_softc *sc, uint8_t type, 199 uint8_t id, void *kern_data, void *user_data, uint16_t len) 200 { 201 int err; 202 uint8_t free_data = 0; 203 204 if (kern_data == NULL) { 205 kern_data = malloc(len, M_USBDEV, M_WAITOK); 206 if (kern_data == NULL) { 207 err = ENOMEM; 208 goto done; 209 } 210 free_data = 1; 211 err = copyin(user_data, kern_data, len); 212 if (err) { 213 goto done; 214 } 215 } 216 err = usbd_req_set_report(sc->sc_udev, NULL, kern_data, 217 len, sc->sc_iface_index, type, id); 218 if (err) { 219 err = ENXIO; 220 goto done; 221 } 222 done: 223 if (free_data) { 224 free(kern_data, M_USBDEV); 225 } 226 return (err); 227 } 228 229 static int 230 uhid_snes_open(struct usb_fifo *fifo, int fflags) 231 { 232 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 233 int error; 234 235 if (sc->sc_fflags & fflags) { 236 uhid_snes_reset(sc); 237 return (EBUSY); 238 } 239 240 mtx_lock(&sc->sc_mutex); 241 usbd_xfer_set_stall(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 242 mtx_unlock(&sc->sc_mutex); 243 244 error = usb_fifo_alloc_buffer(fifo, 245 usbd_xfer_max_len(sc->sc_transfer[UHID_SNES_INTR_DT_RD]), 246 UHID_SNES_IFQ_MAX_LEN); 247 if (error) 248 return (ENOMEM); 249 250 sc->sc_fifo_open[USB_FIFO_RX] = fifo; 251 252 return (0); 253 } 254 255 static void 256 uhid_snes_reset(struct uhid_snes_softc *sc) 257 { 258 struct usb_device_request req; 259 int error; 260 261 req.bRequest = UREQ_SOFT_RESET; 262 USETW(req.wValue, 0); 263 USETW(req.wIndex, sc->sc_iface_num); 264 USETW(req.wLength, 0); 265 266 mtx_lock(&sc->sc_mutex); 267 268 error = usbd_do_request_flags(sc->sc_usb_device, &sc->sc_mutex, 269 &req, NULL, 0, NULL, 2 * USB_MS_HZ); 270 271 if (error) { 272 usbd_do_request_flags(sc->sc_usb_device, &sc->sc_mutex, 273 &req, NULL, 0, NULL, 2 * USB_MS_HZ); 274 } 275 276 mtx_unlock(&sc->sc_mutex); 277 } 278 279 static void 280 uhid_snes_close(struct usb_fifo *fifo, int fflags) 281 { 282 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 283 284 sc->sc_fflags &= ~(fflags & FREAD); 285 usb_fifo_free_buffer(fifo); 286 } 287 288 static int 289 uhid_snes_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, int fflags) 290 { 291 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 292 struct usb_gen_descriptor *ugd; 293 uint32_t size; 294 int error = 0; 295 uint8_t id; 296 297 switch (cmd) { 298 case USB_GET_REPORT_DESC: 299 ugd = data; 300 if (sc->sc_repdesc_size > ugd->ugd_maxlen) { 301 size = ugd->ugd_maxlen; 302 } else { 303 size = sc->sc_repdesc_size; 304 } 305 306 ugd->ugd_actlen = size; 307 if (ugd->ugd_data == NULL) 308 break; /*desciptor length only*/ 309 error = copyout(sc->sc_repdesc_ptr, ugd->ugd_data, size); 310 break; 311 312 case USB_SET_IMMED: 313 if (!(fflags & FREAD)) { 314 error = EPERM; 315 break; 316 } 317 318 if (*(int *)data) { 319 /* do a test read */ 320 error = uhid_get_report(sc, UHID_INPUT_REPORT, 321 sc->sc_iid, NULL, NULL, sc->sc_isize); 322 if (error) { 323 break; 324 } 325 mtx_lock(&sc->sc_mutex); 326 sc->sc_fflags |= UHID_FLAG_IMMED; 327 mtx_unlock(&sc->sc_mutex); 328 } else { 329 mtx_lock(&sc->sc_mutex); 330 sc->sc_fflags &= ~UHID_FLAG_IMMED; 331 mtx_unlock(&sc->sc_mutex); 332 } 333 break; 334 335 case USB_GET_REPORT: 336 if (!(fflags & FREAD)) { 337 error = EPERM; 338 break; 339 } 340 ugd = data; 341 switch (ugd->ugd_report_type) { 342 case UHID_INPUT_REPORT: 343 size = sc->sc_isize; 344 id = sc->sc_iid; 345 break; 346 case UHID_OUTPUT_REPORT: 347 size = sc->sc_osize; 348 id = sc->sc_oid; 349 break; 350 case UHID_FEATURE_REPORT: 351 size = sc->sc_fsize; 352 id = sc->sc_fid; 353 break; 354 default: 355 return (EINVAL); 356 } 357 if (id != 0) 358 copyin(ugd->ugd_data, &id, 1); 359 error = uhid_get_report(sc, ugd->ugd_report_type, id, 360 NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); 361 break; 362 363 case USB_SET_REPORT: 364 if (!(fflags & FWRITE)) { 365 error = EPERM; 366 break; 367 } 368 ugd = data; 369 switch (ugd->ugd_report_type) { 370 case UHID_INPUT_REPORT: 371 size = sc->sc_isize; 372 id = sc->sc_iid; 373 break; 374 case UHID_OUTPUT_REPORT: 375 size = sc->sc_osize; 376 id = sc->sc_oid; 377 break; 378 case UHID_FEATURE_REPORT: 379 size = sc->sc_fsize; 380 id = sc->sc_fid; 381 break; 382 default: 383 return (EINVAL); 384 } 385 if (id != 0) 386 copyin(ugd->ugd_data, &id, 1); 387 error = uhid_set_report(sc, ugd->ugd_report_type, id, 388 NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size)); 389 break; 390 391 case USB_GET_REPORT_ID: 392 /* XXX: we only support reportid 0? */ 393 *(int *)data = 0; 394 break; 395 396 default: 397 error = EINVAL; 398 break; 399 } 400 return (error); 401 } 402 403 static void 404 uhid_snes_watchdog(void *arg) 405 { 406 struct uhid_snes_softc *sc = arg; 407 408 mtx_assert(&sc->sc_mutex, MA_OWNED); 409 410 if (sc->sc_fflags == 0) 411 usbd_transfer_start(sc->sc_transfer[UHID_SNES_STATUS_DT_RD]); 412 413 usb_callout_reset(&sc->sc_watchdog, hz, &uhid_snes_watchdog, sc); 414 } 415 416 static void 417 uhid_snes_start_read(struct usb_fifo *fifo) 418 { 419 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 420 421 usbd_transfer_start(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 422 } 423 424 static void 425 uhid_snes_stop_read(struct usb_fifo *fifo) 426 { 427 struct uhid_snes_softc *sc = usb_fifo_softc(fifo); 428 429 usbd_transfer_stop(sc->sc_transfer[UHID_SNES_INTR_DT_RD]); 430 } 431 432 static void 433 uhid_snes_read_callback(struct usb_xfer *transfer, usb_error_t error) 434 { 435 struct uhid_snes_softc *sc = usbd_xfer_softc(transfer); 436 struct usb_fifo *fifo = sc->sc_fifo_open[USB_FIFO_RX]; 437 struct usb_page_cache *pc; 438 int actual, max; 439 440 usbd_xfer_status(transfer, &actual, NULL, NULL, NULL); 441 if (fifo == NULL) 442 return; 443 444 switch (USB_GET_STATE(transfer)) { 445 case USB_ST_TRANSFERRED: 446 if (actual == 0) { 447 if (sc->sc_zero_length_packets == 4) 448 /* Throttle transfers. */ 449 usbd_xfer_set_interval(transfer, 500); 450 else 451 sc->sc_zero_length_packets++; 452 453 } else { 454 /* disable throttling. */ 455 usbd_xfer_set_interval(transfer, 0); 456 sc->sc_zero_length_packets = 0; 457 } 458 pc = usbd_xfer_get_frame(transfer, 0); 459 usb_fifo_put_data(fifo, pc, 0, actual, 1); 460 /* Fall through */ 461 setup: 462 case USB_ST_SETUP: 463 if (usb_fifo_put_bytes_max(fifo) != 0) { 464 max = usbd_xfer_max_len(transfer); 465 usbd_xfer_set_frame_len(transfer, 0, max); 466 usbd_transfer_submit(transfer); 467 } 468 break; 469 470 default: 471 /*disable throttling. */ 472 usbd_xfer_set_interval(transfer, 0); 473 sc->sc_zero_length_packets = 0; 474 475 if (error != USB_ERR_CANCELLED) { 476 /* Issue a clear-stall request. */ 477 usbd_xfer_set_stall(transfer); 478 goto setup; 479 } 480 break; 481 } 482 } 483 484 static void 485 uhid_snes_status_callback(struct usb_xfer *transfer, usb_error_t error) 486 { 487 struct uhid_snes_softc *sc = usbd_xfer_softc(transfer); 488 struct usb_device_request req; 489 struct usb_page_cache *pc; 490 uint8_t current_status, new_status; 491 492 switch (USB_GET_STATE(transfer)) { 493 case USB_ST_SETUP: 494 req.bmRequestType = UT_READ_CLASS_INTERFACE; 495 req.bRequest = UREQ_GET_PORT_STATUS; 496 USETW(req.wValue, 0); 497 req.wIndex[0] = sc->sc_iface_num; 498 req.wIndex[1] = 0; 499 USETW(req.wLength, 1); 500 501 pc = usbd_xfer_get_frame(transfer, 0); 502 usbd_copy_in(pc, 0, &req, sizeof(req)); 503 usbd_xfer_set_frame_len(transfer, 0, sizeof(req)); 504 usbd_xfer_set_frame_len(transfer, 1, 1); 505 usbd_xfer_set_frames(transfer, 2); 506 usbd_transfer_submit(transfer); 507 break; 508 509 case USB_ST_TRANSFERRED: 510 pc = usbd_xfer_get_frame(transfer, 1); 511 usbd_copy_out(pc, 0, ¤t_status, 1); 512 new_status = current_status & ~sc->sc_previous_status; 513 sc->sc_previous_status = current_status; 514 break; 515 516 default: 517 break; 518 } 519 520 } 521 522 static int 523 uhid_snes_probe(device_t dev) 524 { 525 struct usb_attach_arg *uaa = device_get_ivars(dev); 526 527 if (uaa->usb_mode != USB_MODE_HOST) 528 return (ENXIO); 529 530 return (usbd_lookup_id_by_uaa(snes_devs, sizeof(snes_devs), uaa)); 531 } 532 533 static int 534 uhid_snes_attach(device_t dev) 535 { 536 struct usb_attach_arg *uaa = device_get_ivars(dev); 537 struct uhid_snes_softc *sc = device_get_softc(dev); 538 struct usb_interface_descriptor *idesc; 539 struct usb_config_descriptor *cdesc; 540 uint8_t alt_index, iface_index = uaa->info.bIfaceIndex; 541 int error,unit = device_get_unit(dev); 542 543 sc->sc_dev = dev; 544 sc->sc_usb_device = uaa->device; 545 device_set_usb_desc(dev); 546 mtx_init(&sc->sc_mutex, "uhid_snes", NULL, MTX_DEF | MTX_RECURSE); 547 usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mutex, 0); 548 549 idesc = usbd_get_interface_descriptor(uaa->iface); 550 alt_index = -1; 551 for(;;) { 552 if (idesc == NULL) 553 break; 554 555 if ((idesc->bDescriptorType == UDESC_INTERFACE) && 556 (idesc->bLength >= sizeof(*idesc))) { 557 if (idesc->bInterfaceNumber != uaa->info.bIfaceNum) { 558 break; 559 } else { 560 alt_index++; 561 if (idesc->bInterfaceClass == UICLASS_HID) 562 goto found; 563 } 564 } 565 566 cdesc = usbd_get_config_descriptor(uaa->device); 567 idesc = (void *)usb_desc_foreach(cdesc, (void *)idesc); 568 goto found; 569 } 570 goto detach; 571 572 found: 573 if (alt_index) { 574 error = usbd_set_alt_interface_index(uaa->device, iface_index, alt_index); 575 if (error) 576 goto detach; 577 } 578 579 sc->sc_iface_num = idesc->bInterfaceNumber; 580 581 error = usbd_transfer_setup(uaa->device, &iface_index, 582 sc->sc_transfer, uhid_snes_config, UHID_SNES_N_TRANSFER, sc, 583 &sc->sc_mutex); 584 585 if (error) 586 goto detach; 587 588 error = usb_fifo_attach(uaa->device, sc, &sc->sc_mutex, 589 &uhid_snes_fifo_methods, &sc->sc_fifo, unit, -1, 590 iface_index, UID_ROOT, GID_OPERATOR, 0644); 591 sc->sc_repdesc_size = sizeof(uhid_snes_report_descr); 592 sc->sc_repdesc_ptr = __DECONST(void*, &uhid_snes_report_descr); 593 594 595 if (error) 596 goto detach; 597 598 mtx_lock(&sc->sc_mutex); 599 uhid_snes_watchdog(sc); 600 mtx_unlock(&sc->sc_mutex); 601 return (0); 602 603 detach: 604 uhid_snes_detach(dev); 605 return (ENOMEM); 606 } 607 608 static int 609 uhid_snes_detach(device_t dev) 610 { 611 struct uhid_snes_softc *sc = device_get_softc(dev); 612 613 usb_fifo_detach(&sc->sc_fifo); 614 usb_fifo_detach(&sc->sc_fifo_no_reset); 615 616 mtx_lock(&sc->sc_mutex); 617 usb_callout_stop(&sc->sc_watchdog); 618 mtx_unlock(&sc->sc_mutex); 619 620 usbd_transfer_unsetup(sc->sc_transfer, UHID_SNES_N_TRANSFER); 621 usb_callout_drain(&sc->sc_watchdog); 622 mtx_destroy(&sc->sc_mutex); 623 624 return (0); 625 } 626 627 static device_method_t uhid_snes_methods[] = { 628 DEVMETHOD(device_probe, uhid_snes_probe), 629 DEVMETHOD(device_attach, uhid_snes_attach), 630 DEVMETHOD(device_detach, uhid_snes_detach), 631 DEVMETHOD_END 632 }; 633 634 static driver_t uhid_snes_driver = { 635 "uhid_snes", 636 uhid_snes_methods, 637 sizeof(struct uhid_snes_softc) 638 }; 639 640 static devclass_t uhid_snes_devclass; 641 642 DRIVER_MODULE(uhid_snes, uhub, uhid_snes_driver, uhid_snes_devclass, NULL, 0); 643 MODULE_DEPEND(uhid_snes, usb, 1, 1, 1); 644 USB_PNP_HOST_INFO(snes_devs); 645