* Added USB API Version 3. It's put into USB3.h while the v2 API resides in USB2.h. USB.h just includes USB2.h for now.

* Rewrote both headers on the way.
* The usb module now exports both, the v2 and v3 module_info.
* Changed the internals of the USB Stack to give out usb_ids instead of opaque handles to internal classes.
* Cleaned up some more of the Stack by moving members into other classes and removing unused stuff.
* Updated the usb_raw driver from v2 to v3 API.

Since both usb_hid (which still uses the v2 API) and usb_raw (which now uses the v3 API) work, I'd call it a success ;-)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18539 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2006-08-19 23:09:05 +00:00
parent c3157a2749
commit 5b0ec61f97
18 changed files with 1062 additions and 419 deletions

View File

@ -1,189 +1,8 @@
/*
** USB.h - Version 2 USB Device Driver API
**
** Copyright 1999, Be Incorporated. All Rights Reserved.
**
*/
* This file is here for compatibility reasons.
*
* You should include USB2.h or USB3.h depending on which API version you
* intend to use.
*/
#ifndef _USB_H
#define _USB_H
#include <KernelExport.h>
#include <bus_manager.h>
#include <USB_spec.h>
#include <USB_rle.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct usb_module_info usb_module_info;
/* these are opaque handles to internal stack objects */
typedef struct usb_device usb_device;
typedef struct usb_interface usb_interface;
typedef struct usb_pipe usb_pipe;
typedef struct usb_endpoint_info usb_endpoint_info;
typedef struct usb_interface_info usb_interface_info;
typedef struct usb_interface_list usb_interface_list;
typedef struct usb_configuration_info usb_configuration_info;
typedef struct usb_notify_hooks {
status_t (*device_added)(const usb_device *device, void **cookie);
status_t (*device_removed)(void *cookie);
} usb_notify_hooks;
typedef struct usb_support_descriptor {
uint8 dev_class;
uint8 dev_subclass;
uint8 dev_protocol;
uint16 vendor;
uint16 product;
} usb_support_descriptor;
/* ie, I support any hub device:
** usb_support_descriptor hub_devs = { 9, 0, 0, 0, 0 };
*/
struct usb_endpoint_info {
usb_endpoint_descriptor *descr; /* descriptor and handle */
usb_pipe *handle; /* of this endpoint/pipe */
};
struct usb_interface_info {
usb_interface_descriptor *descr; /* descriptor and handle */
usb_interface *handle; /* of this interface */
size_t endpoint_count; /* count and list of endpoints */
usb_endpoint_info *endpoint; /* in this interface */
size_t generic_count; /* unparsed descriptors in this */
usb_descriptor **generic; /* interface */
};
struct usb_interface_list {
size_t alt_count; /* count and list of alternate */
usb_interface_info *alt; /* interfaces available */
usb_interface_info *active; /* currently active alternate */
};
struct usb_configuration_info {
usb_configuration_descriptor *descr; /* descriptor of this config */
size_t interface_count; /* interfaces in this config */
usb_interface_list *interface;
};
typedef void (*usb_callback_func)(void *cookie, uint32 status,
void *data, uint32 actual_len);
struct usb_module_info {
bus_manager_info binfo;
/* inform the bus manager of our intent to support a set of devices */
status_t (*register_driver)(const char *driver_name,
const usb_support_descriptor *descriptors,
size_t count,
const char *optional_republish_driver_name);
/* request notification from the bus manager for add/remove of devices we
support */
status_t (*install_notify)(const char *driver_name,
const usb_notify_hooks *hooks);
status_t (*uninstall_notify)(const char *driver_name);
/* get the device descriptor */
const usb_device_descriptor *(*get_device_descriptor)(const usb_device *dev);
/* get the nth supported configuration */
const usb_configuration_info *(*get_nth_configuration)(const usb_device *dev, uint index);
/* get the active configuration */
const usb_configuration_info *(*get_configuration)(const usb_device *dev);
/* set the active configuration */
status_t (*set_configuration)(const usb_device *dev,
const usb_configuration_info *configuration);
status_t (*set_alt_interface)(const usb_device *dev,
const usb_interface_info *ifc);
/* standard device requests -- convenience functions */
/* obj may be a usb_device*, usb_pipe*, or usb_interface* */
status_t (*set_feature)(const void *object, uint16 selector);
status_t (*clear_feature)(const void *object, uint16 selector);
status_t (*get_status)(const void *object, uint16 *status);
status_t (*get_descriptor)(const usb_device *d,
uint8 type, uint8 index, uint16 lang,
void *data, size_t len, size_t *actual_len);
/* generic device request function */
status_t (*send_request)(const usb_device *d,
uint8 request_type, uint8 request,
uint16 value, uint16 index, uint16 length,
void *data, size_t data_len, size_t *actual_len);
/* async request queueing */
status_t (*queue_interrupt)(const usb_pipe *handle,
void *data, size_t len,
usb_callback_func notify, void *cookie);
status_t (*queue_bulk)(const usb_pipe *handle,
void *data, size_t len,
usb_callback_func notify, void *cookie);
status_t (*queue_isochronous)(const usb_pipe *handle,
void *data, size_t len,
rlea* rle_array, uint16 buffer_duration_ms,
usb_callback_func notify, void *cookie);
status_t (*queue_request)(const usb_device *d,
uint8 request_type, uint8 request,
uint16 value, uint16 index, uint16 length,
void *data, size_t data_len,
usb_callback_func notify, void *cookie);
status_t (*set_pipe_policy)(const usb_pipe *handle, uint8 max_num_queued_packets,
uint16 max_buffer_duration_ms, uint16 sample_size);
/* cancel pending async requests to an endpoint */
status_t (*cancel_queued_transfers)(const usb_pipe *handle);
/* tuning, timeouts, etc */
status_t (*usb_ioctl)(uint32 opcode, void* buf, size_t buf_size);
};
/* status code for usb callback functions */
#define B_USB_STATUS_SUCCESS 0x0000
#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002
#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004
#define B_USB_STATUS_DEVICE_STALLED 0x0008
#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010
#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020
#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040
#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080
/* result codes for usb bus manager functions */
#define B_USBD_SUCCESS 0
#define B_USBD_BAD_HANDLE 1
#define B_USBD_BAD_ARGS 2
#define B_USBD_NO_DATA 3
#define B_USBD_DEVICE_FAILURE 4
#define B_USBD_COMMAND_FAILED 5
#define B_USBD_PIPE_NOT_CONFIGURED 6
#define B_USBD_DEVICE_ERROR 7
#define B_USBD_PIPE_ERROR 8
#define B_USBD_NO_MEMORY 9
#define B_USB_MODULE_NAME "bus_managers/usb/v2"
#ifdef __cplusplus
}
#endif
#endif
#include <USB2.h>

