d419b482ad
name, as it in fact is like a kit in the kit. It combines the different BUSB* classes as compared to SerialPort.h where there really is a 1:1 relationship between the header and the (one) class. If someone has a better fitting name please shout. Separated the usb_raw.h into usb_raw.h which defines the protocol and usb_raw_private.h which holds the internal device structure for usb_raw. This reduces the header dependencies. Hopefully cought all occurencies of USBKit.a usage (in usb_dev_info and the usb_webcam media add-on) but might have missed something that is not in the image. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24858 a95241bf-73f2-0310-859d-f6bbb57e9c96
362 lines
13 KiB
C++
362 lines
13 KiB
C++
/*
|
|
* Copyright 2007-2008, Haiku Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
#ifndef _USBKIT_H
|
|
#define _USBKIT_H
|
|
|
|
#include <SupportDefs.h>
|
|
#include <USB3.h>
|
|
#include <USB_spec.h>
|
|
|
|
|
|
class BUSBRoster;
|
|
class BUSBDevice;
|
|
class BUSBConfiguration;
|
|
class BUSBInterface;
|
|
class BUSBEndpoint;
|
|
|
|
|
|
/* The BUSBRoster class can be used to watch for devices that get attached or
|
|
removed from the USB bus.
|
|
You subclass the roster and implement the pure virtual DeviceAdded() and
|
|
DeviceRemoved() hooks. */
|
|
class BUSBRoster {
|
|
public:
|
|
BUSBRoster();
|
|
virtual ~BUSBRoster();
|
|
|
|
// The DeviceAdded() hook will be called when a new device gets
|
|
// attached to the USB bus. The hook is called with an initialized
|
|
// BUSBDevice object. If you return B_OK from your hook the object
|
|
// will stay valid and the DeviceRemoved() hook will be called with
|
|
// for it. Otherwise the object is deleted and DeviceRemoved()
|
|
// is not called.
|
|
virtual status_t DeviceAdded(BUSBDevice *device) = 0;
|
|
|
|
// When a device gets detached from the bus that you hold a
|
|
// BUSBDevice object for (gotten through DeviceAdded()) the
|
|
// DeviceRemoved() hook will be called. The device object gets
|
|
// invalid and will be deleted as soon as you return from the hook
|
|
// so be sure to remove all references to it.
|
|
virtual void DeviceRemoved(BUSBDevice *device) = 0;
|
|
|
|
void Start();
|
|
void Stop();
|
|
|
|
private:
|
|
virtual void _ReservedUSBRoster1();
|
|
virtual void _ReservedUSBRoster2();
|
|
virtual void _ReservedUSBRoster3();
|
|
virtual void _ReservedUSBRoster4();
|
|
virtual void _ReservedUSBRoster5();
|
|
|
|
void *fLooper;
|
|
uint32 fReserved[10];
|
|
};
|
|
|
|
|
|
/* The BUSBDevice presents an interface to USB device. You can either get
|
|
it through the BUSBRoster or by creating one yourself and setting it to
|
|
a valid raw usb device (with a path of "/dev/bus/usb/x").
|
|
The device class provides direct accessors for descriptor fields as well
|
|
as convenience functions to directly get string representations of fields.
|
|
The BUSBDevice also provides access for the BUSBConfiguration objects of
|
|
a device. These objects and all of their child objects depend on the
|
|
parent device and will be deleted as soon as the device object is
|
|
destroyed */
|
|
class BUSBDevice {
|
|
public:
|
|
BUSBDevice(const char *path = NULL);
|
|
virtual ~BUSBDevice();
|
|
|
|
virtual status_t InitCheck();
|
|
|
|
status_t SetTo(const char *path);
|
|
void Unset();
|
|
|
|
// Returns the location on the bus represented as hub/device sequence
|
|
const char *Location() const;
|
|
bool IsHub() const;
|
|
|
|
// These are direct accessors to descriptor fields
|
|
uint16 USBVersion() const;
|
|
uint8 Class() const;
|
|
uint8 Subclass() const;
|
|
uint8 Protocol() const;
|
|
uint8 MaxEndpoint0PacketSize() const;
|
|
uint16 VendorID() const;
|
|
uint16 ProductID() const;
|
|
uint16 Version() const;
|
|
|
|
// The string functions return the string representation of the
|
|
// descriptor data. The strings are decoded to normal 0 terminated
|
|
// c strings and are cached and owned by the object.
|
|
// If a string is not available an empty string is returned.
|
|
const char *ManufacturerString() const;
|
|
const char *ProductString() const;
|
|
const char *SerialNumberString() const;
|
|
|
|
const usb_device_descriptor *Descriptor() const;
|
|
|
|
// GetStringDescriptor() can be used to retrieve the raw
|
|
// usb_string_descriptor with a given index. The strings contained
|
|
// in these descriptors are usually two-byte unicode encoded.
|
|
size_t GetStringDescriptor(uint32 index,
|
|
usb_string_descriptor *descriptor,
|
|
size_t length) const;
|
|
|
|
// Use the DecodeStringDescriptor() convenience function to get a
|
|
// 0-terminated c string for a given string index. Note that this
|
|
// will allocate the string as "new char[];" and needs to be deleted
|
|
// like "delete[] string;" by the caller.
|
|
char *DecodeStringDescriptor(uint32 index) const;
|
|
|
|
size_t GetDescriptor(uint8 type, uint8 index,
|
|
uint16 languageID, void *data,
|
|
size_t length) const;
|
|
|
|
// With ConfigurationAt() or ActiveConfiguration() you can get an
|
|
// object that represents the configuration at a certain index or at
|
|
// the index that is currently configured. Note that the index does not
|
|
// necessarily correspond with the configuration value.
|
|
// Use the returned object as an argument to SetConfiguration() to
|
|
// change the active configuration of a device.
|
|
uint32 CountConfigurations() const;
|
|
const BUSBConfiguration *ConfigurationAt(uint32 index) const;
|
|
|
|
const BUSBConfiguration *ActiveConfiguration() const;
|
|
status_t SetConfiguration(
|
|
const BUSBConfiguration *configuration);
|
|
|
|
// ControlTransfer() sends requests using the default pipe
|
|
ssize_t ControlTransfer(uint8 requestType,
|
|
uint8 request, uint16 value,
|
|
uint16 index, uint16 length,
|
|
void *data) const;
|
|
|
|
private:
|
|
virtual void _ReservedUSBDevice1();
|
|
virtual void _ReservedUSBDevice2();
|
|
virtual void _ReservedUSBDevice3();
|
|
virtual void _ReservedUSBDevice4();
|
|
virtual void _ReservedUSBDevice5();
|
|
|
|
char *fPath;
|
|
int fRawFD;
|
|
|
|
usb_device_descriptor fDescriptor;
|
|
BUSBConfiguration **fConfigurations;
|
|
uint32 fActiveConfiguration;
|
|
|
|
mutable char *fManufacturerString;
|
|
mutable char *fProductString;
|
|
mutable char *fSerialNumberString;
|
|
|
|
uint32 fReserved[10];
|
|
};
|
|
|
|
|
|
/* A BUSBConfiguration object represents one of possibly multiple
|
|
configurations a device might have. A valid object can only be gotten
|
|
through the ConfigurationAt() and ActiveConfiguration() methods of a
|
|
BUSBDevice.
|
|
The BUSBConfiguration provides further access into the configuration by
|
|
providing CountInterfaces() and InterfaceAt() to retrieve BUSBInterface
|
|
objects. */
|
|
class BUSBConfiguration {
|
|
public:
|
|
// Device() returns the parent device of this configuration. This
|
|
// configuration is located at the index returned by Index() within
|
|
// that parent device.
|
|
uint32 Index() const;
|
|
const BUSBDevice *Device() const;
|
|
|
|
// Gets a describing string of this configuration if available.
|
|
// Otherwise an empty string is returned.
|
|
const char *ConfigurationString() const;
|
|
|
|
const usb_configuration_descriptor
|
|
*Descriptor() const;
|
|
|
|
// With CountInterfaces() and InterfaceAt() you can iterate through
|
|
// the child interfaces of this configuration. It is the only valid
|
|
// way to get a BUSBInterface object.
|
|
// Note that the interface objects retrieved using InterfaceAt() will
|
|
// be invalid and deleted as soon as this configuration gets deleted.
|
|
uint32 CountInterfaces() const;
|
|
const BUSBInterface *InterfaceAt(uint32 index) const;
|
|
|
|
private:
|
|
friend class BUSBDevice;
|
|
BUSBConfiguration(BUSBDevice *device,
|
|
uint32 index, int rawFD);
|
|
~BUSBConfiguration();
|
|
|
|
BUSBDevice *fDevice;
|
|
uint32 fIndex;
|
|
int fRawFD;
|
|
|
|
usb_configuration_descriptor fDescriptor;
|
|
BUSBInterface **fInterfaces;
|
|
|
|
mutable char *fConfigurationString;
|
|
|
|
uint32 fReserved[10];
|
|
};
|
|
|
|
|
|
/* The BUSBInterface class can be used to access the descriptor fields of
|
|
an underleying USB interface. Most importantly though it can be used to
|
|
iterate over and retrieve BUSBEndpoint objects that can be used to
|
|
transfer data over the bus. */
|
|
class BUSBInterface {
|
|
public:
|
|
// Configuration() returns the parent configuration of this interface.
|
|
// This interface is located at the index returned by Index() in that
|
|
// parent configuration.
|
|
// Device() is a convenience function to directly reach the parent
|
|
// device of this interface instead of going through the configuration.
|
|
uint32 Index() const;
|
|
const BUSBConfiguration *Configuration() const;
|
|
const BUSBDevice *Device() const;
|
|
|
|
// These are accessors to descriptor fields. InterfaceString() tries
|
|
// to return a describing string of this interface. If no string is
|
|
// available an empty string will be returned.
|
|
uint8 Class() const;
|
|
uint8 Subclass() const;
|
|
uint8 Protocol() const;
|
|
const char *InterfaceString() const;
|
|
|
|
const usb_interface_descriptor
|
|
*Descriptor() const;
|
|
|
|
// Use OtherDescriptorAt() to get generic descriptors of an interface.
|
|
// These are usually vendor or device specific extensions.
|
|
status_t OtherDescriptorAt(uint32 index,
|
|
usb_descriptor *descriptor,
|
|
size_t length) const;
|
|
|
|
// CountEndpoints() and EndpointAt() can be used to iterate over the
|
|
// available endpoints within an interface. EndpointAt() is the only
|
|
// valid way to get BUSBEndpoint object. Note that these objects will
|
|
// get invalid and deleted as soon as the parent interface is deleted.
|
|
uint32 CountEndpoints() const;
|
|
const BUSBEndpoint *EndpointAt(uint32 index) const;
|
|
|
|
// Using CountAlternates() you can retrieve the number of alternate
|
|
// interfaces for this interface. Note that this interface itself
|
|
// counts as an alternate so an alternate count of one really means
|
|
// that you are currently using the sole interface present.
|
|
// AlternateAt() returns the interface descriptor of the alternate
|
|
// interface with the specified index. Using that you can peek at the
|
|
// information contained in the descriptor without having to switch
|
|
// to this alternate interface. Note that the alternate index set in
|
|
// the interface descriptor returned is not necessarily the same index
|
|
// you used to get the descriptor. Always use the zero based index you
|
|
// used to get the information with and not the values of the returned
|
|
// descriptor as the stack will handle that translation internally.
|
|
// The interface descriptor returned was allocated by new and is yours.
|
|
// You need to delete it when you're done with it.
|
|
// With SetAlternate() you can switch this BUSBInterface object to the
|
|
// alternate interface at the specified index. Note that all endpoints
|
|
// retrieved through EndpointAt() will become invalid and will be
|
|
// deleted as soon as you set an alternate interface (even if the
|
|
// resulting interface is the same you were using before).
|
|
uint32 CountAlternates() const;
|
|
usb_interface_descriptor *AlternateAt(uint32 alternateIndex);
|
|
status_t SetAlternate(uint32 alternateIndex);
|
|
|
|
private:
|
|
friend class BUSBConfiguration;
|
|
BUSBInterface(BUSBConfiguration *config,
|
|
uint32 index, int rawFD);
|
|
~BUSBInterface();
|
|
|
|
void _UpdateDescriptorAndEndpoints();
|
|
|
|
BUSBConfiguration *fConfiguration;
|
|
uint32 fIndex;
|
|
int fRawFD;
|
|
|
|
usb_interface_descriptor fDescriptor;
|
|
BUSBEndpoint **fEndpoints;
|
|
|
|
mutable char *fInterfaceString;
|
|
|
|
uint32 fReserved[10];
|
|
};
|
|
|
|
|
|
/* The BUSBEndpoint represent a device endpoint that can be used to send or
|
|
receive data. It also allows to query endpoint characteristics like
|
|
endpoint type or direction. */
|
|
class BUSBEndpoint {
|
|
public:
|
|
// Interface() returns the parent interface of this endpoint.
|
|
// This endpoint is located at the index returned by Index() in the
|
|
// parent interface.
|
|
// Configuration() and Device() are convenience functions to directly
|
|
// reach the parent configuration or device of this endpoint instead
|
|
// of going through the parent objects.
|
|
uint32 Index() const;
|
|
const BUSBInterface *Interface() const;
|
|
const BUSBConfiguration *Configuration() const;
|
|
const BUSBDevice *Device() const;
|
|
|
|
// These methods can be used to check for endpoint characteristics.
|
|
bool IsBulk() const;
|
|
bool IsInterrupt() const;
|
|
bool IsIsochronous() const;
|
|
bool IsControl() const;
|
|
|
|
bool IsInput() const;
|
|
bool IsOutput() const;
|
|
|
|
uint16 MaxPacketSize() const;
|
|
uint8 Interval() const;
|
|
|
|
const usb_endpoint_descriptor
|
|
*Descriptor() const;
|
|
|
|
// These methods initiate transfers to or from the endpoint. All
|
|
// transfers are synchronous and the actually transfered amount of
|
|
// data is returned as a result. A negative value indicates an error.
|
|
// Which transfer type to use depends on the endpoint type.
|
|
ssize_t ControlTransfer(uint8 requestType,
|
|
uint8 request, uint16 value,
|
|
uint16 index, uint16 length,
|
|
void *data) const;
|
|
ssize_t InterruptTransfer(void *data,
|
|
size_t length) const;
|
|
ssize_t BulkTransfer(void *data,
|
|
size_t length) const;
|
|
ssize_t IsochronousTransfer(void *data,
|
|
size_t length,
|
|
usb_iso_packet_descriptor *packetDescriptors,
|
|
uint32 packetCount) const;
|
|
|
|
// These are convenience methods for getting and clearing the halt
|
|
// state of an endpoint. They use the control pipe of the device to
|
|
// send the corresponding requests.
|
|
bool IsStalled() const;
|
|
status_t ClearStall() const;
|
|
private:
|
|
friend class BUSBInterface;
|
|
BUSBEndpoint(BUSBInterface *interface,
|
|
uint32 index, int rawFD);
|
|
~BUSBEndpoint();
|
|
|
|
BUSBInterface *fInterface;
|
|
uint32 fIndex;
|
|
int fRawFD;
|
|
|
|
usb_endpoint_descriptor fDescriptor;
|
|
|
|
uint32 fReserved[10];
|
|
};
|
|
|
|
#endif
|