1 /* 2 * Copyright 2022, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 */ 5 6 #include <sys/condvar.h> 7 8 extern "C" { 9 #include <sys/mutex.h> 10 #include <sys/systm.h> 11 #include <sys/taskqueue.h> 12 #include <sys/priority.h> 13 14 #include <dev/usb/usb.h> 15 #include <dev/usb/usbdi.h> 16 #include <dev/usb/usb_device.h> 17 18 #include "device.h" 19 } 20 21 // undo name remappings, so we can use both FreeBSD and Haiku ones in this file 22 #undef usb_device 23 #undef usb_interface 24 #undef usb_endpoint_descriptor 25 26 #include <USB3.h> 27 28 29 struct mtx sUSBLock; 30 usb_module_info* sUSB = NULL; 31 struct taskqueue* sUSBTaskqueue = NULL; 32 33 34 status_t 35 init_usb() 36 { 37 if (sUSB != NULL) 38 return B_OK; 39 40 if (get_module(B_USB_MODULE_NAME, (module_info**)&sUSB) != B_OK) { 41 dprintf("cannot get module \"%s\"\n", B_USB_MODULE_NAME); 42 return B_ERROR; 43 } 44 45 mtx_init(&sUSBLock, "fbsd usb", NULL, MTX_DEF); 46 return B_OK; 47 } 48 49 50 void 51 uninit_usb() 52 { 53 if (sUSB == NULL) 54 return; 55 56 put_module(B_USB_MODULE_NAME); 57 if (sUSBTaskqueue != NULL) 58 taskqueue_free(sUSBTaskqueue); 59 60 sUSB = NULL; 61 sUSBTaskqueue = NULL; 62 mtx_destroy(&sUSBLock); 63 } 64 65 66 status_t 67 get_next_usb_device(uint32* cookie, freebsd_usb_device* result) 68 { 69 // We cheat here: since USB IDs are sequential, instead of doing a 70 // complicated parent/child iteration dance, we simply request device 71 // descriptors and let the USB stack figure out the rest. 72 // 73 // It would be better if we used USB->register_driver, but that is not 74 // an option at present for a variety of reasons... 75 const usb_configuration_info* config; 76 usb_device current; 77 while (*cookie < 1024) { 78 current = *cookie; 79 *cookie = *cookie + 1; 80 81 config = sUSB->get_configuration(current); 82 if (config != NULL) 83 break; 84 } 85 if (config == NULL) 86 return ENODEV; 87 88 result->haiku_usb_device = current; 89 result->endpoints_max = 0; 90 for (size_t i = 0; i < config->interface_count; i++) { 91 usb_interface_info* iface = config->interface[i].active; 92 if (iface == NULL) 93 continue; 94 95 for (size_t j = 0; j < iface->endpoint_count; j++) { 96 if (iface->endpoint[j].descr == NULL) 97 continue; 98 99 const int rep = result->endpoints_max++; 100 result->endpoints[rep].iface_index = i; 101 102 static_assert(sizeof(freebsd_usb_endpoint_descriptor) 103 == sizeof(usb_endpoint_descriptor), "size mismatch"); 104 105 if (result->endpoints[rep].edesc == NULL) 106 result->endpoints[rep].edesc = new freebsd_usb_endpoint_descriptor; 107 108 memcpy(result->endpoints[rep].edesc, iface->endpoint[j].descr, 109 sizeof(usb_endpoint_descriptor)); 110 } 111 } 112 113 return B_OK; 114 } 115 116 117 status_t 118 get_usb_device_attach_arg(struct freebsd_usb_device* device, struct usb_attach_arg* uaa) 119 { 120 memset(uaa, 0, sizeof(struct usb_attach_arg)); 121 122 const usb_device_descriptor* device_desc = 123 sUSB->get_device_descriptor(device->haiku_usb_device); 124 if (device_desc == NULL) 125 return B_BAD_VALUE; 126 127 uaa->info.idVendor = device_desc->vendor_id; 128 uaa->info.idProduct = device_desc->product_id; 129 uaa->info.bcdDevice = device_desc->device_version; 130 uaa->info.bDeviceClass = device_desc->device_class; 131 uaa->info.bDeviceSubClass = device_desc->device_subclass; 132 uaa->info.bDeviceProtocol = device_desc->device_protocol; 133 134 const usb_configuration_info* config = sUSB->get_configuration(device->haiku_usb_device); 135 if (device_desc == NULL) 136 return B_BAD_VALUE; 137 138 // TODO: represent more than just interface[0], but how? 139 usb_interface_info* iface = config->interface[0].active; 140 if (iface == NULL) 141 return B_NO_INIT; 142 143 uaa->info.bInterfaceClass = iface->descr->interface_class; 144 uaa->info.bInterfaceSubClass = iface->descr->interface_subclass; 145 uaa->info.bInterfaceProtocol = iface->descr->interface_protocol; 146 147 // TODO: bIface{Index,Num}, bConfig{Index,Num} 148 149 uaa->device = device; 150 uaa->iface = NULL; 151 152 // TODO: fetch values for these? 153 uaa->usb_mode = USB_MODE_HOST; 154 uaa->port = 1; 155 uaa->dev_state = UAA_DEV_READY; 156 157 return B_OK; 158 } 159 160 161 void 162 usb_cleanup_device(freebsd_usb_device* udev) 163 { 164 for (int i = 0; i < USB_MAX_EP_UNITS; i++) { 165 delete udev->endpoints[i].edesc; 166 udev->endpoints[i].edesc = NULL; 167 } 168 } 169 170 171 static usb_error_t 172 map_usb_error(status_t err) 173 { 174 switch (err) { 175 case B_OK: return USB_ERR_NORMAL_COMPLETION; 176 case B_DEV_STALLED: return USB_ERR_STALLED; 177 case B_CANCELED: return USB_ERR_CANCELLED; 178 case B_TIMED_OUT: return USB_ERR_TIMEOUT; 179 } 180 return USB_ERR_INVAL; 181 } 182 183 184 extern "C" usb_error_t 185 usbd_do_request_flags(struct freebsd_usb_device* udev, struct mtx* mtx, 186 struct usb_device_request* req, void* data, uint16_t flags, 187 uint16_t* actlen, usb_timeout_t timeout) 188 { 189 if (mtx != NULL) 190 mtx_unlock(mtx); 191 192 // FIXME: timeouts 193 // TODO: flags 194 195 size_t actualLen = 0; 196 status_t ret = sUSB->send_request((usb_device)udev->haiku_usb_device, 197 req->bmRequestType, req->bRequest, 198 UGETW(req->wValue), UGETW(req->wIndex), UGETW(req->wLength), 199 data, &actualLen); 200 if (actlen) 201 *actlen = actualLen; 202 203 if (mtx != NULL) 204 mtx_lock(mtx); 205 206 return map_usb_error(ret); 207 } 208 209 210 enum usb_dev_speed 211 usbd_get_speed(struct freebsd_usb_device* udev) 212 { 213 const usb_device_descriptor* descriptor = sUSB->get_device_descriptor( 214 (usb_device)udev->haiku_usb_device); 215 KASSERT(descriptor != NULL, ("no device")); 216 217 if (descriptor->usb_version >= 0x0300) 218 return USB_SPEED_SUPER; 219 else if (descriptor->usb_version >= 0x200) 220 return USB_SPEED_HIGH; 221 else if (descriptor->usb_version >= 0x110) 222 return USB_SPEED_FULL; 223 else if (descriptor->usb_version >= 0x100) 224 return USB_SPEED_LOW; 225 226 panic("unknown USB version!"); 227 return (usb_dev_speed)-1; 228 } 229 230 231 struct usb_page_cache { 232 void* buffer; 233 size_t length; 234 }; 235 236 struct usb_xfer { 237 struct mtx* mutex; 238 void* priv_sc, *priv; 239 usb_callback_t* callback; 240 usb_xfer_flags flags; 241 usb_frlength_t max_data_length; 242 243 usb_device device; 244 uint8 type; 245 usb_pipe pipe; 246 247 iovec* frames; 248 usb_page_cache* buffers; 249 int max_frame_count, nframes; 250 251 uint8 usb_state; 252 bool in_progress; 253 status_t result; 254 int transferred_length; 255 256 struct task invoker; 257 struct cv condition; 258 }; 259 260 261 extern "C" usb_error_t 262 usbd_transfer_setup(struct freebsd_usb_device* udev, 263 const uint8_t* ifaces, struct usb_xfer** ppxfer, 264 const struct usb_config* setup_start, uint16_t n_setup, 265 void* priv_sc, struct mtx* xfer_mtx) 266 { 267 if (xfer_mtx == NULL) 268 xfer_mtx = &Giant; 269 270 // Make sure the taskqueue exists. 271 if (sUSBTaskqueue == NULL) { 272 mtx_lock(&sUSBLock); 273 if (sUSBTaskqueue == NULL) { 274 sUSBTaskqueue = taskqueue_create("usb taskq", 0, 275 taskqueue_thread_enqueue, &sUSBTaskqueue); 276 taskqueue_start_threads(&sUSBTaskqueue, 1, PZERO, "usb taskq"); 277 } 278 mtx_unlock(&sUSBLock); 279 } 280 281 const usb_configuration_info* device_config = sUSB->get_configuration( 282 (usb_device)udev->haiku_usb_device); 283 284 for (const struct usb_config* setup = setup_start; 285 setup < (setup_start + n_setup); setup++) { 286 /* skip transfers w/o callbacks */ 287 if (setup->callback == NULL) 288 continue; 289 290 struct usb_xfer* xfer = new usb_xfer; 291 xfer->mutex = xfer_mtx; 292 xfer->priv_sc = priv_sc; 293 xfer->priv = NULL; 294 xfer->callback = setup->callback; 295 xfer->flags = setup->flags; 296 xfer->max_data_length = setup->bufsize; 297 298 xfer->device = (usb_device)udev->haiku_usb_device; 299 xfer->type = setup->type; 300 301 xfer->pipe = -1; 302 uint8_t endpoint = setup->endpoint; 303 uint8_t iface_index = ifaces[setup->if_index]; 304 if (endpoint == UE_ADDR_ANY) { 305 for (int i = 0; i < udev->endpoints_max; i++) { 306 if (UE_GET_XFERTYPE(udev->endpoints[i].edesc->bmAttributes) != xfer->type) 307 continue; 308 309 endpoint = udev->endpoints[i].edesc->bEndpointAddress; 310 break; 311 } 312 } 313 usb_interface_info* iface = device_config->interface[iface_index].active; 314 for (int i = 0; i < iface->endpoint_count; i++) { 315 if (iface->endpoint[i].descr->endpoint_address != endpoint) 316 continue; 317 318 xfer->pipe = iface->endpoint[i].handle; 319 break; 320 } 321 if (xfer->pipe == -1) 322 panic("failed to locate endpoint!"); 323 324 xfer->nframes = setup->frames; 325 if (xfer->nframes == 0) 326 xfer->nframes = 1; 327 xfer->max_frame_count = xfer->nframes; 328 xfer->frames = (iovec*)calloc(xfer->max_frame_count, sizeof(iovec)); 329 xfer->buffers = NULL; 330 331 xfer->usb_state = USB_ST_SETUP; 332 xfer->in_progress = false; 333 xfer->transferred_length = 0; 334 cv_init(&xfer->condition, "FreeBSD USB transfer"); 335 336 if (xfer->flags.proxy_buffer) 337 panic("not yet supported"); 338 339 ppxfer[setup - setup_start] = xfer; 340 } 341 342 return USB_ERR_NORMAL_COMPLETION; 343 } 344 345 346 extern "C" void 347 usbd_transfer_unsetup(struct usb_xfer** pxfer, uint16_t n_setup) 348 { 349 for (int i = 0; i < n_setup; i++) { 350 struct usb_xfer* xfer = pxfer[i]; 351 usbd_transfer_drain(xfer); 352 cv_destroy(&xfer->condition); 353 354 if (xfer->buffers != NULL) { 355 for (int i = 0; i < xfer->max_frame_count; i++) 356 free(xfer->buffers[i].buffer); 357 free(xfer->buffers); 358 } 359 free(xfer->frames); 360 delete xfer; 361 } 362 } 363 364 365 extern "C" usb_frlength_t 366 usbd_xfer_max_len(struct usb_xfer* xfer) 367 { 368 return xfer->max_data_length; 369 } 370 371 372 extern "C" void* 373 usbd_xfer_softc(struct usb_xfer* xfer) 374 { 375 return xfer->priv_sc; 376 } 377 378 379 extern "C" void* 380 usbd_xfer_get_priv(struct usb_xfer* xfer) 381 { 382 return xfer->priv; 383 } 384 385 386 extern "C" void 387 usbd_xfer_set_priv(struct usb_xfer* xfer, void* ptr) 388 { 389 xfer->priv = ptr; 390 } 391 392 393 extern "C" uint8_t 394 usbd_xfer_state(struct usb_xfer* xfer) 395 { 396 return xfer->usb_state; 397 } 398 399 400 extern "C" void 401 usbd_xfer_set_frames(struct usb_xfer* xfer, usb_frcount_t n) 402 { 403 KASSERT(n <= uint32_t(xfer->max_frame_count), ("frame index overflow")); 404 xfer->nframes = n; 405 } 406 407 408 extern "C" void 409 usbd_xfer_set_frame_data(struct usb_xfer* xfer, 410 usb_frcount_t frindex, void* ptr, usb_frlength_t len) 411 { 412 KASSERT(frindex < uint32_t(xfer->nframes), ("frame index overflow")); 413 414 xfer->frames[frindex].iov_base = ptr; 415 xfer->frames[frindex].iov_len = len; 416 } 417 418 419 extern "C" void 420 usbd_xfer_set_frame_len(struct usb_xfer* xfer, 421 usb_frcount_t frindex, usb_frlength_t len) 422 { 423 KASSERT(frindex < uint32_t(xfer->nframes), ("frame index overflow")); 424 KASSERT(len <= uint32_t(xfer->max_data_length), ("length overflow")); 425 426 // Trigger buffer allocation if necessary. 427 if (xfer->frames[frindex].iov_base == NULL) 428 usbd_xfer_get_frame(xfer, frindex); 429 430 xfer->frames[frindex].iov_len = len; 431 } 432 433 434 extern "C" struct usb_page_cache* 435 usbd_xfer_get_frame(struct usb_xfer* xfer, usb_frcount_t frindex) 436 { 437 KASSERT(frindex < uint32_t(xfer->max_frame_count), ("frame index overflow")); 438 if (xfer->buffers == NULL) 439 xfer->buffers = (usb_page_cache*)calloc(xfer->max_frame_count, sizeof(usb_page_cache)); 440 441 usb_page_cache* cache = &xfer->buffers[frindex]; 442 if (cache->buffer == NULL) { 443 cache->buffer = malloc(xfer->max_data_length); 444 cache->length = xfer->max_data_length; 445 } 446 447 xfer->frames[frindex].iov_base = cache->buffer; 448 return cache; 449 } 450 451 452 extern "C" void 453 usbd_frame_zero(struct usb_page_cache* cache, 454 usb_frlength_t offset, usb_frlength_t len) 455 { 456 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 457 memset((uint8*)cache->buffer + offset, 0, len); 458 } 459 460 461 extern "C" void 462 usbd_copy_in(struct usb_page_cache* cache, usb_frlength_t offset, 463 const void *ptr, usb_frlength_t len) 464 { 465 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 466 memcpy((uint8*)cache->buffer + offset, ptr, len); 467 } 468 469 470 extern "C" void 471 usbd_copy_out(struct usb_page_cache* cache, usb_frlength_t offset, 472 void *ptr, usb_frlength_t len) 473 { 474 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 475 memcpy(ptr, (uint8*)cache->buffer + offset, len); 476 } 477 478 479 extern "C" void 480 usbd_m_copy_in(struct usb_page_cache* cache, usb_frlength_t dst_offset, 481 struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len) 482 { 483 m_copydata(m, src_offset, src_len, (caddr_t)((uint8*)cache->buffer + dst_offset)); 484 } 485 486 487 extern "C" void 488 usbd_xfer_set_stall(struct usb_xfer *xfer) 489 { 490 // Not needed? 491 } 492 493 494 static void 495 usbd_invoker(void* arg, int pending) 496 { 497 struct usb_xfer* xfer = (struct usb_xfer*)arg; 498 mtx_lock(xfer->mutex); 499 xfer->in_progress = false; 500 xfer->usb_state = (xfer->result == B_OK) ? USB_ST_TRANSFERRED : USB_ST_ERROR; 501 xfer->callback(xfer, map_usb_error(xfer->result)); 502 mtx_unlock(xfer->mutex); 503 cv_signal(&xfer->condition); 504 } 505 506 507 static void 508 usbd_callback(void* arg, status_t status, void* data, size_t actualLength) 509 { 510 struct usb_xfer* xfer = (struct usb_xfer*)arg; 511 xfer->result = status; 512 xfer->transferred_length = actualLength; 513 514 TASK_INIT(&xfer->invoker, 0, usbd_invoker, xfer); 515 taskqueue_enqueue(sUSBTaskqueue, &xfer->invoker); 516 } 517 518 519 extern "C" void 520 usbd_transfer_start(struct usb_xfer* xfer) 521 { 522 if (xfer->in_progress) 523 return; 524 525 xfer->usb_state = USB_ST_SETUP; 526 xfer->callback(xfer, USB_ERR_NOT_STARTED); 527 } 528 529 530 extern "C" void 531 usbd_transfer_submit(struct usb_xfer* xfer) 532 { 533 KASSERT(!xfer->in_progress, ("cannot submit in-progress transfer!")); 534 535 xfer->transferred_length = 0; 536 xfer->in_progress = true; 537 status_t status = B_NOT_SUPPORTED; 538 switch (xfer->type) { 539 case UE_BULK: 540 status = sUSB->queue_bulk_v(xfer->pipe, xfer->frames, xfer->nframes, usbd_callback, xfer); 541 break; 542 543 case UE_INTERRUPT: 544 KASSERT(xfer->nframes == 1, ("invalid frame count for interrupt transfer")); 545 status = sUSB->queue_interrupt(xfer->pipe, 546 xfer->frames[0].iov_base, xfer->frames[0].iov_len, 547 usbd_callback, xfer); 548 break; 549 550 default: 551 panic("unhandled pipe type %d", xfer->type); 552 } 553 554 if (status != B_OK) 555 usbd_callback(xfer, status, NULL, 0); 556 } 557 558 559 extern "C" void 560 usbd_transfer_stop(struct usb_xfer* xfer) 561 { 562 if (xfer == NULL) 563 return; 564 mtx_assert(xfer->mutex, MA_OWNED); 565 566 if (!xfer->in_progress) 567 return; 568 569 // Unfortunately we have no way of cancelling just one transfer. 570 sUSB->cancel_queued_transfers(xfer->pipe); 571 } 572 573 574 extern "C" void 575 usbd_transfer_drain(struct usb_xfer* xfer) 576 { 577 if (xfer == NULL) 578 return; 579 580 mtx_lock(xfer->mutex); 581 usbd_transfer_stop(xfer); 582 while (xfer->in_progress) 583 cv_wait(&xfer->condition, xfer->mutex); 584 mtx_unlock(xfer->mutex); 585 } 586 587 588 extern "C" void 589 usbd_xfer_status(struct usb_xfer* xfer, int* actlen, int* sumlen, int* aframes, int* nframes) 590 { 591 if (actlen) 592 *actlen = xfer->transferred_length; 593 if (sumlen) { 594 int sum = 0; 595 for (int i = 0; i < xfer->nframes; i++) 596 sum += xfer->frames[i].iov_len; 597 *sumlen = sum; 598 } 599 if (aframes) { 600 int length = xfer->transferred_length; 601 int frames = 0; 602 for (int i = 0; i < xfer->nframes && length > 0; i++) { 603 length -= xfer->frames[i].iov_len; 604 if (length >= 0) 605 frames++; 606 } 607 *aframes = frames; 608 } 609 if (nframes) 610 *nframes = xfer->nframes; 611 } 612