196da8285SMichael Lotz /* 296da8285SMichael Lotz * Copyright 2003-2006, Haiku Inc. All rights reserved. 396da8285SMichael Lotz * Distributed under the terms of the MIT License. 496da8285SMichael Lotz * 596da8285SMichael Lotz * Authors: 65b0ec61fSMichael Lotz * Michael Lotz <mmlr@mlotz.ch> 796da8285SMichael Lotz * Niels S. Reedijk 896da8285SMichael Lotz */ 91501c2bfSNiels Sascha Reedijk 1021c87a5dSJérôme Duval 111501c2bfSNiels Sascha Reedijk #include <util/kernel_cpp.h> 12853e6be8SMichael Lotz #include "usb_private.h" 131bad4a4eSMichael Lotz #include <USB_rle.h> 141501c2bfSNiels Sascha Reedijk 15f14fe767SMichael Lotz #define USB_MODULE_NAME "module" 1696da8285SMichael Lotz 17b8c6a851SMichael Lotz Stack *gUSBStack = NULL; 18b8c6a851SMichael Lotz 19b8c6a851SMichael Lotz 20159aa93bSMichael Lotz /*! The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to 21159aa93bSMichael Lotz execute transfers. 22159aa93bSMichael Lotz When invoked the first time, a new transfer is started, each time the 23159aa93bSMichael Lotz function is called afterwards, it is checked whether the transfer is already 24159aa93bSMichael Lotz completed. If called with argv[1] == "cancel" the function cancels a 25159aa93bSMichael Lotz possibly pending transfer. 26159aa93bSMichael Lotz */ 27159aa93bSMichael Lotz static status_t 28159aa93bSMichael Lotz debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength, 29159aa93bSMichael Lotz usb_request_data *requestData, bool cancel) 30159aa93bSMichael Lotz { 31159aa93bSMichael Lotz static uint8 transferBuffer[sizeof(Transfer)] 32159aa93bSMichael Lotz __attribute__((aligned(16))); 33159aa93bSMichael Lotz static Transfer *transfer = NULL; 34159aa93bSMichael Lotz 35159aa93bSMichael Lotz BusManager *bus = pipe->GetBusManager(); 36159aa93bSMichael Lotz 37159aa93bSMichael Lotz if (cancel) { 38159aa93bSMichael Lotz if (transfer != NULL) { 39159aa93bSMichael Lotz bus->CancelDebugTransfer(transfer); 40159aa93bSMichael Lotz transfer = NULL; 41159aa93bSMichael Lotz } 42159aa93bSMichael Lotz 43159aa93bSMichael Lotz return B_OK; 44159aa93bSMichael Lotz } 45159aa93bSMichael Lotz 46159aa93bSMichael Lotz if (transfer != NULL) { 47159aa93bSMichael Lotz status_t error = bus->CheckDebugTransfer(transfer); 48159aa93bSMichael Lotz if (error != B_DEV_PENDING) 49159aa93bSMichael Lotz transfer = NULL; 50159aa93bSMichael Lotz 51159aa93bSMichael Lotz return error; 52159aa93bSMichael Lotz } 53159aa93bSMichael Lotz 54159aa93bSMichael Lotz transfer = new(transferBuffer) Transfer(pipe); 55159aa93bSMichael Lotz transfer->SetData(data, dataLength); 56159aa93bSMichael Lotz transfer->SetRequestData(requestData); 57159aa93bSMichael Lotz 58159aa93bSMichael Lotz status_t error = bus->StartDebugTransfer(transfer); 59159aa93bSMichael Lotz if (error != B_OK) { 60159aa93bSMichael Lotz transfer = NULL; 61159aa93bSMichael Lotz return error; 62159aa93bSMichael Lotz } 63159aa93bSMichael Lotz 64159aa93bSMichael Lotz return B_DEV_PENDING; 65159aa93bSMichael Lotz } 66159aa93bSMichael Lotz 67159aa93bSMichael Lotz 686eba0636SMichael Lotz static int 696eba0636SMichael Lotz debug_get_pipe_for_id(int argc, char **argv) 706eba0636SMichael Lotz { 716eba0636SMichael Lotz if (gUSBStack == NULL) 726eba0636SMichael Lotz return 1; 736eba0636SMichael Lotz 746eba0636SMichael Lotz if (!is_debug_variable_defined("_usbPipeID")) 756eba0636SMichael Lotz return 2; 766eba0636SMichael Lotz 776eba0636SMichael Lotz uint64 id = get_debug_variable("_usbPipeID", 0); 786eba0636SMichael Lotz Object *object = gUSBStack->GetObjectNoLock((usb_id)id); 796eba0636SMichael Lotz if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) 806eba0636SMichael Lotz return 3; 816eba0636SMichael Lotz 826eba0636SMichael Lotz set_debug_variable("_usbPipe", (uint64)object); 836eba0636SMichael Lotz return 0; 846eba0636SMichael Lotz } 85159aa93bSMichael Lotz 86159aa93bSMichael Lotz 87159aa93bSMichael Lotz static int 88159aa93bSMichael Lotz debug_process_transfer(int argc, char **argv) 89159aa93bSMichael Lotz { 90159aa93bSMichael Lotz Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0); 91159aa93bSMichael Lotz if (pipe == NULL) 92159aa93bSMichael Lotz return B_BAD_VALUE; 93159aa93bSMichael Lotz 94159aa93bSMichael Lotz uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0); 95159aa93bSMichael Lotz size_t length = (size_t)get_debug_variable("_usbTransferLength", 0); 96159aa93bSMichael Lotz usb_request_data *requestData 97159aa93bSMichael Lotz = (usb_request_data *)get_debug_variable("_usbRequestData", 0); 98159aa93bSMichael Lotz 99159aa93bSMichael Lotz return debug_run_transfer(pipe, data, length, requestData, 100159aa93bSMichael Lotz argc > 1 && strcmp(argv[1], "cancel") == 0); 101159aa93bSMichael Lotz } 102e31cac6eSMichael Lotz 103e31cac6eSMichael Lotz 104e31cac6eSMichael Lotz static int 105e31cac6eSMichael Lotz debug_clear_stall(int argc, char *argv[]) 106e31cac6eSMichael Lotz { 107e31cac6eSMichael Lotz Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0); 108e31cac6eSMichael Lotz if (pipe == NULL) 109e31cac6eSMichael Lotz return B_BAD_VALUE; 110e31cac6eSMichael Lotz 111e31cac6eSMichael Lotz static usb_request_data requestData; 112e31cac6eSMichael Lotz 113e31cac6eSMichael Lotz requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT; 114e31cac6eSMichael Lotz requestData.Request = USB_REQUEST_CLEAR_FEATURE; 115e31cac6eSMichael Lotz requestData.Value = USB_FEATURE_ENDPOINT_HALT; 116e31cac6eSMichael Lotz requestData.Index = pipe->EndpointAddress() 117e31cac6eSMichael Lotz | (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN 118e31cac6eSMichael Lotz : USB_ENDPOINT_ADDR_DIR_OUT); 119e31cac6eSMichael Lotz requestData.Length = 0; 120e31cac6eSMichael Lotz 121e31cac6eSMichael Lotz Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe(); 122e31cac6eSMichael Lotz for (int tries = 0; tries < 100; tries++) { 123e31cac6eSMichael Lotz status_t result 124e31cac6eSMichael Lotz = debug_run_transfer(parentPipe, NULL, 0, &requestData, false); 125e31cac6eSMichael Lotz 126e31cac6eSMichael Lotz if (result == B_DEV_PENDING) 127e31cac6eSMichael Lotz continue; 128e31cac6eSMichael Lotz 129e31cac6eSMichael Lotz if (result == B_OK) { 130e31cac6eSMichael Lotz // clearing a stalled condition resets the data toggle 131e31cac6eSMichael Lotz pipe->SetDataToggle(false); 132e31cac6eSMichael Lotz return B_OK; 133e31cac6eSMichael Lotz } 134e31cac6eSMichael Lotz 135e31cac6eSMichael Lotz return result; 136e31cac6eSMichael Lotz } 137e31cac6eSMichael Lotz 138e31cac6eSMichael Lotz return B_TIMED_OUT; 139e31cac6eSMichael Lotz } 1406eba0636SMichael Lotz 1416eba0636SMichael Lotz 1421501c2bfSNiels Sascha Reedijk static int32 1431501c2bfSNiels Sascha Reedijk bus_std_ops(int32 op, ...) 1441501c2bfSNiels Sascha Reedijk { 1451501c2bfSNiels Sascha Reedijk switch (op) { 14696da8285SMichael Lotz case B_MODULE_INIT: { 147f14fe767SMichael Lotz TRACE_MODULE("init\n"); 1485b0ec61fSMichael Lotz if (gUSBStack) 1495b0ec61fSMichael Lotz return B_OK; 1505b0ec61fSMichael Lotz 15196da8285SMichael Lotz #ifdef TRACE_USB 1521a2e81b5SNiels Sascha Reedijk set_dprintf_enabled(true); 15302ce23a1SMichael Lotz #endif 154b8c6a851SMichael Lotz Stack *stack = new(std::nothrow) Stack(); 155f14fe767SMichael Lotz TRACE_MODULE("usb_module: stack created %p\n", stack); 156b8c6a851SMichael Lotz if (!stack) 157b8c6a851SMichael Lotz return B_NO_MEMORY; 158b8c6a851SMichael Lotz 15996da8285SMichael Lotz if (stack->InitCheck() != B_OK) { 1601a2e81b5SNiels Sascha Reedijk delete stack; 1611501c2bfSNiels Sascha Reedijk return ENODEV; 1621501c2bfSNiels Sascha Reedijk } 16396da8285SMichael Lotz 164eb6a1cbcSMichael Lotz gUSBStack = stack; 165eb01fb72SMichael Lotz 1666eba0636SMichael Lotz add_debugger_command("get_usb_pipe_for_id", 1676eba0636SMichael Lotz &debug_get_pipe_for_id, 168159aa93bSMichael Lotz "Sets _usbPipe by resolving _usbPipeID"); 169159aa93bSMichael Lotz add_debugger_command("usb_process_transfer", 170159aa93bSMichael Lotz &debug_process_transfer, 171159aa93bSMichael Lotz "Transfers _usbTransferData with _usbTransferLength" 172159aa93bSMichael Lotz " (and/or _usbRequestData) to pipe _usbPipe"); 173e31cac6eSMichael Lotz add_debugger_command("usb_clear_stall", 174e31cac6eSMichael Lotz &debug_clear_stall, 175e31cac6eSMichael Lotz "Tries to issue a clear feature request for the endpoint halt" 176e31cac6eSMichael Lotz " feature on pipe _usbPipe"); 1771501c2bfSNiels Sascha Reedijk break; 17896da8285SMichael Lotz } 17996da8285SMichael Lotz 1801501c2bfSNiels Sascha Reedijk case B_MODULE_UNINIT: 181f14fe767SMichael Lotz TRACE_MODULE("uninit\n"); 182b8c6a851SMichael Lotz delete gUSBStack; 183b8c6a851SMichael Lotz gUSBStack = NULL; 184eb01fb72SMichael Lotz 1856eba0636SMichael Lotz remove_debugger_command("get_usb_pipe_for_id", 1866eba0636SMichael Lotz &debug_get_pipe_for_id); 1871501c2bfSNiels Sascha Reedijk break; 18896da8285SMichael Lotz 1891501c2bfSNiels Sascha Reedijk default: 1901501c2bfSNiels Sascha Reedijk return EINVAL; 1911501c2bfSNiels Sascha Reedijk } 19296da8285SMichael Lotz 1931501c2bfSNiels Sascha Reedijk return B_OK; 1941501c2bfSNiels Sascha Reedijk } 1951501c2bfSNiels Sascha Reedijk 1961501c2bfSNiels Sascha Reedijk 197b8c6a851SMichael Lotz status_t 198b8c6a851SMichael Lotz register_driver(const char *driverName, 199b8c6a851SMichael Lotz const usb_support_descriptor *descriptors, 200b8c6a851SMichael Lotz size_t count, const char *optionalRepublishDriverName) 201b8c6a851SMichael Lotz { 202b8c6a851SMichael Lotz return gUSBStack->RegisterDriver(driverName, descriptors, count, 203b8c6a851SMichael Lotz optionalRepublishDriverName); 204b8c6a851SMichael Lotz } 205b8c6a851SMichael Lotz 206b8c6a851SMichael Lotz 207b8c6a851SMichael Lotz status_t 208b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks) 209b8c6a851SMichael Lotz { 210b8c6a851SMichael Lotz return gUSBStack->InstallNotify(driverName, hooks); 211b8c6a851SMichael Lotz } 212b8c6a851SMichael Lotz 213b8c6a851SMichael Lotz 214b8c6a851SMichael Lotz status_t 215b8c6a851SMichael Lotz uninstall_notify(const char *driverName) 216b8c6a851SMichael Lotz { 217b8c6a851SMichael Lotz return gUSBStack->UninstallNotify(driverName); 218b8c6a851SMichael Lotz } 219b8c6a851SMichael Lotz 220b8c6a851SMichael Lotz 221b8c6a851SMichael Lotz const usb_device_descriptor * 222*dd249016SAugustin Cavalier get_device_descriptor(usb_device dev) 223b8c6a851SMichael Lotz { 224*dd249016SAugustin Cavalier TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev); 225*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 2265b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 227b8c6a851SMichael Lotz return NULL; 228*dd249016SAugustin Cavalier Device *device = (Device *)object; 229*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 230*dd249016SAugustin Cavalier return NULL; 231b8c6a851SMichael Lotz 232*dd249016SAugustin Cavalier return device->DeviceDescriptor(); 233b8c6a851SMichael Lotz } 234b8c6a851SMichael Lotz 235b8c6a851SMichael Lotz 236b8c6a851SMichael Lotz const usb_configuration_info * 237*dd249016SAugustin Cavalier get_nth_configuration(usb_device dev, uint32 index) 238b8c6a851SMichael Lotz { 239d8b4cfc9SRene Gollent TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n", 240*dd249016SAugustin Cavalier dev, index); 241*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 2425b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 243b8c6a851SMichael Lotz return NULL; 244*dd249016SAugustin Cavalier Device *device = (Device *)object; 245*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 246*dd249016SAugustin Cavalier return NULL; 247b8c6a851SMichael Lotz 248*dd249016SAugustin Cavalier return device->ConfigurationAt((int32)index); 249b8c6a851SMichael Lotz } 250b8c6a851SMichael Lotz 251b8c6a851SMichael Lotz 252b8c6a851SMichael Lotz const usb_configuration_info * 253*dd249016SAugustin Cavalier get_configuration(usb_device dev) 254b8c6a851SMichael Lotz { 255*dd249016SAugustin Cavalier TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev); 256*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 2575b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 258b8c6a851SMichael Lotz return NULL; 259*dd249016SAugustin Cavalier Device *device = (Device *)object; 260*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 261*dd249016SAugustin Cavalier return NULL; 262b8c6a851SMichael Lotz 263*dd249016SAugustin Cavalier return device->Configuration(); 264b8c6a851SMichael Lotz } 265b8c6a851SMichael Lotz 266b8c6a851SMichael Lotz 267b8c6a851SMichael Lotz status_t 268*dd249016SAugustin Cavalier set_configuration(usb_device dev, 269b8c6a851SMichael Lotz const usb_configuration_info *configuration) 270b8c6a851SMichael Lotz { 271*dd249016SAugustin Cavalier TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev, 272d8b4cfc9SRene Gollent configuration); 273*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 2745b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 27517f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 276*dd249016SAugustin Cavalier Device *device = (Device *)object; 277*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 278*dd249016SAugustin Cavalier return B_NO_INIT; 279b8c6a851SMichael Lotz 280*dd249016SAugustin Cavalier return device->SetConfiguration(configuration); 281b8c6a851SMichael Lotz } 282b8c6a851SMichael Lotz 283b8c6a851SMichael Lotz 284b8c6a851SMichael Lotz status_t 285*dd249016SAugustin Cavalier set_alt_interface(usb_device dev, const usb_interface_info *interface) 286b8c6a851SMichael Lotz { 287*dd249016SAugustin Cavalier TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface); 288*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 2895b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 29017f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 291*dd249016SAugustin Cavalier Device *device = (Device *)object; 292*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 293*dd249016SAugustin Cavalier return B_NO_INIT; 2945b0ec61fSMichael Lotz 295*dd249016SAugustin Cavalier return device->SetAltInterface(interface); 296b8c6a851SMichael Lotz } 297b8c6a851SMichael Lotz 298b8c6a851SMichael Lotz 299b8c6a851SMichael Lotz status_t 3005b0ec61fSMichael Lotz set_feature(usb_id handle, uint16 selector) 301b8c6a851SMichael Lotz { 302d8b4cfc9SRene Gollent TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector); 3035b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(handle); 3048fedfdfcSMichael Lotz if (!object) 30517f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 306b8c6a851SMichael Lotz 3078fedfdfcSMichael Lotz return object->SetFeature(selector); 308b8c6a851SMichael Lotz } 309b8c6a851SMichael Lotz 310b8c6a851SMichael Lotz 311b8c6a851SMichael Lotz status_t 3125b0ec61fSMichael Lotz clear_feature(usb_id handle, uint16 selector) 313b8c6a851SMichael Lotz { 314d8b4cfc9SRene Gollent TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector); 3155b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(handle); 3168fedfdfcSMichael Lotz if (!object) 31717f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 318b8c6a851SMichael Lotz 3198fedfdfcSMichael Lotz return object->ClearFeature(selector); 320b8c6a851SMichael Lotz } 321b8c6a851SMichael Lotz 322b8c6a851SMichael Lotz 323b8c6a851SMichael Lotz status_t 3245b0ec61fSMichael Lotz get_status(usb_id handle, uint16 *status) 325b8c6a851SMichael Lotz { 326d8b4cfc9SRene Gollent TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status); 3275b0ec61fSMichael Lotz if (!status) 3285b0ec61fSMichael Lotz return B_BAD_VALUE; 3295b0ec61fSMichael Lotz 3305b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(handle); 3318fedfdfcSMichael Lotz if (!object) 33217f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 333b8c6a851SMichael Lotz 3348fedfdfcSMichael Lotz return object->GetStatus(status); 335b8c6a851SMichael Lotz } 336b8c6a851SMichael Lotz 337b8c6a851SMichael Lotz 338b8c6a851SMichael Lotz status_t 339*dd249016SAugustin Cavalier get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID, 3405b0ec61fSMichael Lotz void *data, size_t dataLength, size_t *actualLength) 341b8c6a851SMichael Lotz { 342d8b4cfc9SRene Gollent TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, " 343d8b4cfc9SRene Gollent "%" B_PRIuSIZE ", %p)\n", 344*dd249016SAugustin Cavalier dev, type, index, languageID, data, dataLength, actualLength); 345*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 3465b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 34717f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 348*dd249016SAugustin Cavalier Device *device = (Device *)object; 349*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 350*dd249016SAugustin Cavalier return B_NO_INIT; 351b8c6a851SMichael Lotz 352*dd249016SAugustin Cavalier return device->GetDescriptor(type, index, languageID, 353b8c6a851SMichael Lotz data, dataLength, actualLength); 354b8c6a851SMichael Lotz } 355b8c6a851SMichael Lotz 356b8c6a851SMichael Lotz 357b8c6a851SMichael Lotz status_t 358*dd249016SAugustin Cavalier send_request(usb_device dev, uint8 requestType, uint8 request, 3595b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength) 360b8c6a851SMichael Lotz { 361d8b4cfc9SRene Gollent TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, " 362*dd249016SAugustin Cavalier "%d, %p, %p)\n", dev, requestType, request, value, index, length, 363d8b4cfc9SRene Gollent data, actualLength); 364*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 3655b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 36617f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 367*dd249016SAugustin Cavalier Device *device = (Device *)object; 368*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 369*dd249016SAugustin Cavalier return B_NO_INIT; 370b8c6a851SMichael Lotz 371*dd249016SAugustin Cavalier return device->DefaultPipe()->SendRequest(requestType, request, 3728fedfdfcSMichael Lotz value, index, length, data, length, actualLength); 373b8c6a851SMichael Lotz } 374b8c6a851SMichael Lotz 375b8c6a851SMichael Lotz 376b8c6a851SMichael Lotz status_t 377*dd249016SAugustin Cavalier queue_request(usb_device dev, uint8 requestType, uint8 request, 3785b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data, 379b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 380b8c6a851SMichael Lotz { 381d8b4cfc9SRene Gollent TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x," 382*dd249016SAugustin Cavalier " %u, %p, %p, %p)\n", dev, requestType, request, value, index, 383d8b4cfc9SRene Gollent length, data, callback, callbackCookie); 384*dd249016SAugustin Cavalier Object *object = gUSBStack->GetObject(dev); 3855b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 38617f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 387*dd249016SAugustin Cavalier Device *device = (Device *)object; 388*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 389*dd249016SAugustin Cavalier return B_NO_INIT; 390b8c6a851SMichael Lotz 391*dd249016SAugustin Cavalier return device->DefaultPipe()->QueueRequest(requestType, 3928fedfdfcSMichael Lotz request, value, index, length, data, length, callback, callbackCookie); 393b8c6a851SMichael Lotz } 394b8c6a851SMichael Lotz 395b8c6a851SMichael Lotz 396b8c6a851SMichael Lotz status_t 3975b0ec61fSMichael Lotz queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, 398b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 399b8c6a851SMichael Lotz { 400d8b4cfc9SRene Gollent TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n", 401f14fe767SMichael Lotz pipe, data, dataLength, callback, callbackCookie); 4025b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4035b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) 40417f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 405b8c6a851SMichael Lotz 4065b0ec61fSMichael Lotz return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback, 407b8c6a851SMichael Lotz callbackCookie); 408b8c6a851SMichael Lotz } 409b8c6a851SMichael Lotz 410b8c6a851SMichael Lotz 411b8c6a851SMichael Lotz status_t 4125b0ec61fSMichael Lotz queue_bulk(usb_pipe pipe, void *data, size_t dataLength, 413b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 414b8c6a851SMichael Lotz { 415d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n", 416f14fe767SMichael Lotz pipe, data, dataLength, callback, callbackCookie); 4175b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4185b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 41917f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 420b8c6a851SMichael Lotz 4215b0ec61fSMichael Lotz return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback, 422b8c6a851SMichael Lotz callbackCookie); 423b8c6a851SMichael Lotz } 424b8c6a851SMichael Lotz 425b8c6a851SMichael Lotz 426b8c6a851SMichael Lotz status_t 4275b0ec61fSMichael Lotz queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, 4285b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie) 429b8c6a851SMichael Lotz { 430d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n", 431f14fe767SMichael Lotz pipe, vector, vectorCount, callback, callbackCookie); 4325b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4335b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 43417f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 435b8c6a851SMichael Lotz 4361e8c0b36SMichael Lotz return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, 43772457eddSMichael Lotz callbackCookie, false); 43872457eddSMichael Lotz } 43972457eddSMichael Lotz 44072457eddSMichael Lotz 44172457eddSMichael Lotz status_t 44272457eddSMichael Lotz queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount, 44372457eddSMichael Lotz usb_callback_func callback, void *callbackCookie) 44472457eddSMichael Lotz { 445d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE 446d8b4cfc9SRene Gollent ", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie); 44772457eddSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 44872457eddSMichael Lotz if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 44972457eddSMichael Lotz return B_DEV_INVALID_PIPE; 45072457eddSMichael Lotz 45172457eddSMichael Lotz return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, 45272457eddSMichael Lotz callbackCookie, true); 453b8c6a851SMichael Lotz } 454b8c6a851SMichael Lotz 455b8c6a851SMichael Lotz 456b8c6a851SMichael Lotz status_t 4575b0ec61fSMichael Lotz queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, 4581bad4a4eSMichael Lotz usb_iso_packet_descriptor *packetDesc, uint32 packetCount, 4591bad4a4eSMichael Lotz uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback, 4605b0ec61fSMichael Lotz void *callbackCookie) 4615b0ec61fSMichael Lotz { 462d8b4cfc9SRene Gollent TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, " 463d8b4cfc9SRene Gollent "%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n", 464f14fe767SMichael Lotz pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, 465f14fe767SMichael Lotz flags, callback, callbackCookie); 4665b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4675b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 46817f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 4695b0ec61fSMichael Lotz 4705b0ec61fSMichael Lotz return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength, 4711bad4a4eSMichael Lotz packetDesc, packetCount, startingFrameNumber, flags, callback, 4721bad4a4eSMichael Lotz callbackCookie); 4735b0ec61fSMichael Lotz } 4745b0ec61fSMichael Lotz 4755b0ec61fSMichael Lotz 4765b0ec61fSMichael Lotz status_t 4775b0ec61fSMichael Lotz set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, 4785b0ec61fSMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize) 4795b0ec61fSMichael Lotz { 480d8b4cfc9SRene Gollent TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe, 481d8b4cfc9SRene Gollent maxQueuedPackets, maxBufferDurationMS, sampleSize); 4825b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4835b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 48417f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 4855b0ec61fSMichael Lotz 48600f6fab9SMichael Lotz return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets, 48700f6fab9SMichael Lotz maxBufferDurationMS, sampleSize); 4885b0ec61fSMichael Lotz } 4895b0ec61fSMichael Lotz 4905b0ec61fSMichael Lotz 4915b0ec61fSMichael Lotz status_t 4925b0ec61fSMichael Lotz cancel_queued_transfers(usb_pipe pipe) 493b8c6a851SMichael Lotz { 494d8b4cfc9SRene Gollent TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe); 4955b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(pipe); 4965b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) 49717f83b21SMichael Lotz return B_DEV_INVALID_PIPE; 4985b0ec61fSMichael Lotz 49913508e8bSMichael Lotz return ((Pipe *)object)->CancelQueuedTransfers(false); 500b8c6a851SMichael Lotz } 501b8c6a851SMichael Lotz 502b8c6a851SMichael Lotz 503b8c6a851SMichael Lotz status_t 504b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 505b8c6a851SMichael Lotz { 506d8b4cfc9SRene Gollent TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode, 507d8b4cfc9SRene Gollent buffer, bufferSize); 50864f3c065SMichael Lotz 50964f3c065SMichael Lotz switch (opcode) { 51064f3c065SMichael Lotz case 'DNAM': { 5115b0ec61fSMichael Lotz Object *object = gUSBStack->GetObject(*(usb_id *)buffer); 5125b0ec61fSMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 5135b0ec61fSMichael Lotz return B_BAD_VALUE; 514*dd249016SAugustin Cavalier Device *device = (Device *)object; 515*dd249016SAugustin Cavalier if (device->InitCheck() != B_OK) 516*dd249016SAugustin Cavalier return B_NO_INIT; 5175b0ec61fSMichael Lotz 51864f3c065SMichael Lotz uint32 index = 0; 519*dd249016SAugustin Cavalier return device->BuildDeviceName((char *)buffer, &index, 5205b0ec61fSMichael Lotz bufferSize, NULL); 52164f3c065SMichael Lotz } 52264f3c065SMichael Lotz } 52364f3c065SMichael Lotz 52464f3c065SMichael Lotz return B_DEV_INVALID_IOCTL; 525b8c6a851SMichael Lotz } 526b8c6a851SMichael Lotz 527b8c6a851SMichael Lotz 5287e1490e0SMichael Lotz status_t 5297e1490e0SMichael Lotz get_nth_roothub(uint32 index, usb_device *rootHub) 5307e1490e0SMichael Lotz { 5317e1490e0SMichael Lotz if (!rootHub) 5327e1490e0SMichael Lotz return B_BAD_VALUE; 5337e1490e0SMichael Lotz 5347e1490e0SMichael Lotz BusManager *busManager = gUSBStack->BusManagerAt(index); 5357e1490e0SMichael Lotz if (!busManager) 5367e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND; 5377e1490e0SMichael Lotz 5387e1490e0SMichael Lotz Hub *hub = busManager->GetRootHub(); 5397e1490e0SMichael Lotz if (!hub) 5407e1490e0SMichael Lotz return B_NO_INIT; 5417e1490e0SMichael Lotz 5427e1490e0SMichael Lotz *rootHub = hub->USBID(); 5437e1490e0SMichael Lotz return B_OK; 5447e1490e0SMichael Lotz } 5457e1490e0SMichael Lotz 5467e1490e0SMichael Lotz 5477e1490e0SMichael Lotz status_t 5487e1490e0SMichael Lotz get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice) 5497e1490e0SMichael Lotz { 5507e1490e0SMichael Lotz if (!childDevice) 5517e1490e0SMichael Lotz return B_BAD_VALUE; 5527e1490e0SMichael Lotz 5537e1490e0SMichael Lotz Object *object = gUSBStack->GetObject(_hub); 5547e1490e0SMichael Lotz if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 5557e1490e0SMichael Lotz return B_DEV_INVALID_PIPE; 5567e1490e0SMichael Lotz 5577e1490e0SMichael Lotz Hub *hub = (Hub *)object; 5587e1490e0SMichael Lotz for (uint8 i = 0; i < 8; i++) { 5597e1490e0SMichael Lotz if (hub->ChildAt(i) == NULL) 5607e1490e0SMichael Lotz continue; 5617e1490e0SMichael Lotz 5627e1490e0SMichael Lotz if (index-- > 0) 5637e1490e0SMichael Lotz continue; 5647e1490e0SMichael Lotz 5657e1490e0SMichael Lotz *childDevice = hub->ChildAt(i)->USBID(); 5667e1490e0SMichael Lotz return B_OK; 5677e1490e0SMichael Lotz } 5687e1490e0SMichael Lotz 5697e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND; 5707e1490e0SMichael Lotz } 5717e1490e0SMichael Lotz 5727e1490e0SMichael Lotz 5737e1490e0SMichael Lotz status_t 5747e1490e0SMichael Lotz get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex) 5757e1490e0SMichael Lotz { 5767e1490e0SMichael Lotz if (!parentHub || !portIndex) 5777e1490e0SMichael Lotz return B_BAD_VALUE; 5787e1490e0SMichael Lotz 5797e1490e0SMichael Lotz Object *object = gUSBStack->GetObject(_device); 5807e1490e0SMichael Lotz if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 5817e1490e0SMichael Lotz return B_DEV_INVALID_PIPE; 5827e1490e0SMichael Lotz 5837e1490e0SMichael Lotz Object *parent = object->Parent(); 5847e1490e0SMichael Lotz if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0) 5857e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND; 5867e1490e0SMichael Lotz 5877e1490e0SMichael Lotz Hub *hub = (Hub *)parent; 5887e1490e0SMichael Lotz for (uint8 i = 0; i < 8; i++) { 5897e1490e0SMichael Lotz if (hub->ChildAt(i) == object) { 5907e1490e0SMichael Lotz *portIndex = i; 5917e1490e0SMichael Lotz *parentHub = hub->USBID(); 5927e1490e0SMichael Lotz return B_OK; 5937e1490e0SMichael Lotz } 5947e1490e0SMichael Lotz } 5957e1490e0SMichael Lotz 5967e1490e0SMichael Lotz return B_ERROR; 5977e1490e0SMichael Lotz } 5987e1490e0SMichael Lotz 5997e1490e0SMichael Lotz 6007e1490e0SMichael Lotz status_t 6017e1490e0SMichael Lotz reset_port(usb_device _hub, uint8 portIndex) 6027e1490e0SMichael Lotz { 6037e1490e0SMichael Lotz Object *object = gUSBStack->GetObject(_hub); 6047e1490e0SMichael Lotz if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 6057e1490e0SMichael Lotz return B_DEV_INVALID_PIPE; 6067e1490e0SMichael Lotz 6077e1490e0SMichael Lotz Hub *hub = (Hub *)object; 6087e1490e0SMichael Lotz return hub->ResetPort(portIndex); 6097e1490e0SMichael Lotz } 6107e1490e0SMichael Lotz 6117e1490e0SMichael Lotz 6127e1490e0SMichael Lotz status_t 6137e1490e0SMichael Lotz disable_port(usb_device _hub, uint8 portIndex) 6147e1490e0SMichael Lotz { 6157e1490e0SMichael Lotz Object *object = gUSBStack->GetObject(_hub); 6167e1490e0SMichael Lotz if (!object || (object->Type() & USB_OBJECT_HUB) == 0) 6177e1490e0SMichael Lotz return B_DEV_INVALID_PIPE; 6187e1490e0SMichael Lotz 6197e1490e0SMichael Lotz Hub *hub = (Hub *)object; 6207e1490e0SMichael Lotz return hub->DisablePort(portIndex); 6217e1490e0SMichael Lotz } 6227e1490e0SMichael Lotz 6237e1490e0SMichael Lotz 62496da8285SMichael Lotz /* 6255b0ec61fSMichael Lotz This module exports the USB API v3 62696da8285SMichael Lotz */ 6275b0ec61fSMichael Lotz struct usb_module_info gModuleInfoV3 = { 6281501c2bfSNiels Sascha Reedijk // First the bus_manager_info: 6291501c2bfSNiels Sascha Reedijk { 6301501c2bfSNiels Sascha Reedijk { 6315b0ec61fSMichael Lotz "bus_managers/usb/v3", 6321501c2bfSNiels Sascha Reedijk B_KEEP_LOADED, // Keep loaded, even if no driver requires it 6331501c2bfSNiels Sascha Reedijk bus_std_ops 6341501c2bfSNiels Sascha Reedijk }, 6351501c2bfSNiels Sascha Reedijk NULL // the rescan function 6361501c2bfSNiels Sascha Reedijk }, 63796da8285SMichael Lotz 638b8c6a851SMichael Lotz register_driver, // register_driver 639b8c6a851SMichael Lotz install_notify, // install_notify 640b8c6a851SMichael Lotz uninstall_notify, // uninstall_notify 641b8c6a851SMichael Lotz get_device_descriptor, // get_device_descriptor 642b8c6a851SMichael Lotz get_nth_configuration, // get_nth_configuration 643b8c6a851SMichael Lotz get_configuration, // get_configuration 644b8c6a851SMichael Lotz set_configuration, // set_configuration 645b8c6a851SMichael Lotz set_alt_interface, // set_alt_interface 646b8c6a851SMichael Lotz set_feature, // set_feature 647b8c6a851SMichael Lotz clear_feature, // clear_feature 648b8c6a851SMichael Lotz get_status, // get_status 649b8c6a851SMichael Lotz get_descriptor, // get_descriptor 650b8c6a851SMichael Lotz send_request, // send_request 651b8c6a851SMichael Lotz queue_interrupt, // queue_interrupt 652b8c6a851SMichael Lotz queue_bulk, // queue_bulk 6535b0ec61fSMichael Lotz queue_bulk_v, // queue_bulk_v 654b8c6a851SMichael Lotz queue_isochronous, // queue_isochronous 655b8c6a851SMichael Lotz queue_request, // queue_request 656b8c6a851SMichael Lotz set_pipe_policy, // set_pipe_policy 657b8c6a851SMichael Lotz cancel_queued_transfers, // cancel_queued_transfers 6587e1490e0SMichael Lotz usb_ioctl, // usb_ioctl 6597e1490e0SMichael Lotz get_nth_roothub, // get_nth_roothub 6607e1490e0SMichael Lotz get_nth_child, // get_nth_child 6617e1490e0SMichael Lotz get_device_parent, // get_device_parent 6627e1490e0SMichael Lotz reset_port, // reset_port 6637e1490e0SMichael Lotz disable_port // disable_port 66472457eddSMichael Lotz //queue_bulk_v_physical // queue_bulk_v_physical 6651501c2bfSNiels Sascha Reedijk }; 6661501c2bfSNiels Sascha Reedijk 66796da8285SMichael Lotz 6685b0ec61fSMichael Lotz // 6695b0ec61fSMichael Lotz // #pragma mark - 6705b0ec61fSMichael Lotz // 6715b0ec61fSMichael Lotz 6725b0ec61fSMichael Lotz 6735b0ec61fSMichael Lotz const usb_device_descriptor * 6745b0ec61fSMichael Lotz get_device_descriptor_v2(const void *device) 6755b0ec61fSMichael Lotz { 676d8b4cfc9SRene Gollent return get_device_descriptor((usb_id)(ssize_t)device); 6775b0ec61fSMichael Lotz } 6785b0ec61fSMichael Lotz 6795b0ec61fSMichael Lotz 6805b0ec61fSMichael Lotz const usb_configuration_info * 6815b0ec61fSMichael Lotz get_nth_configuration_v2(const void *device, uint index) 6825b0ec61fSMichael Lotz { 683d8b4cfc9SRene Gollent return get_nth_configuration((usb_id)(ssize_t)device, index); 6845b0ec61fSMichael Lotz } 6855b0ec61fSMichael Lotz 6865b0ec61fSMichael Lotz 6875b0ec61fSMichael Lotz const usb_configuration_info * 6885b0ec61fSMichael Lotz get_configuration_v2(const void *device) 6895b0ec61fSMichael Lotz { 690d8b4cfc9SRene Gollent return get_configuration((usb_id)(ssize_t)device); 6915b0ec61fSMichael Lotz } 6925b0ec61fSMichael Lotz 6935b0ec61fSMichael Lotz 6945b0ec61fSMichael Lotz status_t 6955b0ec61fSMichael Lotz set_configuration_v2(const void *device, 6965b0ec61fSMichael Lotz const usb_configuration_info *configuration) 6975b0ec61fSMichael Lotz { 698d8b4cfc9SRene Gollent return set_configuration((usb_id)(ssize_t)device, configuration); 6995b0ec61fSMichael Lotz } 7005b0ec61fSMichael Lotz 7015b0ec61fSMichael Lotz 7025b0ec61fSMichael Lotz status_t 7035b0ec61fSMichael Lotz set_alt_interface_v2(const void *device, const usb_interface_info *interface) 7045b0ec61fSMichael Lotz { 705d8b4cfc9SRene Gollent return set_alt_interface((usb_id)(ssize_t)device, interface); 7065b0ec61fSMichael Lotz } 7075b0ec61fSMichael Lotz 7085b0ec61fSMichael Lotz 7095b0ec61fSMichael Lotz status_t 7105b0ec61fSMichael Lotz set_feature_v2(const void *object, uint16 selector) 7115b0ec61fSMichael Lotz { 712d8b4cfc9SRene Gollent return set_feature((usb_id)(ssize_t)object, selector); 7135b0ec61fSMichael Lotz } 7145b0ec61fSMichael Lotz 7155b0ec61fSMichael Lotz 7165b0ec61fSMichael Lotz status_t 7175b0ec61fSMichael Lotz clear_feature_v2(const void *object, uint16 selector) 7185b0ec61fSMichael Lotz { 719d8b4cfc9SRene Gollent return clear_feature((usb_id)(ssize_t)object, selector); 7205b0ec61fSMichael Lotz } 7215b0ec61fSMichael Lotz 7225b0ec61fSMichael Lotz 7235b0ec61fSMichael Lotz status_t 7245b0ec61fSMichael Lotz get_status_v2(const void *object, uint16 *status) 7255b0ec61fSMichael Lotz { 726d8b4cfc9SRene Gollent return get_status((usb_id)(ssize_t)object, status); 7275b0ec61fSMichael Lotz } 7285b0ec61fSMichael Lotz 7295b0ec61fSMichael Lotz 7305b0ec61fSMichael Lotz status_t 7315b0ec61fSMichael Lotz get_descriptor_v2(const void *device, uint8 type, uint8 index, 7325b0ec61fSMichael Lotz uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 7335b0ec61fSMichael Lotz { 734d8b4cfc9SRene Gollent return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data, 7355b0ec61fSMichael Lotz dataLength, actualLength); 7365b0ec61fSMichael Lotz } 7375b0ec61fSMichael Lotz 7385b0ec61fSMichael Lotz 7395b0ec61fSMichael Lotz status_t 7405b0ec61fSMichael Lotz send_request_v2(const void *device, uint8 requestType, uint8 request, 7415b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data, 7425b0ec61fSMichael Lotz size_t /*dataLength*/, size_t *actualLength) 7435b0ec61fSMichael Lotz { 744d8b4cfc9SRene Gollent return send_request((usb_id)(ssize_t)device, requestType, request, value, index, 7455b0ec61fSMichael Lotz length, data, actualLength); 7465b0ec61fSMichael Lotz } 7475b0ec61fSMichael Lotz 7485b0ec61fSMichael Lotz 7495b0ec61fSMichael Lotz status_t 7505b0ec61fSMichael Lotz queue_request_v2(const void *device, uint8 requestType, uint8 request, 7515b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data, 7525b0ec61fSMichael Lotz size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie) 7535b0ec61fSMichael Lotz { 754d8b4cfc9SRene Gollent return queue_request((usb_id)(ssize_t)device, requestType, request, value, index, 7555b0ec61fSMichael Lotz length, data, callback, callbackCookie); 7565b0ec61fSMichael Lotz } 7575b0ec61fSMichael Lotz 7585b0ec61fSMichael Lotz 7595b0ec61fSMichael Lotz status_t 7605b0ec61fSMichael Lotz queue_interrupt_v2(const void *pipe, void *data, size_t dataLength, 7615b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie) 7625b0ec61fSMichael Lotz { 763d8b4cfc9SRene Gollent return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback, 7645b0ec61fSMichael Lotz callbackCookie); 7655b0ec61fSMichael Lotz } 7665b0ec61fSMichael Lotz 7675b0ec61fSMichael Lotz 7685b0ec61fSMichael Lotz status_t 7695b0ec61fSMichael Lotz queue_bulk_v2(const void *pipe, void *data, size_t dataLength, 7705b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie) 7715b0ec61fSMichael Lotz { 772d8b4cfc9SRene Gollent return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback, 7735b0ec61fSMichael Lotz callbackCookie); 7745b0ec61fSMichael Lotz } 7755b0ec61fSMichael Lotz 7765b0ec61fSMichael Lotz 7775b0ec61fSMichael Lotz status_t 7785b0ec61fSMichael Lotz queue_isochronous_v2(const void *pipe, void *data, size_t dataLength, 7795b0ec61fSMichael Lotz rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 7805b0ec61fSMichael Lotz void *callbackCookie) 7815b0ec61fSMichael Lotz { 7821bad4a4eSMichael Lotz // ToDo: convert rlea to usb_iso_packet_descriptor 7831bad4a4eSMichael Lotz // ToDo: use a flag to indicate that the callback shall produce a rlea 7841bad4a4eSMichael Lotz usb_iso_packet_descriptor *packetDesc = NULL; 785d8b4cfc9SRene Gollent return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0, 7861bad4a4eSMichael Lotz NULL, 0, callback, callbackCookie); 7875b0ec61fSMichael Lotz } 7885b0ec61fSMichael Lotz 7895b0ec61fSMichael Lotz 7905b0ec61fSMichael Lotz status_t 7915b0ec61fSMichael Lotz set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets, 7925b0ec61fSMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize) 7935b0ec61fSMichael Lotz { 794d8b4cfc9SRene Gollent return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS, 7955b0ec61fSMichael Lotz sampleSize); 7965b0ec61fSMichael Lotz } 7975b0ec61fSMichael Lotz 7985b0ec61fSMichael Lotz 7995b0ec61fSMichael Lotz status_t 8005b0ec61fSMichael Lotz cancel_queued_transfers_v2(const void *pipe) 8015b0ec61fSMichael Lotz { 802d8b4cfc9SRene Gollent return cancel_queued_transfers((usb_id)(ssize_t)pipe); 8035b0ec61fSMichael Lotz } 8045b0ec61fSMichael Lotz 8055b0ec61fSMichael Lotz 8065b0ec61fSMichael Lotz struct usb_module_info_v2 { 8075b0ec61fSMichael Lotz bus_manager_info binfo; 8085b0ec61fSMichael Lotz status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *); 8095b0ec61fSMichael Lotz status_t (*install_notify)(const char *, const usb_notify_hooks *); 8105b0ec61fSMichael Lotz status_t (*uninstall_notify)(const char *); 8115b0ec61fSMichael Lotz const usb_device_descriptor *(*get_device_descriptor)(const void *); 8125b0ec61fSMichael Lotz const usb_configuration_info *(*get_nth_configuration)(const void *, uint); 8135b0ec61fSMichael Lotz const usb_configuration_info *(*get_configuration)(const void *); 8145b0ec61fSMichael Lotz status_t (*set_configuration)(const void *, const usb_configuration_info *); 8155b0ec61fSMichael Lotz status_t (*set_alt_interface)(const void *, const usb_interface_info *); 8165b0ec61fSMichael Lotz status_t (*set_feature)(const void *, uint16); 8175b0ec61fSMichael Lotz status_t (*clear_feature)(const void *, uint16); 8185b0ec61fSMichael Lotz status_t (*get_status)(const void *, uint16 *); 8195b0ec61fSMichael Lotz status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *); 8205b0ec61fSMichael Lotz status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *); 8215b0ec61fSMichael Lotz status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *); 8225b0ec61fSMichael Lotz status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *); 8235b0ec61fSMichael Lotz status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *); 8245b0ec61fSMichael Lotz status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *); 8255b0ec61fSMichael Lotz status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16); 8265b0ec61fSMichael Lotz status_t (*cancel_queued_transfers)(const void *); 8275b0ec61fSMichael Lotz status_t (*usb_ioctl)(uint32 opcode, void *,size_t); 8285b0ec61fSMichael Lotz }; 8295b0ec61fSMichael Lotz 8305b0ec61fSMichael Lotz 8315b0ec61fSMichael Lotz /* 8325b0ec61fSMichael Lotz This module exports the USB API v2 8335b0ec61fSMichael Lotz */ 8345b0ec61fSMichael Lotz struct usb_module_info_v2 gModuleInfoV2 = { 8355b0ec61fSMichael Lotz // First the bus_manager_info: 8365b0ec61fSMichael Lotz { 8375b0ec61fSMichael Lotz { 8385b0ec61fSMichael Lotz "bus_managers/usb/v2", 8395b0ec61fSMichael Lotz B_KEEP_LOADED, // Keep loaded, even if no driver requires it 8405b0ec61fSMichael Lotz bus_std_ops 8415b0ec61fSMichael Lotz }, 8425b0ec61fSMichael Lotz NULL // the rescan function 8435b0ec61fSMichael Lotz }, 8445b0ec61fSMichael Lotz 8455b0ec61fSMichael Lotz register_driver, // register_driver 8465b0ec61fSMichael Lotz install_notify, // install_notify 8475b0ec61fSMichael Lotz uninstall_notify, // uninstall_notify 8485b0ec61fSMichael Lotz get_device_descriptor_v2, // get_device_descriptor 8495b0ec61fSMichael Lotz get_nth_configuration_v2, // get_nth_configuration 8505b0ec61fSMichael Lotz get_configuration_v2, // get_configuration 8515b0ec61fSMichael Lotz set_configuration_v2, // set_configuration 8525b0ec61fSMichael Lotz set_alt_interface_v2, // set_alt_interface 8535b0ec61fSMichael Lotz set_feature_v2, // set_feature 8545b0ec61fSMichael Lotz clear_feature_v2, // clear_feature 8555b0ec61fSMichael Lotz get_status_v2, // get_status 8565b0ec61fSMichael Lotz get_descriptor_v2, // get_descriptor 8575b0ec61fSMichael Lotz send_request_v2, // send_request 8585b0ec61fSMichael Lotz queue_interrupt_v2, // queue_interrupt 8595b0ec61fSMichael Lotz queue_bulk_v2, // queue_bulk 8605b0ec61fSMichael Lotz queue_isochronous_v2, // queue_isochronous 8615b0ec61fSMichael Lotz queue_request_v2, // queue_request 8625b0ec61fSMichael Lotz set_pipe_policy_v2, // set_pipe_policy 8635b0ec61fSMichael Lotz cancel_queued_transfers_v2, // cancel_queued_transfers 8645b0ec61fSMichael Lotz usb_ioctl // usb_ioctl 8655b0ec61fSMichael Lotz }; 8665b0ec61fSMichael Lotz 8675b0ec61fSMichael Lotz 8685b0ec61fSMichael Lotz // 8695b0ec61fSMichael Lotz // #pragma mark - 8705b0ec61fSMichael Lotz // 8715b0ec61fSMichael Lotz 8725b0ec61fSMichael Lotz 8731501c2bfSNiels Sascha Reedijk module_info *modules[] = { 8745b0ec61fSMichael Lotz (module_info *)&gModuleInfoV2, 8755b0ec61fSMichael Lotz (module_info *)&gModuleInfoV3, 8761501c2bfSNiels Sascha Reedijk NULL 8771501c2bfSNiels Sascha Reedijk }; 878