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 22*b8c6a851SMichael Lotz Stack *gUSBStack = NULL; 23*b8c6a851SMichael Lotz 24*b8c6a851SMichael 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 34*b8c6a851SMichael Lotz TRACE(("usb_module: init\n")); 3596da8285SMichael Lotz 36*b8c6a851SMichael Lotz Stack *stack = new(std::nothrow) Stack(); 37*b8c6a851SMichael Lotz if (!stack) 38*b8c6a851SMichael Lotz return B_NO_MEMORY; 39*b8c6a851SMichael Lotz 4096da8285SMichael Lotz if (stack->InitCheck() != B_OK) { 411a2e81b5SNiels Sascha Reedijk delete stack; 421501c2bfSNiels Sascha Reedijk return ENODEV; 431501c2bfSNiels Sascha Reedijk } 4496da8285SMichael Lotz 45*b8c6a851SMichael Lotz gUSBStack = stack; 461501c2bfSNiels Sascha Reedijk break; 4796da8285SMichael Lotz } 4896da8285SMichael Lotz 491501c2bfSNiels Sascha Reedijk case B_MODULE_UNINIT: 50*b8c6a851SMichael Lotz TRACE(("usb_module: bus module: uninit\n")); 51*b8c6a851SMichael Lotz delete gUSBStack; 52*b8c6a851SMichael 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 63*b8c6a851SMichael Lotz status_t 64*b8c6a851SMichael Lotz register_driver(const char *driverName, 65*b8c6a851SMichael Lotz const usb_support_descriptor *descriptors, 66*b8c6a851SMichael Lotz size_t count, const char *optionalRepublishDriverName) 67*b8c6a851SMichael Lotz { 68*b8c6a851SMichael Lotz return gUSBStack->RegisterDriver(driverName, descriptors, count, 69*b8c6a851SMichael Lotz optionalRepublishDriverName); 70*b8c6a851SMichael Lotz } 71*b8c6a851SMichael Lotz 72*b8c6a851SMichael Lotz 73*b8c6a851SMichael Lotz status_t 74*b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks) 75*b8c6a851SMichael Lotz { 76*b8c6a851SMichael Lotz return gUSBStack->InstallNotify(driverName, hooks); 77*b8c6a851SMichael Lotz } 78*b8c6a851SMichael Lotz 79*b8c6a851SMichael Lotz 80*b8c6a851SMichael Lotz status_t 81*b8c6a851SMichael Lotz uninstall_notify(const char *driverName) 82*b8c6a851SMichael Lotz { 83*b8c6a851SMichael Lotz return gUSBStack->UninstallNotify(driverName); 84*b8c6a851SMichael Lotz } 85*b8c6a851SMichael Lotz 86*b8c6a851SMichael Lotz 87*b8c6a851SMichael Lotz const usb_device_descriptor * 88*b8c6a851SMichael Lotz get_device_descriptor(const usb_device *device) 89*b8c6a851SMichael Lotz { 90*b8c6a851SMichael Lotz if (!device) 91*b8c6a851SMichael Lotz return NULL; 92*b8c6a851SMichael Lotz 93*b8c6a851SMichael Lotz return ((const Device *)device)->DeviceDescriptor(); 94*b8c6a851SMichael Lotz } 95*b8c6a851SMichael Lotz 96*b8c6a851SMichael Lotz 97*b8c6a851SMichael Lotz const usb_configuration_info * 98*b8c6a851SMichael Lotz get_nth_configuration(const usb_device *device, uint index) 99*b8c6a851SMichael Lotz { 100*b8c6a851SMichael Lotz if (!device) 101*b8c6a851SMichael Lotz return NULL; 102*b8c6a851SMichael Lotz 103*b8c6a851SMichael Lotz return ((const Device *)device)->ConfigurationAt((int32)index); 104*b8c6a851SMichael Lotz } 105*b8c6a851SMichael Lotz 106*b8c6a851SMichael Lotz 107*b8c6a851SMichael Lotz 108*b8c6a851SMichael Lotz const usb_configuration_info * 109*b8c6a851SMichael Lotz get_configuration(const usb_device *device) 110*b8c6a851SMichael Lotz { 111*b8c6a851SMichael Lotz if (!device) 112*b8c6a851SMichael Lotz return NULL; 113*b8c6a851SMichael Lotz 114*b8c6a851SMichael Lotz return ((const Device *)device)->Configuration(); 115*b8c6a851SMichael Lotz } 116*b8c6a851SMichael Lotz 117*b8c6a851SMichael Lotz 118*b8c6a851SMichael Lotz status_t 119*b8c6a851SMichael Lotz set_configuration(const usb_device *device, 120*b8c6a851SMichael Lotz const usb_configuration_info *configuration) 121*b8c6a851SMichael Lotz { 122*b8c6a851SMichael Lotz if (!device) 123*b8c6a851SMichael Lotz return B_BAD_VALUE; 124*b8c6a851SMichael Lotz 125*b8c6a851SMichael Lotz return ((Device *)device)->SetConfiguration(configuration); 126*b8c6a851SMichael Lotz } 127*b8c6a851SMichael Lotz 128*b8c6a851SMichael Lotz 129*b8c6a851SMichael Lotz status_t 130*b8c6a851SMichael Lotz set_alt_interface(const usb_device *device, 131*b8c6a851SMichael Lotz const usb_interface_info *interface) 132*b8c6a851SMichael Lotz { 133*b8c6a851SMichael Lotz return B_ERROR; 134*b8c6a851SMichael Lotz } 135*b8c6a851SMichael Lotz 136*b8c6a851SMichael Lotz 137*b8c6a851SMichael Lotz status_t 138*b8c6a851SMichael Lotz set_feature(const void *object, uint16 selector) 139*b8c6a851SMichael Lotz { 140*b8c6a851SMichael Lotz if (!object) 141*b8c6a851SMichael Lotz return B_BAD_VALUE; 142*b8c6a851SMichael Lotz 143*b8c6a851SMichael Lotz return ((ControlPipe *)object)->SetFeature(selector); 144*b8c6a851SMichael Lotz } 145*b8c6a851SMichael Lotz 146*b8c6a851SMichael Lotz 147*b8c6a851SMichael Lotz status_t 148*b8c6a851SMichael Lotz clear_feature(const void *object, uint16 selector) 149*b8c6a851SMichael Lotz { 150*b8c6a851SMichael Lotz if (!object) 151*b8c6a851SMichael Lotz return B_BAD_VALUE; 152*b8c6a851SMichael Lotz 153*b8c6a851SMichael Lotz return ((ControlPipe *)object)->ClearFeature(selector); 154*b8c6a851SMichael Lotz } 155*b8c6a851SMichael Lotz 156*b8c6a851SMichael Lotz 157*b8c6a851SMichael Lotz status_t 158*b8c6a851SMichael Lotz get_status(const void *object, uint16 *status) 159*b8c6a851SMichael Lotz { 160*b8c6a851SMichael Lotz if (!object || !status) 161*b8c6a851SMichael Lotz return B_BAD_VALUE; 162*b8c6a851SMichael Lotz 163*b8c6a851SMichael Lotz return ((ControlPipe *)object)->GetStatus(status); 164*b8c6a851SMichael Lotz } 165*b8c6a851SMichael Lotz 166*b8c6a851SMichael Lotz 167*b8c6a851SMichael Lotz status_t 168*b8c6a851SMichael Lotz get_descriptor(const usb_device *device, uint8 type, uint8 index, 169*b8c6a851SMichael Lotz uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 170*b8c6a851SMichael Lotz { 171*b8c6a851SMichael Lotz if (!device || !data) 172*b8c6a851SMichael Lotz return B_BAD_VALUE; 173*b8c6a851SMichael Lotz 174*b8c6a851SMichael Lotz return ((Device *)device)->GetDescriptor(type, index, languageID, 175*b8c6a851SMichael Lotz data, dataLength, actualLength); 176*b8c6a851SMichael Lotz } 177*b8c6a851SMichael Lotz 178*b8c6a851SMichael Lotz 179*b8c6a851SMichael Lotz status_t 180*b8c6a851SMichael Lotz send_request(const usb_device *device, uint8 requestType, uint8 request, 181*b8c6a851SMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t dataLength, 182*b8c6a851SMichael Lotz size_t *actualLength) 183*b8c6a851SMichael Lotz { 184*b8c6a851SMichael Lotz if (!device) 185*b8c6a851SMichael Lotz return B_BAD_VALUE; 186*b8c6a851SMichael Lotz 187*b8c6a851SMichael Lotz return ((Device *)device)->SendRequest(requestType, request, value, index, 188*b8c6a851SMichael Lotz length, data, dataLength, actualLength); 189*b8c6a851SMichael Lotz } 190*b8c6a851SMichael Lotz 191*b8c6a851SMichael Lotz 192*b8c6a851SMichael Lotz status_t 193*b8c6a851SMichael Lotz queue_request(const usb_device *device, uint8 requestType, uint8 request, 194*b8c6a851SMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t dataLength, 195*b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 196*b8c6a851SMichael Lotz { 197*b8c6a851SMichael Lotz if (!device) 198*b8c6a851SMichael Lotz return B_BAD_VALUE; 199*b8c6a851SMichael Lotz 200*b8c6a851SMichael Lotz return ((Device *)device)->QueueRequest(requestType, request, value, index, 201*b8c6a851SMichael Lotz length, data, dataLength, callback, callbackCookie); 202*b8c6a851SMichael Lotz } 203*b8c6a851SMichael Lotz 204*b8c6a851SMichael Lotz 205*b8c6a851SMichael Lotz status_t 206*b8c6a851SMichael Lotz queue_interrupt(const usb_pipe *pipe, void *data, size_t dataLength, 207*b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 208*b8c6a851SMichael Lotz { 209*b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Interrupt) 210*b8c6a851SMichael Lotz return B_BAD_VALUE; 211*b8c6a851SMichael Lotz 212*b8c6a851SMichael Lotz return ((InterruptPipe *)pipe)->QueueInterrupt(data, dataLength, callback, 213*b8c6a851SMichael Lotz callbackCookie); 214*b8c6a851SMichael Lotz } 215*b8c6a851SMichael Lotz 216*b8c6a851SMichael Lotz 217*b8c6a851SMichael Lotz status_t 218*b8c6a851SMichael Lotz queue_bulk(const usb_pipe *pipe, void *data, size_t dataLength, 219*b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie) 220*b8c6a851SMichael Lotz { 221*b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Bulk) 222*b8c6a851SMichael Lotz return B_BAD_VALUE; 223*b8c6a851SMichael Lotz 224*b8c6a851SMichael Lotz return ((BulkPipe *)pipe)->QueueBulk(data, dataLength, callback, 225*b8c6a851SMichael Lotz callbackCookie); 226*b8c6a851SMichael Lotz } 227*b8c6a851SMichael Lotz 228*b8c6a851SMichael Lotz 229*b8c6a851SMichael Lotz status_t 230*b8c6a851SMichael Lotz queue_isochronous(const usb_pipe *pipe, void *data, size_t dataLength, 231*b8c6a851SMichael Lotz rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 232*b8c6a851SMichael Lotz void *callbackCookie) 233*b8c6a851SMichael Lotz { 234*b8c6a851SMichael Lotz if (((Pipe *)pipe)->Type() != Pipe::Isochronous) 235*b8c6a851SMichael Lotz return B_BAD_VALUE; 236*b8c6a851SMichael Lotz 237*b8c6a851SMichael Lotz return ((IsochronousPipe *)pipe)->QueueIsochronous(data, dataLength, 238*b8c6a851SMichael Lotz rleArray, bufferDurationMS, callback, callbackCookie); 239*b8c6a851SMichael Lotz } 240*b8c6a851SMichael Lotz 241*b8c6a851SMichael Lotz 242*b8c6a851SMichael Lotz status_t 243*b8c6a851SMichael Lotz set_pipe_policy(const usb_pipe *pipe, uint8 maxQueuedPackets, 244*b8c6a851SMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize) 245*b8c6a851SMichael Lotz { 246*b8c6a851SMichael Lotz return B_ERROR; 247*b8c6a851SMichael Lotz } 248*b8c6a851SMichael Lotz 249*b8c6a851SMichael Lotz 250*b8c6a851SMichael Lotz status_t 251*b8c6a851SMichael Lotz cancel_queued_transfers(const usb_pipe *pipe) 252*b8c6a851SMichael Lotz { 253*b8c6a851SMichael Lotz return ((Pipe *)pipe)->CancelQueuedTransfers(); 254*b8c6a851SMichael Lotz } 255*b8c6a851SMichael Lotz 256*b8c6a851SMichael Lotz 257*b8c6a851SMichael Lotz status_t 258*b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 259*b8c6a851SMichael Lotz { 260*b8c6a851SMichael Lotz return B_ERROR; 261*b8c6a851SMichael Lotz } 262*b8c6a851SMichael Lotz 263*b8c6a851SMichael Lotz 26496da8285SMichael Lotz /* 2651501c2bfSNiels Sascha Reedijk This module exports the USB API 26696da8285SMichael Lotz */ 26796da8285SMichael Lotz struct usb_module_info gModuleInfo = { 2681501c2bfSNiels Sascha Reedijk // First the bus_manager_info: 2691501c2bfSNiels Sascha Reedijk { 2701501c2bfSNiels Sascha Reedijk { 271*b8c6a851SMichael Lotz B_USB_MODULE_NAME, 2721501c2bfSNiels Sascha Reedijk B_KEEP_LOADED, // Keep loaded, even if no driver requires it 2731501c2bfSNiels Sascha Reedijk bus_std_ops 2741501c2bfSNiels Sascha Reedijk }, 2751501c2bfSNiels Sascha Reedijk NULL // the rescan function 2761501c2bfSNiels Sascha Reedijk }, 27796da8285SMichael Lotz 278*b8c6a851SMichael Lotz register_driver, // register_driver 279*b8c6a851SMichael Lotz install_notify, // install_notify 280*b8c6a851SMichael Lotz uninstall_notify, // uninstall_notify 281*b8c6a851SMichael Lotz get_device_descriptor, // get_device_descriptor 282*b8c6a851SMichael Lotz get_nth_configuration, // get_nth_configuration 283*b8c6a851SMichael Lotz get_configuration, // get_configuration 284*b8c6a851SMichael Lotz set_configuration, // set_configuration 285*b8c6a851SMichael Lotz set_alt_interface, // set_alt_interface 286*b8c6a851SMichael Lotz set_feature, // set_feature 287*b8c6a851SMichael Lotz clear_feature, // clear_feature 288*b8c6a851SMichael Lotz get_status, // get_status 289*b8c6a851SMichael Lotz get_descriptor, // get_descriptor 290*b8c6a851SMichael Lotz send_request, // send_request 291*b8c6a851SMichael Lotz queue_interrupt, // queue_interrupt 292*b8c6a851SMichael Lotz queue_bulk, // queue_bulk 293*b8c6a851SMichael Lotz queue_isochronous, // queue_isochronous 294*b8c6a851SMichael Lotz queue_request, // queue_request 295*b8c6a851SMichael Lotz set_pipe_policy, // set_pipe_policy 296*b8c6a851SMichael Lotz cancel_queued_transfers, // cancel_queued_transfers 297*b8c6a851SMichael Lotz usb_ioctl // usb_ioctl 2981501c2bfSNiels Sascha Reedijk }; 2991501c2bfSNiels Sascha Reedijk 30096da8285SMichael Lotz 3011501c2bfSNiels Sascha Reedijk module_info *modules[] = { 30296da8285SMichael Lotz (module_info *)&gModuleInfo, 3031501c2bfSNiels Sascha Reedijk NULL 3041501c2bfSNiels Sascha Reedijk }; 305