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