* 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:
parent
c3157a2749
commit
5b0ec61f97
@ -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
231
headers/os/drivers/USB2.h
Normal 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
235
headers/os/drivers/USB3.h
Normal 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_ */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
|
||||
|
||||
Interface::Interface(Device *device)
|
||||
: ControlPipe(device,
|
||||
device->LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8)
|
||||
: ControlPipe(device, device->Speed(), 0, 8)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ KernelStaticLibrary libusb.a :
|
||||
Transfer.cpp
|
||||
Pipe.cpp
|
||||
Interface.cpp
|
||||
Object.cpp
|
||||
: -fno-pic
|
||||
;
|
||||
|
||||
|
8
src/add-ons/kernel/bus_managers/usb/Object.cpp
Normal file
8
src/add-ons/kernel/bus_managers/usb/Object.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "usb_p.h"
|
||||
|
||||
|
||||
Object::Object(BusManager *bus)
|
||||
{
|
||||
fStack = bus->GetStack();
|
||||
fUSBID = fStack->GetUSBID(this);
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user