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 17Stack *gUSBStack = NULL; 18device_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*/ 28static status_t 29debug_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 69static int 70debug_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 88static int 89debug_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 105static int 106debug_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 143static int32 144bus_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 201class ObjectBusyReleaser { 202public: 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 233private: 234 Object *fObject; 235}; 236 237 238// #pragma mark - public methods 239 240 241status_t 242register_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 251status_t 252install_notify(const char *driverName, const usb_notify_hooks *hooks) 253{ 254 return gUSBStack->InstallNotify(driverName, hooks); 255} 256 257 258status_t 259uninstall_notify(const char *driverName) 260{ 261 return gUSBStack->UninstallNotify(driverName); 262} 263 264 265const usb_device_descriptor * 266get_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 278const usb_configuration_info * 279get_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 292const usb_configuration_info * 293get_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 305status_t 306set_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 320status_t 321set_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 333status_t 334set_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 345status_t 346clear_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 357status_t 358get_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 372status_t 373get_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 389status_t 390send_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 406status_t 407queue_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 424status_t 425queue_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 439status_t 440queue_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 454status_t 455queue_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); 466} 467 468 469status_t 470queue_bulk_v_physical(usb_pipe pipe, physical_entry *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); 481} 482 483 484status_t 485queue_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 504status_t 505set_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 519status_t 520cancel_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 531status_t 532cancel_queued_requests(usb_device dev) 533{ 534 TRACE_MODULE("cancel_queued_requests(%" B_PRId32 ")\n", dev); 535 ObjectBusyReleaser object(gUSBStack->GetObject(dev)); 536 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 537 return B_DEV_INVALID_PIPE; 538 Device *device = (Device *)object.Get(); 539 540 return device->DefaultPipe()->CancelQueuedTransfers(false); 541} 542 543 544status_t 545usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 546{ 547 TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode, 548 buffer, bufferSize); 549 550 switch (opcode) { 551 case 'DNAM': { 552 ObjectBusyReleaser object(gUSBStack->GetObject(*(usb_id *)buffer)); 553 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 554 return B_BAD_VALUE; 555 Device *device = (Device *)object.Get(); 556 557 uint32 index = 0; 558 return device->BuildDeviceName((char *)buffer, &index, 559 bufferSize, NULL); 560 } 561 } 562 563 return B_DEV_INVALID_IOCTL; 564} 565 566 567status_t 568get_nth_roothub(uint32 index, usb_device *rootHub) 569{ 570 if (!rootHub) 571 return B_BAD_VALUE; 572 573 BusManager *busManager = gUSBStack->BusManagerAt(index); 574 if (!busManager) 575 return B_ENTRY_NOT_FOUND; 576 577 Hub *hub = busManager->GetRootHub(); 578 if (!hub) 579 return B_NO_INIT; 580 581 *rootHub = hub->USBID(); 582 return B_OK; 583} 584 585 586status_t 587get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice) 588{ 589 if (!childDevice) 590 return B_BAD_VALUE; 591 592 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 593 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 594 return B_DEV_INVALID_PIPE; 595 596 Hub *hub = (Hub *)object.Get(); 597 for (uint8 i = 0; i < 8; i++) { 598 if (hub->ChildAt(i) == NULL) 599 continue; 600 601 if (index-- > 0) 602 continue; 603 604 *childDevice = hub->ChildAt(i)->USBID(); 605 return B_OK; 606 } 607 608 return B_ENTRY_NOT_FOUND; 609} 610 611 612status_t 613get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) 614{ 615 if (!parentHub || !portIndex) 616 return B_BAD_VALUE; 617 618 ObjectBusyReleaser object(gUSBStack->GetObject(_device)); 619 if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) 620 return B_DEV_INVALID_PIPE; 621 622 Object *parent = object->Parent(); 623 if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0) 624 return B_ENTRY_NOT_FOUND; 625 626 Hub *hub = (Hub *)parent; 627 for (uint8 i = 0; i < 8; i++) { 628 if (hub->ChildAt(i) == object.Get()) { 629 *portIndex = i; 630 *parentHub = hub->USBID(); 631 return B_OK; 632 } 633 } 634 635 return B_ERROR; 636} 637 638 639status_t 640reset_port(usb_device _hub, uint8 portIndex) 641{ 642 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 643 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 644 return B_DEV_INVALID_PIPE; 645 646 Hub *hub = (Hub *)object.Get(); 647 return hub->ResetPort(portIndex); 648} 649 650 651status_t 652disable_port(usb_device _hub, uint8 portIndex) 653{ 654 ObjectBusyReleaser object(gUSBStack->GetObject(_hub)); 655 if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0) 656 return B_DEV_INVALID_PIPE; 657 658 Hub *hub = (Hub *)object.Get(); 659 return hub->DisablePort(portIndex); 660} 661 662 663/* 664 This module exports the USB API v3 665*/ 666struct usb_module_info gModuleInfoV3 = { 667 // First the bus_manager_info: 668 { 669 { 670 "bus_managers/usb/v3.1", 671 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 672 bus_std_ops 673 }, 674 NULL // the rescan function 675 }, 676 677 register_driver, // register_driver 678 install_notify, // install_notify 679 uninstall_notify, // uninstall_notify 680 get_device_descriptor, // get_device_descriptor 681 get_nth_configuration, // get_nth_configuration 682 get_configuration, // get_configuration 683 set_configuration, // set_configuration 684 set_alt_interface, // set_alt_interface 685 set_feature, // set_feature 686 clear_feature, // clear_feature 687 get_status, // get_status 688 get_descriptor, // get_descriptor 689 send_request, // send_request 690 queue_interrupt, // queue_interrupt 691 queue_bulk, // queue_bulk 692 queue_bulk_v, // queue_bulk_v 693 queue_bulk_v_physical, // queue_bulk_v_physical 694 queue_isochronous, // queue_isochronous 695 queue_request, // queue_request 696 set_pipe_policy, // set_pipe_policy 697 cancel_queued_transfers, // cancel_queued_transfers 698 cancel_queued_requests, // cancel_queued_requests 699 usb_ioctl, // usb_ioctl 700 get_nth_roothub, // get_nth_roothub 701 get_nth_child, // get_nth_child 702 get_device_parent, // get_device_parent 703 reset_port, // reset_port 704 disable_port, // disable_port 705}; 706 707 708// 709// #pragma mark - 710// 711 712 713const usb_device_descriptor * 714get_device_descriptor_v2(const void *device) 715{ 716 return get_device_descriptor((usb_id)(ssize_t)device); 717} 718 719 720const usb_configuration_info * 721get_nth_configuration_v2(const void *device, uint index) 722{ 723 return get_nth_configuration((usb_id)(ssize_t)device, index); 724} 725 726 727const usb_configuration_info * 728get_configuration_v2(const void *device) 729{ 730 return get_configuration((usb_id)(ssize_t)device); 731} 732 733 734status_t 735set_configuration_v2(const void *device, 736 const usb_configuration_info *configuration) 737{ 738 return set_configuration((usb_id)(ssize_t)device, configuration); 739} 740 741 742status_t 743set_alt_interface_v2(const void *device, const usb_interface_info *interface) 744{ 745 return set_alt_interface((usb_id)(ssize_t)device, interface); 746} 747 748 749status_t 750set_feature_v2(const void *object, uint16 selector) 751{ 752 return set_feature((usb_id)(ssize_t)object, selector); 753} 754 755 756status_t 757clear_feature_v2(const void *object, uint16 selector) 758{ 759 return clear_feature((usb_id)(ssize_t)object, selector); 760} 761 762 763status_t 764get_status_v2(const void *object, uint16 *status) 765{ 766 return get_status((usb_id)(ssize_t)object, status); 767} 768 769 770status_t 771get_descriptor_v2(const void *device, uint8 type, uint8 index, 772 uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 773{ 774 return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data, 775 dataLength, actualLength); 776} 777 778 779status_t 780send_request_v2(const void *device, uint8 requestType, uint8 request, 781 uint16 value, uint16 index, uint16 length, void *data, 782 size_t /*dataLength*/, size_t *actualLength) 783{ 784 return send_request((usb_id)(ssize_t)device, requestType, request, value, index, 785 length, data, actualLength); 786} 787 788 789status_t 790queue_request_v2(const void *device, uint8 requestType, uint8 request, 791 uint16 value, uint16 index, uint16 length, void *data, 792 size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie) 793{ 794 return queue_request((usb_id)(ssize_t)device, requestType, request, value, index, 795 length, data, callback, callbackCookie); 796} 797 798 799status_t 800queue_interrupt_v2(const void *pipe, void *data, size_t dataLength, 801 usb_callback_func callback, void *callbackCookie) 802{ 803 return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback, 804 callbackCookie); 805} 806 807 808status_t 809queue_bulk_v2(const void *pipe, void *data, size_t dataLength, 810 usb_callback_func callback, void *callbackCookie) 811{ 812 return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback, 813 callbackCookie); 814} 815 816 817status_t 818queue_isochronous_v2(const void *pipe, void *data, size_t dataLength, 819 rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 820 void *callbackCookie) 821{ 822 // ToDo: convert rlea to usb_iso_packet_descriptor 823 // ToDo: use a flag to indicate that the callback shall produce a rlea 824 usb_iso_packet_descriptor *packetDesc = NULL; 825 return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0, 826 NULL, 0, callback, callbackCookie); 827} 828 829 830status_t 831set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets, 832 uint16 maxBufferDurationMS, uint16 sampleSize) 833{ 834 return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS, 835 sampleSize); 836} 837 838 839status_t 840cancel_queued_transfers_v2(const void *pipe) 841{ 842 return cancel_queued_transfers((usb_id)(ssize_t)pipe); 843} 844 845 846struct usb_module_info_v2 { 847 bus_manager_info binfo; 848 status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *); 849 status_t (*install_notify)(const char *, const usb_notify_hooks *); 850 status_t (*uninstall_notify)(const char *); 851 const usb_device_descriptor *(*get_device_descriptor)(const void *); 852 const usb_configuration_info *(*get_nth_configuration)(const void *, uint); 853 const usb_configuration_info *(*get_configuration)(const void *); 854 status_t (*set_configuration)(const void *, const usb_configuration_info *); 855 status_t (*set_alt_interface)(const void *, const usb_interface_info *); 856 status_t (*set_feature)(const void *, uint16); 857 status_t (*clear_feature)(const void *, uint16); 858 status_t (*get_status)(const void *, uint16 *); 859 status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *); 860 status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *); 861 status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *); 862 status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *); 863 status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *); 864 status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *); 865 status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16); 866 status_t (*cancel_queued_transfers)(const void *); 867 status_t (*usb_ioctl)(uint32 opcode, void *,size_t); 868}; 869 870 871/* 872 This module exports the USB API v2 873*/ 874struct usb_module_info_v2 gModuleInfoV2 = { 875 // First the bus_manager_info: 876 { 877 { 878 "bus_managers/usb/v2", 879 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 880 bus_std_ops 881 }, 882 NULL // the rescan function 883 }, 884 885 register_driver, // register_driver 886 install_notify, // install_notify 887 uninstall_notify, // uninstall_notify 888 get_device_descriptor_v2, // get_device_descriptor 889 get_nth_configuration_v2, // get_nth_configuration 890 get_configuration_v2, // get_configuration 891 set_configuration_v2, // set_configuration 892 set_alt_interface_v2, // set_alt_interface 893 set_feature_v2, // set_feature 894 clear_feature_v2, // clear_feature 895 get_status_v2, // get_status 896 get_descriptor_v2, // get_descriptor 897 send_request_v2, // send_request 898 queue_interrupt_v2, // queue_interrupt 899 queue_bulk_v2, // queue_bulk 900 queue_isochronous_v2, // queue_isochronous 901 queue_request_v2, // queue_request 902 set_pipe_policy_v2, // set_pipe_policy 903 cancel_queued_transfers_v2, // cancel_queued_transfers 904 usb_ioctl // usb_ioctl 905}; 906 907 908// 909// #pragma mark - 910// 911 912 913status_t 914usb_added_device(device_node *parent) 915{ 916 return B_OK; 917} 918 919 920status_t 921usb_get_stack(void** stack) 922{ 923 *stack = gUSBStack; 924 return B_OK; 925} 926 927 928usb_for_controller_interface gForControllerModule = { 929 { 930 { 931 USB_FOR_CONTROLLER_MODULE_NAME, 932 B_KEEP_LOADED, 933 &bus_std_ops 934 }, 935 936 NULL, // supported devices 937 usb_added_device, 938 NULL, 939 NULL, 940 NULL 941 }, 942 943 usb_get_stack, 944}; 945 946 947static status_t 948device_std_ops(int32 op, ...) 949{ 950 switch (op) { 951 case B_MODULE_INIT: 952 { 953 // Link to USB bus. 954 // USB device driver must have USB bus loaded, but it calls its 955 // functions directly instead via official interface, so this 956 // pointer is never read. 957 module_info *dummy; 958 return get_module(B_USB_MODULE_NAME, &dummy); 959 } 960 case B_MODULE_UNINIT: 961 return put_module(B_USB_MODULE_NAME); 962 963 default: 964 return B_ERROR; 965 } 966} 967 968 969usb_device_interface gUSBDeviceModule = { 970 { 971 { 972 USB_DEVICE_MODULE_NAME, 973 0, 974 device_std_ops 975 }, 976 977 NULL, // supported devices 978 NULL, // register node 979 NULL, //usb_init_device, 980 NULL, // (void (*)(void *)) usb_uninit_device, 981 NULL, // register child devices 982 NULL, // rescan 983 NULL// (void (*)(void *)) usb_device_removed 984 }, 985}; 986 987 988module_dependency module_dependencies[] = { 989 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 990 {} 991}; 992 993 994module_info *modules[] = { 995 (module_info *)&gModuleInfoV2, 996 (module_info *)&gModuleInfoV3, 997 (module_info *)&gForControllerModule, 998 (module_info *)&gUSBDeviceModule, 999 NULL 1000}; 1001