231
headers/os/drivers/USB2.h Normal file
View File

@ -0,0 +1,231 @@
/*
* Version 2 USB Device Driver API
*
* Copyright 2006, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _USB_V2_H_
#define _USB_V2_H_
#include <KernelExport.h>
#include <bus_manager.h>
#include <USB_spec.h>
#include <USB_rle.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct usb_module_info usb_module_info;
/* these are opaque handles to internal stack objects */
typedef struct usb_device usb_device;
typedef struct usb_interface usb_interface;
typedef struct usb_pipe usb_pipe;
typedef struct usb_endpoint_info usb_endpoint_info;
typedef struct usb_interface_info usb_interface_info;
typedef struct usb_interface_list usb_interface_list;
typedef struct usb_configuration_info usb_configuration_info;
typedef struct usb_notify_hooks {
status_t (*device_added)(const usb_device *device, void **cookie);
status_t (*device_removed)(void *cookie);
} usb_notify_hooks;
typedef struct usb_support_descriptor {
uint8 dev_class;
uint8 dev_subclass;
uint8 dev_protocol;
uint16 vendor;
uint16 product;
} usb_support_descriptor;
struct usb_endpoint_info {
usb_endpoint_descriptor *descr; /* descriptor and handle */
usb_pipe *handle; /* of this endpoint/pipe */
};
struct usb_interface_info {
usb_interface_descriptor *descr; /* descriptor and handle */
usb_interface *handle; /* of this interface */
size_t endpoint_count; /* count and list of endpoints */
usb_endpoint_info *endpoint; /* in this interface */
size_t generic_count; /* unparsed descriptors in */
usb_descriptor **generic; /* this interface */
};
struct usb_interface_list {
size_t alt_count; /* count and list of alternate */
usb_interface_info *alt; /* interfaces available */
usb_interface_info *active; /* currently active alternate */
};
struct usb_configuration_info {
usb_configuration_descriptor *descr; /* descriptor of this config */
size_t interface_count;/* interfaces in this config */
usb_interface_list *interface;
};
typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data,
uint32 actualLength);
/* The usb_module_info represents the public API of the USB Stack. */
struct usb_module_info {
bus_manager_info binfo;
/*
* Use register_driver() to inform the Stack of your interest to support
* USB devices. Support descriptors are used to indicate support for a
* specific device class/subclass/protocol or vendor/product.
* A value of 0 can be used as a wildcard for all fields.
*
* Would you like to be notified about all added hubs (class 0x09) you
* would a support descriptor like this to register_driver:
* usb_support_descriptor hub_devs = { 9, 0, 0, 0, 0 };
*
* If you intend to support just any device, or you at least want to be
* notified about any device, just pass NULL as the supportDescriptor and
* 0 as the supportDescriptorCount to register_driver.
*/
status_t (*register_driver)(const char *driverName,
const usb_support_descriptor *supportDescriptors,
size_t supportDescriptorCount,
const char *optionalRepublishDriverName);
/*
* Install notification hooks using your registered driverName. The
* device_added hook will be called for every device that matches the
* support descriptors you provided in register_driver.
* When first installing the hooks you will receive a notification about
* any already present matching device. If you return B_OK in this hook,
* you can use the id that is provided. If the hook indicates an error,
* the resources will be deallocated and you may not use the usb_device
* that is provided. In this case you will not receive a device_removed
* notification for the device either.
*/
status_t (*install_notify)(const char *driverName,
const usb_notify_hooks *hooks);
status_t (*uninstall_notify)(const char *driverName);
/* Get the device descriptor of a device. */
const usb_device_descriptor *(*get_device_descriptor)(const usb_device *device);
/* Get the nth supported configuration of a device*/
const usb_configuration_info *(*get_nth_configuration)(const usb_device *device,
uint index);
/* Get the current configuration */
const usb_configuration_info *(*get_configuration)(const usb_device *device);
/* Set the current configuration */
status_t (*set_configuration)(const usb_device *device,
const usb_configuration_info *configuration);
status_t (*set_alt_interface)(const usb_device *device,
const usb_interface_info *interface);
/*
* Standard device requests - convenience functions
* The provided object may be a usb_device, usb_pipe or usb_interface
*/
status_t (*set_feature)(const void *object, uint16 selector);
status_t (*clear_feature)(const void *object, uint16 selector);
status_t (*get_status)(const void *object, uint16 *status);
status_t (*get_descriptor)(const usb_device *device,
uint8 descriptorType, uint8 index,
uint16 languageID, void *data,
size_t dataLength,
size_t *actualLength);
/* Generic device request function - synchronous */
status_t (*send_request)(const usb_device *device,
uint8 requestType, uint8 request,
uint16 value, uint16 index,
uint16 length, void *data,
size_t dataLength,
size_t *actualLength);
/*
* Asynchronous request queueing. These functions return immediately
* and the return code only tells whether the _queuing_ of the request
* was successful or not. It doesn't indicate transfer success or error.
*
* When the transfer is finished, the provided callback function is
* called with the transfer status, a pointer to the data buffer and
* the actually transfered length as well as with the callbackCookie
* that was used when queuing the request.
*/
status_t (*queue_interrupt)(const usb_pipe *pipe,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_bulk)(const usb_pipe *pipe,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_isochronous)(const usb_pipe *pipe,
void *data, size_t dataLength,
rlea *rleArray,
uint16 bufferDurationMS,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_request)(const usb_device *device,
uint8 requestType, uint8 request,
uint16 value, uint16 index,
uint16 length, void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t (*set_pipe_policy)(const usb_pipe *pipe,
uint8 maxNumQueuedPackets,
uint16 maxBufferDurationMS,
uint16 sampleSize);
/* Cancel all pending async requests in a pipe */
status_t (*cancel_queued_transfers)(const usb_pipe *pipe);
/* tuning, timeouts, etc */
status_t (*usb_ioctl)(uint32 opcode, void *buffer,
size_t bufferSize);
};
/*
* These status are passed to the usb_callback_func callbacks. They indicate
* the status of a completed queued transfer. Multiple of these status codes
* may be combined. For example it is possible to have:
* B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED
* This indicates that a timeout happened and that the used pipe is now
* stalled.
*/
#define B_USB_STATUS_SUCCESS 0x0000
#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002
#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004
#define B_USB_STATUS_DEVICE_STALLED 0x0008
#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010
#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020
#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040
#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080
#define B_USB_MODULE_NAME "bus_managers/usb/v2"
#ifdef __cplusplus
}
#endif
#endif /* !_USB_V2_H_ */

235
headers/os/drivers/USB3.h Normal file
View File

