#ifndef _USB_PRIVATE_H
#define _USB_PRIVATE_H
#include <device_manager.h>
#include <bus/USB.h>
#include "usbspec_private.h"
#include <lock.h>
#include <Referenceable.h>
#include <util/Vector.h>
#include <vm/vm.h>
#include <util/iovec_support.h>
#define TRACE_OUTPUT(x, y, z...) \
{ \
dprintf("usb %s%s %" B_PRId32 ": ", y, (x)->TypeName(), (x)->USBID()); \
dprintf(z); \
}
#ifdef TRACE_USB
#define TRACE(x...) TRACE_OUTPUT(this, "", x)
#define TRACE_STATIC(x, y...) TRACE_OUTPUT(x, "", y)
#define TRACE_MODULE(x...) dprintf("usb " USB_MODULE_NAME ": " x)
#else
#define TRACE(x...)
#define TRACE_STATIC(x, y...)
#define TRACE_MODULE(x...)
#endif
#define TRACE_ALWAYS(x...) TRACE_OUTPUT(this, "", x)
#define TRACE_ERROR(x...) TRACE_OUTPUT(this, "error ", x)
#define TRACE_MODULE_ALWAYS(x...) dprintf("usb " USB_MODULE_NAME ": " x)
#define TRACE_MODULE_ERROR(x...) dprintf("usb " USB_MODULE_NAME ": " x)
extern device_manager_info *gDeviceManager;
class Hub;
class Stack;
class Device;
class Transfer;
class BusManager;
class Pipe;
class ControlPipe;
class Object;
class PhysicalMemoryAllocator;
struct usb_host_controller_info {
module_info info;
status_t (*control)(uint32 op, void *data, size_t length);
status_t (*add_to)(Stack *stack);
};
struct usb_driver_cookie {
usb_id device;
void *cookie;
usb_driver_cookie *link;
};
struct usb_driver_info {
const char *driver_name;
usb_support_descriptor *support_descriptors;
uint32 support_descriptor_count;
const char *republish_driver_name;
usb_notify_hooks notify_hooks;
usb_driver_cookie *cookies;
usb_driver_info *link;
};
struct change_item {
bool added;
Device *device;
change_item *link;
};
struct rescan_item {
const char *name;
rescan_item *link;
};
typedef enum {
USB_SPEED_LOWSPEED = 0,
USB_SPEED_FULLSPEED,
USB_SPEED_HIGHSPEED,
USB_SPEED_SUPERSPEED,
USB_SPEED_SUPERSPEEDPLUS,
USB_SPEED_MAX = USB_SPEED_SUPERSPEEDPLUS
} usb_speed;
typedef enum {
USB_CHANGE_CREATED = 0,
USB_CHANGE_DESTROYED,
USB_CHANGE_PIPE_POLICY_CHANGED
} usb_change;
#define USB_OBJECT_NONE 0x00000000
#define USB_OBJECT_PIPE 0x00000001
#define USB_OBJECT_CONTROL_PIPE 0x00000002
#define USB_OBJECT_INTERRUPT_PIPE 0x00000004
#define USB_OBJECT_BULK_PIPE 0x00000008
#define USB_OBJECT_ISO_PIPE 0x00000010
#define USB_OBJECT_INTERFACE 0x00000020
#define USB_OBJECT_DEVICE 0x00000040
#define USB_OBJECT_HUB 0x00000080
class Stack {
public:
Stack();
~Stack();
status_t InitCheck();
bool Lock();
void Unlock();
usb_id GetUSBID(Object *object);
void PutUSBID(Object *object);
Object * GetObject(usb_id id);
Object * GetObjectNoLock(usb_id id) const;
void AddBusManager(BusManager *bus);
int32 IndexOfBusManager(BusManager *bus) const;
BusManager * BusManagerAt(int32 index) const;
status_t AllocateChunk(void **logicalAddress,
phys_addr_t *physicalAddress,
size_t size);
status_t FreeChunk(void *logicalAddress,
phys_addr_t physicalAddress,
size_t size);
area_id AllocateArea(void **logicalAddress,
phys_addr_t *physicalAddress,
size_t size, const char *name);
void NotifyDeviceChange(Device *device,
rescan_item **rescanList,
bool added);
void RescanDrivers(rescan_item *rescanItem);
status_t RegisterDriver(const char *driverName,
const usb_support_descriptor *
descriptors,
size_t descriptorCount,
const char *republishDriverName);
status_t InstallNotify(const char *driverName,
const usb_notify_hooks *hooks);
status_t UninstallNotify(const char *driverName);
usb_id USBID() const { return 0; }
const char * TypeName() const { return "stack"; }
void Explore();
private:
static int32 ExploreThread(void *data);
Vector<BusManager *> fBusManagers;
thread_id fExploreThread;
sem_id fExploreSem;
mutex fStackLock;
mutex fExploreLock;
PhysicalMemoryAllocator * fAllocator;
uint32 fObjectIndex;
uint32 fObjectMaxCount;
Object ** fObjectArray;
usb_driver_info * fDriverList;
};
class BusManager {
public:
BusManager(Stack *stack, device_node* node);
virtual ~BusManager();
virtual status_t InitCheck();
bool Lock();
void Unlock();
int8 AllocateAddress();
void FreeAddress(int8 address);
virtual Device * AllocateDevice(Hub *parent,
int8 hubAddress, uint8 hubPort,
usb_speed speed);
virtual void FreeDevice(Device *device);
virtual status_t Start();
virtual status_t Stop();
virtual status_t StartDebugTransfer(Transfer *transfer);
virtual status_t CheckDebugTransfer(Transfer *transfer);
virtual void CancelDebugTransfer(Transfer *transfer);
virtual status_t SubmitTransfer(Transfer *transfer);
virtual status_t CancelQueuedTransfers(Pipe *pipe,
bool force);
virtual status_t NotifyPipeChange(Pipe *pipe,
usb_change change);
Object * RootObject() const
{ return fRootObject; }
Hub * GetRootHub() const { return fRootHub; }
void SetRootHub(Hub *hub) { fRootHub = hub; }
virtual const char * TypeName() const = 0;
device_node * Node() const
{ return fNode; }
protected:
usb_id USBID() const { return fStackIndex; }
protected:
bool fInitOK;
private:
ControlPipe * _GetDefaultPipe(usb_speed);
mutex fLock;
bool fDeviceMap[128];
int8 fDeviceIndex;
Stack * fStack;
ControlPipe * fDefaultPipes[USB_SPEED_MAX + 1];
Hub * fRootHub;
Object * fRootObject;
usb_id fStackIndex;
device_node* fNode;
};
class Object : public BReferenceable {
public:
Object(Stack *stack, BusManager *bus);
Object(Object *parent);
virtual ~Object();
Object * Parent() const { return fParent; }
BusManager * GetBusManager() const
{ return fBusManager; }
Stack * GetStack() const { return fStack; }
usb_id USBID() const { return fUSBID; }
virtual uint32 Type() const { return USB_OBJECT_NONE; }
virtual const char * TypeName() const { return "object"; }
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
virtual status_t GetStatus(uint16 *status);
protected:
void PutUSBID(bool waitForIdle = true);
void WaitForIdle();
private:
Object * fParent;
BusManager * fBusManager;
Stack * fStack;
usb_id fUSBID;
};
class Pipe : public Object {
public:
enum pipeDirection { In, Out, Default };
Pipe(Object *parent);
virtual ~Pipe();
virtual void InitCommon(int8 deviceAddress,
uint8 endpointAddress,
usb_speed speed,
pipeDirection direction,
size_t maxPacketSize,
uint8 interval,
int8 hubAddress, uint8 hubPort);
virtual void InitSuperSpeed(uint8 maxBurst,
uint16 bytesPerInterval);
virtual uint32 Type() const { return USB_OBJECT_PIPE; }
virtual const char * TypeName() const { return "pipe"; }
int8 DeviceAddress() const
{ return fDeviceAddress; }
usb_speed Speed() const { return fSpeed; }
pipeDirection Direction() const { return fDirection; }
uint8 EndpointAddress() const
{ return fEndpointAddress; }
size_t MaxPacketSize() const
{ return fMaxPacketSize; }
uint8 Interval() const { return fInterval; }
uint8 MaxBurst() const
{ return fMaxBurst; }
uint16 BytesPerInterval() const
{ return fBytesPerInterval; }
void SetHubInfo(int8 address, uint8 port);
int8 HubAddress() const
{ return fHubAddress; }
uint8 HubPort() const { return fHubPort; }
virtual bool DataToggle() const
{ return fDataToggle; }
virtual void SetDataToggle(bool toggle)
{ fDataToggle = toggle; }
status_t SubmitTransfer(Transfer *transfer);
virtual status_t CancelQueuedTransfers(bool force);
void SetControllerCookie(void *cookie)
{ fControllerCookie = cookie; }
void * ControllerCookie() const
{ return fControllerCookie; }
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
virtual status_t GetStatus(uint16 *status);
protected:
friend class Device;
private:
int8 fDeviceAddress;
uint8 fEndpointAddress;
pipeDirection fDirection;
usb_speed fSpeed;
size_t fMaxPacketSize;
uint8 fInterval;
uint8 fMaxBurst;
uint16 fBytesPerInterval;
int8 fHubAddress;
uint8 fHubPort;
bool fDataToggle;
void * fControllerCookie;
};
class ControlPipe : public Pipe {
public:
ControlPipe(Object *parent);
virtual ~ControlPipe();
virtual void InitCommon(int8 deviceAddress,
uint8 endpointAddress,
usb_speed speed,
pipeDirection direction,
size_t maxPacketSize,
uint8 interval,
int8 hubAddress, uint8 hubPort);
virtual uint32 Type() const { return USB_OBJECT_PIPE
| USB_OBJECT_CONTROL_PIPE; }
virtual const char * TypeName() const
{ return "control pipe"; }
virtual bool DataToggle() const { return true; }
virtual void SetDataToggle(bool toggle) {}
status_t SendRequest(uint8 requestType,
uint8 request, uint16 value,
uint16 index, uint16 length,
void *data, size_t dataLength,
size_t *actualLength);
static void SendRequestCallback(void *cookie,
status_t status, void *data,
size_t actualLength);
status_t QueueRequest(uint8 requestType,
uint8 request, uint16 value,
uint16 index, uint16 length,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
virtual status_t CancelQueuedTransfers(bool force);
private:
mutex fSendRequestLock;
sem_id fNotifySem;
status_t fTransferStatus;
size_t fActualLength;
};
class InterruptPipe : public Pipe {
public:
InterruptPipe(Object *parent);
virtual uint32 Type() const { return USB_OBJECT_PIPE
| USB_OBJECT_INTERRUPT_PIPE; }
virtual const char * TypeName() const
{ return "interrupt pipe"; }
status_t QueueInterrupt(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
class BulkPipe : public Pipe {
public:
BulkPipe(Object *parent);
virtual void InitCommon(int8 deviceAddress,
uint8 endpointAddress,
usb_speed speed,
pipeDirection direction,
size_t maxPacketSize,
uint8 interval,
int8 hubAddress, uint8 hubPort);
virtual uint32 Type() const { return USB_OBJECT_PIPE
| USB_OBJECT_BULK_PIPE; }
virtual const char * TypeName() const { return "bulk pipe"; }
status_t QueueBulk(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t QueueBulkV(iovec *vector, size_t vectorCount,
usb_callback_func callback, void *callbackCookie);
status_t QueueBulkV(physical_entry *vector, size_t vectorCount,
usb_callback_func callback, void *callbackCookie);};
class IsochronousPipe : public Pipe {
public:
IsochronousPipe(Object *parent);
virtual uint32 Type() const { return USB_OBJECT_PIPE
| USB_OBJECT_ISO_PIPE; }
virtual const char * TypeName() const { return "iso pipe"; }
status_t QueueIsochronous(void *data,
size_t dataLength,
usb_iso_packet_descriptor *
packetDescriptor,
uint32 packetCount,
uint32 *startingFrameNumber,
uint32 flags,
usb_callback_func callback,
void *callbackCookie);
status_t SetPipePolicy(uint8 maxQueuedPackets,
uint16 maxBufferDurationMS,
uint16 sampleSize);
status_t GetPipePolicy(uint8 *maxQueuedPackets,
uint16 *maxBufferDurationMS,
uint16 *sampleSize);
private:
uint8 fMaxQueuedPackets;
uint16 fMaxBufferDuration;
uint16 fSampleSize;
};
class Interface : public Object {
public:
Interface(Object *parent,
uint8 interfaceIndex);
virtual uint32 Type() const
{ return USB_OBJECT_INTERFACE; }
virtual const char * TypeName() const { return "interface"; }
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
virtual status_t GetStatus(uint16 *status);
private:
uint8 fInterfaceIndex;
};
class Device : public Object {
public:
Device(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc,
int8 deviceAddress,
usb_speed speed, bool isRootHub,
void *controllerCookie = NULL);
virtual ~Device();
status_t InitCheck();
virtual status_t Changed(change_item **changeList,
bool added);
virtual uint32 Type() const
{ return USB_OBJECT_DEVICE; }
virtual const char * TypeName() const { return "device"; }
ControlPipe * DefaultPipe() const
{ return fDefaultPipe; }
virtual status_t GetDescriptor(uint8 descriptorType,
uint8 index, uint16 languageID,
void *data, size_t dataLength,
size_t *actualLength);
int8 DeviceAddress() const
{ return fDeviceAddress; }
const usb_device_descriptor * DeviceDescriptor() const;
usb_speed Speed() const { return fSpeed; }
const usb_configuration_info * Configuration() const;
const usb_configuration_info * ConfigurationAt(uint8 index) const;
status_t SetConfiguration(
const usb_configuration_info *
configuration);
status_t SetConfigurationAt(uint8 index);
status_t Unconfigure(bool atDeviceLevel);
status_t SetAltInterface(
const usb_interface_info *
interface);
void InitEndpoints(int32 interfaceIndex);
void ClearEndpoints(int32 interfaceIndex);
virtual status_t ReportDevice(
usb_support_descriptor *
supportDescriptors,
uint32 supportDescriptorCount,
const usb_notify_hooks *hooks,
usb_driver_cookie **cookies,
bool added, bool recursive);
virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize,
Device *device);
device_node * RegisterNode(device_node* parent = NULL);
int8 HubAddress() const
{ return fHubAddress; }
uint8 HubPort() const { return fHubPort; }
void SetControllerCookie(void *cookie)
{ fControllerCookie = cookie; }
void * ControllerCookie() const
{ return fControllerCookie; }
device_node * Node() const
{ return fNode; }
void SetNode(device_node* node) { fNode = node; }
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
virtual status_t GetStatus(uint16 *status);
protected:
usb_device_descriptor fDeviceDescriptor;
bool fInitOK;
private:
bool fAvailable;
bool fIsRootHub;
usb_configuration_info * fConfigurations;
usb_configuration_info * fCurrentConfiguration;
usb_speed fSpeed;
int8 fDeviceAddress;
int8 fHubAddress;
uint8 fHubPort;
ControlPipe * fDefaultPipe;
void * fControllerCookie;
device_node* fNode;
};
class Hub : public Device {
public:
Hub(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc,
int8 deviceAddress,
usb_speed speed, bool isRootHub,
void *controllerCookie = NULL);
virtual ~Hub();
virtual status_t Changed(change_item **changeList,
bool added);
virtual uint32 Type() const { return USB_OBJECT_DEVICE
| USB_OBJECT_HUB; }
virtual const char * TypeName() const { return "hub"; }
virtual status_t GetDescriptor(uint8 descriptorType,
uint8 index, uint16 languageID,
void *data, size_t dataLength,
size_t *actualLength);
Device * ChildAt(uint8 index) const
{ return fChildren[index]; }
status_t UpdatePortStatus(uint8 index);
status_t ResetPort(uint8 index);
status_t DisablePort(uint8 index);
void Explore(change_item **changeList);
static void InterruptCallback(void *cookie,
status_t status, void *data,
size_t actualLength);
virtual status_t ReportDevice(
usb_support_descriptor *
supportDescriptors,
uint32 supportDescriptorCount,
const usb_notify_hooks *hooks,
usb_driver_cookie **cookies,
bool added, bool recursive);
virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize,
Device *device);
private:
status_t _DebouncePort(uint8 index);
InterruptPipe * fInterruptPipe;
usb_hub_descriptor fHubDescriptor;
usb_port_status fInterruptStatus[USB_MAX_PORT_COUNT];
usb_port_status fPortStatus[USB_MAX_PORT_COUNT];
Device * fChildren[USB_MAX_PORT_COUNT];
};
class Transfer {
public:
Transfer(Pipe *pipe);
~Transfer();
Pipe * TransferPipe() const { return fPipe; }
void SetRequestData(usb_request_data *data);
usb_request_data * RequestData() const { return fRequestData; }
void SetIsochronousData(
usb_isochronous_data *data);
usb_isochronous_data * IsochronousData() const
{ return fIsochronousData; }
void SetData(uint8 *buffer, size_t length);
uint8 * Data() const
{ return fPhysical ? NULL : (uint8 *)fData.base; }
size_t DataLength() const { return fData.length; }
bool IsPhysical() const { return fPhysical; }
void SetVector(iovec *vector, size_t vectorCount);
void SetVector(physical_entry *vector, size_t vectorCount);
generic_io_vec * Vector() { return fVector; }
size_t VectorCount() const { return fVectorCount; }
uint16 Bandwidth() const { return fBandwidth; }
bool IsFragmented() const { return fFragmented; }
void AdvanceByFragment(size_t actualLength);
size_t FragmentLength() const;
status_t InitKernelAccess();
status_t PrepareKernelAccess();
void SetCallback(usb_callback_func callback,
void *cookie);
usb_callback_func Callback() const
{ return fCallback; }
void * CallbackCookie() const
{ return fCallbackCookie; }
void Finished(uint32 status,
size_t actualLength);
usb_id USBID() const { return 0; }
const char * TypeName() const { return "transfer"; }
private:
void _CheckFragmented();
status_t _CalculateBandwidth();
BReference<Pipe> fPipe;
generic_io_vec fData;
generic_io_vec * fVector;
size_t fVectorCount;
void * fBaseAddress;
bool fPhysical;
bool fFragmented;
size_t fActualLength;
area_id fUserArea;
area_id fClonedArea;
usb_callback_func fCallback;
void * fCallbackCookie;
usb_request_data * fRequestData;
usb_isochronous_data * fIsochronousData;
uint16 fBandwidth;
};
typedef struct usb_bus_interface {
driver_module_info info;
} usb_bus_interface;
typedef struct {
driver_module_info info;
status_t (*get_stack)(void** stack);
} usb_for_controller_interface;
#define USB_FOR_CONTROLLER_MODULE_NAME "bus_managers/usb/controller/driver_v1"
typedef struct {
driver_module_info info;
} usb_device_interface;
#define USB_DEVICE_MODULE_NAME "bus_managers/usb/device/driver_v1"
#endif