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) 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) 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 141 uaa->info.bInterfaceClass = iface->descr->interface_class; 142 uaa->info.bInterfaceSubClass = iface->descr->interface_subclass; 143 uaa->info.bInterfaceProtocol = iface->descr->interface_protocol; 144 145 // TODO: bIface{Index,Num}, bConfig{Index,Num} 146 147 uaa->device = device; 148 uaa->iface = NULL; 149 150 // TODO: fetch values for these? 151 uaa->usb_mode = USB_MODE_HOST; 152 uaa->port = 1; 153 uaa->dev_state = UAA_DEV_READY; 154 155 return B_OK; 156 } 157 158 159 void 160 usb_cleanup_device(freebsd_usb_device* udev) 161 { 162 for (int i = 0; i < USB_MAX_EP_UNITS; i++) { 163 delete udev->endpoints[i].edesc; 164 udev->endpoints[i].edesc = NULL; 165 } 166 } 167 168 169 static usb_error_t 170 map_usb_error(status_t err) 171 { 172 switch (err) { 173 case B_OK: return USB_ERR_NORMAL_COMPLETION; 174 case B_DEV_STALLED: return USB_ERR_STALLED; 175 case B_CANCELED: return USB_ERR_CANCELLED; 176 case B_TIMED_OUT: return USB_ERR_TIMEOUT; 177 } 178 return USB_ERR_INVAL; 179 } 180 181 182 extern "C" usb_error_t 183 usbd_do_request_flags(struct freebsd_usb_device* udev, struct mtx* mtx, 184 struct usb_device_request* req, void* data, uint16_t flags, 185 uint16_t* actlen, usb_timeout_t timeout) 186 { 187 if (mtx != NULL) 188 mtx_unlock(mtx); 189 190 // FIXME: timeouts 191 // TODO: flags 192 193 size_t actualLen = 0; 194 status_t ret = sUSB->send_request((usb_device)udev->haiku_usb_device, 195 req->bmRequestType, req->bRequest, 196 UGETW(req->wValue), UGETW(req->wIndex), UGETW(req->wLength), 197 data, &actualLen); 198 if (actlen) 199 *actlen = actualLen; 200 201 if (mtx != NULL) 202 mtx_lock(mtx); 203 204 return map_usb_error(ret); 205 } 206 207 208 enum usb_dev_speed 209 usbd_get_speed(struct freebsd_usb_device* udev) 210 { 211 const usb_device_descriptor* descriptor = sUSB->get_device_descriptor( 212 (usb_device)udev->haiku_usb_device); 213 KASSERT(descriptor != NULL, ("no device")); 214 215 if (descriptor->usb_version >= 0x0300) 216 return USB_SPEED_SUPER; 217 else if (descriptor->usb_version >= 0x200) 218 return USB_SPEED_HIGH; 219 else if (descriptor->usb_version >= 0x110) 220 return USB_SPEED_FULL; 221 else if (descriptor->usb_version >= 0x100) 222 return USB_SPEED_LOW; 223 224 panic("unknown USB version!"); 225 return (usb_dev_speed)-1; 226 } 227 228 229 struct usb_page_cache { 230 void* buffer; 231 size_t length; 232 }; 233 234 struct usb_xfer { 235 struct mtx* mutex; 236 void* priv_sc, *priv; 237 usb_callback_t* callback; 238 usb_xfer_flags flags; 239 usb_frlength_t max_data_length; 240 241 usb_device device; 242 uint8 type; 243 usb_pipe pipe; 244 245 iovec* frames; 246 usb_page_cache* buffers; 247 int max_frame_count, nframes; 248 249 uint8 usb_state; 250 bool in_progress; 251 status_t result; 252 int transferred_length; 253 254 struct task invoker; 255 struct cv condition; 256 }; 257 258 259 extern "C" usb_error_t 260 usbd_transfer_setup(struct freebsd_usb_device* udev, 261 const uint8_t* ifaces, struct usb_xfer** ppxfer, 262 const struct usb_config* setup_start, uint16_t n_setup, 263 void* priv_sc, struct mtx* xfer_mtx) 264 { 265 if (xfer_mtx == NULL) 266 xfer_mtx = &Giant; 267 268 // Make sure the taskqueue exists. 269 if (sUSBTaskqueue == NULL) { 270 mtx_lock(&sUSBLock); 271 if (sUSBTaskqueue == NULL) { 272 sUSBTaskqueue = taskqueue_create("usb taskq", 0, 273 taskqueue_thread_enqueue, &sUSBTaskqueue); 274 taskqueue_start_threads(&sUSBTaskqueue, 1, PZERO, "usb taskq"); 275 } 276 mtx_unlock(&sUSBLock); 277 } 278 279 const usb_configuration_info* device_config = sUSB->get_configuration( 280 (usb_device)udev->haiku_usb_device); 281 282 for (const struct usb_config* setup = setup_start; 283 setup < (setup_start + n_setup); setup++) { 284 /* skip transfers w/o callbacks */ 285 if (setup->callback == NULL) 286 continue; 287 288 struct usb_xfer* xfer = new usb_xfer; 289 xfer->mutex = xfer_mtx; 290 xfer->priv_sc = priv_sc; 291 xfer->priv = NULL; 292 xfer->callback = setup->callback; 293 xfer->flags = setup->flags; 294 xfer->max_data_length = setup->bufsize; 295 296 xfer->device = (usb_device)udev->haiku_usb_device; 297 xfer->type = setup->type; 298 299 xfer->pipe = -1; 300 uint8_t endpoint = setup->endpoint; 301 uint8_t iface_index = ifaces[setup->if_index]; 302 if (endpoint == UE_ADDR_ANY) { 303 for (int i = 0; i < udev->endpoints_max; i++) { 304 if (UE_GET_XFERTYPE(udev->endpoints[i].edesc->bmAttributes) != xfer->type) 305 continue; 306 307 endpoint = udev->endpoints[i].edesc->bEndpointAddress; 308 break; 309 } 310 } 311 usb_interface_info* iface = device_config->interface[iface_index].active; 312 for (int i = 0; i < iface->endpoint_count; i++) { 313 if (iface->endpoint[i].descr->endpoint_address != endpoint) 314 continue; 315 316 xfer->pipe = iface->endpoint[i].handle; 317 break; 318 } 319 if (xfer->pipe == -1) 320 panic("failed to locate endpoint!"); 321 322 xfer->nframes = setup->frames; 323 if (xfer->nframes == 0) 324 xfer->nframes = 1; 325 xfer->max_frame_count = xfer->nframes; 326 xfer->frames = (iovec*)calloc(xfer->max_frame_count, sizeof(iovec)); 327 xfer->buffers = NULL; 328 329 xfer->usb_state = USB_ST_SETUP; 330 xfer->in_progress = false; 331 xfer->transferred_length = 0; 332 cv_init(&xfer->condition, "FreeBSD USB transfer"); 333 334 if (xfer->flags.proxy_buffer) 335 panic("not yet supported"); 336 337 ppxfer[setup - setup_start] = xfer; 338 } 339 340 return USB_ERR_NORMAL_COMPLETION; 341 } 342 343 344 extern "C" void 345 usbd_transfer_unsetup(struct usb_xfer** pxfer, uint16_t n_setup) 346 { 347 for (int i = 0; i < n_setup; i++) { 348 struct usb_xfer* xfer = pxfer[i]; 349 usbd_transfer_drain(xfer); 350 cv_destroy(&xfer->condition); 351 352 if (xfer->buffers != NULL) { 353 for (int i = 0; i < xfer->max_frame_count; i++) 354 free(xfer->buffers[i].buffer); 355 free(xfer->buffers); 356 } 357 free(xfer->frames); 358 delete xfer; 359 } 360 } 361 362 363 extern "C" usb_frlength_t 364 usbd_xfer_max_len(struct usb_xfer* xfer) 365 { 366 return xfer->max_data_length; 367 } 368 369 370 extern "C" void* 371 usbd_xfer_softc(struct usb_xfer* xfer) 372 { 373 return xfer->priv_sc; 374 } 375 376 377 extern "C" void* 378 usbd_xfer_get_priv(struct usb_xfer* xfer) 379 { 380 return xfer->priv; 381 } 382 383 384 extern "C" void 385 usbd_xfer_set_priv(struct usb_xfer* xfer, void* ptr) 386 { 387 xfer->priv = ptr; 388 } 389 390 391 extern "C" uint8_t 392 usbd_xfer_state(struct usb_xfer* xfer) 393 { 394 return xfer->usb_state; 395 } 396 397 398 extern "C" void 399 usbd_xfer_set_frames(struct usb_xfer* xfer, usb_frcount_t n) 400 { 401 KASSERT(n <= uint32_t(xfer->max_frame_count), ("frame index overflow")); 402 xfer->nframes = n; 403 } 404 405 406 extern "C" void 407 usbd_xfer_set_frame_data(struct usb_xfer* xfer, 408 usb_frcount_t frindex, void* ptr, usb_frlength_t len) 409 { 410 KASSERT(frindex < uint32_t(xfer->nframes), ("frame index overflow")); 411 412 xfer->frames[frindex].iov_base = ptr; 413 xfer->frames[frindex].iov_len = len; 414 } 415 416 417 extern "C" void 418 usbd_xfer_set_frame_len(struct usb_xfer* xfer, 419 usb_frcount_t frindex, usb_frlength_t len) 420 { 421 KASSERT(frindex < uint32_t(xfer->nframes), ("frame index overflow")); 422 KASSERT(len <= uint32_t(xfer->max_data_length), ("length overflow")); 423 424 // Trigger buffer allocation if necessary. 425 if (xfer->frames[frindex].iov_base == NULL) 426 usbd_xfer_get_frame(xfer, frindex); 427 428 xfer->frames[frindex].iov_len = len; 429 } 430 431 432 extern "C" struct usb_page_cache* 433 usbd_xfer_get_frame(struct usb_xfer* xfer, usb_frcount_t frindex) 434 { 435 KASSERT(frindex < uint32_t(xfer->max_frame_count), ("frame index overflow")); 436 if (xfer->buffers == NULL) 437 xfer->buffers = (usb_page_cache*)calloc(xfer->max_frame_count, sizeof(usb_page_cache)); 438 439 usb_page_cache* cache = &xfer->buffers[frindex]; 440 if (cache->buffer == NULL) { 441 cache->buffer = malloc(xfer->max_data_length); 442 cache->length = xfer->max_data_length; 443 } 444 445 xfer->frames[frindex].iov_base = cache->buffer; 446 return cache; 447 } 448 449 450 extern "C" void 451 usbd_frame_zero(struct usb_page_cache* cache, 452 usb_frlength_t offset, usb_frlength_t len) 453 { 454 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 455 memset((uint8*)cache->buffer + offset, 0, len); 456 } 457 458 459 extern "C" void 460 usbd_copy_in(struct usb_page_cache* cache, usb_frlength_t offset, 461 const void *ptr, usb_frlength_t len) 462 { 463 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 464 memcpy((uint8*)cache->buffer + offset, ptr, len); 465 } 466 467 468 extern "C" void 469 usbd_copy_out(struct usb_page_cache* cache, usb_frlength_t offset, 470 void *ptr, usb_frlength_t len) 471 { 472 KASSERT((offset + len) < uint32_t(cache->length), ("buffer overflow")); 473 memcpy(ptr, (uint8*)cache->buffer + offset, len); 474 } 475 476 477 extern "C" void 478 usbd_m_copy_in(struct usb_page_cache* cache, usb_frlength_t dst_offset, 479 struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len) 480 { 481 m_copydata(m, src_offset, src_len, (caddr_t)((uint8*)cache->buffer + dst_offset)); 482 } 483 484 485 extern "C" void 486 usbd_xfer_set_stall(struct usb_xfer *xfer) 487 { 488 // Not needed? 489 } 490 491 492 static void 493 usbd_invoker(void* arg, int pending) 494 { 495 struct usb_xfer* xfer = (struct usb_xfer*)arg; 496 mtx_lock(xfer->mutex); 497 xfer->in_progress = false; 498 xfer->usb_state = (xfer->result == B_OK) ? USB_ST_TRANSFERRED : USB_ST_ERROR; 499 xfer->callback(xfer, map_usb_error(xfer->result)); 500 mtx_unlock(xfer->mutex); 501 cv_signal(&xfer->condition); 502 } 503 504 505 static void 506 usbd_callback(void* arg, status_t status, void* data, size_t actualLength) 507 { 508 struct usb_xfer* xfer = (struct usb_xfer*)arg; 509 xfer->result = status; 510 xfer->transferred_length = actualLength; 511 512 TASK_INIT(&xfer->invoker, 0, usbd_invoker, xfer); 513 taskqueue_enqueue(sUSBTaskqueue, &xfer->invoker); 514 } 515 516 517 extern "C" void 518 usbd_transfer_start(struct usb_xfer* xfer) 519 { 520 if (xfer->in_progress) 521 return; 522 523 xfer->usb_state = USB_ST_SETUP; 524 xfer->callback(xfer, USB_ERR_NOT_STARTED); 525 } 526 527 528 extern "C" void 529 usbd_transfer_submit(struct usb_xfer* xfer) 530 { 531 KASSERT(!xfer->in_progress, ("cannot submit in-progress transfer!")); 532 533 xfer->transferred_length = 0; 534 xfer->in_progress = true; 535 status_t status = B_NOT_SUPPORTED; 536 switch (xfer->type) { 537 case UE_BULK: 538 status = sUSB->queue_bulk_v(xfer->pipe, xfer->frames, xfer->nframes, usbd_callback, xfer); 539 break; 540 541 case UE_INTERRUPT: 542 KASSERT(xfer->nframes == 1, ("invalid frame count for interrupt transfer")); 543 status = sUSB->queue_interrupt(xfer->pipe, 544 xfer->frames[0].iov_base, xfer->frames[0].iov_len, 545 usbd_callback, xfer); 546 break; 547 548 default: 549 panic("unhandled pipe type %d", xfer->type); 550 } 551 552 if (status != B_OK) 553 usbd_callback(xfer, status, NULL, 0); 554 } 555 556 557 extern "C" void 558 usbd_transfer_stop(struct usb_xfer* xfer) 559 { 560 if (xfer == NULL) 561 return; 562 mtx_assert(xfer->mutex, MA_OWNED); 563 564 if (!xfer->in_progress) 565 return; 566 567 // Unfortunately we have no way of cancelling just one transfer. 568 sUSB->cancel_queued_transfers(xfer->pipe); 569 } 570 571 572 extern "C" void 573 usbd_transfer_drain(struct usb_xfer* xfer) 574 { 575 if (xfer == NULL) 576 return; 577 578 mtx_lock(xfer->mutex); 579 usbd_transfer_stop(xfer); 580 while (xfer->in_progress) 581 cv_wait(&xfer->condition, xfer->mutex); 582 mtx_unlock(xfer->mutex); 583 } 584 585 586 extern "C" void 587 usbd_xfer_status(struct usb_xfer* xfer, int* actlen, int* sumlen, int* aframes, int* nframes) 588 { 589 if (actlen) 590 *actlen = xfer->transferred_length; 591 if (sumlen) { 592 int sum = 0; 593 for (int i = 0; i < xfer->nframes; i++) 594 sum += xfer->frames[i].iov_len; 595 *sumlen = sum; 596 } 597 if (aframes) { 598 int length = xfer->transferred_length; 599 int frames = 0; 600 for (int i = 0; i < xfer->nframes && length > 0; i++) { 601 length -= xfer->frames[i].iov_len; 602 if (length >= 0) 603 frames++; 604 } 605 *aframes = frames; 606 } 607 if (nframes) 608 *nframes = xfer->nframes; 609 } 610