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