@ -0,0 +1,235 @@
/*
* Version 3 USB Device Driver API
*
* Copyright 2006, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _USB_V3_H_
#define _USB_V3_H_
#include <KernelExport.h>
#include <bus_manager.h>
#include <iovec.h>
#include <USB_spec.h>
#include <USB_rle.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct usb_module_info usb_module_info;
typedef uint32 usb_id;
typedef usb_id usb_device;
typedef usb_id usb_interface;
typedef usb_id usb_pipe;
typedef struct usb_endpoint_info usb_endpoint_info;
typedef struct usb_interface_info usb_interface_info;
typedef struct usb_interface_list usb_interface_list;
typedef struct usb_configuration_info usb_configuration_info;
typedef struct usb_notify_hooks {
status_t (*device_added)(usb_device device, void **cookie);
status_t (*device_removed)(void *cookie);
} usb_notify_hooks;
typedef struct usb_support_descriptor {
uint8 dev_class;
uint8 dev_subclass;
uint8 dev_protocol;
uint16 vendor;
uint16 product;
} usb_support_descriptor;
struct usb_endpoint_info {
usb_endpoint_descriptor *descr; /* descriptor and handle */
usb_pipe handle; /* of this endpoint/pipe */
};
struct usb_interface_info {
usb_interface_descriptor *descr; /* descriptor and handle */
usb_interface handle; /* of this interface */
size_t endpoint_count; /* count and list of endpoints */
usb_endpoint_info *endpoint; /* in this interface */
size_t generic_count; /* unparsed descriptors in */
usb_descriptor **generic; /* this interface */
};
struct usb_interface_list {
size_t alt_count; /* count and list of alternate */
usb_interface_info *alt; /* interfaces available */
usb_interface_info *active; /* currently active alternate */
};
struct usb_configuration_info {
usb_configuration_descriptor *descr; /* descriptor of this config */
size_t interface_count;/* interfaces in this config */
usb_interface_list *interface;
};
typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data,
uint32 actualLength);
/* The usb_module_info represents the public API of the USB Stack. */
struct usb_module_info {
bus_manager_info binfo;
/*
* Use register_driver() to inform the Stack of your interest to support
* USB devices. Support descriptors are used to indicate support for a
* specific device class/subclass/protocol or vendor/product.
* A value of 0 can be used as a wildcard for all fields.
*
* Would you like to be notified about all added hubs (class 0x09) you
* would a support descriptor like this to register_driver:
* usb_support_descriptor hub_devs = { 9, 0, 0, 0, 0 };
*
* If you intend to support just any device, or you at least want to be
* notified about any device, just pass NULL as the supportDescriptor and
* 0 as the supportDescriptorCount to register_driver.
*/
status_t (*register_driver)(const char *driverName,
const usb_support_descriptor *supportDescriptors,
size_t supportDescriptorCount,
const char *optionalRepublishDriverName);
/*
* Install notification hooks using your registered driverName. The
* device_added hook will be called for every device that matches the
* support descriptors you provided in register_driver.
* When first installing the hooks you will receive a notification about
* any already present matching device. If you return B_OK in this hook,
* you can use the id that is provided. If the hook indicates an error,
* the resources will be deallocated and you may not use the usb_device
* that is provided. In this case you will not receive a device_removed
* notification for the device either.
*/
status_t (*install_notify)(const char *driverName,
const usb_notify_hooks *hooks);
status_t (*uninstall_notify)(const char *driverName);
/* Get the device descriptor of a device. */
const usb_device_descriptor *(*get_device_descriptor)(usb_device device);
/* Get the nth supported configuration of a device*/
const usb_configuration_info *(*get_nth_configuration)(usb_device device,
uint index);
/* Get the current configuration */
const usb_configuration_info *(*get_configuration)(usb_device device);
/* Set the current configuration */
status_t (*set_configuration)(usb_device device,
const usb_configuration_info *configuration);
status_t (*set_alt_interface)(usb_device device,
const usb_interface_info *interface);
/*
* Standard device requests - convenience functions
* The provided handle may be a usb_device, usb_pipe or usb_interface
*/
status_t (*set_feature)(usb_id handle, uint16 selector);
status_t (*clear_feature)(usb_id handle, uint16 selector);
status_t (*get_status)(usb_id handle, uint16 *status);
status_t (*get_descriptor)(usb_device device,
uint8 descriptorType, uint8 index,
uint16 languageID, void *data,
size_t dataLength,
size_t *actualLength);
/* Generic device request function - synchronous */
status_t (*send_request)(usb_device device,
uint8 requestType, uint8 request,
uint16 value, uint16 index,
uint16 length, void *data,
size_t *actualLength);
/*
* Asynchronous request queueing. These functions return immediately
* and the return code only tells whether the _queuing_ of the request
* was successful or not. It doesn't indicate transfer success or error.
*
* When the transfer is finished, the provided callback function is
* called with the transfer status, a pointer to the data buffer and
* the actually transfered length as well as with the callbackCookie
* that was used when queuing the request.
*/
status_t (*queue_interrupt)(usb_pipe pipe,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_bulk)(usb_pipe pipe,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_bulk_v)(usb_pipe pipe,
iovec *vector, size_t vectorCount,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_isochronous)(usb_pipe pipe,
void *data, size_t dataLength,
rlea *rleArray,
uint16 bufferDurationMS,
usb_callback_func callback,
void *callbackCookie);
status_t (*queue_request)(usb_device device,
uint8 requestType, uint8 request,
uint16 value, uint16 index,
uint16 length, void *data,
usb_callback_func callback,
void *callbackCookie);
status_t (*set_pipe_policy)(usb_pipe pipe,
uint8 maxNumQueuedPackets,
uint16 maxBufferDurationMS,
uint16 sampleSize);
/* Cancel all pending async requests in a pipe */
status_t (*cancel_queued_transfers)(usb_pipe pipe);
/* tuning, timeouts, etc */
status_t (*usb_ioctl)(uint32 opcode, void *buffer,
size_t bufferSize);
};
/*
* These status are passed to the usb_callback_func callbacks. They indicate
* the status of a completed queued transfer. Multiple of these status codes
* may be combined. For example it is possible to have:
* B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED
* This indicates that a timeout happened and that the used pipe is now
* stalled.
*/
#define B_USB_STATUS_SUCCESS 0x0000
#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002
#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004
#define B_USB_STATUS_DEVICE_STALLED 0x0008
#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010
#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020
#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040
#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080
#define B_USB_MODULE_NAME "bus_managers/usb/v3"
#ifdef __cplusplus
}
#endif
#endif /* !_USB_V3_H_ */

View File

