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 // #pragma mark - ObjectBusyReleaser 198 199 200 class ObjectBusyReleaser { 201 public: 202 ObjectBusyReleaser(Object* object) : fObject(object) {} 203 204 ~ObjectBusyReleaser() 205 { 206 Release(); 207 } 208 209 void Release() 210 { 211 if (fObject != NULL) { 212 fObject->SetBusy(false); 213 fObject = NULL; 214 } 215 } 216 217 inline bool IsSet() const 218 { 219 return fObject != NULL; 220 } 221 222 inline Object *Get() const 223 { 224 return fObject; 225 } 226 227 inline Object *operator->() const 228 { 229 return fObject; 230 } 231 232 private: 233 Object *fObject; 234 }; 235 236 237 // #pragma mark - public methods 238 239 240 status_t 241 register_driver(const char *driverName, 242 const usb_support_descriptor *descriptors, 243 size_t count, const char *optionalRepublishDriverName) 244 { 245 return gUSBStack->RegisterDriver(driverName, descriptors, count, 246 optionalRepublishDriverName); 247 } 248 249 250 status_t 251 install_notify(const char *driverName, const usb_notify_hooks *hooks) 252 { 253 return gUSBStack->InstallNotify(driverName, hooks); 254 } 255 256 257 status_t 258 uninstall_notify(const char *driverName) 259 { 260 return gUSBStack->UninstallNotify(driverName); 261 } 262 263 264 const usb_device_descriptor * 265 get_device_descriptor(usb_device dev) 266 { 267 TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev); 268 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 269 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 270 return NULL; 271 Device *device = (Device *)object.Get(); 272 273 return device->DeviceDescriptor(); 274 } 275 276 277 const usb_configuration_info * 278 get_nth_configuration(usb_device dev, uint32 index) 279 { 280 TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n", 281 dev, index); 282 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 283 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 284 return NULL; 285 Device *device = (Device *)object.Get(); 286 287 return device->ConfigurationAt((int32)index); 288 } 289 290 291 const usb_configuration_info * 292 get_configuration(usb_device dev) 293 { 294 TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev); 295 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 296 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 297 return NULL; 298 Device *device = (Device *)object.Get(); 299 300 return device->Configuration(); 301 } 302 303 304 status_t 305 set_configuration(usb_device dev, 306 const usb_configuration_info *configuration) 307 { 308 TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev, 309 configuration); 310 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 311 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 312 return B_DEV_INVALID_PIPE; 313 Device *device = (Device *)object.Get(); 314 315 return device->SetConfiguration(configuration); 316 } 317 318 319 status_t 320 set_alt_interface(usb_device dev, const usb_interface_info *interface) 321 { 322 TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface); 323 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 324 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 325 return B_DEV_INVALID_PIPE; 326 Device *device = (Device *)object.Get(); 327 328 return device->SetAltInterface(interface); 329 } 330 331 332 status_t 333 set_feature(usb_id handle, uint16 selector) 334 { 335 TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector); 336 ObjectBusyReleaser object(gUSBStack->GetObject(handle)); 337 if (!object.IsSet()) 338 return B_DEV_INVALID_PIPE; 339 340 return object->SetFeature(selector); 341 } 342 343 344 status_t 345 clear_feature(usb_id handle, uint16 selector) 346 { 347 TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector); 348 ObjectBusyReleaser object(gUSBStack->GetObject(handle)); 349 if (!object.IsSet()) 350 return B_DEV_INVALID_PIPE; 351 352 return object->ClearFeature(selector); 353 } 354 355 356 status_t 357 get_status(usb_id handle, uint16 *status) 358 { 359 TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status); 360 if (!status) 361 return B_BAD_VALUE; 362 363 ObjectBusyReleaser object(gUSBStack->GetObject(handle)); 364 if (!object.IsSet()) 365 return B_DEV_INVALID_PIPE; 366 367 return object->GetStatus(status); 368 } 369 370 371 status_t 372 get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID, 373 void *data, size_t dataLength, size_t *actualLength) 374 { 375 TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, " 376 "%" B_PRIuSIZE ", %p)\n", 377 dev, type, index, languageID, data, dataLength, actualLength); 378 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 379 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 380 return B_DEV_INVALID_PIPE; 381 Device *device = (Device *)object.Get(); 382 383 return device->GetDescriptor(type, index, languageID, 384 data, dataLength, actualLength); 385 } 386 387 388 status_t 389 send_request(usb_device dev, uint8 requestType, uint8 request, 390 uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength) 391 { 392 TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, " 393 "%d, %p, %p)\n", dev, requestType, request, value, index, length, 394 data, actualLength); 395 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 396 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 397 return B_DEV_INVALID_PIPE; 398 Device *device = (Device *)object.Get(); 399 400 return device->DefaultPipe()->SendRequest(requestType, request, 401 value, index, length, data, length, actualLength); 402 } 403 404 405 status_t 406 queue_request(usb_device dev, uint8 requestType, uint8 request, 407 uint16 value, uint16 index, uint16 length, void *data, 408 usb_callback_func callback, void *callbackCookie) 409 { 410 TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x," 411 " %u, %p, %p, %p)\n", dev, requestType, request, value, index, 412 length, data, callback, callbackCookie); 413 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 414 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 415 return B_DEV_INVALID_PIPE; 416 Device *device = (Device *)object.Get(); 417 418 return device->DefaultPipe()->QueueRequest(requestType, 419 request, value, index, length, data, length, callback, callbackCookie); 420 } 421 422 423 status_t 424 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, 425 usb_callback_func callback, void *callbackCookie) 426 { 427 TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n", 428 pipe, data, dataLength, callback, callbackCookie); 429 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 430 if (!object.IsSet() || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) 431 return B_DEV_INVALID_PIPE; 432 433 return ((InterruptPipe *)object.Get())->QueueInterrupt(data, dataLength, 434 callback, callbackCookie); 435 } 436 437 438 status_t 439 queue_bulk(usb_pipe pipe, void *data, size_t dataLength, 440 usb_callback_func callback, void *callbackCookie) 441 { 442 TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n", 443 pipe, data, dataLength, callback, callbackCookie); 444 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 445 if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 446 return B_DEV_INVALID_PIPE; 447 448 return ((BulkPipe *)object.Get())->QueueBulk(data, dataLength, callback, 449 callbackCookie); 450 } 451 452 453 status_t 454 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, 455 usb_callback_func callback, void *callbackCookie) 456 { 457 TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n", 458 pipe, vector, vectorCount, callback, callbackCookie); 459 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 460 if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 461 return B_DEV_INVALID_PIPE; 462 463 return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount, 464 callback, callbackCookie, false); 465 } 466 467 468 status_t 469 queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount, 470 usb_callback_func callback, void *callbackCookie) 471 { 472 TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE 473 ", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie); 474 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 475 if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 476 return B_DEV_INVALID_PIPE; 477 478 return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount, 479 callback, callbackCookie, true); 480 } 481 482 483 status_t 484 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, 485 usb_iso_packet_descriptor *packetDesc, uint32 packetCount, 486 uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback, 487 void *callbackCookie) 488 { 489 TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, " 490 "%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n", 491 pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, 492 flags, callback, callbackCookie); 493 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 494 if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 495 return B_DEV_INVALID_PIPE; 496 497 return ((IsochronousPipe *)object.Get())->QueueIsochronous(data, dataLength, 498 packetDesc, packetCount, startingFrameNumber, flags, callback, 499 callbackCookie); 500 } 501 502 503 status_t 504 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, 505 uint16 maxBufferDurationMS, uint16 sampleSize) 506 { 507 TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe, 508 maxQueuedPackets, maxBufferDurationMS, sampleSize); 509 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 510 if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 511 return B_DEV_INVALID_PIPE; 512 513 return ((IsochronousPipe *)object.IsSet())->SetPipePolicy(maxQueuedPackets, 514 maxBufferDurationMS, sampleSize); 515 } 516 517 518 status_t 519 cancel_queued_transfers(usb_pipe pipe) 520 { 521 TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe); 522 ObjectBusyReleaser object(gUSBStack->GetObject(pipe)); 523 if (!object.IsSet() || (object->Type() & USB_OBJECT_PIPE) == 0) 524 return B_DEV_INVALID_PIPE; 525 526 return ((Pipe *)object.Get())->CancelQueuedTransfers(false); 527 } 528 529 530 status_t 531 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 532 { 533 TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode, 534 buffer, bufferSize); 535 536 switch (opcode) { 537 case 'DNAM': { 538 ObjectBusyReleaser object(gUSBStack->GetObject(*(usb_id *)buffer)); 539 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 540 return B_BAD_VALUE; 541 Device *device = (Device *)object.Get(); 542 543 uint32 index = 0; 544 return device->BuildDeviceName((char *)buffer, &index, 545 bufferSize, NULL); 546 } 547 } 548 549 return B_DEV_INVALID_IOCTL; 550 } 551 552 553 status_t 554 get_nth_roothub(uint32 index, usb_device *rootHub) 555 { 556 if (!rootHub) 557 return B_BAD_VALUE; 558 559 BusManager *busManager = gUSBStack->BusManagerAt(index); 560 if (!busManager) 561 return B_ENTRY_NOT_FOUND; 562 563 Hub *hub = busManager->GetRootHub(); 564 if (!hub) 565 return B_NO_INIT; 566 567 *rootHub = hub->USBID(); 568 return B_OK; 569 } 570 571 572 status_t 573 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice) 574 { 575 if (!childDevice) 576 return B_BAD_VALUE; 577 578 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 579 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 580 return B_DEV_INVALID_PIPE; 581 582 Hub *hub = (Hub *)object.Get(); 583 for (uint8 i = 0; i < 8; i++) { 584 if (hub->ChildAt(i) == NULL) 585 continue; 586 587 if (index-- > 0) 588 continue; 589 590 *childDevice = hub->ChildAt(i)->USBID(); 591 return B_OK; 592 } 593 594 return B_ENTRY_NOT_FOUND; 595 } 596 597 598 status_t 599 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) 600 { 601 if (!parentHub || !portIndex) 602 return B_BAD_VALUE; 603 604 ObjectBusyReleaser object(gUSBStack->GetObject(_device)); 605 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 606 return B_DEV_INVALID_PIPE; 607 608 Object *parent = object->Parent(); 609 if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0) 610 return B_ENTRY_NOT_FOUND; 611 612 Hub *hub = (Hub *)parent; 613 for (uint8 i = 0; i < 8; i++) { 614 if (hub->ChildAt(i) == object.Get()) { 615 *portIndex = i; 616 *parentHub = hub->USBID(); 617 return B_OK; 618 } 619 } 620 621 return B_ERROR; 622 } 623 624 625 status_t 626 reset_port(usb_device _hub, uint8 portIndex) 627 { 628 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 629 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 630 return B_DEV_INVALID_PIPE; 631 632 Hub *hub = (Hub *)object.Get(); 633 return hub->ResetPort(portIndex); 634 } 635 636 637 status_t 638 disable_port(usb_device _hub, uint8 portIndex) 639 { 640 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 641 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 642 return B_DEV_INVALID_PIPE; 643 644 Hub *hub = (Hub *)object.Get(); 645 return hub->DisablePort(portIndex); 646 } 647 648 649 /* 650 This module exports the USB API v3 651 */ 652 struct usb_module_info gModuleInfoV3 = { 653 // First the bus_manager_info: 654 { 655 { 656 "bus_managers/usb/v3", 657 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 658 bus_std_ops 659 }, 660 NULL // the rescan function 661 }, 662 663 register_driver, // register_driver 664 install_notify, // install_notify 665 uninstall_notify, // uninstall_notify 666 get_device_descriptor, // get_device_descriptor 667 get_nth_configuration, // get_nth_configuration 668 get_configuration, // get_configuration 669 set_configuration, // set_configuration 670 set_alt_interface, // set_alt_interface 671 set_feature, // set_feature 672 clear_feature, // clear_feature 673 get_status, // get_status 674 get_descriptor, // get_descriptor 675 send_request, // send_request 676 queue_interrupt, // queue_interrupt 677 queue_bulk, // queue_bulk 678 queue_bulk_v, // queue_bulk_v 679 queue_isochronous, // queue_isochronous 680 queue_request, // queue_request 681 set_pipe_policy, // set_pipe_policy 682 cancel_queued_transfers, // cancel_queued_transfers 683 usb_ioctl, // usb_ioctl 684 get_nth_roothub, // get_nth_roothub 685 get_nth_child, // get_nth_child 686 get_device_parent, // get_device_parent 687 reset_port, // reset_port 688 disable_port // disable_port 689 //queue_bulk_v_physical // queue_bulk_v_physical 690 }; 691 692 693 // 694 // #pragma mark - 695 // 696 697 698 const usb_device_descriptor * 699 get_device_descriptor_v2(const void *device) 700 { 701 return get_device_descriptor((usb_id)(ssize_t)device); 702 } 703 704 705 const usb_configuration_info * 706 get_nth_configuration_v2(const void *device, uint index) 707 { 708 return get_nth_configuration((usb_id)(ssize_t)device, index); 709 } 710 711 712 const usb_configuration_info * 713 get_configuration_v2(const void *device) 714 { 715 return get_configuration((usb_id)(ssize_t)device); 716 } 717 718 719 status_t 720 set_configuration_v2(const void *device, 721 const usb_configuration_info *configuration) 722 { 723 return set_configuration((usb_id)(ssize_t)device, configuration); 724 } 725 726 727 status_t 728 set_alt_interface_v2(const void *device, const usb_interface_info *interface) 729 { 730 return set_alt_interface((usb_id)(ssize_t)device, interface); 731 } 732 733 734 status_t 735 set_feature_v2(const void *object, uint16 selector) 736 { 737 return set_feature((usb_id)(ssize_t)object, selector); 738 } 739 740 741 status_t 742 clear_feature_v2(const void *object, uint16 selector) 743 { 744 return clear_feature((usb_id)(ssize_t)object, selector); 745 } 746 747 748 status_t 749 get_status_v2(const void *object, uint16 *status) 750 { 751 return get_status((usb_id)(ssize_t)object, status); 752 } 753 754 755 status_t 756 get_descriptor_v2(const void *device, uint8 type, uint8 index, 757 uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 758 { 759 return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data, 760 dataLength, actualLength); 761 } 762 763 764 status_t 765 send_request_v2(const void *device, uint8 requestType, uint8 request, 766 uint16 value, uint16 index, uint16 length, void *data, 767 size_t /*dataLength*/, size_t *actualLength) 768 { 769 return send_request((usb_id)(ssize_t)device, requestType, request, value, index, 770 length, data, actualLength); 771 } 772 773 774 status_t 775 queue_request_v2(const void *device, uint8 requestType, uint8 request, 776 uint16 value, uint16 index, uint16 length, void *data, 777 size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie) 778 { 779 return queue_request((usb_id)(ssize_t)device, requestType, request, value, index, 780 length, data, callback, callbackCookie); 781 } 782 783 784 status_t 785 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength, 786 usb_callback_func callback, void *callbackCookie) 787 { 788 return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback, 789 callbackCookie); 790 } 791 792 793 status_t 794 queue_bulk_v2(const void *pipe, void *data, size_t dataLength, 795 usb_callback_func callback, void *callbackCookie) 796 { 797 return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback, 798 callbackCookie); 799 } 800 801 802 status_t 803 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength, 804 rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 805 void *callbackCookie) 806 { 807 // ToDo: convert rlea to usb_iso_packet_descriptor 808 // ToDo: use a flag to indicate that the callback shall produce a rlea 809 usb_iso_packet_descriptor *packetDesc = NULL; 810 return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0, 811 NULL, 0, callback, callbackCookie); 812 } 813 814 815 status_t 816 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets, 817 uint16 maxBufferDurationMS, uint16 sampleSize) 818 { 819 return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS, 820 sampleSize); 821 } 822 823 824 status_t 825 cancel_queued_transfers_v2(const void *pipe) 826 { 827 return cancel_queued_transfers((usb_id)(ssize_t)pipe); 828 } 829 830 831 struct usb_module_info_v2 { 832 bus_manager_info binfo; 833 status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *); 834 status_t (*install_notify)(const char *, const usb_notify_hooks *); 835 status_t (*uninstall_notify)(const char *); 836 const usb_device_descriptor *(*get_device_descriptor)(const void *); 837 const usb_configuration_info *(*get_nth_configuration)(const void *, uint); 838 const usb_configuration_info *(*get_configuration)(const void *); 839 status_t (*set_configuration)(const void *, const usb_configuration_info *); 840 status_t (*set_alt_interface)(const void *, const usb_interface_info *); 841 status_t (*set_feature)(const void *, uint16); 842 status_t (*clear_feature)(const void *, uint16); 843 status_t (*get_status)(const void *, uint16 *); 844 status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *); 845 status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *); 846 status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *); 847 status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *); 848 status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *); 849 status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *); 850 status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16); 851 status_t (*cancel_queued_transfers)(const void *); 852 status_t (*usb_ioctl)(uint32 opcode, void *,size_t); 853 }; 854 855 856 /* 857 This module exports the USB API v2 858 */ 859 struct usb_module_info_v2 gModuleInfoV2 = { 860 // First the bus_manager_info: 861 { 862 { 863 "bus_managers/usb/v2", 864 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 865 bus_std_ops 866 }, 867 NULL // the rescan function 868 }, 869 870 register_driver, // register_driver 871 install_notify, // install_notify 872 uninstall_notify, // uninstall_notify 873 get_device_descriptor_v2, // get_device_descriptor 874 get_nth_configuration_v2, // get_nth_configuration 875 get_configuration_v2, // get_configuration 876 set_configuration_v2, // set_configuration 877 set_alt_interface_v2, // set_alt_interface 878 set_feature_v2, // set_feature 879 clear_feature_v2, // clear_feature 880 get_status_v2, // get_status 881 get_descriptor_v2, // get_descriptor 882 send_request_v2, // send_request 883 queue_interrupt_v2, // queue_interrupt 884 queue_bulk_v2, // queue_bulk 885 queue_isochronous_v2, // queue_isochronous 886 queue_request_v2, // queue_request 887 set_pipe_policy_v2, // set_pipe_policy 888 cancel_queued_transfers_v2, // cancel_queued_transfers 889 usb_ioctl // usb_ioctl 890 }; 891 892 893 // 894 // #pragma mark - 895 // 896 897 898 module_info *modules[] = { 899 (module_info *)&gModuleInfoV2, 900 (module_info *)&gModuleInfoV3, 901 NULL 902 }; 903