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: 696da8285SMichael Lotz * Niels S. Reedijk 796da8285SMichael Lotz */ 81501c2bfSNiels Sascha Reedijk 91501c2bfSNiels Sascha Reedijk #include <USB.h> 101501c2bfSNiels Sascha Reedijk #include <util/kernel_cpp.h> 111501c2bfSNiels Sascha Reedijk #include "usb_p.h" 121501c2bfSNiels Sascha Reedijk 1396da8285SMichael Lotz 1496da8285SMichael Lotz #define TRACE_USB 1596da8285SMichael Lotz #ifdef TRACE_USB 1696da8285SMichael Lotz #define TRACE(x) dprintf x 171501c2bfSNiels Sascha Reedijk #else 1896da8285SMichael Lotz #define TRACE(x) /* nothing */ 191501c2bfSNiels Sascha Reedijk #endif 201501c2bfSNiels Sascha Reedijk 211501c2bfSNiels Sascha Reedijk 22b8c6a851SMichael Lotz Stack *gUSBStack = NULL; 23b8c6a851SMichael Lotz 24b8c6a851SMichael Lotz 251501c2bfSNiels Sascha Reedijk static int32 261501c2bfSNiels Sascha Reedijk bus_std_ops(int32 op, ...) 271501c2bfSNiels Sascha Reedijk { 281501c2bfSNiels Sascha Reedijk switch (op) { 2996da8285SMichael Lotz case B_MODULE_INIT: { 3096da8285SMichael Lotz #ifdef TRACE_USB 311a2e81b5SNiels Sascha Reedijk set_dprintf_enabled(true); 321a2e81b5SNiels Sascha Reedijk load_driver_symbols("usb"); 331a2e81b5SNiels Sascha Reedijk #endif 34b8c6a851SMichael Lotz TRACE(("usb_module: init\n")); 3596da8285SMichael Lotz 36b8c6a851SMichael Lotz Stack *stack = new(std::nothrow) Stack(); 37b8c6a851SMichael Lotz if (!stack) 38b8c6a851SMichael Lotz return B_NO_MEMORY; 39b8c6a851SMichael Lotz 4096da8285SMichael Lotz if (stack->InitCheck() != B_OK) { 411a2e81b5SNiels Sascha Reedijk delete stack; 421501c2bfSNiels Sascha Reedijk return ENODEV; 431501c2bfSNiels Sascha Reedijk } 4496da8285SMichael Lotz 45b8c6a851SMichael Lotz gUSBStack = stack; 461501c2bfSNiels Sascha Reedijk break; 4796da8285SMichael Lotz } 4896da8285SMichael Lotz 491501c2bfSNiels Sascha Reedijk case B_MODULE_UNINIT: 50b8c6a851SMichael Lotz TRACE(("usb_module: bus module: uninit\n")); 51b8c6a851SMichael Lotz delete gUSBStack; 52b8c6a851SMichael Lotz gUSBStack = NULL; 531501c2bfSNiels Sascha Reedijk break; 5496da8285SMichael Lotz 551501c2bfSNiels Sascha Reedijk default: 561501c2bfSNiels Sascha Reedijk return EINVAL; 571501c2bfSNiels Sascha Reedijk } 5896da8285SMichael Lotz 591501c2bfSNiels Sascha Reedijk return B_OK; 601501c2bfSNiels Sascha Reedijk } 611501c2bfSNiels Sascha Reedijk 621501c2bfSNiels Sascha Reedijk 63b8c6a851SMichael Lotz status_t 64b8c6a851SMichael Lotz register_driver(const char *driverName, 65b8c6a851SMichael Lotz const usb_support_descriptor *descriptors, 66b8c6a851SMichael Lotz size_t count, const char *optionalRepublishDriverName) 67b8c6a851SMichael Lotz { 68b8c6a851SMichael Lotz return gUSBStack->RegisterDriver(driverName, descriptors, count, 69b8c6a851SMichael Lotz optionalRepublishDriverName); 70b8c6a851SMichael Lotz } 71b8c6a851SMichael Lotz 72b8c6a851SMichael Lotz 73b8c6a851SMichael Lotz status_t 74b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks) 75b8c6a851SMichael Lotz { 76b8c6a851SMichael Lotz return gUSBStack->InstallNotify(driverName, hooks); 77b8c6a851SMichael Lotz } 78b8c6a851SMichael Lotz 79b8c6a851SMichael Lotz 80b8c6a851SMichael Lotz status_t 81b8c6a851SMichael Lotz uninstall_notify(const char *driverName) 82b8c6a851SMichael Lotz { 83b8c6a851SMichael Lotz return gUSBStack->UninstallNotify(driverName); 84b8c6a851SMichael Lotz } 85b8c6a851SMichael Lotz 86b8c6a851SMichael Lotz 87b8c6a851SMichael Lotz const usb_device_descriptor * 88b8c6a851SMichael Lotz get_device_descriptor(const usb_device *device) 89b8c6a851SMichael Lotz { 90f1020a6cSMichael Lotz TRACE(("usb_module: get_device_descriptor(0x%08x)\n", device)); 91b8c6a851SMichael Lotz if (!device) 92b8c6a851SMichael Lotz return NULL; 93b8c6a851SMichael Lotz 94b8c6a851SMichael Lotz return ((const Device *)device)->DeviceDescriptor(); 95b8c6a851SMichael Lotz } 96b8c6a851SMichael Lotz 97b8c6a851SMichael Lotz 98b8c6a851SMichael Lotz const usb_configuration_info * 99b8c6a851SMichael Lotz get_nth_configuration(const usb_device *device, uint index) 100b8c6a851SMichael Lotz { 101f1020a6cSMichael Lotz TRACE(("usb_module: get_nth_configuration(0x%08x, %d)\n", device, index)); 102b8c6a851SMichael Lotz if (!device) 103b8c6a851SMichael Lotz return NULL; 104b8c6a851SMichael Lotz 105b8c6a851SMichael Lotz return ((const Device *)device)->ConfigurationAt((int32)index); 106b8c6a851SMichael Lotz } 107b8c6a851SMichael Lotz 108b8c6a851SMichael Lotz 109b8c6a851SMichael Lotz 110b8c6a851SMichael Lotz const usb_configuration_info * 111b8c6a851SMichael Lotz get_configuration(const usb_device *device) 112b8c6a851SMichael Lotz { 113f1020a6cSMichael Lotz TRACE(("usb_module: get_configuration(0x%08x)\n", device)); 114b8c6a851SMichael Lotz if (!device) 115b8c6a851SMichael Lotz return NULL; 116b8c6a851SMichael Lotz 117b8c6a851SMichael Lotz return ((const Device *)device)->Configuration(); 118b8c6a851SMichael Lotz } 119b8c6a851SMichael Lotz 120b8c6a851SMichael Lotz 121b8c6a851SMichael Lotz status_t 122b8c6a851SMichael Lotz set_configuration(const usb_device *device, 123b8c6a851SMichael Lotz const usb_configuration_info *configuration) 124b8c6a851SMichael Lotz { 125f1020a6cSMichael Lotz TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration)); 126b8c6a851SMichael Lotz if (!device) 127b8c6a851SMichael Lotz return B_BAD_VALUE; 128b8c6a851SMichael Lotz 129b8c6a851SMichael Lotz return ((Device *)device)->SetConfiguration(configuration); 130b8c6a851SMichael Lotz } 131b8c6a851SMichael Lotz 132b8c6a851SMichael Lotz 133b8c6a851SMichael Lotz status_t 134b8c6a851SMichael Lotz set_alt_interface(const usb_device *device, 135b8c6a851SMichael Lotz const usb_interface_info *interface) 136b8c6a851SMichael Lotz { 137f1020a6cSMichael Lotz TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface)); 138b8c6a851SMichael Lotz return B_ERROR; 139b8c6a851SMichael Lotz } 140b8c6a851SMichael Lotz 141b8c6a851SMichael Lotz 142b8c6a851SMichael Lotz status_t 143b8c6a851SMichael Lotz set_feature(const void *object, uint16 selector) 144b8c6a851SMichael Lotz { 145f1020a6cSMichael Lotz TRACE(("usb_module: set_feature(0x%08x, %d)\n", object, selector)); 146b8c6a851SMichael Lotz if (!object) 147b8c6a851SMichael Lotz return B_BAD_VALUE; 148b8c6a851SMichael Lotz 14949617128SMichael Lotz return ((Pipe *)object)->SetFeature(selector); 150b8c6a851SMichael Lotz } 151b8c6a851SMichael Lotz 152b8c6a851SMichael Lotz 153b8c6a851SMichael Lotz status_t 154b8c6a851SMichael Lotz clear_feature(const void *object, uint16 selector) 155b8c6a851SMichael Lotz { 156f1020a6cSMichael Lotz TRACE(("usb_module: clear_feature(0x%08x, %d)\n", object, selector)); 157b8c6a851SMichael Lotz if (!object) 158b8c6a851SMichael Lotz return B_BAD_VALUE; 159b8c6a851SMichael Lotz 16049617128SMichael Lotz return ((Pipe *)object)->ClearFeature(selector); 161b8c6a851SMichael Lotz } 162b8c6a851SMichael Lotz 163b8c6a851SMichael Lotz 164b8c6a851SMichael Lotz status_t 165b8c6a851SMichael Lotz get_status(const void *object, uint16 *status) 166b8c6a851SMichael Lotz { 167f1020a6cSMichael Lotz TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", object, status)); 168b8c6a851SMichael Lotz if (!object || !status) 169b8c6a851SMichael Lotz return B_BAD_VALUE; 170b8c6a851SMichael Lotz 17149617128SMichael Lotz return ((Pipe *)object)->GetStatus(status); 172b8c6a851SMichael Lotz } 173b8c6a851SMichael Lotz 174b8c6a851SMichael Lotz 175b8c6a851SMichael Lotz status_t 176b8c6a851SMichael Lotz get_descriptor(const usb_device *device, uint8 type, uint8 index, 177b8c6a851SMichael Lotz uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 178b8c6a851SMichael Lotz { 179f1020a6cSMichael Lotz TRACE(("usb_module: get_descriptor(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%08x, %d, 0x%08x)\n", device, type, index, languageID, data, dataLength, actualLength)); 180b8c6a851SMichael Lotz if (!device || !data) 181b8c6a851SMichael Lotz return B_BAD_VALUE; 182b8c6a851SMichael Lotz 183b8c6a851SMichael Lotz return ((Device *)device)->GetDescriptor(type, index, languageID, 184b8c6a851SMichael Lotz data, dataLength, actualLength); 185b8c6a851SMichael Lotz } 186b8c6a851SMichael Lotz 187b8c6a851SMichael Lotz 188b8c6a851SMichael Lotz status_t 189b8c6a851SMichael Lotz send_request(const usb_device *device, uint8 requestType, uint8 request, 190b8c6a851SMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t dataLength, 191b8c6a851SMichael Lotz size_t *actualLength) 192b8c6a851SMichael Lotz { 193f1020a6cSMichael Lotz TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, %d, 0x%08x)\n", device, requestType, request, value, index, length, data, dataLength, actualLength)); 194b8c6a851SMichael Lotz if (!device) 195b8c6a851SMichael Lotz return B_BAD_VALUE; 196b8c6a851SMichael Lotz 197b8c6a851SMichael Lotz return ((Device *)device)->SendRequest(requestType, request, value, index, 198b8c6a851SMichael Lotz length, data, dataLength, actualLength); 199b8c6a851SMichael Lotz } 200b8c6a851SMichael Lotz 201b8c6a851SMichael Lotz 202b8c6a851SMichael Lotz status_t 203b8c6a851SMichael Lotz queue_request(const usb_device *device, uint8 requestType, uint8 request, 204b8c6a851SMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t dataLength, 205b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 206b8c6a851SMichael Lotz { 207f1020a6cSMichael Lotz TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, dataLength, callback, callbackCookie)); 208b8c6a851SMichael Lotz if (!device) 209b8c6a851SMichael Lotz return B_BAD_VALUE; 210b8c6a851SMichael Lotz 211b8c6a851SMichael Lotz return ((Device *)device)->QueueRequest(requestType, request, value, index, 212b8c6a851SMichael Lotz length, data, dataLength, callback, callbackCookie); 213b8c6a851SMichael Lotz } 214b8c6a851SMichael Lotz 215b8c6a851SMichael Lotz 216b8c6a851SMichael Lotz status_t 217b8c6a851SMichael Lotz queue_interrupt(const usb_pipe *pipe, void *data, size_t dataLength, 218b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 219b8c6a851SMichael Lotz { 220f1020a6cSMichael Lotz TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); 221b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Interrupt) 222b8c6a851SMichael Lotz return B_BAD_VALUE; 223b8c6a851SMichael Lotz 224b8c6a851SMichael Lotz return ((InterruptPipe *)pipe)->QueueInterrupt(data, dataLength, callback, 225b8c6a851SMichael Lotz callbackCookie); 226b8c6a851SMichael Lotz } 227b8c6a851SMichael Lotz 228b8c6a851SMichael Lotz 229b8c6a851SMichael Lotz status_t 230b8c6a851SMichael Lotz queue_bulk(const usb_pipe *pipe, void *data, size_t dataLength, 231b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 232b8c6a851SMichael Lotz { 233f1020a6cSMichael Lotz TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); 234b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Bulk) 235b8c6a851SMichael Lotz return B_BAD_VALUE; 236b8c6a851SMichael Lotz 237b8c6a851SMichael Lotz return ((BulkPipe *)pipe)->QueueBulk(data, dataLength, callback, 238b8c6a851SMichael Lotz callbackCookie); 239b8c6a851SMichael Lotz } 240b8c6a851SMichael Lotz 241b8c6a851SMichael Lotz 242b8c6a851SMichael Lotz status_t 243b8c6a851SMichael Lotz queue_isochronous(const usb_pipe *pipe, void *data, size_t dataLength, 244b8c6a851SMichael Lotz rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 245b8c6a851SMichael Lotz void *callbackCookie) 246b8c6a851SMichael Lotz { 247f1020a6cSMichael Lotz TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, rleArray, bufferDurationMS, callback, callbackCookie)); 248b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Isochronous) 249b8c6a851SMichael Lotz return B_BAD_VALUE; 250b8c6a851SMichael Lotz 251b8c6a851SMichael Lotz return ((IsochronousPipe *)pipe)->QueueIsochronous(data, dataLength, 252b8c6a851SMichael Lotz rleArray, bufferDurationMS, callback, callbackCookie); 253b8c6a851SMichael Lotz } 254b8c6a851SMichael Lotz 255b8c6a851SMichael Lotz 256b8c6a851SMichael Lotz status_t 257b8c6a851SMichael Lotz set_pipe_policy(const usb_pipe *pipe, uint8 maxQueuedPackets, 258b8c6a851SMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize) 259b8c6a851SMichael Lotz { 260f1020a6cSMichael Lotz TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize)); 261b8c6a851SMichael Lotz return B_ERROR; 262b8c6a851SMichael Lotz } 263b8c6a851SMichael Lotz 264b8c6a851SMichael Lotz 265b8c6a851SMichael Lotz status_t 266b8c6a851SMichael Lotz cancel_queued_transfers(const usb_pipe *pipe) 267b8c6a851SMichael Lotz { 268f1020a6cSMichael Lotz TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe)); 269b8c6a851SMichael Lotz return ((Pipe *)pipe)->CancelQueuedTransfers(); 270b8c6a851SMichael Lotz } 271b8c6a851SMichael Lotz 272b8c6a851SMichael Lotz 273b8c6a851SMichael Lotz status_t 274b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 275b8c6a851SMichael Lotz { 276f1020a6cSMichael Lotz TRACE(("usb_module: usb_ioctl(0x%08x, 0x%08x, %d)\n", opcode, buffer, bufferSize)); 277*64f3c065SMichael Lotz 278*64f3c065SMichael Lotz switch (opcode) { 279*64f3c065SMichael Lotz case 'DNAM': { 280*64f3c065SMichael Lotz uint32 index = 0; 281*64f3c065SMichael Lotz Device *device = *(Device **)buffer; 282*64f3c065SMichael Lotz return device->BuildDeviceName((char *)buffer, &index, bufferSize, NULL); 283*64f3c065SMichael Lotz } 284*64f3c065SMichael Lotz } 285*64f3c065SMichael Lotz 286*64f3c065SMichael Lotz return B_DEV_INVALID_IOCTL; 287b8c6a851SMichael Lotz } 288b8c6a851SMichael Lotz 289b8c6a851SMichael Lotz 29096da8285SMichael Lotz /* 2911501c2bfSNiels Sascha Reedijk This module exports the USB API 29296da8285SMichael Lotz */ 29396da8285SMichael Lotz struct usb_module_info gModuleInfo = { 2941501c2bfSNiels Sascha Reedijk // First the bus_manager_info: 2951501c2bfSNiels Sascha Reedijk { 2961501c2bfSNiels Sascha Reedijk { 297b8c6a851SMichael Lotz B_USB_MODULE_NAME, 2981501c2bfSNiels Sascha Reedijk B_KEEP_LOADED, // Keep loaded, even if no driver requires it 2991501c2bfSNiels Sascha Reedijk bus_std_ops 3001501c2bfSNiels Sascha Reedijk }, 3011501c2bfSNiels Sascha Reedijk NULL // the rescan function 3021501c2bfSNiels Sascha Reedijk }, 30396da8285SMichael Lotz 304b8c6a851SMichael Lotz register_driver, // register_driver 305b8c6a851SMichael Lotz install_notify, // install_notify 306b8c6a851SMichael Lotz uninstall_notify, // uninstall_notify 307b8c6a851SMichael Lotz get_device_descriptor, // get_device_descriptor 308b8c6a851SMichael Lotz get_nth_configuration, // get_nth_configuration 309b8c6a851SMichael Lotz get_configuration, // get_configuration 310b8c6a851SMichael Lotz set_configuration, // set_configuration 311b8c6a851SMichael Lotz set_alt_interface, // set_alt_interface 312b8c6a851SMichael Lotz set_feature, // set_feature 313b8c6a851SMichael Lotz clear_feature, // clear_feature 314b8c6a851SMichael Lotz get_status, // get_status 315b8c6a851SMichael Lotz get_descriptor, // get_descriptor 316b8c6a851SMichael Lotz send_request, // send_request 317b8c6a851SMichael Lotz queue_interrupt, // queue_interrupt 318b8c6a851SMichael Lotz queue_bulk, // queue_bulk 319b8c6a851SMichael Lotz queue_isochronous, // queue_isochronous 320b8c6a851SMichael Lotz queue_request, // queue_request 321b8c6a851SMichael Lotz set_pipe_policy, // set_pipe_policy 322b8c6a851SMichael Lotz cancel_queued_transfers, // cancel_queued_transfers 323b8c6a851SMichael Lotz usb_ioctl // usb_ioctl 3241501c2bfSNiels Sascha Reedijk }; 3251501c2bfSNiels Sascha Reedijk 32696da8285SMichael Lotz 3271501c2bfSNiels Sascha Reedijk module_info *modules[] = { 32896da8285SMichael Lotz (module_info *)&gModuleInfo, 3291501c2bfSNiels Sascha Reedijk NULL 3301501c2bfSNiels Sascha Reedijk }; 331