1 /* 2 * Copyright 2003-2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Niels S. Reedijk 8 */ 9 10 11 #include <util/kernel_cpp.h> 12 #include "usb_private.h" 13 #include <USB_rle.h> 14 15 #define USB_MODULE_NAME "module" 16 17 Stack *gUSBStack = NULL; 18 19 20 /*! The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to 21 execute transfers. 22 When invoked the first time, a new transfer is started, each time the 23 function is called afterwards, it is checked whether the transfer is already 24 completed. If called with argv[1] == "cancel" the function cancels a 25 possibly pending transfer. 26 */ 27 static status_t 28 debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength, 29 usb_request_data *requestData, bool cancel) 30 { 31 static uint8 transferBuffer[sizeof(Transfer)] 32 __attribute__((aligned(16))); 33 static Transfer *transfer = NULL; 34 35 BusManager *bus = pipe->GetBusManager(); 36 37 if (cancel) { 38 if (transfer != NULL) { 39 bus->CancelDebugTransfer(transfer); 40 transfer = NULL; 41 } 42 43 return B_OK; 44 } 45 46 if (transfer != NULL) { 47 status_t error = bus->CheckDebugTransfer(transfer); 48 if (error != B_DEV_PENDING) 49 transfer = NULL; 50 51 return error; 52 } 53 54 transfer = new(transferBuffer) Transfer(pipe); 55 transfer->SetData(data, dataLength); 56 transfer->SetRequestData(requestData); 57 58 status_t error = bus->StartDebugTransfer(transfer); 59 if (error != B_OK) { 60 transfer = NULL; 61 return error; 62 } 63 64 return B_DEV_PENDING; 65 } 66 67 68 static int 69 debug_get_pipe_for_id(int argc, char **argv) 70 { 71 if (gUSBStack == NULL) 72 return 1; 73 74 if (!is_debug_variable_defined("_usbPipeID")) 75 return 2; 76 77 uint64 id = get_debug_variable("_usbPipeID", 0); 78 Object *object = gUSBStack->GetObjectNoLock((usb_id)id); 79 if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) 80 return 3; 81 82 set_debug_variable("_usbPipe", (uint64)object); 83 return 0; 84 } 85 86 87 static int 88 debug_process_transfer(int argc, char **argv) 89 { 90 Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0); 91 if (pipe == NULL) 92 return B_BAD_VALUE; 93 94 uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0); 95 size_t length = (size_t)get_debug_variable("_usbTransferLength", 0); 96 usb_request_data *requestData 97 = (usb_request_data *)get_debug_variable("_usbRequestData", 0); 98 99 return debug_run_transfer(pipe, data, length, requestData, 100 argc > 1 && strcmp(argv[1], "cancel") == 0); 101 } 102 103 104 static int 105 debug_clear_stall(int argc, char *argv[]) 106 { 107 Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0); 108 if (pipe == NULL) 109 return B_BAD_VALUE; 110 111 static usb_request_data requestData; 112 113 requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT; 114 requestData.Request = USB_REQUEST_CLEAR_FEATURE; 115 requestData.Value = USB_FEATURE_ENDPOINT_HALT; 116 requestData.Index = pipe->EndpointAddress() 117 | (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN 118 : USB_ENDPOINT_ADDR_DIR_OUT); 119 requestData.Length = 0; 120 121 Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe(); 122 for (int tries = 0; tries < 100; tries++) { 123 status_t result 124 = debug_run_transfer(parentPipe, NULL, 0, &requestData, false); 125 126 if (result == B_DEV_PENDING) 127 continue; 128 129 if (result == B_OK) { 130 // clearing a stalled condition resets the data toggle 131 pipe->SetDataToggle(false); 132 return B_OK; 133 } 134 135 return result; 136 } 137 138 return B_TIMED_OUT; 139 } 140 141 142 static int32 143 bus_std_ops(int32 op, ...) 144 { 145 switch (op) { 146 case B_MODULE_INIT: { 147 TRACE_MODULE("init\n"); 148 if (gUSBStack) 149 return B_OK; 150 151 #ifdef TRACE_USB 152 set_dprintf_enabled(true); 153 #endif 154 Stack *stack = new(std::nothrow) Stack(); 155 TRACE_MODULE("usb_module: stack created %p\n", stack); 156 if (!stack) 157 return B_NO_MEMORY; 158 159 if (stack->InitCheck() != B_OK) { 160 delete stack; 161 return ENODEV; 162 } 163 164 gUSBStack = stack; 165 166 add_debugger_command("get_usb_pipe_for_id", 167 &debug_get_pipe_for_id, 168 "Sets _usbPipe by resolving _usbPipeID"); 169 add_debugger_command("usb_process_transfer", 170 &debug_process_transfer, 171 "Transfers _usbTransferData with _usbTransferLength" 172 " (and/or _usbRequestData) to pipe _usbPipe"); 173 add_debugger_command("usb_clear_stall", 174 &debug_clear_stall, 175 "Tries to issue a clear feature request for the endpoint halt" 176 " feature on pipe _usbPipe"); 177 break; 178 } 179 180 case B_MODULE_UNINIT: 181 TRACE_MODULE("uninit\n"); 182 delete gUSBStack; 183 gUSBStack = NULL; 184 185 remove_debugger_command("get_usb_pipe_for_id", 186 &debug_get_pipe_for_id); 187 break; 188 189 default: 190 return EINVAL; 191 } 192 193 return B_OK; 194 } 195 196 197 status_t 198 register_driver(const char *driverName, 199 const usb_support_descriptor *descriptors, 200 size_t count, const char *optionalRepublishDriverName) 201 { 202 return gUSBStack->RegisterDriver(driverName, descriptors, count, 203 optionalRepublishDriverName); 204 } 205 206 207 status_t 208 install_notify(const char *driverName, const usb_notify_hooks *hooks) 209 { 210 return gUSBStack->InstallNotify(driverName, hooks); 211 } 212 213 214 status_t 215 uninstall_notify(const char *driverName) 216 { 217 return gUSBStack->UninstallNotify(driverName); 218 } 219 220 221 const usb_device_descriptor * 222 get_device_descriptor(usb_device device) 223 { 224 TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device); 225 Object *object = gUSBStack->GetObject(device); 226 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 227 return NULL; 228 229 return ((Device *)object)->DeviceDescriptor(); 230 } 231 232 233 const usb_configuration_info * 234 get_nth_configuration(usb_device device, uint32 index) 235 { 236 TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n", 237 device, index); 238 Object *object = gUSBStack->GetObject(device); 239 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 240 return NULL; 241 242 return ((Device *)object)->ConfigurationAt((int32)index); 243 } 244 245 246 const usb_configuration_info * 247 get_configuration(usb_device device) 248 { 249 TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device); 250 Object *object = gUSBStack->GetObject(device); 251 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 252 return NULL; 253 254 return ((Device *)object)->Configuration(); 255 } 256 257 258 status_t 259 set_configuration(usb_device device, 260 const usb_configuration_info *configuration) 261 { 262 TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device, 263 configuration); 264 Object *object = gUSBStack->GetObject(device); 265 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 266 return B_DEV_INVALID_PIPE; 267 268 return ((Device *)object)->SetConfiguration(configuration); 269 } 270 271 272 status_t 273 set_alt_interface(usb_device device, const usb_interface_info *interface) 274 { 275 TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface); 276 Object *object = gUSBStack->GetObject(device); 277 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 278 return B_DEV_INVALID_PIPE; 279 280 return ((Device *)object)->SetAltInterface(interface); 281 } 282 283 284 status_t 285 set_feature(usb_id handle, uint16 selector) 286 { 287 TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector); 288 Object *object = gUSBStack->GetObject(handle); 289 if (!object) 290 return B_DEV_INVALID_PIPE; 291 292 return object->SetFeature(selector); 293 } 294 295 296 status_t 297 clear_feature(usb_id handle, uint16 selector) 298 { 299 TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector); 300 Object *object = gUSBStack->GetObject(handle); 301 if (!object) 302 return B_DEV_INVALID_PIPE; 303 304 return object->ClearFeature(selector); 305 } 306 307 308 status_t 309 get_status(usb_id handle, uint16 *status) 310 { 311 TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status); 312 if (!status) 313 return B_BAD_VALUE; 314 315 Object *object = gUSBStack->GetObject(handle); 316 if (!object) 317 return B_DEV_INVALID_PIPE; 318 319 return object->GetStatus(status); 320 } 321 322 323 status_t 324 get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID, 325 void *data, size_t dataLength, size_t *actualLength) 326 { 327 TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, " 328 "%" B_PRIuSIZE ", %p)\n", 329 device, type, index, languageID, data, dataLength, actualLength); 330 Object *object = gUSBStack->GetObject(device); 331 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 332 return B_DEV_INVALID_PIPE; 333 334 return ((Device *)object)->GetDescriptor(type, index, languageID, 335 data, dataLength, actualLength); 336 } 337 338 339 status_t 340 send_request(usb_device device, uint8 requestType, uint8 request, 341 uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength) 342 { 343 TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, " 344 "%d, %p, %p)\n", device, requestType, request, value, index, length, 345 data, actualLength); 346 Object *object = gUSBStack->GetObject(device); 347 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 348 return B_DEV_INVALID_PIPE; 349 350 return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request, 351 value, index, length, data, length, actualLength); 352 } 353 354 355 status_t 356 queue_request(usb_device device, uint8 requestType, uint8 request, 357 uint16 value, uint16 index, uint16 length, void *data, 358 usb_callback_func callback, void *callbackCookie) 359 { 360 TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x," 361 " %u, %p, %p, %p)\n", device, requestType, request, value, index, 362 length, data, callback, callbackCookie); 363 Object *object = gUSBStack->GetObject(device); 364 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 365 return B_DEV_INVALID_PIPE; 366 367 return ((Device *)object)->DefaultPipe()->QueueRequest(requestType, 368 request, value, index, length, data, length, callback, callbackCookie); 369 } 370 371 372 status_t 373 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, 374 usb_callback_func callback, void *callbackCookie) 375 { 376 TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n", 377 pipe, data, dataLength, callback, callbackCookie); 378 Object *object = gUSBStack->GetObject(pipe); 379 if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) 380 return B_DEV_INVALID_PIPE; 381 382 return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback, 383 callbackCookie); 384 } 385 386 387 status_t 388 queue_bulk(usb_pipe pipe, void *data, size_t dataLength, 389 usb_callback_func callback, void *callbackCookie) 390 { 391 TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n", 392 pipe, data, dataLength, callback, callbackCookie); 393 Object *object = gUSBStack->GetObject(pipe); 394 if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 395 return B_DEV_INVALID_PIPE; 396 397 return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback, 398 callbackCookie); 399 } 400 401 402 status_t 403 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, 404 usb_callback_func callback, void *callbackCookie) 405 { 406 TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n", 407 pipe, vector, vectorCount, callback, callbackCookie); 408 Object *object = gUSBStack->GetObject(pipe); 409 if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 410 return B_DEV_INVALID_PIPE; 411 412 return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, 413 callbackCookie, false); 414 } 415 416 417 status_t 418 queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount, 419 usb_callback_func callback, void *callbackCookie) 420 { 421 TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE 422 ", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie); 423 Object *object = gUSBStack->GetObject(pipe); 424 if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 425 return B_DEV_INVALID_PIPE; 426 427 return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, 428 callbackCookie, true); 429 } 430 431 432 status_t 433 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, 434 usb_iso_packet_descriptor *packetDesc, uint32 packetCount, 435 uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback, 436 void *callbackCookie) 437 { 438 TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, " 439 "%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n", 440 pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, 441 flags, callback, callbackCookie); 442 Object *object = gUSBStack->GetObject(pipe); 443 if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 444 return B_DEV_INVALID_PIPE; 445 446 return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength, 447 packetDesc, packetCount, startingFrameNumber, flags, callback, 448 callbackCookie); 449 } 450 451 452 status_t 453 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, 454 uint16 maxBufferDurationMS, uint16 sampleSize) 455 { 456 TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe, 457 maxQueuedPackets, maxBufferDurationMS, sampleSize); 458 Object *object = gUSBStack->GetObject(pipe); 459 if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 460 return B_DEV_INVALID_PIPE; 461 462 return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets, 463 maxBufferDurationMS, sampleSize); 464 } 465 466 467 status_t 468 cancel_queued_transfers(usb_pipe pipe) 469 { 470 TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe); 471 Object *object = gUSBStack->GetObject(pipe); 472 if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) 473 return B_DEV_INVALID_PIPE; 474 475 return ((Pipe *)object)->CancelQueuedTransfers(false); 476 } 477 478 479 status_t 480 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 481 { 482 TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode, 483 buffer, bufferSize); 484 485 switch (opcode) { 486 case 'DNAM': { 487 Object *object = gUSBStack->GetObject(*(usb_id *)buffer); 488 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 489 return B_BAD_VALUE; 490 491 uint32 index = 0; 492 return ((Device *)object)->BuildDeviceName((char *)buffer, &index, 493 bufferSize, NULL); 494 } 495 } 496 497 return B_DEV_INVALID_IOCTL; 498 } 499 500 501 status_t 502 get_nth_roothub(uint32 index, usb_device *rootHub) 503 { 504 if (!rootHub) 505 return B_BAD_VALUE; 506 507 BusManager *busManager = gUSBStack->BusManagerAt(index); 508 if (!busManager) 509 return B_ENTRY_NOT_FOUND; 510 511 Hub *hub = busManager->GetRootHub(); 512 if (!hub) 513 return B_NO_INIT; 514 515 *rootHub = hub->USBID(); 516 return B_OK; 517 } 518 519 520 status_t 521 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice) 522 { 523 if (!childDevice) 524 return B_BAD_VALUE; 525 526 Object *object = gUSBStack->GetObject(_hub); 527 if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 528 return B_DEV_INVALID_PIPE; 529 530 Hub *hub = (Hub *)object; 531 for (uint8 i = 0; i < 8; i++) { 532 if (hub->ChildAt(i) == NULL) 533 continue; 534 535 if (index-- > 0) 536 continue; 537 538 *childDevice = hub->ChildAt(i)->USBID(); 539 return B_OK; 540 } 541 542 return B_ENTRY_NOT_FOUND; 543 } 544 545 546 status_t 547 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) 548 { 549 if (!parentHub || !portIndex) 550 return B_BAD_VALUE; 551 552 Object *object = gUSBStack->GetObject(_device); 553 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 554 return B_DEV_INVALID_PIPE; 555 556 Object *parent = object->Parent(); 557 if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0) 558 return B_ENTRY_NOT_FOUND; 559 560 Hub *hub = (Hub *)parent; 561 for (uint8 i = 0; i < 8; i++) { 562 if (hub->ChildAt(i) == object) { 563 *portIndex = i; 564 *parentHub = hub->USBID(); 565 return B_OK; 566 } 567 } 568 569 return B_ERROR; 570 } 571 572 573 status_t 574 reset_port(usb_device _hub, uint8 portIndex) 575 { 576 Object *object = gUSBStack->GetObject(_hub); 577 if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 578 return B_DEV_INVALID_PIPE; 579 580 Hub *hub = (Hub *)object; 581 return hub->ResetPort(portIndex); 582 } 583 584 585 status_t 586 disable_port(usb_device _hub, uint8 portIndex) 587 { 588 Object *object = gUSBStack->GetObject(_hub); 589 if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 590 return B_DEV_INVALID_PIPE; 591 592 Hub *hub = (Hub *)object; 593 return hub->DisablePort(portIndex); 594 } 595 596 597 /* 598 This module exports the USB API v3 599 */ 600 struct usb_module_info gModuleInfoV3 = { 601 // First the bus_manager_info: 602 { 603 { 604 "bus_managers/usb/v3", 605 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 606 bus_std_ops 607 }, 608 NULL // the rescan function 609 }, 610 611 register_driver, // register_driver 612 install_notify, // install_notify 613 uninstall_notify, // uninstall_notify 614 get_device_descriptor, // get_device_descriptor 615 get_nth_configuration, // get_nth_configuration 616 get_configuration, // get_configuration 617 set_configuration, // set_configuration 618 set_alt_interface, // set_alt_interface 619 set_feature, // set_feature 620 clear_feature, // clear_feature 621 get_status, // get_status 622 get_descriptor, // get_descriptor 623 send_request, // send_request 624 queue_interrupt, // queue_interrupt 625 queue_bulk, // queue_bulk 626 queue_bulk_v, // queue_bulk_v 627 queue_isochronous, // queue_isochronous 628 queue_request, // queue_request 629 set_pipe_policy, // set_pipe_policy 630 cancel_queued_transfers, // cancel_queued_transfers 631 usb_ioctl, // usb_ioctl 632 get_nth_roothub, // get_nth_roothub 633 get_nth_child, // get_nth_child 634 get_device_parent, // get_device_parent 635 reset_port, // reset_port 636 disable_port // disable_port 637 //queue_bulk_v_physical // queue_bulk_v_physical 638 }; 639 640 641 // 642 // #pragma mark - 643 // 644 645 646 const usb_device_descriptor * 647 get_device_descriptor_v2(const void *device) 648 { 649 return get_device_descriptor((usb_id)(ssize_t)device); 650 } 651 652 653 const usb_configuration_info * 654 get_nth_configuration_v2(const void *device, uint index) 655 { 656 return get_nth_configuration((usb_id)(ssize_t)device, index); 657 } 658 659 660 const usb_configuration_info * 661 get_configuration_v2(const void *device) 662 { 663 return get_configuration((usb_id)(ssize_t)device); 664 } 665 666 667 status_t 668 set_configuration_v2(const void *device, 669 const usb_configuration_info *configuration) 670 { 671 return set_configuration((usb_id)(ssize_t)device, configuration); 672 } 673 674 675 status_t 676 set_alt_interface_v2(const void *device, const usb_interface_info *interface) 677 { 678 return set_alt_interface((usb_id)(ssize_t)device, interface); 679 } 680 681 682 status_t 683 set_feature_v2(const void *object, uint16 selector) 684 { 685 return set_feature((usb_id)(ssize_t)object, selector); 686 } 687 688 689 status_t 690 clear_feature_v2(const void *object, uint16 selector) 691 { 692 return clear_feature((usb_id)(ssize_t)object, selector); 693 } 694 695 696 status_t 697 get_status_v2(const void *object, uint16 *status) 698 { 699 return get_status((usb_id)(ssize_t)object, status); 700 } 701 702 703 status_t 704 get_descriptor_v2(const void *device, uint8 type, uint8 index, 705 uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 706 { 707 return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data, 708 dataLength, actualLength); 709 } 710 711 712 status_t 713 send_request_v2(const void *device, uint8 requestType, uint8 request, 714 uint16 value, uint16 index, uint16 length, void *data, 715 size_t /*dataLength*/, size_t *actualLength) 716 { 717 return send_request((usb_id)(ssize_t)device, requestType, request, value, index, 718 length, data, actualLength); 719 } 720 721 722 status_t 723 queue_request_v2(const void *device, uint8 requestType, uint8 request, 724 uint16 value, uint16 index, uint16 length, void *data, 725 size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie) 726 { 727 return queue_request((usb_id)(ssize_t)device, requestType, request, value, index, 728 length, data, callback, callbackCookie); 729 } 730 731 732 status_t 733 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength, 734 usb_callback_func callback, void *callbackCookie) 735 { 736 return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback, 737 callbackCookie); 738 } 739 740 741 status_t 742 queue_bulk_v2(const void *pipe, void *data, size_t dataLength, 743 usb_callback_func callback, void *callbackCookie) 744 { 745 return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback, 746 callbackCookie); 747 } 748 749 750 status_t 751 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength, 752 rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 753 void *callbackCookie) 754 { 755 // ToDo: convert rlea to usb_iso_packet_descriptor 756 // ToDo: use a flag to indicate that the callback shall produce a rlea 757 usb_iso_packet_descriptor *packetDesc = NULL; 758 return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0, 759 NULL, 0, callback, callbackCookie); 760 } 761 762 763 status_t 764 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets, 765 uint16 maxBufferDurationMS, uint16 sampleSize) 766 { 767 return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS, 768 sampleSize); 769 } 770 771 772 status_t 773 cancel_queued_transfers_v2(const void *pipe) 774 { 775 return cancel_queued_transfers((usb_id)(ssize_t)pipe); 776 } 777 778 779 struct usb_module_info_v2 { 780 bus_manager_info binfo; 781 status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *); 782 status_t (*install_notify)(const char *, const usb_notify_hooks *); 783 status_t (*uninstall_notify)(const char *); 784 const usb_device_descriptor *(*get_device_descriptor)(const void *); 785 const usb_configuration_info *(*get_nth_configuration)(const void *, uint); 786 const usb_configuration_info *(*get_configuration)(const void *); 787 status_t (*set_configuration)(const void *, const usb_configuration_info *); 788 status_t (*set_alt_interface)(const void *, const usb_interface_info *); 789 status_t (*set_feature)(const void *, uint16); 790 status_t (*clear_feature)(const void *, uint16); 791 status_t (*get_status)(const void *, uint16 *); 792 status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *); 793 status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *); 794 status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *); 795 status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *); 796 status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *); 797 status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *); 798 status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16); 799 status_t (*cancel_queued_transfers)(const void *); 800 status_t (*usb_ioctl)(uint32 opcode, void *,size_t); 801 }; 802 803 804 /* 805 This module exports the USB API v2 806 */ 807 struct usb_module_info_v2 gModuleInfoV2 = { 808 // First the bus_manager_info: 809 { 810 { 811 "bus_managers/usb/v2", 812 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 813 bus_std_ops 814 }, 815 NULL // the rescan function 816 }, 817 818 register_driver, // register_driver 819 install_notify, // install_notify 820 uninstall_notify, // uninstall_notify 821 get_device_descriptor_v2, // get_device_descriptor 822 get_nth_configuration_v2, // get_nth_configuration 823 get_configuration_v2, // get_configuration 824 set_configuration_v2, // set_configuration 825 set_alt_interface_v2, // set_alt_interface 826 set_feature_v2, // set_feature 827 clear_feature_v2, // clear_feature 828 get_status_v2, // get_status 829 get_descriptor_v2, // get_descriptor 830 send_request_v2, // send_request 831 queue_interrupt_v2, // queue_interrupt 832 queue_bulk_v2, // queue_bulk 833 queue_isochronous_v2, // queue_isochronous 834 queue_request_v2, // queue_request 835 set_pipe_policy_v2, // set_pipe_policy 836 cancel_queued_transfers_v2, // cancel_queued_transfers 837 usb_ioctl // usb_ioctl 838 }; 839 840 841 // 842 // #pragma mark - 843 // 844 845 846 module_info *modules[] = { 847 (module_info *)&gModuleInfoV2, 848 (module_info *)&gModuleInfoV3, 849 NULL 850 }; 851