1853e6be8SMichael Lotz /* 2853e6be8SMichael Lotz * Copyright 2003-2006, Haiku Inc. All rights reserved. 3853e6be8SMichael Lotz * Distributed under the terms of the MIT License. 4853e6be8SMichael Lotz * 5853e6be8SMichael Lotz * Authors: 6853e6be8SMichael Lotz * Michael Lotz <mmlr@mlotz.ch> 7853e6be8SMichael Lotz * Niels S. Reedijk 8853e6be8SMichael Lotz */ 9cc9f959dSMichael Lotz #ifndef _USB_PRIVATE_H 10cc9f959dSMichael Lotz #define _USB_PRIVATE_H 11853e6be8SMichael Lotz 12cc9f959dSMichael Lotz #include "usbspec_private.h" 13853e6be8SMichael Lotz #include <lock.h> 140e76cf0bSJérôme Duval #include <util/Vector.h> 15853e6be8SMichael Lotz 16853e6be8SMichael Lotz 17853e6be8SMichael Lotz #define TRACE_OUTPUT(x, y, z...) \ 18853e6be8SMichael Lotz { \ 19d8b4cfc9SRene Gollent dprintf("usb %s%s %" B_PRId32 ": ", y, (x)->TypeName(), (x)->USBID()); \ 20853e6be8SMichael Lotz dprintf(z); \ 21853e6be8SMichael Lotz } 22853e6be8SMichael Lotz 23853e6be8SMichael Lotz //#define TRACE_USB 24853e6be8SMichael Lotz #ifdef TRACE_USB 25853e6be8SMichael Lotz #define TRACE(x...) TRACE_OUTPUT(this, "", x) 26853e6be8SMichael Lotz #define TRACE_STATIC(x, y...) TRACE_OUTPUT(x, "", y) 27853e6be8SMichael Lotz #define TRACE_MODULE(x...) dprintf("usb " USB_MODULE_NAME ": " x) 28853e6be8SMichael Lotz #else 29853e6be8SMichael Lotz #define TRACE(x...) /* nothing */ 30853e6be8SMichael Lotz #define TRACE_STATIC(x, y...) /* nothing */ 31853e6be8SMichael Lotz #define TRACE_MODULE(x...) /* nothing */ 32853e6be8SMichael Lotz #endif 33853e6be8SMichael Lotz 34853e6be8SMichael Lotz #define TRACE_ALWAYS(x...) TRACE_OUTPUT(this, "", x) 35853e6be8SMichael Lotz #define TRACE_ERROR(x...) TRACE_OUTPUT(this, "error ", x) 36853e6be8SMichael Lotz #define TRACE_MODULE_ALWAYS(x...) dprintf("usb " USB_MODULE_NAME ": " x) 37853e6be8SMichael Lotz #define TRACE_MODULE_ERROR(x...) dprintf("usb " USB_MODULE_NAME ": " x) 38853e6be8SMichael Lotz 39853e6be8SMichael Lotz class Hub; 40853e6be8SMichael Lotz class Stack; 41853e6be8SMichael Lotz class Device; 42853e6be8SMichael Lotz class Transfer; 43853e6be8SMichael Lotz class BusManager; 44853e6be8SMichael Lotz class Pipe; 45853e6be8SMichael Lotz class ControlPipe; 46853e6be8SMichael Lotz class Object; 47853e6be8SMichael Lotz class PhysicalMemoryAllocator; 48853e6be8SMichael Lotz 49853e6be8SMichael Lotz 50853e6be8SMichael Lotz struct usb_host_controller_info { 51853e6be8SMichael Lotz module_info info; 52853e6be8SMichael Lotz status_t (*control)(uint32 op, void *data, size_t length); 53853e6be8SMichael Lotz status_t (*add_to)(Stack *stack); 54853e6be8SMichael Lotz }; 55853e6be8SMichael Lotz 56853e6be8SMichael Lotz 57853e6be8SMichael Lotz struct usb_driver_cookie { 58853e6be8SMichael Lotz usb_id device; 59853e6be8SMichael Lotz void *cookie; 60853e6be8SMichael Lotz usb_driver_cookie *link; 61853e6be8SMichael Lotz }; 62853e6be8SMichael Lotz 63853e6be8SMichael Lotz 64853e6be8SMichael Lotz struct usb_driver_info { 65853e6be8SMichael Lotz const char *driver_name; 66853e6be8SMichael Lotz usb_support_descriptor *support_descriptors; 67853e6be8SMichael Lotz uint32 support_descriptor_count; 68853e6be8SMichael Lotz const char *republish_driver_name; 69853e6be8SMichael Lotz usb_notify_hooks notify_hooks; 70853e6be8SMichael Lotz usb_driver_cookie *cookies; 71853e6be8SMichael Lotz usb_driver_info *link; 72853e6be8SMichael Lotz }; 73853e6be8SMichael Lotz 74853e6be8SMichael Lotz 75853e6be8SMichael Lotz struct change_item { 76853e6be8SMichael Lotz bool added; 77853e6be8SMichael Lotz Device *device; 78853e6be8SMichael Lotz change_item *link; 79853e6be8SMichael Lotz }; 80853e6be8SMichael Lotz 81853e6be8SMichael Lotz 82853e6be8SMichael Lotz struct rescan_item { 83853e6be8SMichael Lotz const char *name; 84853e6be8SMichael Lotz rescan_item *link; 85853e6be8SMichael Lotz }; 86853e6be8SMichael Lotz 87853e6be8SMichael Lotz 88853e6be8SMichael Lotz typedef enum { 89853e6be8SMichael Lotz USB_SPEED_LOWSPEED = 0, 90853e6be8SMichael Lotz USB_SPEED_FULLSPEED, 91853e6be8SMichael Lotz USB_SPEED_HIGHSPEED, 926e2bbbb1SAugustin Cavalier USB_SPEED_SUPERSPEED, 936e2bbbb1SAugustin Cavalier USB_SPEED_MAX = USB_SPEED_SUPERSPEED 94853e6be8SMichael Lotz } usb_speed; 95853e6be8SMichael Lotz 96853e6be8SMichael Lotz 97853e6be8SMichael Lotz typedef enum { 98853e6be8SMichael Lotz USB_CHANGE_CREATED = 0, 99853e6be8SMichael Lotz USB_CHANGE_DESTROYED, 100853e6be8SMichael Lotz USB_CHANGE_PIPE_POLICY_CHANGED 101853e6be8SMichael Lotz } usb_change; 102853e6be8SMichael Lotz 103853e6be8SMichael Lotz 104853e6be8SMichael Lotz #define USB_OBJECT_NONE 0x00000000 105853e6be8SMichael Lotz #define USB_OBJECT_PIPE 0x00000001 106853e6be8SMichael Lotz #define USB_OBJECT_CONTROL_PIPE 0x00000002 107853e6be8SMichael Lotz #define USB_OBJECT_INTERRUPT_PIPE 0x00000004 108853e6be8SMichael Lotz #define USB_OBJECT_BULK_PIPE 0x00000008 109853e6be8SMichael Lotz #define USB_OBJECT_ISO_PIPE 0x00000010 110853e6be8SMichael Lotz #define USB_OBJECT_INTERFACE 0x00000020 111853e6be8SMichael Lotz #define USB_OBJECT_DEVICE 0x00000040 112853e6be8SMichael Lotz #define USB_OBJECT_HUB 0x00000080 113853e6be8SMichael Lotz 114853e6be8SMichael Lotz 115853e6be8SMichael Lotz class Stack { 116853e6be8SMichael Lotz public: 117853e6be8SMichael Lotz Stack(); 118853e6be8SMichael Lotz ~Stack(); 119853e6be8SMichael Lotz 120853e6be8SMichael Lotz status_t InitCheck(); 121853e6be8SMichael Lotz 122853e6be8SMichael Lotz bool Lock(); 123853e6be8SMichael Lotz void Unlock(); 124853e6be8SMichael Lotz 125853e6be8SMichael Lotz usb_id GetUSBID(Object *object); 1261e02632bSAugustin Cavalier void PutUSBID(Object *object); 1275ee91867SAugustin Cavalier 1285ee91867SAugustin Cavalier // This sets the object as busy; the caller must set it un-busy. 129853e6be8SMichael Lotz Object * GetObject(usb_id id); 130853e6be8SMichael Lotz 131853e6be8SMichael Lotz // only for the kernel debugger 13238fc536eSMichael Lotz Object * GetObjectNoLock(usb_id id) const; 133853e6be8SMichael Lotz 134853e6be8SMichael Lotz void AddBusManager(BusManager *bus); 135853e6be8SMichael Lotz int32 IndexOfBusManager(BusManager *bus); 13638fc536eSMichael Lotz BusManager * BusManagerAt(int32 index) const; 137853e6be8SMichael Lotz 138853e6be8SMichael Lotz status_t AllocateChunk(void **logicalAddress, 139d8b4cfc9SRene Gollent phys_addr_t *physicalAddress, 14019b8f8a0SMichael Lotz size_t size); 141853e6be8SMichael Lotz status_t FreeChunk(void *logicalAddress, 142d8b4cfc9SRene Gollent phys_addr_t physicalAddress, 143d8b4cfc9SRene Gollent size_t size); 144853e6be8SMichael Lotz 145853e6be8SMichael Lotz area_id AllocateArea(void **logicalAddress, 146d8b4cfc9SRene Gollent phys_addr_t *physicalAddress, 147853e6be8SMichael Lotz size_t size, const char *name); 148853e6be8SMichael Lotz 149853e6be8SMichael Lotz void NotifyDeviceChange(Device *device, 150853e6be8SMichael Lotz rescan_item **rescanList, 151853e6be8SMichael Lotz bool added); 152853e6be8SMichael Lotz void RescanDrivers(rescan_item *rescanItem); 153853e6be8SMichael Lotz 154853e6be8SMichael Lotz // USB API 155853e6be8SMichael Lotz status_t RegisterDriver(const char *driverName, 15619b8f8a0SMichael Lotz const usb_support_descriptor * 15719b8f8a0SMichael Lotz descriptors, 158853e6be8SMichael Lotz size_t descriptorCount, 159853e6be8SMichael Lotz const char *republishDriverName); 160853e6be8SMichael Lotz 161853e6be8SMichael Lotz status_t InstallNotify(const char *driverName, 162853e6be8SMichael Lotz const usb_notify_hooks *hooks); 163853e6be8SMichael Lotz status_t UninstallNotify(const char *driverName); 164853e6be8SMichael Lotz 16519b8f8a0SMichael Lotz usb_id USBID() const { return 0; } 16619b8f8a0SMichael Lotz const char * TypeName() const { return "stack"; } 167853e6be8SMichael Lotz 168853e6be8SMichael Lotz private: 169853e6be8SMichael Lotz static int32 ExploreThread(void *data); 170853e6be8SMichael Lotz 171853e6be8SMichael Lotz Vector<BusManager *> fBusManagers; 172853e6be8SMichael Lotz thread_id fExploreThread; 173853e6be8SMichael Lotz bool fFirstExploreDone; 174853e6be8SMichael Lotz bool fStopThreads; 175853e6be8SMichael Lotz 176853e6be8SMichael Lotz mutex fStackLock; 177853e6be8SMichael Lotz mutex fExploreLock; 178853e6be8SMichael Lotz PhysicalMemoryAllocator * fAllocator; 179853e6be8SMichael Lotz 180853e6be8SMichael Lotz uint32 fObjectIndex; 181853e6be8SMichael Lotz uint32 fObjectMaxCount; 182853e6be8SMichael Lotz Object ** fObjectArray; 183853e6be8SMichael Lotz 184853e6be8SMichael Lotz usb_driver_info * fDriverList; 185853e6be8SMichael Lotz }; 186853e6be8SMichael Lotz 187853e6be8SMichael Lotz 188853e6be8SMichael Lotz /* 189853e6be8SMichael Lotz * This class manages a bus. It is created by the Stack object 190853e6be8SMichael Lotz * after a host controller gives positive feedback on whether the hardware 191853e6be8SMichael Lotz * is found. 192853e6be8SMichael Lotz */ 193853e6be8SMichael Lotz class BusManager { 194853e6be8SMichael Lotz public: 195853e6be8SMichael Lotz BusManager(Stack *stack); 196853e6be8SMichael Lotz virtual ~BusManager(); 197853e6be8SMichael Lotz 198853e6be8SMichael Lotz virtual status_t InitCheck(); 199853e6be8SMichael Lotz 200853e6be8SMichael Lotz bool Lock(); 201853e6be8SMichael Lotz void Unlock(); 202853e6be8SMichael Lotz 203853e6be8SMichael Lotz int8 AllocateAddress(); 204853e6be8SMichael Lotz void FreeAddress(int8 address); 205853e6be8SMichael Lotz 206319a3798SJérôme Duval virtual Device * AllocateDevice(Hub *parent, 207853e6be8SMichael Lotz int8 hubAddress, uint8 hubPort, 208853e6be8SMichael Lotz usb_speed speed); 209319a3798SJérôme Duval virtual void FreeDevice(Device *device); 210853e6be8SMichael Lotz 211853e6be8SMichael Lotz virtual status_t Start(); 212853e6be8SMichael Lotz virtual status_t Stop(); 213853e6be8SMichael Lotz 214159aa93bSMichael Lotz virtual status_t StartDebugTransfer(Transfer *transfer); 215159aa93bSMichael Lotz virtual status_t CheckDebugTransfer(Transfer *transfer); 216159aa93bSMichael Lotz virtual void CancelDebugTransfer(Transfer *transfer); 217159aa93bSMichael Lotz 218853e6be8SMichael Lotz virtual status_t SubmitTransfer(Transfer *transfer); 219853e6be8SMichael Lotz virtual status_t CancelQueuedTransfers(Pipe *pipe, 220853e6be8SMichael Lotz bool force); 221853e6be8SMichael Lotz 222853e6be8SMichael Lotz virtual status_t NotifyPipeChange(Pipe *pipe, 223853e6be8SMichael Lotz usb_change change); 224853e6be8SMichael Lotz 22519b8f8a0SMichael Lotz Object * RootObject() const 22619b8f8a0SMichael Lotz { return fRootObject; } 227853e6be8SMichael Lotz 22819b8f8a0SMichael Lotz Hub * GetRootHub() const { return fRootHub; } 22919b8f8a0SMichael Lotz void SetRootHub(Hub *hub) { fRootHub = hub; } 230853e6be8SMichael Lotz 23138fc536eSMichael Lotz virtual const char * TypeName() const = 0; 232853e6be8SMichael Lotz 233853e6be8SMichael Lotz protected: 234decd5b8fSAugustin Cavalier usb_id USBID() const { return fStackIndex; } 235decd5b8fSAugustin Cavalier 236decd5b8fSAugustin Cavalier protected: 237853e6be8SMichael Lotz bool fInitOK; 238853e6be8SMichael Lotz 239853e6be8SMichael Lotz private: 240853e6be8SMichael Lotz ControlPipe * _GetDefaultPipe(usb_speed); 241853e6be8SMichael Lotz 242853e6be8SMichael Lotz mutex fLock; 243853e6be8SMichael Lotz 244853e6be8SMichael Lotz bool fDeviceMap[128]; 245853e6be8SMichael Lotz int8 fDeviceIndex; 246853e6be8SMichael Lotz 247853e6be8SMichael Lotz Stack * fStack; 248853e6be8SMichael Lotz ControlPipe * fDefaultPipes[USB_SPEED_MAX + 1]; 249853e6be8SMichael Lotz Hub * fRootHub; 250853e6be8SMichael Lotz Object * fRootObject; 25119b8f8a0SMichael Lotz 252decd5b8fSAugustin Cavalier usb_id fStackIndex; 253853e6be8SMichael Lotz }; 254853e6be8SMichael Lotz 255853e6be8SMichael Lotz 256853e6be8SMichael Lotz class Object { 257853e6be8SMichael Lotz public: 258853e6be8SMichael Lotz Object(Stack *stack, BusManager *bus); 259853e6be8SMichael Lotz Object(Object *parent); 260853e6be8SMichael Lotz virtual ~Object(); 261853e6be8SMichael Lotz 26219b8f8a0SMichael Lotz Object * Parent() const { return fParent; } 263853e6be8SMichael Lotz 26419b8f8a0SMichael Lotz BusManager * GetBusManager() const 26519b8f8a0SMichael Lotz { return fBusManager; } 26619b8f8a0SMichael Lotz Stack * GetStack() const { return fStack; } 267853e6be8SMichael Lotz 26819b8f8a0SMichael Lotz usb_id USBID() const { return fUSBID; } 2695ee91867SAugustin Cavalier void SetBusy(bool busy) 2705ee91867SAugustin Cavalier { atomic_add(&fBusy, busy ? 1 : -1); } 2715ee91867SAugustin Cavalier 27219b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_NONE; } 27319b8f8a0SMichael Lotz virtual const char * TypeName() const { return "object"; } 274853e6be8SMichael Lotz 275853e6be8SMichael Lotz // Convenience functions for standard requests 276853e6be8SMichael Lotz virtual status_t SetFeature(uint16 selector); 277853e6be8SMichael Lotz virtual status_t ClearFeature(uint16 selector); 278853e6be8SMichael Lotz virtual status_t GetStatus(uint16 *status); 279853e6be8SMichael Lotz 2801e02632bSAugustin Cavalier protected: 2811e02632bSAugustin Cavalier void PutUSBID(); 2821e02632bSAugustin Cavalier 283853e6be8SMichael Lotz private: 284853e6be8SMichael Lotz Object * fParent; 285853e6be8SMichael Lotz BusManager * fBusManager; 286853e6be8SMichael Lotz Stack * fStack; 287853e6be8SMichael Lotz usb_id fUSBID; 2885ee91867SAugustin Cavalier int32 fBusy; 289853e6be8SMichael Lotz }; 290853e6be8SMichael Lotz 291853e6be8SMichael Lotz 292853e6be8SMichael Lotz /* 293853e6be8SMichael Lotz * The Pipe class is the communication management between the hardware and 294853e6be8SMichael Lotz * the stack. It creates packets, manages these and performs callbacks. 295853e6be8SMichael Lotz */ 296853e6be8SMichael Lotz class Pipe : public Object { 297853e6be8SMichael Lotz public: 298853e6be8SMichael Lotz enum pipeDirection { In, Out, Default }; 299853e6be8SMichael Lotz 300853e6be8SMichael Lotz Pipe(Object *parent); 301853e6be8SMichael Lotz virtual ~Pipe(); 302853e6be8SMichael Lotz 303334c06aeSJérôme Duval virtual void InitCommon(int8 deviceAddress, 304853e6be8SMichael Lotz uint8 endpointAddress, 305853e6be8SMichael Lotz usb_speed speed, 306853e6be8SMichael Lotz pipeDirection direction, 307853e6be8SMichael Lotz size_t maxPacketSize, 308853e6be8SMichael Lotz uint8 interval, 309853e6be8SMichael Lotz int8 hubAddress, uint8 hubPort); 310086528f6SAugustin Cavalier virtual void InitSuperSpeed(uint8 maxBurst, 311086528f6SAugustin Cavalier uint16 bytesPerInterval); 312853e6be8SMichael Lotz 31319b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_PIPE; } 31419b8f8a0SMichael Lotz virtual const char * TypeName() const { return "pipe"; } 315853e6be8SMichael Lotz 31619b8f8a0SMichael Lotz int8 DeviceAddress() const 31719b8f8a0SMichael Lotz { return fDeviceAddress; } 31819b8f8a0SMichael Lotz usb_speed Speed() const { return fSpeed; } 31919b8f8a0SMichael Lotz pipeDirection Direction() const { return fDirection; } 32019b8f8a0SMichael Lotz uint8 EndpointAddress() const 32119b8f8a0SMichael Lotz { return fEndpointAddress; } 32219b8f8a0SMichael Lotz size_t MaxPacketSize() const 32319b8f8a0SMichael Lotz { return fMaxPacketSize; } 32419b8f8a0SMichael Lotz uint8 Interval() const { return fInterval; } 325853e6be8SMichael Lotz 326086528f6SAugustin Cavalier // SuperSpeed-only parameters 327086528f6SAugustin Cavalier uint8 MaxBurst() const 328086528f6SAugustin Cavalier { return fMaxBurst; } 329086528f6SAugustin Cavalier uint16 BytesPerInterval() const 330086528f6SAugustin Cavalier { return fBytesPerInterval; } 331086528f6SAugustin Cavalier 332853e6be8SMichael Lotz // Hub port being the one-based logical port number on the hub 333853e6be8SMichael Lotz void SetHubInfo(int8 address, uint8 port); 33419b8f8a0SMichael Lotz int8 HubAddress() const 33519b8f8a0SMichael Lotz { return fHubAddress; } 33619b8f8a0SMichael Lotz uint8 HubPort() const { return fHubPort; } 337853e6be8SMichael Lotz 33819b8f8a0SMichael Lotz virtual bool DataToggle() const 33919b8f8a0SMichael Lotz { return fDataToggle; } 34019b8f8a0SMichael Lotz virtual void SetDataToggle(bool toggle) 34119b8f8a0SMichael Lotz { fDataToggle = toggle; } 342853e6be8SMichael Lotz 343853e6be8SMichael Lotz status_t SubmitTransfer(Transfer *transfer); 344853e6be8SMichael Lotz status_t CancelQueuedTransfers(bool force); 345853e6be8SMichael Lotz 34619b8f8a0SMichael Lotz void SetControllerCookie(void *cookie) 34719b8f8a0SMichael Lotz { fControllerCookie = cookie; } 34819b8f8a0SMichael Lotz void * ControllerCookie() const 34919b8f8a0SMichael Lotz { return fControllerCookie; } 350853e6be8SMichael Lotz 351853e6be8SMichael Lotz // Convenience functions for standard requests 352853e6be8SMichael Lotz virtual status_t SetFeature(uint16 selector); 353853e6be8SMichael Lotz virtual status_t ClearFeature(uint16 selector); 354853e6be8SMichael Lotz virtual status_t GetStatus(uint16 *status); 355853e6be8SMichael Lotz 35683825112SAugustin Cavalier protected: 35783825112SAugustin Cavalier friend class Device; 35883825112SAugustin Cavalier 359853e6be8SMichael Lotz private: 360853e6be8SMichael Lotz int8 fDeviceAddress; 361853e6be8SMichael Lotz uint8 fEndpointAddress; 362853e6be8SMichael Lotz pipeDirection fDirection; 363853e6be8SMichael Lotz usb_speed fSpeed; 364853e6be8SMichael Lotz size_t fMaxPacketSize; 365853e6be8SMichael Lotz uint8 fInterval; 366086528f6SAugustin Cavalier uint8 fMaxBurst; 367086528f6SAugustin Cavalier uint16 fBytesPerInterval; 368853e6be8SMichael Lotz int8 fHubAddress; 369853e6be8SMichael Lotz uint8 fHubPort; 370853e6be8SMichael Lotz bool fDataToggle; 371853e6be8SMichael Lotz void * fControllerCookie; 372853e6be8SMichael Lotz }; 373853e6be8SMichael Lotz 374853e6be8SMichael Lotz 375853e6be8SMichael Lotz class ControlPipe : public Pipe { 376853e6be8SMichael Lotz public: 377853e6be8SMichael Lotz ControlPipe(Object *parent); 378853e6be8SMichael Lotz virtual ~ControlPipe(); 379853e6be8SMichael Lotz 380b62bb24fSMichael Lotz virtual void InitCommon(int8 deviceAddress, 381b62bb24fSMichael Lotz uint8 endpointAddress, 382b62bb24fSMichael Lotz usb_speed speed, 383b62bb24fSMichael Lotz pipeDirection direction, 384b62bb24fSMichael Lotz size_t maxPacketSize, 385b62bb24fSMichael Lotz uint8 interval, 386b62bb24fSMichael Lotz int8 hubAddress, uint8 hubPort); 387b62bb24fSMichael Lotz 38819b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_PIPE 38919b8f8a0SMichael Lotz | USB_OBJECT_CONTROL_PIPE; } 39019b8f8a0SMichael Lotz virtual const char * TypeName() const 39119b8f8a0SMichael Lotz { return "control pipe"; } 392853e6be8SMichael Lotz 393853e6be8SMichael Lotz // The data toggle is not relevant 394853e6be8SMichael Lotz // for control transfers, as they are 395853e6be8SMichael Lotz // always enclosed by a setup and 396853e6be8SMichael Lotz // status packet. The toggle always 397853e6be8SMichael Lotz // starts at 1. 39819b8f8a0SMichael Lotz virtual bool DataToggle() const { return true; } 39938fc536eSMichael Lotz virtual void SetDataToggle(bool toggle) {} 400853e6be8SMichael Lotz 401853e6be8SMichael Lotz status_t SendRequest(uint8 requestType, 402853e6be8SMichael Lotz uint8 request, uint16 value, 403853e6be8SMichael Lotz uint16 index, uint16 length, 404853e6be8SMichael Lotz void *data, size_t dataLength, 405853e6be8SMichael Lotz size_t *actualLength); 406853e6be8SMichael Lotz static void SendRequestCallback(void *cookie, 407853e6be8SMichael Lotz status_t status, void *data, 408853e6be8SMichael Lotz size_t actualLength); 409853e6be8SMichael Lotz 410853e6be8SMichael Lotz status_t QueueRequest(uint8 requestType, 411853e6be8SMichael Lotz uint8 request, uint16 value, 412853e6be8SMichael Lotz uint16 index, uint16 length, 413853e6be8SMichael Lotz void *data, size_t dataLength, 414853e6be8SMichael Lotz usb_callback_func callback, 415853e6be8SMichael Lotz void *callbackCookie); 416853e6be8SMichael Lotz 417853e6be8SMichael Lotz private: 418853e6be8SMichael Lotz mutex fSendRequestLock; 419853e6be8SMichael Lotz sem_id fNotifySem; 420853e6be8SMichael Lotz status_t fTransferStatus; 421853e6be8SMichael Lotz size_t fActualLength; 422853e6be8SMichael Lotz }; 423853e6be8SMichael Lotz 424853e6be8SMichael Lotz 425853e6be8SMichael Lotz class InterruptPipe : public Pipe { 426853e6be8SMichael Lotz public: 427853e6be8SMichael Lotz InterruptPipe(Object *parent); 428853e6be8SMichael Lotz 42919b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_PIPE 43019b8f8a0SMichael Lotz | USB_OBJECT_INTERRUPT_PIPE; } 43119b8f8a0SMichael Lotz virtual const char * TypeName() const 43219b8f8a0SMichael Lotz { return "interrupt pipe"; } 433853e6be8SMichael Lotz 434853e6be8SMichael Lotz status_t QueueInterrupt(void *data, 435853e6be8SMichael Lotz size_t dataLength, 436853e6be8SMichael Lotz usb_callback_func callback, 437853e6be8SMichael Lotz void *callbackCookie); 438853e6be8SMichael Lotz }; 439853e6be8SMichael Lotz 440853e6be8SMichael Lotz 441853e6be8SMichael Lotz class BulkPipe : public Pipe { 442853e6be8SMichael Lotz public: 443853e6be8SMichael Lotz BulkPipe(Object *parent); 444853e6be8SMichael Lotz 445334c06aeSJérôme Duval virtual void InitCommon(int8 deviceAddress, 446334c06aeSJérôme Duval uint8 endpointAddress, 447334c06aeSJérôme Duval usb_speed speed, 448334c06aeSJérôme Duval pipeDirection direction, 449334c06aeSJérôme Duval size_t maxPacketSize, 450334c06aeSJérôme Duval uint8 interval, 451334c06aeSJérôme Duval int8 hubAddress, uint8 hubPort); 452334c06aeSJérôme Duval 45319b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_PIPE 45419b8f8a0SMichael Lotz | USB_OBJECT_BULK_PIPE; } 45519b8f8a0SMichael Lotz virtual const char * TypeName() const { return "bulk pipe"; } 456853e6be8SMichael Lotz 457853e6be8SMichael Lotz status_t QueueBulk(void *data, 458853e6be8SMichael Lotz size_t dataLength, 459853e6be8SMichael Lotz usb_callback_func callback, 460853e6be8SMichael Lotz void *callbackCookie); 461853e6be8SMichael Lotz status_t QueueBulkV(iovec *vector, 462853e6be8SMichael Lotz size_t vectorCount, 463853e6be8SMichael Lotz usb_callback_func callback, 464853e6be8SMichael Lotz void *callbackCookie, 465853e6be8SMichael Lotz bool physical); 466853e6be8SMichael Lotz }; 467853e6be8SMichael Lotz 468853e6be8SMichael Lotz 469853e6be8SMichael Lotz class IsochronousPipe : public Pipe { 470853e6be8SMichael Lotz public: 471853e6be8SMichael Lotz IsochronousPipe(Object *parent); 472853e6be8SMichael Lotz 47319b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_PIPE 47419b8f8a0SMichael Lotz | USB_OBJECT_ISO_PIPE; } 47519b8f8a0SMichael Lotz virtual const char * TypeName() const { return "iso pipe"; } 476853e6be8SMichael Lotz 477853e6be8SMichael Lotz status_t QueueIsochronous(void *data, 478853e6be8SMichael Lotz size_t dataLength, 47919b8f8a0SMichael Lotz usb_iso_packet_descriptor * 48019b8f8a0SMichael Lotz packetDescriptor, 481853e6be8SMichael Lotz uint32 packetCount, 482853e6be8SMichael Lotz uint32 *startingFrameNumber, 483853e6be8SMichael Lotz uint32 flags, 484853e6be8SMichael Lotz usb_callback_func callback, 485853e6be8SMichael Lotz void *callbackCookie); 486853e6be8SMichael Lotz 487853e6be8SMichael Lotz status_t SetPipePolicy(uint8 maxQueuedPackets, 488853e6be8SMichael Lotz uint16 maxBufferDurationMS, 489853e6be8SMichael Lotz uint16 sampleSize); 490853e6be8SMichael Lotz status_t GetPipePolicy(uint8 *maxQueuedPackets, 491853e6be8SMichael Lotz uint16 *maxBufferDurationMS, 492853e6be8SMichael Lotz uint16 *sampleSize); 493853e6be8SMichael Lotz 494853e6be8SMichael Lotz private: 495853e6be8SMichael Lotz uint8 fMaxQueuedPackets; 496853e6be8SMichael Lotz uint16 fMaxBufferDuration; 497853e6be8SMichael Lotz uint16 fSampleSize; 498853e6be8SMichael Lotz }; 499853e6be8SMichael Lotz 500853e6be8SMichael Lotz 501853e6be8SMichael Lotz class Interface : public Object { 502853e6be8SMichael Lotz public: 503853e6be8SMichael Lotz Interface(Object *parent, 504853e6be8SMichael Lotz uint8 interfaceIndex); 505853e6be8SMichael Lotz 50619b8f8a0SMichael Lotz virtual uint32 Type() const 50719b8f8a0SMichael Lotz { return USB_OBJECT_INTERFACE; } 50819b8f8a0SMichael Lotz virtual const char * TypeName() const { return "interface"; } 509853e6be8SMichael Lotz 510853e6be8SMichael Lotz // Convenience functions for standard requests 511853e6be8SMichael Lotz virtual status_t SetFeature(uint16 selector); 512853e6be8SMichael Lotz virtual status_t ClearFeature(uint16 selector); 513853e6be8SMichael Lotz virtual status_t GetStatus(uint16 *status); 514853e6be8SMichael Lotz 515853e6be8SMichael Lotz private: 516853e6be8SMichael Lotz uint8 fInterfaceIndex; 517853e6be8SMichael Lotz }; 518853e6be8SMichael Lotz 519853e6be8SMichael Lotz 520853e6be8SMichael Lotz class Device : public Object { 521853e6be8SMichael Lotz public: 522853e6be8SMichael Lotz Device(Object *parent, int8 hubAddress, 523853e6be8SMichael Lotz uint8 hubPort, 524853e6be8SMichael Lotz usb_device_descriptor &desc, 525853e6be8SMichael Lotz int8 deviceAddress, 5262b31b4a8SJérôme Duval usb_speed speed, bool isRootHub, 5272b31b4a8SJérôme Duval void *controllerCookie = NULL); 528853e6be8SMichael Lotz virtual ~Device(); 529853e6be8SMichael Lotz 530853e6be8SMichael Lotz status_t InitCheck(); 531853e6be8SMichael Lotz 532853e6be8SMichael Lotz virtual status_t Changed(change_item **changeList, 533853e6be8SMichael Lotz bool added); 534853e6be8SMichael Lotz 53519b8f8a0SMichael Lotz virtual uint32 Type() const 53619b8f8a0SMichael Lotz { return USB_OBJECT_DEVICE; } 53719b8f8a0SMichael Lotz virtual const char * TypeName() const { return "device"; } 538853e6be8SMichael Lotz 53919b8f8a0SMichael Lotz ControlPipe * DefaultPipe() const 54019b8f8a0SMichael Lotz { return fDefaultPipe; } 541853e6be8SMichael Lotz 542853e6be8SMichael Lotz virtual status_t GetDescriptor(uint8 descriptorType, 543853e6be8SMichael Lotz uint8 index, uint16 languageID, 544853e6be8SMichael Lotz void *data, size_t dataLength, 545853e6be8SMichael Lotz size_t *actualLength); 546853e6be8SMichael Lotz 54719b8f8a0SMichael Lotz int8 DeviceAddress() const 54819b8f8a0SMichael Lotz { return fDeviceAddress; } 549853e6be8SMichael Lotz const usb_device_descriptor * DeviceDescriptor() const; 55019b8f8a0SMichael Lotz usb_speed Speed() const { return fSpeed; } 551853e6be8SMichael Lotz 552853e6be8SMichael Lotz const usb_configuration_info * Configuration() const; 553853e6be8SMichael Lotz const usb_configuration_info * ConfigurationAt(uint8 index) const; 55419b8f8a0SMichael Lotz status_t SetConfiguration( 55519b8f8a0SMichael Lotz const usb_configuration_info * 55619b8f8a0SMichael Lotz configuration); 557853e6be8SMichael Lotz status_t SetConfigurationAt(uint8 index); 558853e6be8SMichael Lotz status_t Unconfigure(bool atDeviceLevel); 559853e6be8SMichael Lotz 56019b8f8a0SMichael Lotz status_t SetAltInterface( 56119b8f8a0SMichael Lotz const usb_interface_info * 56219b8f8a0SMichael Lotz interface); 563853e6be8SMichael Lotz 564853e6be8SMichael Lotz void InitEndpoints(int32 interfaceIndex); 565853e6be8SMichael Lotz void ClearEndpoints(int32 interfaceIndex); 566853e6be8SMichael Lotz 567853e6be8SMichael Lotz virtual status_t ReportDevice( 56819b8f8a0SMichael Lotz usb_support_descriptor * 56919b8f8a0SMichael Lotz supportDescriptors, 570853e6be8SMichael Lotz uint32 supportDescriptorCount, 571853e6be8SMichael Lotz const usb_notify_hooks *hooks, 572853e6be8SMichael Lotz usb_driver_cookie **cookies, 573853e6be8SMichael Lotz bool added, bool recursive); 574853e6be8SMichael Lotz virtual status_t BuildDeviceName(char *string, 575853e6be8SMichael Lotz uint32 *index, size_t bufferSize, 576853e6be8SMichael Lotz Device *device); 577853e6be8SMichael Lotz 57819b8f8a0SMichael Lotz int8 HubAddress() const 57919b8f8a0SMichael Lotz { return fHubAddress; } 58019b8f8a0SMichael Lotz uint8 HubPort() const { return fHubPort; } 581853e6be8SMichael Lotz 5822b31b4a8SJérôme Duval void SetControllerCookie(void *cookie) 5832b31b4a8SJérôme Duval { fControllerCookie = cookie; } 5842b31b4a8SJérôme Duval void * ControllerCookie() const 5852b31b4a8SJérôme Duval { return fControllerCookie; } 5862b31b4a8SJérôme Duval 587853e6be8SMichael Lotz // Convenience functions for standard requests 588853e6be8SMichael Lotz virtual status_t SetFeature(uint16 selector); 589853e6be8SMichael Lotz virtual status_t ClearFeature(uint16 selector); 590853e6be8SMichael Lotz virtual status_t GetStatus(uint16 *status); 591853e6be8SMichael Lotz 592853e6be8SMichael Lotz protected: 593853e6be8SMichael Lotz usb_device_descriptor fDeviceDescriptor; 594853e6be8SMichael Lotz bool fInitOK; 595853e6be8SMichael Lotz 596853e6be8SMichael Lotz private: 597853e6be8SMichael Lotz bool fAvailable; 598853e6be8SMichael Lotz bool fIsRootHub; 599853e6be8SMichael Lotz usb_configuration_info * fConfigurations; 600853e6be8SMichael Lotz usb_configuration_info * fCurrentConfiguration; 601853e6be8SMichael Lotz usb_speed fSpeed; 602853e6be8SMichael Lotz int8 fDeviceAddress; 603853e6be8SMichael Lotz int8 fHubAddress; 604853e6be8SMichael Lotz uint8 fHubPort; 605853e6be8SMichael Lotz ControlPipe * fDefaultPipe; 6062b31b4a8SJérôme Duval void * fControllerCookie; 607853e6be8SMichael Lotz }; 608853e6be8SMichael Lotz 609853e6be8SMichael Lotz 610853e6be8SMichael Lotz class Hub : public Device { 611853e6be8SMichael Lotz public: 612853e6be8SMichael Lotz Hub(Object *parent, int8 hubAddress, 613853e6be8SMichael Lotz uint8 hubPort, 614853e6be8SMichael Lotz usb_device_descriptor &desc, 615853e6be8SMichael Lotz int8 deviceAddress, 61617aa359bSAkshay Jaggi usb_speed speed, bool isRootHub, 61717aa359bSAkshay Jaggi void *controllerCookie = NULL); 618853e6be8SMichael Lotz virtual ~Hub(); 619853e6be8SMichael Lotz 620853e6be8SMichael Lotz virtual status_t Changed(change_item **changeList, 621853e6be8SMichael Lotz bool added); 622853e6be8SMichael Lotz 62319b8f8a0SMichael Lotz virtual uint32 Type() const { return USB_OBJECT_DEVICE 62419b8f8a0SMichael Lotz | USB_OBJECT_HUB; } 62519b8f8a0SMichael Lotz virtual const char * TypeName() const { return "hub"; } 626853e6be8SMichael Lotz 627853e6be8SMichael Lotz virtual status_t GetDescriptor(uint8 descriptorType, 628853e6be8SMichael Lotz uint8 index, uint16 languageID, 629853e6be8SMichael Lotz void *data, size_t dataLength, 630853e6be8SMichael Lotz size_t *actualLength); 631853e6be8SMichael Lotz 63219b8f8a0SMichael Lotz Device * ChildAt(uint8 index) const 63319b8f8a0SMichael Lotz { return fChildren[index]; } 634853e6be8SMichael Lotz 635853e6be8SMichael Lotz status_t UpdatePortStatus(uint8 index); 636853e6be8SMichael Lotz status_t ResetPort(uint8 index); 637853e6be8SMichael Lotz status_t DisablePort(uint8 index); 638853e6be8SMichael Lotz 639853e6be8SMichael Lotz void Explore(change_item **changeList); 640853e6be8SMichael Lotz static void InterruptCallback(void *cookie, 641853e6be8SMichael Lotz status_t status, void *data, 642853e6be8SMichael Lotz size_t actualLength); 643853e6be8SMichael Lotz 644853e6be8SMichael Lotz virtual status_t ReportDevice( 64519b8f8a0SMichael Lotz usb_support_descriptor * 64619b8f8a0SMichael Lotz supportDescriptors, 647853e6be8SMichael Lotz uint32 supportDescriptorCount, 648853e6be8SMichael Lotz const usb_notify_hooks *hooks, 649853e6be8SMichael Lotz usb_driver_cookie **cookies, 650853e6be8SMichael Lotz bool added, bool recursive); 651853e6be8SMichael Lotz virtual status_t BuildDeviceName(char *string, 652853e6be8SMichael Lotz uint32 *index, size_t bufferSize, 653853e6be8SMichael Lotz Device *device); 654853e6be8SMichael Lotz 655853e6be8SMichael Lotz private: 656827c7224SMichael Lotz status_t _DebouncePort(uint8 index); 657827c7224SMichael Lotz 658853e6be8SMichael Lotz InterruptPipe * fInterruptPipe; 659853e6be8SMichael Lotz usb_hub_descriptor fHubDescriptor; 660853e6be8SMichael Lotz 661853e6be8SMichael Lotz usb_port_status fInterruptStatus[USB_MAX_PORT_COUNT]; 662853e6be8SMichael Lotz usb_port_status fPortStatus[USB_MAX_PORT_COUNT]; 663853e6be8SMichael Lotz Device * fChildren[USB_MAX_PORT_COUNT]; 664853e6be8SMichael Lotz }; 665853e6be8SMichael Lotz 666853e6be8SMichael Lotz 667853e6be8SMichael Lotz /* 668853e6be8SMichael Lotz * A Transfer is allocated on the heap and passed to the Host Controller in 669853e6be8SMichael Lotz * SubmitTransfer(). It is generated for all queued transfers. If queuing 670853e6be8SMichael Lotz * succeds (SubmitTransfer() returns with >= B_OK) the Host Controller takes 671853e6be8SMichael Lotz * ownership of the Transfer and will delete it as soon as it has called the 672853e6be8SMichael Lotz * set callback function. If SubmitTransfer() failes, the calling function is 673853e6be8SMichael Lotz * responsible for deleting the Transfer. 674853e6be8SMichael Lotz * Also, the transfer takes ownership of the usb_request_data passed to it in 675853e6be8SMichael Lotz * SetRequestData(), but does not take ownership of the data buffer set by 676853e6be8SMichael Lotz * SetData(). 677853e6be8SMichael Lotz */ 678853e6be8SMichael Lotz class Transfer { 679853e6be8SMichael Lotz public: 680853e6be8SMichael Lotz Transfer(Pipe *pipe); 681853e6be8SMichael Lotz ~Transfer(); 682853e6be8SMichael Lotz 68319b8f8a0SMichael Lotz Pipe * TransferPipe() const { return fPipe; } 684853e6be8SMichael Lotz 685853e6be8SMichael Lotz void SetRequestData(usb_request_data *data); 68619b8f8a0SMichael Lotz usb_request_data * RequestData() const { return fRequestData; } 687853e6be8SMichael Lotz 68819b8f8a0SMichael Lotz void SetIsochronousData( 68919b8f8a0SMichael Lotz usb_isochronous_data *data); 69019b8f8a0SMichael Lotz usb_isochronous_data * IsochronousData() const 69119b8f8a0SMichael Lotz { return fIsochronousData; } 692853e6be8SMichael Lotz 693853e6be8SMichael Lotz void SetData(uint8 *buffer, size_t length); 69419b8f8a0SMichael Lotz uint8 * Data() const 69519b8f8a0SMichael Lotz { return (uint8 *)fData.iov_base; } 69619b8f8a0SMichael Lotz size_t DataLength() const { return fData.iov_len; } 697853e6be8SMichael Lotz 698853e6be8SMichael Lotz void SetPhysical(bool physical); 69919b8f8a0SMichael Lotz bool IsPhysical() const { return fPhysical; } 700853e6be8SMichael Lotz 70119b8f8a0SMichael Lotz void SetVector(iovec *vector, 70219b8f8a0SMichael Lotz size_t vectorCount); 70319b8f8a0SMichael Lotz iovec * Vector() { return fVector; } 70419b8f8a0SMichael Lotz size_t VectorCount() const { return fVectorCount; } 705853e6be8SMichael Lotz 70619b8f8a0SMichael Lotz uint16 Bandwidth() const { return fBandwidth; } 707853e6be8SMichael Lotz 70819b8f8a0SMichael Lotz bool IsFragmented() const { return fFragmented; } 709853e6be8SMichael Lotz void AdvanceByFragment(size_t actualLength); 710*bc7fd433SAugustin Cavalier size_t FragmentLength() const; 711853e6be8SMichael Lotz 712853e6be8SMichael Lotz status_t InitKernelAccess(); 713853e6be8SMichael Lotz status_t PrepareKernelAccess(); 714853e6be8SMichael Lotz 715853e6be8SMichael Lotz void SetCallback(usb_callback_func callback, 716853e6be8SMichael Lotz void *cookie); 717159aa93bSMichael Lotz usb_callback_func Callback() const 718159aa93bSMichael Lotz { return fCallback; } 719159aa93bSMichael Lotz void * CallbackCookie() const 720159aa93bSMichael Lotz { return fCallbackCookie; } 721853e6be8SMichael Lotz 72219b8f8a0SMichael Lotz void Finished(uint32 status, 72319b8f8a0SMichael Lotz size_t actualLength); 724853e6be8SMichael Lotz 72519b8f8a0SMichael Lotz usb_id USBID() const { return 0; } 72619b8f8a0SMichael Lotz const char * TypeName() const { return "transfer"; } 727853e6be8SMichael Lotz 728853e6be8SMichael Lotz private: 729853e6be8SMichael Lotz status_t _CalculateBandwidth(); 730853e6be8SMichael Lotz 731853e6be8SMichael Lotz // Data that is related to the transfer 732853e6be8SMichael Lotz Pipe * fPipe; 733853e6be8SMichael Lotz iovec fData; 734853e6be8SMichael Lotz iovec * fVector; 735853e6be8SMichael Lotz size_t fVectorCount; 736853e6be8SMichael Lotz void * fBaseAddress; 737853e6be8SMichael Lotz bool fPhysical; 738853e6be8SMichael Lotz bool fFragmented; 739853e6be8SMichael Lotz size_t fActualLength; 740853e6be8SMichael Lotz area_id fUserArea; 741853e6be8SMichael Lotz area_id fClonedArea; 742853e6be8SMichael Lotz 743853e6be8SMichael Lotz usb_callback_func fCallback; 744853e6be8SMichael Lotz void * fCallbackCookie; 745853e6be8SMichael Lotz 746853e6be8SMichael Lotz // For control transfers 747853e6be8SMichael Lotz usb_request_data * fRequestData; 748853e6be8SMichael Lotz 749853e6be8SMichael Lotz // For isochronous transfers 750853e6be8SMichael Lotz usb_isochronous_data * fIsochronousData; 751853e6be8SMichael Lotz 752853e6be8SMichael Lotz // For bandwidth management. 753853e6be8SMichael Lotz // It contains the bandwidth necessary in microseconds 754853e6be8SMichael Lotz // for either isochronous, interrupt or control transfers. 755853e6be8SMichael Lotz // Not used for bulk transactions. 756853e6be8SMichael Lotz uint16 fBandwidth; 757853e6be8SMichael Lotz }; 758853e6be8SMichael Lotz 759cc9f959dSMichael Lotz #endif // _USB_PRIVATE_H 760