@ -18,38 +18,40 @@
#endif
BusManager::BusManager()
BusManager::BusManager(Stack *stack)
: fInitOK(false),
fDefaultPipe(NULL),
fDefaultPipeLowSpeed(NULL),
fRootHub(NULL),
fStack(stack),
fExploreThread(-1)
{
fInitOK = false;
fRootHub = NULL;
// Set up the semaphore
fLock = create_sem(1, "bus manager lock");
if (fLock < B_OK)
if (benaphore_init(&fLock, "usb busmanager lock") < B_OK) {
TRACE(("usb BusManager: failed to create busmanager lock\n"));
return;
set_sem_owner(B_SYSTEM_TEAM, fLock);
}
// Clear the device map
for (int32 i = 0; i < 128; i++)
fDeviceMap[i] = false;
// Set up the default pipes
fDefaultPipe = new(std::nothrow) ControlPipe(this, 0, Pipe::NormalSpeed, 0, 8);
fDefaultPipe = new(std::nothrow) ControlPipe(this, 0, Pipe::NormalSpeed, 8);
if (!fDefaultPipe)
return;
fDefaultPipeLowSpeed = new(std::nothrow) ControlPipe(this, 0, Pipe::LowSpeed, 0, 8);
fDefaultPipeLowSpeed = new(std::nothrow) ControlPipe(this, 0, Pipe::LowSpeed, 8);
if (!fDefaultPipeLowSpeed)
return;
fExploreThread = -1;
fInitOK = true;
}
BusManager::~BusManager()
{
Lock();
benaphore_destroy(&fLock);
}
@ -63,6 +65,20 @@ BusManager::InitCheck()
}
bool
BusManager::Lock()
{
return (benaphore_lock(&fLock) == B_OK);
}
void
BusManager::Unlock()
{
benaphore_unlock(&fLock);
}
/*
This is the 'main' function of the explore thread, which keeps track of
the hub states.
@ -127,7 +143,7 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
// Create a temporary pipe with the new address
ControlPipe pipe(this, deviceAddress,
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8);
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 8);
// Get the device descriptor
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
@ -206,7 +222,8 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
int8
BusManager::AllocateAddress()
{
acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0);
if (!Lock())
return -1;
int8 deviceAddress = -1;
for (int32 i = 1; i < 128; i++) {
@ -217,7 +234,7 @@ BusManager::AllocateAddress()
}
}
release_sem(fLock);
Unlock();
return deviceAddress;
}

View File

@ -20,7 +20,7 @@
Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
int8 deviceAddress, bool lowSpeed)
: ControlPipe(bus, deviceAddress,
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0,
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed,
desc.max_packet_size_0),
fDeviceDescriptor(desc),
fConfigurations(NULL),
@ -155,7 +155,7 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
interfaceInfo->generic = NULL;
Interface *interface = new(std::nothrow) Interface(this);
interfaceInfo->handle = (usb_interface *)interface;
interfaceInfo->handle = interface->USBID();
currentInterface = interfaceInfo;
break;
@ -190,7 +190,7 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
switch (endpointDescriptor->attributes & 0x03) {
case 0x00: /* Control Endpoint */
endpoint = new(std::nothrow) ControlPipe(this,
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
Speed(),
endpointDescriptor->endpoint_address & 0x0f,
endpointDescriptor->max_packet_size);
break;
@ -198,7 +198,7 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
case 0x01: /* Isochronous Endpoint */
endpoint = new(std::nothrow) IsochronousPipe(this,
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
Speed(),
endpointDescriptor->endpoint_address & 0x0f,
endpointDescriptor->max_packet_size);
break;
@ -206,7 +206,7 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
case 0x02: /* Bulk Endpoint */
endpoint = new(std::nothrow) BulkPipe(this,
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
Speed(),
endpointDescriptor->endpoint_address & 0x0f,
endpointDescriptor->max_packet_size);
break;
@ -214,13 +214,13 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
case 0x03: /* Interrupt Endpoint */
endpoint = new(std::nothrow) InterruptPipe(this,
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
Speed(),
endpointDescriptor->endpoint_address & 0x0f,
endpointDescriptor->max_packet_size);
break;
}
endpointInfo->handle = (usb_pipe *)endpoint;
endpointInfo->handle = endpoint->USBID();
break;
}
@ -358,7 +358,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
TRACE(("USB Device ReportDevice\n"));
if (supportDescriptorCount == 0 || supportDescriptors == NULL) {
if (added && hooks->device_added != NULL)
hooks->device_added((const usb_device *)this, &fNotifyCookie);
hooks->device_added(USBID(), &fNotifyCookie);
else if (!added && hooks->device_removed != NULL)
hooks->device_removed(fNotifyCookie);
return;
@ -379,7 +379,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|| fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
if (added && hooks->device_added != NULL)
hooks->device_added((const usb_device *)this, &fNotifyCookie);
hooks->device_added(USBID(), &fNotifyCookie);
else if (!added && hooks->device_removed != NULL)
hooks->device_removed(fNotifyCookie);
return;
@ -398,7 +398,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|| descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
if (added && hooks->device_added != NULL)
hooks->device_added((const usb_device *)this, &fNotifyCookie);
hooks->device_added(USBID(), &fNotifyCookie);
else if (!added && hooks->device_removed != NULL)
hooks->device_removed(fNotifyCookie);
return;

View File

@ -61,13 +61,13 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable));
TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask));
Pipe *pipe = (Pipe *)Configuration()->interface->active->endpoint[0].handle;
if (!pipe || pipe->Type() != Pipe::Interrupt) {
Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle);
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) {
TRACE(("USB Hub: no interrupt pipe found\n"));
return;
}
fInterruptPipe = (InterruptPipe *)pipe;
fInterruptPipe = (InterruptPipe *)object;
fInterruptPipe->QueueInterrupt(fInterruptStatus, sizeof(fInterruptStatus),
InterruptCallback, this);
@ -193,7 +193,7 @@ Hub::Explore()
if (newDevice) {
fChildren[i] = newDevice;
Manager()->GetStack()->NotifyDeviceChange(fChildren[i], true);
GetStack()->NotifyDeviceChange(fChildren[i], true);
} else {
// the device failed to setup correctly, disable the port
// so that the device doesn't get in the way of future
@ -206,7 +206,7 @@ Hub::Explore()
// Device removed...
TRACE(("USB Hub Explore(): Device removed\n"));
if (fChildren[i]) {
Manager()->GetStack()->NotifyDeviceChange(fChildren[i], false);
GetStack()->NotifyDeviceChange(fChildren[i], false);
delete fChildren[i];
fChildren[i] = NULL;
}
@ -221,7 +221,7 @@ Hub::Explore()
// explore down the tree if we have hubs connected
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (!fChildren[i] || !fChildren[i]->IsHub())
if (!fChildren[i] || (fChildren[i]->Type() & USB_OBJECT_HUB) == 0)
continue;
((Hub *)fChildren[i])->Explore();
@ -280,7 +280,7 @@ Hub::BuildDeviceName(char *string, uint32 *index, size_t bufferSize,
status_t result = Device::BuildDeviceName(string, index, bufferSize, device);
if (result < B_OK) {
// recursion to parent failed, we're at the root(hub)
int32 managerIndex = Manager()->GetStack()->IndexOfBusManager(Manager());
int32 managerIndex = GetStack()->IndexOfBusManager(Manager());
*index += snprintf(string + *index, bufferSize - *index, "%d", managerIndex);
}

View File

@ -10,8 +10,7 @@
Interface::Interface(Device *device)
: ControlPipe(device,
device->LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8)
: ControlPipe(device, device->Speed(), 0, 8)
{
}

View File

@ -15,6 +15,7 @@ KernelStaticLibrary libusb.a :
Transfer.cpp
Pipe.cpp
Interface.cpp
Object.cpp
: -fno-pic
;

View File

@ -0,0 +1,8 @@
#include "usb_p.h"
Object::Object(BusManager *bus)
{
fStack = bus->GetStack();
fUSBID = fStack->GetUSBID(this);
}

View File

@ -12,16 +12,31 @@
Pipe::Pipe(Device *device, pipeDirection direction, pipeSpeed speed,
uint8 endpointAddress, uint32 maxPacketSize)
: fDevice(device),
fBus(NULL),
: Object(device->Manager()),
fDevice(device),
fDeviceAddress(device->Address()),
fBus(device->Manager()),
fDirection(direction),
fSpeed(speed),
fEndpoint(endpointAddress),
fMaxPacketSize(maxPacketSize),
fDataToggle(false)
{
if (fDevice)
fBus = fDevice->Manager();
}
Pipe::Pipe(BusManager *bus, int8 deviceAddress, pipeSpeed speed,
uint32 maxPacketSize)
: Object(bus),
fDevice(NULL),
fDeviceAddress(deviceAddress),
fBus(bus),
fDirection(Default),
fSpeed(speed),
fEndpoint(0),
fMaxPacketSize(maxPacketSize),
fDataToggle(true)
{
}
@ -34,7 +49,7 @@ int8
Pipe::DeviceAddress()
{
if (!fDevice)
return -1;
return fDeviceAddress;
return fDevice->Address();
}
@ -210,21 +225,9 @@ ControlPipe::ControlPipe(Device *device, pipeSpeed speed,
ControlPipe::ControlPipe(BusManager *bus, int8 deviceAddress, pipeSpeed speed,
uint8 endpointAddress, uint32 maxPacketSize)
: Pipe(NULL, Pipe::Default, speed, endpointAddress, maxPacketSize),
fDeviceAddress(deviceAddress)
uint32 maxPacketSize)
: Pipe(bus, deviceAddress, speed, maxPacketSize)
{
fBus = bus;
}
int8
ControlPipe::DeviceAddress()
{
if (!fDevice)
return fDeviceAddress;
return fDevice->Address();
}

View File

@ -20,7 +20,10 @@
Stack::Stack()
: fDriverList(NULL)
: fObjectIndex(1),
fObjectMaxCount(1024),
fObjectArray(NULL),
fDriverList(NULL)
{
TRACE(("usb stack: stack init\n"));
@ -29,6 +32,10 @@ Stack::Stack()
return;
}
size_t objectArraySize = fObjectMaxCount * sizeof(Object *);
fObjectArray = (Object **)malloc(objectArraySize);
memset(fObjectArray, 0, objectArraySize);
// Initialise the memory chunks: create 8, 16 and 32 byte-heaps
// NOTE: This is probably the most ugly code you will see in the
// whole stack. Unfortunately this is needed because of the fact
@ -185,6 +192,61 @@ Stack::Unlock()
}
usb_id
Stack::GetUSBID(Object *object)
{
if (!Lock())
return 0;
if (fObjectIndex >= fObjectMaxCount) {
Unlock();
return 0;
}
uint32 id = fObjectIndex++;
fObjectArray[id] = object;
Unlock();
return (usb_id)id;
}
void
Stack::PutUSBID(usb_id id)
{
if (!Lock())
return;
if (id >= fObjectMaxCount) {
TRACE(("usb stack: tried to put invalid usb_id!\n"));
Unlock();
return;
}
fObjectArray[id] = NULL;
Unlock();
}
Object *
Stack::GetObject(usb_id id)
{
if (!Lock())
return NULL;
if (id >= fObjectMaxCount) {
TRACE(("usb stack: tried to get object with invalid id\n"));
Unlock();
return NULL;
}
Object *result = fObjectArray[id];
Unlock();
return result;
}
void
Stack::AddBusManager(BusManager *busManager)
{

View File

@ -3,10 +3,10 @@
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* Niels S. Reedijk
*/
#include <USB.h>
#include <util/kernel_cpp.h>
#include "usb_p.h"
@ -27,6 +27,9 @@ bus_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT: {
if (gUSBStack)
return B_OK;
#ifdef TRACE_USB
set_dprintf_enabled(true);
load_driver_symbols("usb");
@ -85,65 +88,72 @@ uninstall_notify(const char *driverName)
const usb_device_descriptor *
get_device_descriptor(const usb_device *device)
get_device_descriptor(usb_device device)
{
TRACE(("usb_module: get_device_descriptor(0x%08x)\n", device));
if (!device)
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
return ((const Device *)device)->DeviceDescriptor();
return ((Device *)object)->DeviceDescriptor();
}
const usb_configuration_info *
get_nth_configuration(const usb_device *device, uint index)
get_nth_configuration(usb_device device, uint index)
{
TRACE(("usb_module: get_nth_configuration(0x%08x, %d)\n", device, index));
if (!device)
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
return ((const Device *)device)->ConfigurationAt((int32)index);
return ((Device *)object)->ConfigurationAt((int32)index);
}
const usb_configuration_info *
get_configuration(const usb_device *device)
get_configuration(usb_device device)
{
TRACE(("usb_module: get_configuration(0x%08x)\n", device));
if (!device)
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL;
return ((const Device *)device)->Configuration();
return ((Device *)object)->Configuration();
}
status_t
set_configuration(const usb_device *device,
set_configuration(usb_device device,
const usb_configuration_info *configuration)
{
TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration));
if (!device)
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
return ((Device *)device)->SetConfiguration(configuration);
return ((Device *)object)->SetConfiguration(configuration);
}
status_t
set_alt_interface(const usb_device *device,
const usb_interface_info *interface)
set_alt_interface(usb_device device, const usb_interface_info *interface)
{
TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface));
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
return B_ERROR;
}
status_t
set_feature(const void *object, uint16 selector)
set_feature(usb_id handle, uint16 selector)
{
TRACE(("usb_module: set_feature(0x%08x, %d)\n", object, selector));
if (!object)
TRACE(("usb_module: set_feature(0x%08x, %d)\n", handle, selector));
Object *object = gUSBStack->GetObject(handle);
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
return B_BAD_VALUE;
return ((Pipe *)object)->SetFeature(selector);
@ -151,10 +161,11 @@ set_feature(const void *object, uint16 selector)
status_t
clear_feature(const void *object, uint16 selector)
clear_feature(usb_id handle, uint16 selector)
{
TRACE(("usb_module: clear_feature(0x%08x, %d)\n", object, selector));
if (!object)
TRACE(("usb_module: clear_feature(0x%08x, %d)\n", handle, selector));
Object *object = gUSBStack->GetObject(handle);
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
return B_BAD_VALUE;
return ((Pipe *)object)->ClearFeature(selector);
@ -162,10 +173,14 @@ clear_feature(const void *object, uint16 selector)
status_t
get_status(const void *object, uint16 *status)
get_status(usb_id handle, uint16 *status)
{
TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", object, status));
if (!object || !status)
TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", handle, status));
if (!status)
return B_BAD_VALUE;
Object *object = gUSBStack->GetObject(handle);
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
return B_BAD_VALUE;
return ((Pipe *)object)->GetStatus(status);
@ -173,100 +188,126 @@ get_status(const void *object, uint16 *status)
status_t
get_descriptor(const usb_device *device, uint8 type, uint8 index,
uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
void *data, size_t dataLength, size_t *actualLength)
{
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));
if (!device || !data)
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
return ((Device *)device)->GetDescriptor(type, index, languageID,
return ((Device *)object)->GetDescriptor(type, index, languageID,
data, dataLength, actualLength);
}
status_t
send_request(const usb_device *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t dataLength,
size_t *actualLength)
send_request(usb_device device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
{
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));
if (!device)
TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, actualLength));
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
return ((Device *)device)->SendRequest(requestType, request, value, index,
length, data, dataLength, actualLength);
return ((Device *)object)->SendRequest(requestType, request, value, index,
length, data, length, actualLength);
}
status_t
queue_request(const usb_device *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t dataLength,
queue_request(usb_device device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data,
usb_callback_func callback, void *callbackCookie)
{
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));
if (!device)
TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, callback, callbackCookie));
Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
return ((Device *)device)->QueueRequest(requestType, request, value, index,
length, data, dataLength, callback, callbackCookie);
return ((Device *)object)->QueueRequest(requestType, request, value, index,
length, data, length, callback, callbackCookie);
}
status_t
queue_interrupt(const usb_pipe *pipe, void *data, size_t dataLength,
queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
if (((Pipe *)pipe)->Type() != Pipe::Interrupt)
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
return B_BAD_VALUE;
return ((InterruptPipe *)pipe)->QueueInterrupt(data, dataLength, callback,
return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
callbackCookie);
}
status_t
queue_bulk(const usb_pipe *pipe, void *data, size_t dataLength,
queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie));
if (((Pipe *)pipe)->Type() != Pipe::Bulk)
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
return B_BAD_VALUE;
return ((BulkPipe *)pipe)->QueueBulk(data, dataLength, callback,
return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
callbackCookie);
}
status_t
queue_isochronous(const usb_pipe *pipe, void *data, size_t dataLength,
rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
void *callbackCookie)
queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
usb_callback_func callback, void *callbackCookie)
{
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));
if (((Pipe *)pipe)->Type() != Pipe::Isochronous)
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, vector, vectorCount, callback, callbackCookie));
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
return B_BAD_VALUE;
return ((IsochronousPipe *)pipe)->QueueIsochronous(data, dataLength,
rleArray, bufferDurationMS, callback, callbackCookie);
}
status_t
set_pipe_policy(const usb_pipe *pipe, uint8 maxQueuedPackets,
uint16 maxBufferDurationMS, uint16 sampleSize)
{
TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
return B_ERROR;
}
status_t
cancel_queued_transfers(const usb_pipe *pipe)
queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
void *callbackCookie)
{
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));
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
return B_BAD_VALUE;
return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
rleArray, bufferDurationMS, callback, callbackCookie);
}
status_t
set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
uint16 maxBufferDurationMS, uint16 sampleSize)
{
TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
return B_BAD_VALUE;
return B_ERROR;
}
status_t
cancel_queued_transfers(usb_pipe pipe)
{
TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe));
return ((Pipe *)pipe)->CancelQueuedTransfers();
Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
return B_BAD_VALUE;
return ((Pipe *)object)->CancelQueuedTransfers();
}
@ -277,9 +318,13 @@ usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
switch (opcode) {
case 'DNAM': {
Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_BAD_VALUE;
uint32 index = 0;
Device *device = *(Device **)buffer;
return device->BuildDeviceName((char *)buffer, &index, bufferSize, NULL);
return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
bufferSize, NULL);
}
}
@ -288,13 +333,13 @@ usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
/*
This module exports the USB API
This module exports the USB API v3
*/
struct usb_module_info gModuleInfo = {
struct usb_module_info gModuleInfoV3 = {
// First the bus_manager_info:
{
{
B_USB_MODULE_NAME,
"bus_managers/usb/v3",
B_KEEP_LOADED, // Keep loaded, even if no driver requires it
bus_std_ops
},
@ -316,6 +361,7 @@ struct usb_module_info gModuleInfo = {
send_request, // send_request
queue_interrupt, // queue_interrupt
queue_bulk, // queue_bulk
queue_bulk_v, // queue_bulk_v
queue_isochronous, // queue_isochronous
queue_request, // queue_request
set_pipe_policy, // set_pipe_policy
@ -324,7 +370,210 @@ struct usb_module_info gModuleInfo = {
};
//
// #pragma mark -
//
const usb_device_descriptor *
get_device_descriptor_v2(const void *device)
{
return get_device_descriptor((usb_id)device);
}
const usb_configuration_info *
get_nth_configuration_v2(const void *device, uint index)
{
return get_nth_configuration((usb_id)device, index);
}
const usb_configuration_info *
get_configuration_v2(const void *device)
{
return get_configuration((usb_id)device);
}
status_t
set_configuration_v2(const void *device,
const usb_configuration_info *configuration)
{
return set_configuration((usb_id)device, configuration);
}
status_t
set_alt_interface_v2(const void *device, const usb_interface_info *interface)
{
return set_alt_interface((usb_id)device, interface);
}
status_t
set_feature_v2(const void *object, uint16 selector)
{
return set_feature((usb_id)object, selector);
}
status_t
clear_feature_v2(const void *object, uint16 selector)
{
return clear_feature((usb_id)object, selector);
}
status_t
get_status_v2(const void *object, uint16 *status)
{
return get_status((usb_id)object, status);
}
status_t
get_descriptor_v2(const void *device, uint8 type, uint8 index,
uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
{
return get_descriptor((usb_id)device, type, index, languageID, data,
dataLength, actualLength);
}
status_t
send_request_v2(const void *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data,
size_t /*dataLength*/, size_t *actualLength)
{
return send_request((usb_id)device, requestType, request, value, index,
length, data, actualLength);
}
status_t
queue_request_v2(const void *device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data,
size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
{
return queue_request((usb_id)device, requestType, request, value, index,
length, data, callback, callbackCookie);
}
status_t
queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
return queue_interrupt((usb_id)pipe, data, dataLength, callback,
callbackCookie);
}
status_t
queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie)
{
return queue_bulk((usb_id)pipe, data, dataLength, callback,
callbackCookie);
}
status_t
queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
void *callbackCookie)
{
return queue_isochronous((usb_id)pipe, data, dataLength, rleArray,
bufferDurationMS, callback, callbackCookie);
}
status_t
set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
uint16 maxBufferDurationMS, uint16 sampleSize)
{
return set_pipe_policy((usb_id)pipe, maxQueuedPackets, maxBufferDurationMS,
sampleSize);
}
status_t
cancel_queued_transfers_v2(const void *pipe)
{
return cancel_queued_transfers((usb_id)pipe);
}
struct usb_module_info_v2 {
bus_manager_info binfo;
status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
status_t (*install_notify)(const char *, const usb_notify_hooks *);
status_t (*uninstall_notify)(const char *);
const usb_device_descriptor *(*get_device_descriptor)(const void *);
const usb_configuration_info *(*get_nth_configuration)(const void *, uint);
const usb_configuration_info *(*get_configuration)(const void *);
status_t (*set_configuration)(const void *, const usb_configuration_info *);
status_t (*set_alt_interface)(const void *, const usb_interface_info *);
status_t (*set_feature)(const void *, uint16);
status_t (*clear_feature)(const void *, uint16);
status_t (*get_status)(const void *, uint16 *);
status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16);
status_t (*cancel_queued_transfers)(const void *);
status_t (*usb_ioctl)(uint32 opcode, void *,size_t);
};
/*
This module exports the USB API v2
*/
struct usb_module_info_v2 gModuleInfoV2 = {
// First the bus_manager_info:
{
{
"bus_managers/usb/v2",
B_KEEP_LOADED, // Keep loaded, even if no driver requires it
bus_std_ops
},
NULL // the rescan function
},
register_driver, // register_driver
install_notify, // install_notify
uninstall_notify, // uninstall_notify
get_device_descriptor_v2, // get_device_descriptor
get_nth_configuration_v2, // get_nth_configuration
get_configuration_v2, // get_configuration
set_configuration_v2, // set_configuration
set_alt_interface_v2, // set_alt_interface
set_feature_v2, // set_feature
clear_feature_v2, // clear_feature
get_status_v2, // get_status
get_descriptor_v2, // get_descriptor
send_request_v2, // send_request
queue_interrupt_v2, // queue_interrupt
queue_bulk_v2, // queue_bulk
queue_isochronous_v2, // queue_isochronous
queue_request_v2, // queue_request
set_pipe_policy_v2, // set_pipe_policy
cancel_queued_transfers_v2, // cancel_queued_transfers
usb_ioctl // usb_ioctl
};
//
// #pragma mark -
//
module_info *modules[] = {
(module_info *)&gModuleInfo,
(module_info *)&gModuleInfoV2,
(module_info *)&gModuleInfoV3,
NULL
};

View File

@ -16,12 +16,12 @@
class Hub;
class Device;
class Stack;
class Device;
class Transfer;
class BusManager;
class ControlPipe;
class Object;
struct host_controller_info {
@ -41,6 +41,17 @@ struct usb_driver_info {
};
#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();
@ -51,6 +62,10 @@ public:
bool Lock();
void Unlock();
usb_id GetUSBID(Object *object);
void PutUSBID(usb_id id);
Object *GetObject(usb_id id);
void AddBusManager(BusManager *bus);
int32 IndexOfBusManager(BusManager *bus);
@ -90,6 +105,10 @@ private:
addr_t fListhead32;
addr_t fListhead64;
uint32 fObjectIndex;
uint32 fObjectMaxCount;
Object **fObjectArray;
usb_driver_info *fDriverList;
};
@ -101,11 +120,14 @@ private:
*/
class BusManager {
public:
BusManager();
BusManager(Stack *stack);
virtual ~BusManager();
virtual status_t InitCheck();
bool Lock();
void Unlock();
Device *AllocateNewDevice(Device *parent,
bool lowSpeed);
@ -129,7 +151,7 @@ protected:
private:
static int32 ExploreThread(void *data);
sem_id fLock;
benaphore fLock;
bool fDeviceMap[128];
ControlPipe *fDefaultPipe;
ControlPipe *fDefaultPipeLowSpeed;
@ -139,29 +161,48 @@ static int32 ExploreThread(void *data);
};
class Object {
public:
Object(BusManager *bus);
Stack *GetStack() { return fStack; };
usb_id USBID() { return fUSBID; };
virtual uint32 Type() { return USB_OBJECT_NONE; };
private:
Stack *fStack;
usb_id fUSBID;
};
/*
* The Pipe class is the communication management between the hardware and
* the stack. It creates packets, manages these and performs callbacks.
*/
class Pipe {
class Pipe : public Object {
public:
enum pipeDirection { In, Out, Default };
enum pipeSpeed { LowSpeed, NormalSpeed };
enum pipeType { Control, Bulk, Isochronous, Interrupt, Invalid };
Pipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
Pipe(BusManager *bus,
int8 deviceAddress,
pipeSpeed speed,
uint32 maxPacketSize);
virtual ~Pipe();
virtual int8 DeviceAddress();
virtual pipeType Type() { return Invalid; };
virtual pipeSpeed Speed() { return fSpeed; };
virtual pipeDirection Direction() { return fDirection; };
virtual int8 EndpointAddress() { return fEndpoint; };
virtual uint32 MaxPacketSize() { return fMaxPacketSize; };
virtual uint32 Type() { return USB_OBJECT_PIPE; };
int8 DeviceAddress();
pipeSpeed Speed() { return fSpeed; };
pipeDirection Direction() { return fDirection; };
int8 EndpointAddress() { return fEndpoint; };
uint32 MaxPacketSize() { return fMaxPacketSize; };
virtual bool DataToggle() { return fDataToggle; };
virtual void SetDataToggle(bool toggle) { fDataToggle = toggle; };
@ -176,7 +217,9 @@ virtual status_t GetStatus(uint16 *status);
protected:
Device *fDevice;
int8 fDeviceAddress;
BusManager *fBus;
usb_id fUSBID;
pipeDirection fDirection;
pipeSpeed fSpeed;
uint8 fEndpoint;
@ -185,59 +228,6 @@ protected:
};
class InterruptPipe : public Pipe {
public:
InterruptPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual pipeType Type() { return Interrupt; };
status_t QueueInterrupt(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
class BulkPipe : public Pipe {
public:
BulkPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual pipeType Type() { return Bulk; };
status_t QueueBulk(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
class IsochronousPipe : public Pipe {
public:
IsochronousPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual pipeType Type() { return Isochronous; };
status_t QueueIsochronous(void *data,
size_t dataLength,
rlea *rleArray,
uint16 bufferDurationMS,
usb_callback_func callback,
void *callbackCookie);
};
class ControlPipe : public Pipe {
public:
ControlPipe(Device *device,
@ -249,11 +239,9 @@ public:
ControlPipe(BusManager *bus,
int8 deviceAddress,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual int8 DeviceAddress();
virtual pipeType Type() { return Control; };
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE; };
// The data toggle is not relevant
// for control transfers, as they are
@ -278,9 +266,59 @@ static void SendRequestCallback(void *cookie,
void *data, size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
private:
int8 fDeviceAddress;
class InterruptPipe : public Pipe {
public:
InterruptPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_INTERRUPT_PIPE; };
status_t QueueInterrupt(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
class BulkPipe : public Pipe {
public:
BulkPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_BULK_PIPE; };
status_t QueueBulk(void *data,
size_t dataLength,
usb_callback_func callback,
void *callbackCookie);
};
class IsochronousPipe : public Pipe {
public:
IsochronousPipe(Device *device,
pipeDirection direction,
pipeSpeed speed,
uint8 endpointAddress,
uint32 maxPacketSize);
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; };
status_t QueueIsochronous(void *data,
size_t dataLength,
rlea *rleArray,
uint16 bufferDurationMS,
usb_callback_func callback,
void *callbackCookie);
};
@ -288,13 +326,12 @@ class Interface : public ControlPipe {
public:
Interface(Device *device);
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE | USB_OBJECT_INTERFACE; };
// Convenience functions for standard requests
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
virtual status_t GetStatus(uint16 *status);
private:
Device *fDevice;
};
@ -306,10 +343,10 @@ public:
status_t InitCheck();
virtual bool IsHub() { return false; };
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE | USB_OBJECT_DEVICE; };
int8 Address() { return fDeviceAddress; };
BusManager *Manager() { return fBus; };
bool LowSpeed() { return fLowSpeed; };
virtual status_t GetDescriptor(uint8 descriptorType,
uint8 index, uint16 languageID,
@ -359,7 +396,7 @@ public:
usb_device_descriptor &desc,
int8 deviceAddress, bool lowSpeed);
virtual bool IsHub() { return true; };
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE | USB_OBJECT_DEVICE | USB_OBJECT_HUB; };
virtual status_t GetDescriptor(uint8 descriptorType,
uint8 index, uint16 languageID,

View File

@ -11,7 +11,7 @@
#include <KernelExport.h>
#include <util/Vector.h>
#include <USB.h>
#include <USB3.h>
#include <util/kernel_cpp.h>
#define USB_MAX_AREAS 8

View File

@ -33,7 +33,7 @@
// ---------------------------
#include <module.h>
#include <PCI.h>
#include <USB.h>
#include <USB3.h>
#include <KernelExport.h>
#include <stdlib.h>
@ -187,6 +187,7 @@ module_info *modules[] =
//------------------------------------------------------------------------
OHCI::OHCI( pci_info *info , Stack *stack )
: BusManager(stack)
{
m_pcii = info;
m_stack = stack;

View File

@ -9,7 +9,7 @@
#include <module.h>
#include <PCI.h>
#include <USB.h>
#include <USB3.h>
#include <KernelExport.h>
#include <stdlib.h>
@ -323,7 +323,7 @@ Queue::PrintToStream()
UHCI::UHCI(pci_info *info, Stack *stack)
: BusManager(),
: BusManager(stack),
fPCIInfo(info),
fStack(stack),
fFrameArea(-1),
@ -338,14 +338,14 @@ UHCI::UHCI(pci_info *info, Stack *stack)
fRootHub(NULL),
fRootHubAddress(0)
{
TRACE(("usb_uhci: constructing new UHCI Host Controller Driver\n"));
fInitOK = false;
if (benaphore_init(&fUHCILock, "usb uhci lock") < B_OK) {
TRACE_ERROR(("usb_uhci: failed to create busmanager lock\n"));
if (!fInitOK) {
TRACE(("usb_uhci: bus manager failed to init\n"));
return;
}
TRACE(("usb_uhci: constructing new UHCI Host Controller Driver\n"));
fInitOK = false;
fRegisterBase = sPCIModule->read_pci_config(fPCIInfo->bus,
fPCIInfo->device, fPCIInfo->function, PCI_memory_base, 4);
fRegisterBase &= PCI_address_io_mask;
@ -454,23 +454,9 @@ UHCI::~UHCI()
delete [] fQueues;
delete fRootHub;
delete_area(fFrameArea);
benaphore_destroy(&fUHCILock);
put_module(B_PCI_MODULE_NAME);
}
bool
UHCI::Lock()
{
return (benaphore_lock(&fUHCILock) == B_OK);
}
void
UHCI::Unlock()
{
benaphore_unlock(&fUHCILock);
Unlock();
}
@ -518,7 +504,6 @@ UHCI::Start()
}
SetRootHub(fRootHub);
SetStack(fStack);
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
@ -535,7 +520,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
return fRootHub->SubmitTransfer(transfer);
if (transfer->TransferPipe()->Type() == Pipe::Control)
if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE)
return SubmitRequest(transfer);
if (!transfer->Data() || transfer->DataLength() == 0)
@ -565,7 +550,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
}
Queue *queue = fQueues[3];
if (pipe->Type() == Pipe::Interrupt)
if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE)
queue = fQueues[2];
result = AddPendingTransfer(transfer, queue, firstDescriptor,

View File

@ -67,9 +67,6 @@ public:
UHCI(pci_info *info, Stack *stack);
~UHCI();
bool Lock();
void Unlock();
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
virtual status_t SubmitRequest(Transfer *transfer);
@ -139,7 +136,6 @@ static pci_module_info *sPCIModule;
uint32 fRegisterBase;
pci_info *fPCIInfo;
Stack *fStack;
benaphore fUHCILock;
// Frame list memory
area_id fFrameArea;

View File

@ -135,7 +135,7 @@ UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
status_t
UHCIRootHub::SubmitTransfer(Transfer *transfer)
{
if (transfer->TransferPipe()->Type() != Pipe::Control)
if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
return B_ERROR;
usb_request_data *request = transfer->RequestData();