* Implemented most of the USB module public API (using opaque handles like in R5 will change that to using IDs later)
* Fixed the UHCI root hub and the hub implementation. Interface and endpoint descriptors are part of the configuration descriptor, they cannot be requested individually. * Added simple support for interrupt and bulk transfers to UHCI. It's enough to get my USB mouse working to a stable and usable degree. * Cleaned up and reworked some other parts, added allocation checks and such. Yes, my internet connection is back up :) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18496 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
852c3506f5
commit
b8c6a85136
@ -35,10 +35,13 @@ BusManager::BusManager()
|
||||
fDeviceMap[i] = false;
|
||||
|
||||
// Set up the default pipes
|
||||
fDefaultPipe = new ControlPipe(this, 0, Pipe::Default, Pipe::NormalSpeed,
|
||||
0, 8);
|
||||
fDefaultPipeLowSpeed = new ControlPipe(this, 0, Pipe::Default,
|
||||
Pipe::LowSpeed, 0, 8);
|
||||
fDefaultPipe = new(std::nothrow) ControlPipe(this, 0, Pipe::NormalSpeed, 0, 8);
|
||||
if (!fDefaultPipe)
|
||||
return;
|
||||
|
||||
fDefaultPipeLowSpeed = new(std::nothrow) ControlPipe(this, 0, Pipe::LowSpeed, 0, 8);
|
||||
if (!fDefaultPipeLowSpeed)
|
||||
return;
|
||||
|
||||
fExploreThread = -1;
|
||||
fInitOK = true;
|
||||
@ -97,7 +100,7 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
|
||||
|
||||
// Set the address of the device USB 1.1 spec p202
|
||||
status_t result = defaultPipe->SendRequest(
|
||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, // type
|
||||
USB_REQUEST_SET_ADDRESS, // request
|
||||
deviceAddress, // value
|
||||
0, // index
|
||||
@ -115,7 +118,7 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
|
||||
snooze(10000);
|
||||
|
||||
// Create a temporary pipe with the new address
|
||||
ControlPipe pipe(this, deviceAddress, Pipe::Default,
|
||||
ControlPipe pipe(this, deviceAddress,
|
||||
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, 8);
|
||||
|
||||
// Get the device descriptor
|
||||
@ -153,19 +156,42 @@ BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
|
||||
// Create a new instance based on the type (Hub or Device)
|
||||
if (deviceDescriptor.device_class == 0x09) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
|
||||
Device *ret = new Hub(this, parent, deviceDescriptor, deviceAddress,
|
||||
lowSpeed);
|
||||
Hub *hub = new(std::nothrow) Hub(this, parent, deviceDescriptor,
|
||||
deviceAddress, lowSpeed);
|
||||
if (!hub) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): no memory to allocate hub\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hub->InitCheck() < B_OK) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): hub failed init check\n"));
|
||||
delete hub;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
// root hub
|
||||
fRootHub = ret;
|
||||
fRootHub = hub;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return (Device *)hub;
|
||||
}
|
||||
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
|
||||
return new Device(this, parent, deviceDescriptor, deviceAddress, lowSpeed);
|
||||
Device *device = new(std::nothrow) Device(this, parent, deviceDescriptor,
|
||||
deviceAddress, lowSpeed);
|
||||
if (!device) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): no memory to allocate device\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (device->InitCheck() < B_OK) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): device failed init check\n"));
|
||||
delete device;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,13 +19,20 @@
|
||||
|
||||
Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
int8 deviceAddress, bool lowSpeed)
|
||||
: ControlPipe(bus, deviceAddress,
|
||||
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0,
|
||||
desc.max_packet_size_0),
|
||||
fDeviceDescriptor(desc),
|
||||
fConfigurations(NULL),
|
||||
fCurrentConfiguration(NULL),
|
||||
fInitOK(false),
|
||||
fLowSpeed(lowSpeed),
|
||||
fBus(bus),
|
||||
fParent(parent),
|
||||
fDeviceAddress(deviceAddress),
|
||||
fLock(-1),
|
||||
fNotifyCookie(NULL)
|
||||
{
|
||||
fBus = bus;
|
||||
fParent = parent;
|
||||
fInitOK = false;
|
||||
fCurrentConfiguration = NULL;
|
||||
fDeviceAddress = deviceAddress;
|
||||
|
||||
TRACE(("USB Device: new device\n"));
|
||||
|
||||
fLock = create_sem(1, "USB Device Lock");
|
||||
@ -36,18 +43,15 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
|
||||
set_sem_owner(fLock, B_SYSTEM_TEAM);
|
||||
|
||||
fLowSpeed = lowSpeed;
|
||||
fDeviceDescriptor = desc;
|
||||
fMaxPacketIn[0] = fMaxPacketOut[0] = fDeviceDescriptor.max_packet_size_0;
|
||||
fDefaultPipe = new ControlPipe(this, Pipe::Default,
|
||||
lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed, 0, fMaxPacketIn[0]);
|
||||
|
||||
// Get the device descriptor
|
||||
// We already have a part of it, but we want it all
|
||||
status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0,
|
||||
(void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor));
|
||||
size_t actualLength;
|
||||
status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0,
|
||||
(void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
|
||||
|
||||
if (status != sizeof(fDeviceDescriptor)) {
|
||||
if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
|
||||
TRACE(("USB Device: error while getting the device descriptor\n"));
|
||||
return;
|
||||
}
|
||||
@ -69,28 +73,190 @@ Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
TRACE(("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations));
|
||||
|
||||
// Get the configurations
|
||||
fConfigurations = (usb_configuration_descriptor *)malloc(fDeviceDescriptor.num_configurations
|
||||
* sizeof(usb_configuration_descriptor));
|
||||
fConfigurations = (usb_configuration_info *)malloc(
|
||||
fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
|
||||
if (fConfigurations == NULL) {
|
||||
TRACE(("USB Device: out of memory during config creations!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
|
||||
size_t size = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i,
|
||||
(void *)&fConfigurations[i], sizeof(usb_configuration_descriptor));
|
||||
usb_configuration_descriptor configDescriptor;
|
||||
status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
|
||||
(void *)&configDescriptor, sizeof(usb_configuration_descriptor),
|
||||
&actualLength);
|
||||
|
||||
if (size != sizeof(usb_configuration_descriptor)) {
|
||||
if (status < B_OK || actualLength != sizeof(usb_configuration_descriptor)) {
|
||||
TRACE(("USB Device %d: error fetching configuration %d\n", fDeviceAddress, i));
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE(("USB Device %d: configuration %d\n", fDeviceAddress, i));
|
||||
TRACE(("\tlength:..............%d\n", configDescriptor.length));
|
||||
TRACE(("\tdescriptor_type:.....0x%02x\n", configDescriptor.descriptor_type));
|
||||
TRACE(("\ttotal_length:........%d\n", configDescriptor.total_length));
|
||||
TRACE(("\tnumber_interfaces:...%d\n", configDescriptor.number_interfaces));
|
||||
TRACE(("\tconfiguration_value:.0x%02x\n", configDescriptor.configuration_value));
|
||||
TRACE(("\tconfiguration:.......0x%02x\n", configDescriptor.configuration));
|
||||
TRACE(("\tattributes:..........0x%02x\n", configDescriptor.attributes));
|
||||
TRACE(("\tmax_power:...........%d\n", configDescriptor.max_power));
|
||||
|
||||
uint8 *configData = (uint8 *)malloc(configDescriptor.total_length);
|
||||
status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
|
||||
(void *)configData, configDescriptor.total_length, &actualLength);
|
||||
|
||||
if (status < B_OK || actualLength != configDescriptor.total_length) {
|
||||
TRACE(("USB Device %d: error fetching full configuration descriptor %d\n", fDeviceAddress, i));
|
||||
return;
|
||||
}
|
||||
|
||||
usb_configuration_descriptor *configuration = (usb_configuration_descriptor *)configData;
|
||||
fConfigurations[i].descr = configuration;
|
||||
fConfigurations[i].interface_count = configuration->number_interfaces;
|
||||
fConfigurations[i].interface = (usb_interface_list *)malloc(
|
||||
configuration->number_interfaces * sizeof(usb_interface_list));
|
||||
memset(fConfigurations[i].interface, 0,
|
||||
configuration->number_interfaces * sizeof(usb_interface_list));
|
||||
|
||||
usb_interface_info *currentInterface = NULL;
|
||||
uint32 descriptorStart = sizeof(usb_configuration_descriptor);
|
||||
while (descriptorStart < actualLength) {
|
||||
switch (configData[descriptorStart + 1]) {
|
||||
case USB_DESCRIPTOR_INTERFACE: {
|
||||
TRACE(("USB Device %d: got interface descriptor\n", fDeviceAddress));
|
||||
usb_interface_descriptor *interfaceDescriptor = (usb_interface_descriptor *)&configData[descriptorStart];
|
||||
TRACE(("\tlength:.............%d\n", interfaceDescriptor->length));
|
||||
TRACE(("\tdescriptor_type:....0x%02x\n", interfaceDescriptor->descriptor_type));
|
||||
TRACE(("\tinterface_number:...%d\n", interfaceDescriptor->interface_number));
|
||||
TRACE(("\talternate_setting:..%d\n", interfaceDescriptor->alternate_setting));
|
||||
TRACE(("\tnum_endpoints:......%d\n", interfaceDescriptor->num_endpoints));
|
||||
TRACE(("\tinterface_class:....0x%02x\n", interfaceDescriptor->interface_class));
|
||||
TRACE(("\tinterface_subclass:.0x%02x\n", interfaceDescriptor->interface_subclass));
|
||||
TRACE(("\tinterface_protocol:.0x%02x\n", interfaceDescriptor->interface_protocol));
|
||||
TRACE(("\tinterface:..........%d\n", interfaceDescriptor->interface));
|
||||
|
||||
usb_interface_list *interfaceList =
|
||||
&fConfigurations[i].interface[interfaceDescriptor->interface_number];
|
||||
|
||||
/* allocate this alternate */
|
||||
interfaceList->alt_count++;
|
||||
interfaceList->alt = (usb_interface_info *)realloc(
|
||||
interfaceList->alt, interfaceList->alt_count
|
||||
* sizeof(usb_interface_info));
|
||||
interfaceList->active = interfaceList->alt;
|
||||
|
||||
/* setup this alternate */
|
||||
usb_interface_info *interfaceInfo =
|
||||
&interfaceList->alt[interfaceList->alt_count - 1];
|
||||
interfaceInfo->descr = interfaceDescriptor;
|
||||
interfaceInfo->endpoint_count = 0;
|
||||
interfaceInfo->endpoint = NULL;
|
||||
interfaceInfo->generic_count = 0;
|
||||
interfaceInfo->generic = NULL;
|
||||
|
||||
Interface *interface = new(std::nothrow) Interface(this);
|
||||
interfaceInfo->handle = (usb_interface *)interface;
|
||||
|
||||
currentInterface = interfaceInfo;
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_DESCRIPTOR_ENDPOINT: {
|
||||
TRACE(("USB Device %d: got endpoint descriptor\n", fDeviceAddress));
|
||||
usb_endpoint_descriptor *endpointDescriptor = (usb_endpoint_descriptor *)&configData[descriptorStart];
|
||||
TRACE(("\tlength:.............%d\n", endpointDescriptor->length));
|
||||
TRACE(("\tdescriptor_type:....0x%02x\n", endpointDescriptor->descriptor_type));
|
||||
TRACE(("\tendpoint_address:...0x%02x\n", endpointDescriptor->endpoint_address));
|
||||
TRACE(("\tattributes:.........0x%02x\n", endpointDescriptor->attributes));
|
||||
TRACE(("\tmax_packet_size:....%d\n", endpointDescriptor->max_packet_size));
|
||||
TRACE(("\tinterval:...........%d\n", endpointDescriptor->interval));
|
||||
|
||||
if (!currentInterface)
|
||||
break;
|
||||
|
||||
/* allocate this endpoint */
|
||||
currentInterface->endpoint_count++;
|
||||
currentInterface->endpoint = (usb_endpoint_info *)realloc(
|
||||
currentInterface->endpoint,
|
||||
currentInterface->endpoint_count
|
||||
* sizeof(usb_endpoint_info));
|
||||
|
||||
/* setup this endpoint */
|
||||
usb_endpoint_info *endpointInfo =
|
||||
¤tInterface->endpoint[currentInterface->endpoint_count - 1];
|
||||
endpointInfo->descr = endpointDescriptor;
|
||||
|
||||
Pipe *endpoint = NULL;
|
||||
switch (endpointDescriptor->attributes & 0x03) {
|
||||
case 0x00: /* Control Endpoint */
|
||||
endpoint = new(std::nothrow) ControlPipe(this,
|
||||
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
|
||||
endpointDescriptor->endpoint_address & 0x0f,
|
||||
endpointDescriptor->max_packet_size);
|
||||
break;
|
||||
|
||||
case 0x01: /* Isochronous Endpoint */
|
||||
endpoint = new(std::nothrow) IsochronousPipe(this,
|
||||
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
|
||||
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
|
||||
endpointDescriptor->endpoint_address & 0x0f,
|
||||
endpointDescriptor->max_packet_size);
|
||||
break;
|
||||
|
||||
case 0x02: /* Bulk Endpoint */
|
||||
endpoint = new(std::nothrow) BulkPipe(this,
|
||||
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
|
||||
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
|
||||
endpointDescriptor->endpoint_address & 0x0f,
|
||||
endpointDescriptor->max_packet_size);
|
||||
break;
|
||||
|
||||
case 0x03: /* Interrupt Endpoint */
|
||||
endpoint = new(std::nothrow) InterruptPipe(this,
|
||||
endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
|
||||
LowSpeed() ? Pipe::LowSpeed : Pipe::NormalSpeed,
|
||||
endpointDescriptor->endpoint_address & 0x0f,
|
||||
endpointDescriptor->max_packet_size);
|
||||
break;
|
||||
}
|
||||
|
||||
endpointInfo->handle = (usb_pipe *)endpoint;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE(("USB Device %d: got generic descriptor\n", fDeviceAddress));
|
||||
usb_generic_descriptor *genericDescriptor = (usb_generic_descriptor *)&configData[descriptorStart];
|
||||
TRACE(("\tlength:.............%d\n", genericDescriptor->length));
|
||||
TRACE(("\tdescriptor_type:....0x%02x\n", genericDescriptor->descriptor_type));
|
||||
|
||||
if (!currentInterface)
|
||||
break;
|
||||
|
||||
/* allocate this descriptor */
|
||||
currentInterface->generic_count++;
|
||||
currentInterface->generic = (usb_descriptor **)realloc(
|
||||
currentInterface->generic,
|
||||
currentInterface->generic_count
|
||||
* sizeof(usb_descriptor *));
|
||||
|
||||
/* add this descriptor */
|
||||
currentInterface->generic[currentInterface->generic_count] =
|
||||
(usb_descriptor *)genericDescriptor;
|
||||
break;
|
||||
}
|
||||
|
||||
descriptorStart += configData[descriptorStart];
|
||||
}
|
||||
}
|
||||
|
||||
// Set default configuration
|
||||
TRACE(("USB Device %d: setting default configuration\n", fDeviceAddress));
|
||||
SetConfiguration(0);
|
||||
if (SetConfigurationAt(0) < B_OK) {
|
||||
TRACE(("USB Device %d: failed to set default configuration\n", fDeviceAddress));
|
||||
return;
|
||||
}
|
||||
|
||||
// ToDo: Find drivers for the device
|
||||
fInitOK = true;
|
||||
}
|
||||
|
||||
@ -105,36 +271,61 @@ Device::InitCheck()
|
||||
}
|
||||
|
||||
|
||||
// Returns the length that was copied (index gives the number of the config)
|
||||
size_t
|
||||
Device::GetDescriptor(uint8 descriptorType, uint16 index, void *buffer,
|
||||
size_t bufferSize)
|
||||
status_t
|
||||
Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength, size_t *actualLength)
|
||||
{
|
||||
size_t actualLength = 0;
|
||||
fDefaultPipe->SendRequest(
|
||||
return SendRequest(
|
||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||
(descriptorType << 8) | index, // value
|
||||
0, // index
|
||||
bufferSize, // length
|
||||
buffer, // buffer
|
||||
bufferSize, // buffer length
|
||||
&actualLength); // actual length
|
||||
|
||||
return actualLength;
|
||||
languageID, // index
|
||||
dataLength, // length
|
||||
data, // buffer
|
||||
dataLength, // buffer length
|
||||
actualLength); // actual length
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::SetConfiguration(uint8 value)
|
||||
const usb_configuration_info *
|
||||
Device::Configuration() const
|
||||
{
|
||||
if (value >= fDeviceDescriptor.num_configurations)
|
||||
return EINVAL;
|
||||
return fCurrentConfiguration;
|
||||
}
|
||||
|
||||
status_t result = fDefaultPipe->SendRequest(
|
||||
|
||||
const usb_configuration_info *
|
||||
Device::ConfigurationAt(uint8 index) const
|
||||
{
|
||||
if (index >= fDeviceDescriptor.num_configurations)
|
||||
return NULL;
|
||||
|
||||
return &fConfigurations[index];
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::SetConfiguration(const usb_configuration_info *configuration)
|
||||
{
|
||||
for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
|
||||
if (configuration == &fConfigurations[i])
|
||||
return SetConfigurationAt(i);
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::SetConfigurationAt(uint8 index)
|
||||
{
|
||||
if (index >= fDeviceDescriptor.num_configurations)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t result = SendRequest(
|
||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_SET_CONFIGURATION, // request
|
||||
value, // value
|
||||
index, // value
|
||||
0, // index
|
||||
0, // length
|
||||
NULL, // buffer
|
||||
@ -145,6 +336,120 @@ Device::SetConfiguration(uint8 value)
|
||||
return result;
|
||||
|
||||
// Set current configuration
|
||||
fCurrentConfiguration = &fConfigurations[value];
|
||||
fCurrentConfiguration = &fConfigurations[index];
|
||||
|
||||
// Wait some for the configuration being finished
|
||||
snooze(10000);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
const usb_device_descriptor *
|
||||
Device::DeviceDescriptor() const
|
||||
{
|
||||
return &fDeviceDescriptor;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount, const usb_notify_hooks *hooks, bool added)
|
||||
{
|
||||
TRACE(("USB Device ReportDevice\n"));
|
||||
if (supportDescriptorCount == 0 || supportDescriptors == NULL) {
|
||||
if (added && hooks->device_added != NULL)
|
||||
hooks->device_added((const usb_device *)this, &fNotifyCookie);
|
||||
else if (!added && hooks->device_removed != NULL)
|
||||
hooks->device_removed(fNotifyCookie);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < supportDescriptorCount; i++) {
|
||||
if ((supportDescriptors[i].vendor != 0
|
||||
&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
|
||||
|| (supportDescriptors[i].product != 0
|
||||
&& fDeviceDescriptor.product_id != supportDescriptors[i].product))
|
||||
continue;
|
||||
|
||||
if ((supportDescriptors[i].dev_class == 0
|
||||
|| fDeviceDescriptor.device_class == supportDescriptors[i].dev_class)
|
||||
&& (supportDescriptors[i].dev_subclass == 0
|
||||
|| fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass)
|
||||
&& (supportDescriptors[i].dev_protocol == 0
|
||||
|| fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
|
||||
|
||||
if (added && hooks->device_added != NULL)
|
||||
hooks->device_added((const usb_device *)this, &fNotifyCookie);
|
||||
else if (!added && hooks->device_removed != NULL)
|
||||
hooks->device_removed(fNotifyCookie);
|
||||
return;
|
||||
}
|
||||
|
||||
// we have to check all interfaces for matching class/subclass/protocol
|
||||
for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) {
|
||||
for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) {
|
||||
for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) {
|
||||
usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr;
|
||||
if ((supportDescriptors[i].dev_class == 0
|
||||
|| descriptor->interface_class == supportDescriptors[i].dev_class)
|
||||
&& (supportDescriptors[i].dev_subclass == 0
|
||||
|| descriptor->interface_subclass == supportDescriptors[i].dev_subclass)
|
||||
&& (supportDescriptors[i].dev_protocol == 0
|
||||
|| descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
|
||||
|
||||
if (added && hooks->device_added != NULL)
|
||||
hooks->device_added((const usb_device *)this, &fNotifyCookie);
|
||||
else if (!added && hooks->device_removed != NULL)
|
||||
hooks->device_removed(fNotifyCookie);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::SetFeature(uint16 selector)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::ClearFeature(uint16 selector)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::GetStatus(uint16 *status)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
|
||||
USB_REQUEST_GET_STATUS,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
(void *)status,
|
||||
2,
|
||||
NULL);
|
||||
}
|
||||
|
@ -31,50 +31,45 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
// Set to false again for the hub init.
|
||||
fInitOK = false;
|
||||
|
||||
if (fDeviceDescriptor.device_subclass != 0
|
||||
for (int32 i = 0; i < 8; i++)
|
||||
fChildren[i] = NULL;
|
||||
|
||||
if (fDeviceDescriptor.device_class != 9
|
||||
|| fDeviceDescriptor.device_subclass != 0
|
||||
|| fDeviceDescriptor.device_protocol != 0) {
|
||||
TRACE(("USB Hub: wrong class/subclass/protocol! Bailing out\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fCurrentConfiguration->number_interfaces > 1) {
|
||||
if (Configuration()->descr->number_interfaces > 1) {
|
||||
TRACE(("USB Hub: too many interfaces\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
size_t actualLength;
|
||||
if (GetDescriptor(USB_DESCRIPTOR_INTERFACE, 0, (void *)&fInterruptInterface,
|
||||
sizeof(usb_interface_descriptor)) != sizeof(usb_interface_descriptor)) {
|
||||
TRACE(("USB Hub: error getting the interrupt interface\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fInterruptInterface.num_endpoints > 1) {
|
||||
fInterruptInterface = Configuration()->interface->active->descr;
|
||||
if (fInterruptInterface->num_endpoints > 1) {
|
||||
TRACE(("USB Hub: too many endpoints\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetDescriptor(USB_DESCRIPTOR_ENDPOINT, 0, (void *)&fInterruptEndpoint,
|
||||
sizeof(usb_endpoint_descriptor)) != sizeof(usb_endpoint_descriptor)) {
|
||||
TRACE(("USB Hub: Error getting the endpoint\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fInterruptEndpoint.attributes != 0x03) { // interrupt transfer
|
||||
fInterruptEndpoint = Configuration()->interface->active->endpoint[0].descr;
|
||||
if (fInterruptEndpoint->attributes != 0x03) { // interrupt endpoint
|
||||
TRACE(("USB Hub: Not an interrupt endpoint\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE(("USB Hub: Getting hub descriptor...\n"));
|
||||
if (GetDescriptor(USB_DESCRIPTOR_HUB, 0, (void *)&fHubDescriptor,
|
||||
sizeof(usb_hub_descriptor)) != sizeof(usb_hub_descriptor)) {
|
||||
size_t actualLength;
|
||||
status_t status = GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
|
||||
(void *)&fHubDescriptor, sizeof(usb_hub_descriptor), &actualLength);
|
||||
if (status < B_OK || actualLength != sizeof(usb_hub_descriptor)) {
|
||||
TRACE(("USB Hub: Error getting hub descriptor\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable port power on all ports
|
||||
for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) {
|
||||
fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
PORT_POWER,
|
||||
i + 1,
|
||||
@ -85,7 +80,7 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
|
||||
}
|
||||
|
||||
// Wait for power to stabilize
|
||||
snooze(fHubDescriptor.bPwrOn2PwrGood * 2);
|
||||
snooze(fHubDescriptor.bPwrOn2PwrGood * 2000);
|
||||
|
||||
fInitOK = true;
|
||||
TRACE(("USB Hub: initialised ok\n"));
|
||||
@ -99,7 +94,7 @@ Hub::Explore()
|
||||
size_t actualLength;
|
||||
|
||||
// Get the current port status
|
||||
fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN,
|
||||
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN,
|
||||
USB_REQUEST_GET_STATUS,
|
||||
0,
|
||||
i + 1,
|
||||
@ -117,7 +112,7 @@ Hub::Explore()
|
||||
|
||||
// We need to test the port change against a number of things
|
||||
if (fPortStatus[i].status & PORT_RESET) {
|
||||
fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
PORT_RESET,
|
||||
i + 1,
|
||||
@ -133,7 +128,7 @@ Hub::Explore()
|
||||
|
||||
if ((fPortStatus[i].status & PORT_STATUS_ENABLE) == 0) {
|
||||
// enable the port if it isn't
|
||||
fDefaultPipe->SendRequest(
|
||||
SendRequest(
|
||||
USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
PORT_ENABLE,
|
||||
@ -146,22 +141,25 @@ Hub::Explore()
|
||||
|
||||
TRACE(("USB Hub: Explore(): New device connected\n"));
|
||||
|
||||
Device *newDevice;
|
||||
if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED)
|
||||
newDevice = fBus->AllocateNewDevice(this, true);
|
||||
else
|
||||
newDevice = fBus->AllocateNewDevice(this, false);
|
||||
Device *newDevice = fBus->AllocateNewDevice(this,
|
||||
(fPortStatus[i].status & PORT_STATUS_LOW_SPEED) > 0);
|
||||
|
||||
if (newDevice)
|
||||
if (newDevice) {
|
||||
fChildren[i] = newDevice;
|
||||
Manager()->GetStack()->NotifyDeviceChange(fChildren[i], true);
|
||||
}
|
||||
} else {
|
||||
// Device removed...
|
||||
// ToDo: do something
|
||||
TRACE(("USB Hub Explore(): Device removed\n"));
|
||||
if (fChildren[i]) {
|
||||
Manager()->GetStack()->NotifyDeviceChange(fChildren[i], false);
|
||||
delete fChildren[i];
|
||||
fChildren[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear status change
|
||||
fDefaultPipe->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
C_PORT_CONNECTION,
|
||||
i + 1,
|
||||
@ -172,3 +170,39 @@ Hub::Explore()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength, size_t *actualLength)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_CLASS, // type
|
||||
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||
(descriptorType << 8) | index, // value
|
||||
languageID, // index
|
||||
dataLength, // length
|
||||
data, // buffer
|
||||
dataLength, // buffer length
|
||||
actualLength); // actual length
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount, const usb_notify_hooks *hooks, bool added)
|
||||
{
|
||||
TRACE(("USB Hub ReportDevice\n"));
|
||||
|
||||
// Report ourselfs first
|
||||
Device::ReportDevice(supportDescriptors, supportDescriptorCount, hooks, added);
|
||||
|
||||
// Then report all of our children
|
||||
for (int32 i = 0; i < fHubDescriptor.bNbrPorts; i++) {
|
||||
if (!fChildren[i])
|
||||
continue;
|
||||
|
||||
fChildren[i]->ReportDevice(supportDescriptors,
|
||||
supportDescriptorCount, hooks, added);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ KernelStaticLibrary libusb.a :
|
||||
BusManager.cpp
|
||||
Transfer.cpp
|
||||
Pipe.cpp
|
||||
Interface.cpp
|
||||
: -fno-pic
|
||||
;
|
||||
|
||||
|
@ -3,21 +3,23 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* Niels S. Reedijk
|
||||
*/
|
||||
|
||||
#include "usb_p.h"
|
||||
|
||||
|
||||
Pipe::Pipe(Device *device, pipeDirection direction, uint8 endpointAddress,
|
||||
uint32 maxPacketSize)
|
||||
Pipe::Pipe(Device *device, pipeDirection direction, pipeSpeed speed,
|
||||
uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: fDevice(device),
|
||||
fBus(NULL),
|
||||
fDirection(direction),
|
||||
fSpeed(speed),
|
||||
fEndpoint(endpointAddress),
|
||||
fMaxPacketSize(maxPacketSize),
|
||||
fDataToggle(false)
|
||||
{
|
||||
fDirection = direction;
|
||||
fDevice = device;
|
||||
fEndpoint = endpointAddress;
|
||||
fMaxPacketSize = maxPacketSize;
|
||||
|
||||
fBus = NULL;
|
||||
if (fDevice)
|
||||
fBus = fDevice->Manager();
|
||||
}
|
||||
@ -38,27 +40,124 @@ Pipe::DeviceAddress()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
// ToDo: keep track of all submited transfers to be able to cancel them
|
||||
return fBus->SubmitTransfer(transfer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::CancelQueuedTransfers()
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
|
||||
|
||||
ControlPipe::ControlPipe(Device *device, pipeDirection direction,
|
||||
InterruptPipe::InterruptPipe(Device *device, pipeDirection direction,
|
||||
pipeSpeed speed, uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: Pipe(device, direction, endpointAddress, maxPacketSize)
|
||||
: Pipe(device, direction, speed, endpointAddress, maxPacketSize)
|
||||
{
|
||||
fSpeed = speed;
|
||||
}
|
||||
|
||||
|
||||
ControlPipe::ControlPipe(BusManager *bus, int8 deviceAddress,
|
||||
pipeDirection direction, pipeSpeed speed, uint8 endpointAddress,
|
||||
uint32 maxPacketSize)
|
||||
: Pipe(NULL, direction, endpointAddress, maxPacketSize)
|
||||
status_t
|
||||
InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
|
||||
usb_callback_func callback, void *callbackCookie)
|
||||
{
|
||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
||||
if (!transfer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
transfer->SetData((uint8 *)data, dataLength);
|
||||
transfer->SetCallback(callback, callbackCookie);
|
||||
|
||||
status_t result = SubmitTransfer(transfer);
|
||||
if (result == B_OK || result == EINPROGRESS)
|
||||
return B_OK;
|
||||
|
||||
delete transfer;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
|
||||
|
||||
BulkPipe::BulkPipe(Device *device, pipeDirection direction,
|
||||
pipeSpeed speed, uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: Pipe(device, direction, speed, endpointAddress, maxPacketSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
|
||||
void *callbackCookie)
|
||||
{
|
||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
||||
if (!transfer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
transfer->SetData((uint8 *)data, dataLength);
|
||||
transfer->SetCallback(callback, callbackCookie);
|
||||
|
||||
status_t result = SubmitTransfer(transfer);
|
||||
if (result == B_OK || result == EINPROGRESS)
|
||||
return B_OK;
|
||||
|
||||
delete transfer;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
|
||||
|
||||
IsochronousPipe::IsochronousPipe(Device *device, pipeDirection direction,
|
||||
pipeSpeed speed, uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: Pipe(device, direction, speed, endpointAddress, maxPacketSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IsochronousPipe::QueueIsochronous(void *data, size_t dataLength,
|
||||
rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
|
||||
void *callbackCookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
|
||||
|
||||
ControlPipe::ControlPipe(Device *device, pipeSpeed speed,
|
||||
uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: Pipe(device, Pipe::Default, speed, endpointAddress, maxPacketSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ControlPipe::ControlPipe(BusManager *bus, int8 deviceAddress, pipeSpeed speed,
|
||||
uint8 endpointAddress, uint32 maxPacketSize)
|
||||
: Pipe(NULL, Pipe::Default, speed, endpointAddress, maxPacketSize),
|
||||
fDeviceAddress(deviceAddress)
|
||||
{
|
||||
fBus = bus;
|
||||
fDeviceAddress = deviceAddress;
|
||||
fSpeed = speed;
|
||||
}
|
||||
|
||||
|
||||
@ -78,30 +177,104 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
|
||||
size_t *actualLength)
|
||||
{
|
||||
usb_request_data requestData;
|
||||
|
||||
requestData.RequestType = requestType;
|
||||
requestData.Request = request;
|
||||
requestData.Value = value;
|
||||
requestData.Index = index;
|
||||
requestData.Length = length;
|
||||
|
||||
return SendControlMessage(&requestData, data, dataLength, actualLength,
|
||||
3 * 1000 * 1000);
|
||||
Transfer *transfer = new(std::nothrow) Transfer(this, true);
|
||||
if (!transfer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
transfer->SetRequestData(&requestData);
|
||||
transfer->SetData((uint8 *)data, dataLength);
|
||||
transfer->SetActualLength(actualLength);
|
||||
|
||||
status_t result = SubmitTransfer(transfer);
|
||||
if (result == EINPROGRESS)
|
||||
return transfer->WaitForFinish();
|
||||
|
||||
if (result < B_OK)
|
||||
delete transfer;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ControlPipe::SendControlMessage(usb_request_data *command, void *data,
|
||||
size_t dataLength, size_t *actualLength, bigtime_t timeout)
|
||||
ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
||||
uint16 index, uint16 length, void *data, size_t dataLength,
|
||||
usb_callback_func callback, void *callbackCookie)
|
||||
{
|
||||
// builds an usb packet with the needed data
|
||||
Transfer transfer(this, true);
|
||||
usb_request_data *requestData = new(std::nothrow) usb_request_data;
|
||||
if (!requestData)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
transfer.SetRequestData(command);
|
||||
transfer.SetBuffer((uint8 *)data);
|
||||
transfer.SetBufferLength(dataLength);
|
||||
transfer.SetActualLength(actualLength);
|
||||
requestData->RequestType = requestType;
|
||||
requestData->Request = request;
|
||||
requestData->Value = value;
|
||||
requestData->Index = index;
|
||||
requestData->Length = length;
|
||||
|
||||
fBus->SubmitTransfer(&transfer);
|
||||
return transfer.WaitForFinish();
|
||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
||||
if (!transfer) {
|
||||
delete requestData;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
transfer->SetRequestData(requestData);
|
||||
transfer->SetData((uint8 *)data, dataLength);
|
||||
transfer->SetCallback(callback, callbackCookie);
|
||||
|
||||
status_t result = SubmitTransfer(transfer);
|
||||
if (result == B_OK || result == EINPROGRESS)
|
||||
return B_OK;
|
||||
|
||||
delete transfer;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ControlPipe::SetFeature(uint16 selector)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ControlPipe::ClearFeature(uint16 selector)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ControlPipe::GetStatus(uint16 *status)
|
||||
{
|
||||
return SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_IN,
|
||||
USB_REQUEST_GET_STATUS,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
(void *)status,
|
||||
2,
|
||||
NULL);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
|
||||
Stack::Stack()
|
||||
: fDriverList(NULL)
|
||||
{
|
||||
TRACE(("usb stack: stack init\n"));
|
||||
|
||||
@ -31,9 +32,6 @@ Stack::Stack()
|
||||
fDataLock = create_sem(1, "usb data lock");
|
||||
set_sem_owner(fDataLock, B_SYSTEM_TEAM);
|
||||
|
||||
// Set the global "data" variable to this
|
||||
usb_stack = this;
|
||||
|
||||
// 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
|
||||
@ -103,6 +101,27 @@ Stack::Stack()
|
||||
chunk->next_item = NULL;
|
||||
}
|
||||
|
||||
// 64-byte heap
|
||||
fAreaFreeCount[3] = 0;
|
||||
fAreas[3] = AllocateArea(&fLogical[3], &fPhysical[3], B_PAGE_SIZE,
|
||||
"64-byte chunk area");
|
||||
|
||||
if (fAreas[3] < B_OK) {
|
||||
TRACE(("usb stack: 64-byte chunk area failed to initialise\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
fListhead64 = (addr_t)fLogical[3];
|
||||
for (int32 i = 0; i < B_PAGE_SIZE / 64; i++) {
|
||||
memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[3] + 64 * i);
|
||||
chunk->physical = (addr_t)fPhysical[3] + 64 * i;
|
||||
|
||||
if (i < B_PAGE_SIZE / 64 - 1)
|
||||
chunk->next_item = (addr_t)fLogical[3] + 64 * (i + 1);
|
||||
else
|
||||
chunk->next_item = NULL;
|
||||
}
|
||||
|
||||
// Check for host controller modules
|
||||
void *moduleList = open_module_list("busses/usb");
|
||||
char moduleName[B_PATH_NAME_LENGTH];
|
||||
@ -152,10 +171,10 @@ Stack::InitCheck()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
Stack::Lock()
|
||||
{
|
||||
acquire_sem(fMasterLock);
|
||||
return (acquire_sem(fMasterLock) == B_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -185,6 +204,8 @@ Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, uint8 size)
|
||||
listhead = fListhead16;
|
||||
else if (size <= 32)
|
||||
listhead = fListhead32;
|
||||
else if (size <= 64)
|
||||
listhead = fListhead64;
|
||||
else {
|
||||
TRACE(("usb stack: Chunk size %d to big\n", size));
|
||||
Unlock();
|
||||
@ -215,6 +236,8 @@ Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, uint8 size)
|
||||
fListhead16 = listhead;
|
||||
else if (size <= 32)
|
||||
fListhead32 = listhead;
|
||||
else if (size <= 64)
|
||||
fListhead64 = listhead;
|
||||
|
||||
Unlock();
|
||||
//TRACE(("usb stack: allocated a new chunk with size %u\n", size));
|
||||
@ -234,6 +257,8 @@ Stack::FreeChunk(void *logicalAddress, void *physicalAddress, uint8 size)
|
||||
listhead = fListhead16;
|
||||
else if (size <= 32)
|
||||
listhead = fListhead32;
|
||||
else if (size <= 64)
|
||||
listhead = fListhead64;
|
||||
else {
|
||||
TRACE(("usb stack: Chunk size %d invalid\n", size));
|
||||
Unlock();
|
||||
@ -250,6 +275,8 @@ Stack::FreeChunk(void *logicalAddress, void *physicalAddress, uint8 size)
|
||||
fListhead16 = (addr_t)logicalAddress;
|
||||
else if (size <= 32)
|
||||
fListhead32 = (addr_t)logicalAddress;
|
||||
else if (size <= 64)
|
||||
fListhead64 = (addr_t)logicalAddress;
|
||||
|
||||
Unlock();
|
||||
return B_OK;
|
||||
@ -293,4 +320,112 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
|
||||
}
|
||||
|
||||
|
||||
Stack *usb_stack = NULL;
|
||||
void
|
||||
Stack::NotifyDeviceChange(Device *device, bool added)
|
||||
{
|
||||
TRACE(("usb stack: device %s\n", added ? "added" : "removed"));
|
||||
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element) {
|
||||
if ((added && element->notify_hooks.device_added != NULL)
|
||||
|| (!added && element->notify_hooks.device_removed != NULL)) {
|
||||
device->ReportDevice(element->support_descriptors,
|
||||
element->support_descriptor_count,
|
||||
&element->notify_hooks, added);
|
||||
}
|
||||
|
||||
element = element->link;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Stack::RegisterDriver(const char *driverName,
|
||||
const usb_support_descriptor *descriptors,
|
||||
size_t descriptorCount, const char *republishDriverName)
|
||||
{
|
||||
TRACE(("usb stack: register driver \"%s\"\n", driverName));
|
||||
usb_driver_info *info = new(std::nothrow) usb_driver_info;
|
||||
if (!info)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
info->driver_name = strdup(driverName);
|
||||
info->republish_driver_name = strdup(republishDriverName);
|
||||
|
||||
size_t descriptorsSize = descriptorCount * sizeof(usb_support_descriptor);
|
||||
info->support_descriptors = (usb_support_descriptor *)malloc(descriptorsSize);
|
||||
memcpy(info->support_descriptors, descriptors, descriptorsSize);
|
||||
info->support_descriptor_count = descriptorCount;
|
||||
|
||||
info->notify_hooks.device_added = NULL;
|
||||
info->notify_hooks.device_removed = NULL;
|
||||
info->link = NULL;
|
||||
|
||||
if (!Lock()) {
|
||||
delete info;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (fDriverList) {
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element->link)
|
||||
element = element->link;
|
||||
|
||||
element->link = info;
|
||||
} else
|
||||
fDriverList = info;
|
||||
|
||||
Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
|
||||
{
|
||||
TRACE(("usb stack: installing notify hooks for driver \"%s\"\n", driverName));
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element) {
|
||||
if (strcmp(element->driver_name, driverName) == 0) {
|
||||
// inform driver about any already present devices
|
||||
for (int32 i = 0; i < fBusManagers.Count(); i++) {
|
||||
Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub();
|
||||
if (rootHub) {
|
||||
// Ensure that all devices are already recognized
|
||||
rootHub->Explore();
|
||||
|
||||
// Report device will recurse down the whole tree
|
||||
rootHub->ReportDevice(element->support_descriptors,
|
||||
element->support_descriptor_count, hooks, true);
|
||||
}
|
||||
}
|
||||
|
||||
element->notify_hooks.device_added = hooks->device_added;
|
||||
element->notify_hooks.device_removed = hooks->device_removed;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
element = element->link;
|
||||
}
|
||||
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Stack::UninstallNotify(const char *driverName)
|
||||
{
|
||||
TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName));
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element) {
|
||||
if (strcmp(element->driver_name, driverName) == 0) {
|
||||
element->notify_hooks.device_added = NULL;
|
||||
element->notify_hooks.device_removed = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
element = element->link;
|
||||
}
|
||||
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
|
@ -10,16 +10,19 @@
|
||||
|
||||
|
||||
Transfer::Transfer(Pipe *pipe, bool synchronous)
|
||||
: fPipe(pipe),
|
||||
fData(NULL),
|
||||
fDataLength(0),
|
||||
fActualLength(NULL),
|
||||
fOwnActualLength(0),
|
||||
fStatus(B_NO_INIT),
|
||||
fCallback(NULL),
|
||||
fCallbackCookie(NULL),
|
||||
fSem(-1),
|
||||
fHostPrivate(NULL),
|
||||
fRequestData(NULL)
|
||||
{
|
||||
fPipe = pipe;
|
||||
fBuffer = NULL;
|
||||
fBufferLength = 0;
|
||||
fActualLength = NULL;
|
||||
fStatus = B_NO_INIT;
|
||||
fSem = -1;
|
||||
fHostPrivate = NULL;
|
||||
fCallback = NULL;
|
||||
|
||||
fActualLength = &fOwnActualLength;
|
||||
if (synchronous) {
|
||||
fSem = create_sem(0, "USB Transfer");
|
||||
set_sem_owner(fSem, B_SYSTEM_TEAM);
|
||||
@ -37,21 +40,15 @@ Transfer::~Transfer()
|
||||
void
|
||||
Transfer::SetRequestData(usb_request_data *data)
|
||||
{
|
||||
fRequest = data;
|
||||
fRequestData = data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Transfer::SetBuffer(uint8 *buffer)
|
||||
Transfer::SetData(uint8 *data, size_t dataLength)
|
||||
{
|
||||
fBuffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Transfer::SetBufferLength(size_t length)
|
||||
{
|
||||
fBufferLength = length;
|
||||
fData = data;
|
||||
fDataLength = dataLength;
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +60,7 @@ Transfer::SetActualLength(size_t *actualLength)
|
||||
|
||||
|
||||
void
|
||||
Transfer::SetCallbackFunction(usb_callback_func callback, void *cookie)
|
||||
Transfer::SetCallback(usb_callback_func callback, void *cookie)
|
||||
{
|
||||
fCallback = callback;
|
||||
fCallbackCookie = cookie;
|
||||
@ -98,11 +95,15 @@ Transfer::Finished(status_t result)
|
||||
{
|
||||
fStatus = result;
|
||||
|
||||
// If we are synchronous, release the sem
|
||||
if (fSem > B_OK)
|
||||
release_sem(fSem);
|
||||
// Call the callback function ...
|
||||
if (fCallback) {
|
||||
fCallback(fCallbackCookie, fStatus, fData, *fActualLength);
|
||||
return;
|
||||
}
|
||||
|
||||
// ToDo: implement callback correctly
|
||||
if (fCallback)
|
||||
fCallback(fCallbackCookie, fStatus, fBuffer, 0);
|
||||
// ... or release the sem
|
||||
if (fSem > B_OK) {
|
||||
release_sem(fSem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
Stack *gUSBStack = NULL;
|
||||
|
||||
|
||||
static int32
|
||||
bus_std_ops(int32 op, ...)
|
||||
{
|
||||
@ -28,20 +31,25 @@ bus_std_ops(int32 op, ...)
|
||||
set_dprintf_enabled(true);
|
||||
load_driver_symbols("usb");
|
||||
#endif
|
||||
TRACE(("usb_nielx: bus module: init\n"));
|
||||
TRACE(("usb_module: init\n"));
|
||||
|
||||
Stack *stack = new(std::nothrow) Stack();
|
||||
if (!stack)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
Stack *stack = new Stack();
|
||||
if (stack->InitCheck() != B_OK) {
|
||||
delete stack;
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
gUSBStack = stack;
|
||||
break;
|
||||
}
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
TRACE(("usb_nielx: bus module: uninit\n"));
|
||||
delete usb_stack;
|
||||
TRACE(("usb_module: bus module: uninit\n"));
|
||||
delete gUSBStack;
|
||||
gUSBStack = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -52,6 +60,207 @@ bus_std_ops(int32 op, ...)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
register_driver(const char *driverName,
|
||||
const usb_support_descriptor *descriptors,
|
||||
size_t count, const char *optionalRepublishDriverName)
|
||||
{
|
||||
return gUSBStack->RegisterDriver(driverName, descriptors, count,
|
||||
optionalRepublishDriverName);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
install_notify(const char *driverName, const usb_notify_hooks *hooks)
|
||||
{
|
||||
return gUSBStack->InstallNotify(driverName, hooks);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
uninstall_notify(const char *driverName)
|
||||
{
|
||||
return gUSBStack->UninstallNotify(driverName);
|
||||
}
|
||||
|
||||
|
||||
const usb_device_descriptor *
|
||||
get_device_descriptor(const usb_device *device)
|
||||
{
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
return ((const Device *)device)->DeviceDescriptor();
|
||||
}
|
||||
|
||||
|
||||
const usb_configuration_info *
|
||||
get_nth_configuration(const usb_device *device, uint index)
|
||||
{
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
return ((const Device *)device)->ConfigurationAt((int32)index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const usb_configuration_info *
|
||||
get_configuration(const usb_device *device)
|
||||
{
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
return ((const Device *)device)->Configuration();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
set_configuration(const usb_device *device,
|
||||
const usb_configuration_info *configuration)
|
||||
{
|
||||
if (!device)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((Device *)device)->SetConfiguration(configuration);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
set_alt_interface(const usb_device *device,
|
||||
const usb_interface_info *interface)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
set_feature(const void *object, uint16 selector)
|
||||
{
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->SetFeature(selector);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
clear_feature(const void *object, uint16 selector)
|
||||
{
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->ClearFeature(selector);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
get_status(const void *object, uint16 *status)
|
||||
{
|
||||
if (!object || !status)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->GetStatus(status);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
get_descriptor(const usb_device *device, uint8 type, uint8 index,
|
||||
uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
|
||||
{
|
||||
if (!device || !data)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((Device *)device)->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)
|
||||
{
|
||||
if (!device)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((Device *)device)->SendRequest(requestType, request, value, index,
|
||||
length, data, dataLength, actualLength);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if (!device)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((Device *)device)->QueueRequest(requestType, request, value, index,
|
||||
length, data, dataLength, callback, callbackCookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
queue_interrupt(const usb_pipe *pipe, void *data, size_t dataLength,
|
||||
usb_callback_func callback, void *callbackCookie)
|
||||
{
|
||||
if (((Pipe *)pipe)->Type() != Pipe::Interrupt)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((InterruptPipe *)pipe)->QueueInterrupt(data, dataLength, callback,
|
||||
callbackCookie);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
queue_bulk(const usb_pipe *pipe, void *data, size_t dataLength,
|
||||
usb_callback_func callback, void *callbackCookie)
|
||||
{
|
||||
if (((Pipe *)pipe)->Type() != Pipe::Bulk)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((BulkPipe *)pipe)->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)
|
||||
{
|
||||
if (((Pipe *)pipe)->Type() != Pipe::Isochronous)
|
||||
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)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
cancel_queued_transfers(const usb_pipe *pipe)
|
||||
{
|
||||
return ((Pipe *)pipe)->CancelQueuedTransfers();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This module exports the USB API
|
||||
*/
|
||||
@ -59,33 +268,33 @@ struct usb_module_info gModuleInfo = {
|
||||
// First the bus_manager_info:
|
||||
{
|
||||
{
|
||||
"bus_managers/usb/nielx",
|
||||
B_USB_MODULE_NAME,
|
||||
B_KEEP_LOADED, // Keep loaded, even if no driver requires it
|
||||
bus_std_ops
|
||||
},
|
||||
NULL // the rescan function
|
||||
NULL // the rescan function
|
||||
},
|
||||
|
||||
NULL, // register_driver
|
||||
NULL, // install_notify
|
||||
NULL, // uninstall_notify
|
||||
NULL, // get_device_descriptor
|
||||
NULL, // get_nth_configuration_info
|
||||
NULL, // get_configuration
|
||||
NULL, // set_configuration
|
||||
NULL, // set_alt_interface
|
||||
NULL, // set_feature
|
||||
NULL, // clear_feature
|
||||
NULL, // get_status
|
||||
NULL, // get_descriptor
|
||||
NULL, // send_request
|
||||
NULL, // queue_interrupt
|
||||
NULL, // queue_bulk
|
||||
NULL, // queue_isochronous
|
||||
NULL, // queue_request
|
||||
NULL, // set_pipe_policy
|
||||
NULL, // cancel_queued_transfers
|
||||
NULL // usb_ioctl
|
||||
register_driver, // register_driver
|
||||
install_notify, // install_notify
|
||||
uninstall_notify, // uninstall_notify
|
||||
get_device_descriptor, // get_device_descriptor
|
||||
get_nth_configuration, // get_nth_configuration
|
||||
get_configuration, // get_configuration
|
||||
set_configuration, // set_configuration
|
||||
set_alt_interface, // set_alt_interface
|
||||
set_feature, // set_feature
|
||||
clear_feature, // clear_feature
|
||||
get_status, // get_status
|
||||
get_descriptor, // get_descriptor
|
||||
send_request, // send_request
|
||||
queue_interrupt, // queue_interrupt
|
||||
queue_bulk, // queue_bulk
|
||||
queue_isochronous, // queue_isochronous
|
||||
queue_request, // queue_request
|
||||
set_pipe_policy, // set_pipe_policy
|
||||
cancel_queued_transfers, // cancel_queued_transfers
|
||||
usb_ioctl // usb_ioctl
|
||||
};
|
||||
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "usbspec_p.h"
|
||||
|
||||
|
||||
class Hub;
|
||||
class Device;
|
||||
class Stack;
|
||||
class Device;
|
||||
class Transfer;
|
||||
@ -27,6 +29,16 @@ struct host_controller_info {
|
||||
};
|
||||
|
||||
|
||||
struct usb_driver_info {
|
||||
const char *driver_name;
|
||||
usb_support_descriptor *support_descriptors;
|
||||
uint32 support_descriptor_count;
|
||||
const char *republish_driver_name;
|
||||
usb_notify_hooks notify_hooks;
|
||||
usb_driver_info *link;
|
||||
};
|
||||
|
||||
|
||||
class Stack {
|
||||
public:
|
||||
Stack();
|
||||
@ -34,7 +46,7 @@ public:
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
void Lock();
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
|
||||
void AddBusManager(BusManager *bus);
|
||||
@ -48,6 +60,19 @@ public:
|
||||
void **physicalAddress,
|
||||
size_t size, const char *name);
|
||||
|
||||
void NotifyDeviceChange(Device *device,
|
||||
bool added);
|
||||
|
||||
// USB API
|
||||
status_t RegisterDriver(const char *driverName,
|
||||
const usb_support_descriptor *descriptors,
|
||||
size_t descriptorCount,
|
||||
const char *republishDriverName);
|
||||
|
||||
status_t InstallNotify(const char *driverName,
|
||||
const usb_notify_hooks *hooks);
|
||||
status_t UninstallNotify(const char *driverName);
|
||||
|
||||
private:
|
||||
Vector<BusManager *> fBusManagers;
|
||||
|
||||
@ -62,61 +87,9 @@ private:
|
||||
addr_t fListhead8;
|
||||
addr_t fListhead16;
|
||||
addr_t fListhead32;
|
||||
};
|
||||
addr_t fListhead64;
|
||||
|
||||
extern "C" Stack *usb_stack;
|
||||
|
||||
class Device {
|
||||
public:
|
||||
Device(BusManager *bus, Device *parent,
|
||||
usb_device_descriptor &desc,
|
||||
int8 deviceAddress, bool lowSpeed);
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual bool IsHub() { return false; };
|
||||
int8 Address() { return fDeviceAddress; };
|
||||
BusManager *Manager() { return fBus; };
|
||||
|
||||
size_t GetDescriptor(uint8 descriptorType,
|
||||
uint16 index, void *buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
status_t SetConfiguration(uint8 value);
|
||||
|
||||
protected:
|
||||
usb_device_descriptor fDeviceDescriptor;
|
||||
usb_configuration_descriptor *fConfigurations;
|
||||
usb_configuration_descriptor *fCurrentConfiguration;
|
||||
ControlPipe *fDefaultPipe;
|
||||
bool fInitOK;
|
||||
bool fLowSpeed;
|
||||
BusManager *fBus;
|
||||
Device *fParent;
|
||||
int8 fDeviceAddress;
|
||||
uint32 fMaxPacketIn[16];
|
||||
uint32 fMaxPacketOut[16];
|
||||
sem_id fLock;
|
||||
};
|
||||
|
||||
|
||||
class Hub : public Device {
|
||||
public:
|
||||
Hub(BusManager *bus, Device *parent,
|
||||
usb_device_descriptor &desc,
|
||||
int8 deviceAddress, bool lowSpeed);
|
||||
|
||||
virtual bool IsHub() { return true; };
|
||||
|
||||
void Explore();
|
||||
|
||||
private:
|
||||
usb_interface_descriptor fInterruptInterface;
|
||||
usb_endpoint_descriptor fInterruptEndpoint;
|
||||
usb_hub_descriptor fHubDescriptor;
|
||||
|
||||
usb_port_status fPortStatus[8];
|
||||
Device *fChildren[8];
|
||||
usb_driver_info *fDriverList;
|
||||
};
|
||||
|
||||
|
||||
@ -143,10 +116,13 @@ virtual status_t Stop();
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t SubmitRequest(Transfer *transfer);
|
||||
|
||||
protected:
|
||||
void SetRootHub(Hub *hub) { fRootHub = hub; };
|
||||
Device *GetRootHub() { return fRootHub; };
|
||||
Stack *GetStack() { return fStack; };
|
||||
void SetStack(Stack *stack) { fStack = stack; };
|
||||
|
||||
Hub *GetRootHub() { return fRootHub; };
|
||||
void SetRootHub(Hub *hub) { fRootHub = hub; };
|
||||
|
||||
protected:
|
||||
bool fInitOK;
|
||||
|
||||
private:
|
||||
@ -156,13 +132,14 @@ static int32 ExploreThread(void *data);
|
||||
bool fDeviceMap[128];
|
||||
ControlPipe *fDefaultPipe;
|
||||
ControlPipe *fDefaultPipeLowSpeed;
|
||||
Device *fRootHub;
|
||||
Hub *fRootHub;
|
||||
Stack *fStack;
|
||||
thread_id fExploreThread;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The Pipe class is the communication management between the hardware and\
|
||||
* The Pipe class is the communication management between the hardware and
|
||||
* the stack. It creates packets, manages these and performs callbacks.
|
||||
*/
|
||||
class Pipe {
|
||||
@ -173,60 +150,230 @@ enum pipeType { Control, Bulk, Isochronous, Interrupt, Invalid };
|
||||
|
||||
Pipe(Device *device,
|
||||
pipeDirection direction,
|
||||
pipeSpeed speed,
|
||||
uint8 endpointAddress,
|
||||
uint32 maxPacketSize);
|
||||
virtual ~Pipe();
|
||||
|
||||
virtual int8 DeviceAddress();
|
||||
virtual pipeType Type() { return Invalid; };
|
||||
virtual pipeSpeed Speed() { return LowSpeed; };
|
||||
//Provide a default: should never be called
|
||||
virtual pipeSpeed Speed() { return fSpeed; };
|
||||
virtual pipeDirection Direction() { return fDirection; };
|
||||
virtual int8 EndpointAddress() { return fEndpoint; };
|
||||
virtual uint32 MaxPacketSize() { return fMaxPacketSize; };
|
||||
|
||||
virtual bool DataToggle() { return fDataToggle; };
|
||||
virtual void SetDataToggle(bool toggle) { fDataToggle = toggle; };
|
||||
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
status_t CancelQueuedTransfers();
|
||||
|
||||
protected:
|
||||
Device *fDevice;
|
||||
BusManager *fBus;
|
||||
pipeDirection fDirection;
|
||||
pipeSpeed fSpeed;
|
||||
uint8 fEndpoint;
|
||||
uint32 fMaxPacketSize;
|
||||
bool fDataToggle;
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
pipeDirection direction,
|
||||
pipeSpeed speed,
|
||||
uint8 endpointAddress,
|
||||
uint32 maxPacketSize);
|
||||
ControlPipe(Device *device,
|
||||
pipeSpeed speed,
|
||||
uint8 endpointAddress,
|
||||
uint32 maxPacketSize);
|
||||
|
||||
// Constructor for default control pipe
|
||||
ControlPipe(BusManager *bus,
|
||||
int8 deviceAddress,
|
||||
pipeDirection direction,
|
||||
pipeSpeed speed,
|
||||
uint8 endpointAddress,
|
||||
uint32 maxPacketSize);
|
||||
// Constructor for default control pipe
|
||||
ControlPipe(BusManager *bus,
|
||||
int8 deviceAddress,
|
||||
pipeSpeed speed,
|
||||
uint8 endpointAddress,
|
||||
uint32 maxPacketSize);
|
||||
|
||||
virtual int8 DeviceAddress();
|
||||
virtual pipeType Type() { return Control; };
|
||||
virtual pipeSpeed Speed() { return fSpeed; };
|
||||
virtual int8 DeviceAddress();
|
||||
virtual pipeType Type() { return Control; };
|
||||
|
||||
status_t SendRequest(uint8 requestType,
|
||||
uint8 request, uint16 value,
|
||||
uint16 index, uint16 length,
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength);
|
||||
// The data toggle is not relevant
|
||||
// for control transfers, as they are
|
||||
// always enclosed by a setup and
|
||||
// status packet. The toggle always
|
||||
// starts at 1.
|
||||
virtual bool DataToggle() { return true; };
|
||||
virtual void SetDataToggle(bool toggle) {};
|
||||
|
||||
status_t SendControlMessage(usb_request_data *command,
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength,
|
||||
bigtime_t timeout);
|
||||
status_t SendRequest(uint8 requestType,
|
||||
uint8 request, uint16 value,
|
||||
uint16 index, uint16 length,
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength);
|
||||
|
||||
status_t QueueRequest(uint8 requestType,
|
||||
uint8 request, uint16 value,
|
||||
uint16 index, uint16 length,
|
||||
void *data, size_t dataLength,
|
||||
usb_callback_func callback,
|
||||
void *callbackCookie);
|
||||
|
||||
// Convenience functions for standard requests
|
||||
virtual status_t SetFeature(uint16 selector);
|
||||
virtual status_t ClearFeature(uint16 selector);
|
||||
virtual status_t GetStatus(uint16 *status);
|
||||
|
||||
private:
|
||||
int8 fDeviceAddress;
|
||||
pipeSpeed fSpeed;
|
||||
int8 fDeviceAddress;
|
||||
};
|
||||
|
||||
|
||||
class Interface : public ControlPipe {
|
||||
public:
|
||||
Interface(Device *device);
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
class Device : public ControlPipe {
|
||||
public:
|
||||
Device(BusManager *bus, Device *parent,
|
||||
usb_device_descriptor &desc,
|
||||
int8 deviceAddress, bool lowSpeed);
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual bool IsHub() { return false; };
|
||||
int8 Address() { return fDeviceAddress; };
|
||||
BusManager *Manager() { return fBus; };
|
||||
bool LowSpeed() { return fLowSpeed; };
|
||||
|
||||
virtual status_t GetDescriptor(uint8 descriptorType,
|
||||
uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength);
|
||||
|
||||
const usb_device_descriptor *DeviceDescriptor() const;
|
||||
|
||||
const usb_configuration_info *Configuration() const;
|
||||
const usb_configuration_info *ConfigurationAt(uint8 index) const;
|
||||
status_t SetConfiguration(const usb_configuration_info *configuration);
|
||||
status_t SetConfigurationAt(uint8 index);
|
||||
|
||||
virtual void ReportDevice(
|
||||
usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount,
|
||||
const usb_notify_hooks *hooks,
|
||||
bool added);
|
||||
|
||||
// Convenience functions for standard requests
|
||||
virtual status_t SetFeature(uint16 selector);
|
||||
virtual status_t ClearFeature(uint16 selector);
|
||||
virtual status_t GetStatus(uint16 *status);
|
||||
|
||||
protected:
|
||||
usb_device_descriptor fDeviceDescriptor;
|
||||
usb_configuration_info *fConfigurations;
|
||||
usb_configuration_info *fCurrentConfiguration;
|
||||
bool fInitOK;
|
||||
bool fLowSpeed;
|
||||
BusManager *fBus;
|
||||
Device *fParent;
|
||||
int8 fDeviceAddress;
|
||||
uint32 fMaxPacketIn[16];
|
||||
uint32 fMaxPacketOut[16];
|
||||
sem_id fLock;
|
||||
void *fNotifyCookie;
|
||||
};
|
||||
|
||||
|
||||
class Hub : public Device {
|
||||
public:
|
||||
Hub(BusManager *bus, Device *parent,
|
||||
usb_device_descriptor &desc,
|
||||
int8 deviceAddress, bool lowSpeed);
|
||||
|
||||
virtual bool IsHub() { return true; };
|
||||
|
||||
virtual status_t GetDescriptor(uint8 descriptorType,
|
||||
uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength,
|
||||
size_t *actualLength);
|
||||
|
||||
void Explore();
|
||||
|
||||
virtual void ReportDevice(
|
||||
usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount,
|
||||
const usb_notify_hooks *hooks,
|
||||
bool added);
|
||||
|
||||
private:
|
||||
usb_interface_descriptor *fInterruptInterface;
|
||||
usb_endpoint_descriptor *fInterruptEndpoint;
|
||||
usb_hub_descriptor fHubDescriptor;
|
||||
|
||||
usb_port_status fPortStatus[8];
|
||||
Device *fChildren[8];
|
||||
};
|
||||
|
||||
|
||||
@ -250,13 +397,11 @@ public:
|
||||
Pipe *TransferPipe() { return fPipe; };
|
||||
|
||||
void SetRequestData(usb_request_data *data);
|
||||
usb_request_data *RequestData() { return fRequest; };
|
||||
usb_request_data *RequestData() { return fRequestData; };
|
||||
|
||||
void SetBuffer(uint8 *buffer);
|
||||
uint8 *Buffer() { return fBuffer; };
|
||||
|
||||
void SetBufferLength(size_t length);
|
||||
size_t BufferLength() { return fBufferLength; };
|
||||
void SetData(uint8 *buffer, size_t length);
|
||||
uint8 *Data() { return fData; };
|
||||
size_t DataLength() { return fDataLength; };
|
||||
|
||||
void SetActualLength(size_t *actualLength);
|
||||
size_t *ActualLength() { return fActualLength; };
|
||||
@ -264,19 +409,19 @@ public:
|
||||
void SetHostPrivate(hostcontroller_priv *priv);
|
||||
hostcontroller_priv *HostPrivate() { return fHostPrivate; };
|
||||
|
||||
void SetCallbackFunction(
|
||||
usb_callback_func callback,
|
||||
void SetCallback(usb_callback_func callback,
|
||||
void *cookie);
|
||||
|
||||
|
||||
status_t WaitForFinish();
|
||||
void Finished(status_t result);
|
||||
|
||||
private:
|
||||
// Data that is related to the transfer
|
||||
Pipe *fPipe;
|
||||
uint8 *fBuffer;
|
||||
size_t fBufferLength;
|
||||
uint8 *fData;
|
||||
size_t fDataLength;
|
||||
size_t *fActualLength;
|
||||
size_t fOwnActualLength;
|
||||
status_t fStatus;
|
||||
|
||||
usb_callback_func fCallback;
|
||||
@ -286,7 +431,7 @@ private:
|
||||
hostcontroller_priv *fHostPrivate;
|
||||
|
||||
// For control transfers
|
||||
usb_request_data *fRequest;
|
||||
usb_request_data *fRequestData;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -21,8 +21,10 @@
|
||||
#define TRACE_UHCI
|
||||
#ifdef TRACE_UHCI
|
||||
#define TRACE(x) dprintf x
|
||||
#define TRACE_ERROR(x) dprintf x
|
||||
#else
|
||||
#define TRACE(x) /* nothing */
|
||||
#define TRACE_ERROR(x) dprintf x
|
||||
#endif
|
||||
|
||||
|
||||
@ -101,15 +103,11 @@ Queue::Queue(Stack *stack)
|
||||
{
|
||||
fStack = stack;
|
||||
|
||||
fLockAtom = 0;
|
||||
fLockSem = create_sem(1, "uhci queue lock");
|
||||
if (fLockSem < B_OK) {
|
||||
if (benaphore_init(&fLock, "uhci queue lock") < B_OK) {
|
||||
TRACE(("usb_uhci: failed to create queue lock\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
set_sem_owner(fLockSem, B_SYSTEM_TEAM);
|
||||
|
||||
void *physicalAddress;
|
||||
fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress, 32);
|
||||
if (fStatus < B_OK)
|
||||
@ -117,7 +115,6 @@ Queue::Queue(Stack *stack)
|
||||
|
||||
fQueueHead->this_phy = (addr_t)physicalAddress;
|
||||
fQueueHead->element_phy = QH_TERMINATE;
|
||||
fQueueHead->element_log = 0;
|
||||
|
||||
fStrayDescriptor = NULL;
|
||||
fQueueTop = NULL;
|
||||
@ -127,7 +124,7 @@ Queue::Queue(Stack *stack)
|
||||
Queue::~Queue()
|
||||
{
|
||||
Lock();
|
||||
delete_sem(fLockSem);
|
||||
benaphore_destroy(&fLock);
|
||||
|
||||
fStack->FreeChunk(fQueueHead, (void *)fQueueHead->this_phy, 32);
|
||||
|
||||
@ -146,18 +143,14 @@ Queue::InitCheck()
|
||||
bool
|
||||
Queue::Lock()
|
||||
{
|
||||
if (atomic_add(&fLockAtom, 1) > 0)
|
||||
return acquire_sem(fLockSem) == B_OK;
|
||||
|
||||
return true;
|
||||
return (benaphore_lock(&fLock) == B_OK);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Queue::Unlock()
|
||||
{
|
||||
if (atomic_add(&fLockAtom, -1) > 1)
|
||||
release_sem(fLockSem);
|
||||
benaphore_unlock(&fLock);
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +203,6 @@ Queue::TerminateByStrayDescriptor()
|
||||
fQueueHead->link_phy = fStrayDescriptor->this_phy;
|
||||
fQueueHead->link_log = fStrayDescriptor;
|
||||
fQueueHead->element_phy = QH_TERMINATE;
|
||||
fQueueHead->element_log = 0;
|
||||
Unlock();
|
||||
|
||||
return B_OK;
|
||||
@ -231,18 +223,17 @@ Queue::AppendDescriptor(uhci_td *descriptor)
|
||||
|
||||
if (fQueueHead->element_phy & QH_TERMINATE) {
|
||||
// the queue is empty, make this the first element
|
||||
fQueueHead->element_phy = descriptor->this_phy;
|
||||
fQueueHead->element_log = descriptor;
|
||||
fQueueTop = descriptor;
|
||||
fQueueHead->element_phy = descriptor->this_phy;
|
||||
TRACE(("usb_uhci: first transfer in queue\n"));
|
||||
} else {
|
||||
// there are transfers linked, append to the queue
|
||||
uhci_td *element = (uhci_td *)fQueueHead->element_log;
|
||||
uhci_td *element = fQueueTop;
|
||||
while ((element->link_phy & TD_TERMINATE) == 0)
|
||||
element = (uhci_td *)element->link_log;
|
||||
|
||||
element->link_phy = descriptor->this_phy | TD_DEPTH_FIRST;
|
||||
element->link_log = descriptor;
|
||||
element->link_phy = descriptor->this_phy | TD_DEPTH_FIRST;
|
||||
TRACE(("usb_uhci: appended transfer to queue\n"));
|
||||
}
|
||||
|
||||
@ -254,27 +245,57 @@ Queue::AppendDescriptor(uhci_td *descriptor)
|
||||
status_t
|
||||
Queue::RemoveDescriptors(uhci_td *firstDescriptor, uhci_td *lastDescriptor)
|
||||
{
|
||||
TRACE(("usb_uhci: removing descriptors\n"));
|
||||
|
||||
if (!Lock())
|
||||
return B_ERROR;
|
||||
|
||||
if (fQueueTop == firstDescriptor) {
|
||||
// it was the first chain in this queue
|
||||
fQueueTop = (uhci_td *)lastDescriptor->link_log;
|
||||
Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
if ((lastDescriptor->link_phy & TD_TERMINATE) > 0) {
|
||||
// it was the only transfer
|
||||
fQueueTop = NULL;
|
||||
fQueueHead->element_phy = QH_TERMINATE;
|
||||
} else {
|
||||
// there are still linked transfers
|
||||
fQueueTop = (uhci_td *)lastDescriptor->link_log;
|
||||
fQueueHead->element_phy = fQueueTop->this_phy & TD_LINK_MASK;
|
||||
}
|
||||
} else {
|
||||
uhci_td *descriptor = fQueueTop;
|
||||
while (descriptor) {
|
||||
if (descriptor->link_log == firstDescriptor) {
|
||||
descriptor->link_log = lastDescriptor->link_log;
|
||||
descriptor->link_phy = lastDescriptor->link_phy;
|
||||
break;
|
||||
}
|
||||
|
||||
uhci_td *descriptor = fQueueTop;
|
||||
while (descriptor) {
|
||||
if (descriptor->link_log == firstDescriptor) {
|
||||
descriptor->link_log = lastDescriptor->link_log;
|
||||
descriptor->link_phy = lastDescriptor->link_phy;
|
||||
break;
|
||||
descriptor = (uhci_td *)descriptor->link_log;
|
||||
}
|
||||
|
||||
descriptor = (uhci_td *)descriptor->link_log;
|
||||
descriptor = firstDescriptor;
|
||||
while (descriptor) {
|
||||
if ((fQueueHead->element_phy & TD_LINK_MASK)
|
||||
== (descriptor->this_phy & TD_LINK_MASK)) {
|
||||
if ((lastDescriptor->link_phy) & TD_TERMINATE > 0)
|
||||
fQueueHead->element_phy = QH_TERMINATE;
|
||||
else
|
||||
fQueueHead->element_phy = lastDescriptor->link_phy & TD_LINK_MASK;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
descriptor = (uhci_td *)descriptor->link_log;
|
||||
}
|
||||
}
|
||||
|
||||
lastDescriptor->link_log = NULL;
|
||||
lastDescriptor->link_phy = TD_TERMINATE;
|
||||
|
||||
#ifdef TRACE_UHCI
|
||||
print_descriptor_chain(firstDescriptor);
|
||||
#endif
|
||||
|
||||
Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
@ -324,15 +345,11 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
TRACE(("usb_uhci: constructing new UHCI Host Controller Driver\n"));
|
||||
fInitOK = false;
|
||||
|
||||
fLockAtom = 0;
|
||||
fLockSem = create_sem(1, "usb uhci lock");
|
||||
if (fLockSem < B_OK) {
|
||||
if (benaphore_init(&fUHCILock, "usb uhci lock") < B_OK) {
|
||||
TRACE(("usb_uhci: failed to create busmanager lock\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
set_sem_owner(fLockSem, B_SYSTEM_TEAM);
|
||||
|
||||
fRegisterBase = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function, PCI_memory_base, 4);
|
||||
fRegisterBase &= PCI_address_io_mask;
|
||||
@ -378,10 +395,15 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
WriteReg16(UHCI_FRNUM, 0);
|
||||
|
||||
fQueueCount = 4;
|
||||
fQueues = new Queue *[fQueueCount];
|
||||
fQueues = new(std::nothrow) Queue *[fQueueCount];
|
||||
if (!fQueues) {
|
||||
delete_area(fFrameArea);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < fQueueCount; i++) {
|
||||
fQueues[i] = new Queue(fStack);
|
||||
if (fQueues[i]->InitCheck() < B_OK) {
|
||||
fQueues[i] = new(std::nothrow) Queue(fStack);
|
||||
if (!fQueues[i] || fQueues[i]->InitCheck() < B_OK) {
|
||||
TRACE(("usb_uhci: cannot create queues\n"));
|
||||
delete_area(fFrameArea);
|
||||
return;
|
||||
@ -436,7 +458,7 @@ UHCI::~UHCI()
|
||||
delete [] fQueues;
|
||||
delete fRootHub;
|
||||
delete_area(fFrameArea);
|
||||
delete_sem(fLockSem);
|
||||
benaphore_destroy(&fUHCILock);
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
}
|
||||
@ -445,18 +467,14 @@ UHCI::~UHCI()
|
||||
bool
|
||||
UHCI::Lock()
|
||||
{
|
||||
if (atomic_add(&fLockAtom, 1) > 0)
|
||||
return acquire_sem(fLockSem) == B_OK;
|
||||
|
||||
return true;
|
||||
return (benaphore_lock(&fUHCILock) == B_OK);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UHCI::Unlock()
|
||||
{
|
||||
if (atomic_add(&fLockAtom, -1) > 1)
|
||||
release_sem(fLockSem);
|
||||
benaphore_unlock(&fUHCILock);
|
||||
}
|
||||
|
||||
|
||||
@ -490,8 +508,20 @@ UHCI::Start()
|
||||
}
|
||||
|
||||
fRootHubAddress = AllocateAddress();
|
||||
fRootHub = new UHCIRootHub(this, fRootHubAddress);
|
||||
fRootHub = new(std::nothrow) UHCIRootHub(this, fRootHubAddress);
|
||||
if (!fRootHub) {
|
||||
TRACE(("usb_uhci: no memory to allocate root hub\n"));
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (fRootHub->InitCheck() < B_OK) {
|
||||
TRACE(("usb_uhci: root hub could not be created\n"));
|
||||
delete fRootHub;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
SetRootHub(fRootHub);
|
||||
SetStack(fStack);
|
||||
|
||||
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
|
||||
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
|
||||
@ -511,7 +541,52 @@ UHCI::SubmitTransfer(Transfer *transfer)
|
||||
if (transfer->TransferPipe()->Type() == Pipe::Control)
|
||||
return SubmitRequest(transfer);
|
||||
|
||||
return B_ERROR;
|
||||
if (!transfer->Data() || transfer->DataLength() == 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
Pipe *pipe = transfer->TransferPipe();
|
||||
bool directionIn = (pipe->Direction() == Pipe::In);
|
||||
|
||||
uhci_td *firstDescriptor = NULL;
|
||||
uhci_td *lastDescriptor = NULL;
|
||||
status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
|
||||
&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
|
||||
transfer->DataLength());
|
||||
|
||||
if (result < B_OK)
|
||||
return result;
|
||||
if (!firstDescriptor || !lastDescriptor)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
lastDescriptor->status |= TD_STATUS_IOC;
|
||||
lastDescriptor->link_phy = TD_TERMINATE;
|
||||
lastDescriptor->link_log = 0;
|
||||
|
||||
if (!directionIn) {
|
||||
WriteDescriptorChain(firstDescriptor, transfer->Data(),
|
||||
transfer->DataLength());
|
||||
}
|
||||
|
||||
Queue *queue = fQueues[3];
|
||||
if (pipe->Type() == Pipe::Interrupt)
|
||||
queue = fQueues[2];
|
||||
|
||||
result = AddPendingTransfer(transfer, queue, firstDescriptor,
|
||||
firstDescriptor, lastDescriptor, directionIn);
|
||||
if (result < B_OK) {
|
||||
TRACE(("usb_uhci: failed to add pending transfer\n"));
|
||||
FreeDescriptorChain(firstDescriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = queue->AppendDescriptor(firstDescriptor);
|
||||
if (result < B_OK) {
|
||||
TRACE(("usb_uhci: failed to append descriptors\n"));
|
||||
FreeDescriptorChain(firstDescriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
return EINPROGRESS;
|
||||
}
|
||||
|
||||
|
||||
@ -544,11 +619,11 @@ UHCI::SubmitRequest(Transfer *transfer)
|
||||
statusDescriptor->link_log = 0;
|
||||
|
||||
uhci_td *dataDescriptor = NULL;
|
||||
if (transfer->Buffer() && transfer->BufferLength() > 0) {
|
||||
if (transfer->Data() && transfer->DataLength() > 0) {
|
||||
uhci_td *lastDescriptor = NULL;
|
||||
status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
|
||||
&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
|
||||
transfer->BufferLength());
|
||||
transfer->DataLength());
|
||||
|
||||
if (result < B_OK) {
|
||||
FreeDescriptor(setupDescriptor);
|
||||
@ -557,8 +632,8 @@ UHCI::SubmitRequest(Transfer *transfer)
|
||||
}
|
||||
|
||||
if (!directionIn) {
|
||||
WriteDescriptorChain(dataDescriptor, transfer->Buffer(),
|
||||
transfer->BufferLength());
|
||||
WriteDescriptorChain(dataDescriptor, transfer->Data(),
|
||||
transfer->DataLength());
|
||||
}
|
||||
|
||||
LinkDescriptors(setupDescriptor, dataDescriptor);
|
||||
@ -568,17 +643,22 @@ UHCI::SubmitRequest(Transfer *transfer)
|
||||
LinkDescriptors(setupDescriptor, statusDescriptor);
|
||||
}
|
||||
|
||||
AddPendingTransfer(transfer, fQueues[1], setupDescriptor, dataDescriptor,
|
||||
statusDescriptor, directionIn);
|
||||
status_t result = AddPendingTransfer(transfer, fQueues[1], setupDescriptor,
|
||||
dataDescriptor, statusDescriptor, directionIn);
|
||||
if (result < B_OK) {
|
||||
TRACE(("usb_uhci: failed to add pending transfer\n"));
|
||||
FreeDescriptorChain(setupDescriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
status_t result = fQueues[1]->AppendDescriptor(setupDescriptor);
|
||||
result = fQueues[1]->AppendDescriptor(setupDescriptor);
|
||||
if (result < B_OK) {
|
||||
TRACE(("usb_uhci: failed to append descriptors\n"));
|
||||
FreeDescriptorChain(setupDescriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
return EINPROGRESS;
|
||||
return EINPROGRESS;
|
||||
}
|
||||
|
||||
|
||||
@ -588,7 +668,10 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue,
|
||||
bool directionIn)
|
||||
{
|
||||
TRACE(("usb_uhci: add pending transfer\n"));
|
||||
transfer_data *data = new transfer_data();
|
||||
transfer_data *data = new(std::nothrow) transfer_data();
|
||||
if (!data)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
data->transfer = transfer;
|
||||
data->queue = queue;
|
||||
data->first_descriptor = firstDescriptor;
|
||||
@ -640,6 +723,8 @@ UHCI::FinishTransfers()
|
||||
TRACE(("usb_uhci: finishing transfers (first transfer: 0x%08x; last transfer: 0x%08x)\n", fFirstTransfer, fLastTransfer));
|
||||
transfer_data *lastTransfer = NULL;
|
||||
transfer_data *transfer = fFirstTransfer;
|
||||
Unlock();
|
||||
|
||||
while (transfer) {
|
||||
bool transferDone = false;
|
||||
uhci_td *descriptor = transfer->first_descriptor;
|
||||
@ -653,7 +738,7 @@ UHCI::FinishTransfers()
|
||||
}
|
||||
|
||||
if (status & TD_ERROR_MASK) {
|
||||
TRACE(("usb_uhci: td (0x%08x) error: 0x%08x\n", descriptor->this_phy, status));
|
||||
TRACE_ERROR(("usb_uhci: td (0x%08x) error: 0x%08x\n", descriptor->this_phy, status));
|
||||
// an error occured. we have to remove the
|
||||
// transfer from the queue and clean up
|
||||
transfer->queue->RemoveDescriptors(transfer->first_descriptor,
|
||||
@ -675,12 +760,10 @@ UHCI::FinishTransfers()
|
||||
// data to read out
|
||||
TRACE(("usb_uhci: reading incoming data buffer to transfer 0x%08x\n", transfer));
|
||||
size_t length = ReadDescriptorChain(transfer->data_descriptor,
|
||||
transfer->transfer->Buffer(),
|
||||
transfer->transfer->BufferLength());
|
||||
transfer->transfer->Data(),
|
||||
transfer->transfer->DataLength());
|
||||
|
||||
size_t *actualLength = transfer->transfer->ActualLength();
|
||||
if (actualLength)
|
||||
*actualLength = length;
|
||||
*(transfer->transfer->ActualLength()) = length;
|
||||
}
|
||||
|
||||
FreeDescriptorChain(transfer->first_descriptor);
|
||||
@ -695,17 +778,21 @@ UHCI::FinishTransfers()
|
||||
|
||||
if (transferDone) {
|
||||
TRACE(("usb_uhci: transfer (0x%08x) done\n", transfer));
|
||||
if (lastTransfer)
|
||||
lastTransfer->link = transfer->link;
|
||||
if (Lock()) {
|
||||
if (lastTransfer)
|
||||
lastTransfer->link = transfer->link;
|
||||
|
||||
if (transfer == fFirstTransfer)
|
||||
fFirstTransfer = transfer->link;
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
if (transfer == fFirstTransfer)
|
||||
fFirstTransfer = transfer->link;
|
||||
if (transfer == fLastTransfer)
|
||||
fLastTransfer = lastTransfer;
|
||||
|
||||
transfer_data *next = transfer->link;
|
||||
delete transfer;
|
||||
transfer = next;
|
||||
transfer_data *next = transfer->link;
|
||||
delete transfer;
|
||||
transfer = next;
|
||||
|
||||
Unlock();
|
||||
}
|
||||
} else {
|
||||
TRACE(("usb_uhci: transfer (0x%08x) not done\n", transfer));
|
||||
lastTransfer = transfer;
|
||||
@ -906,7 +993,13 @@ UHCI::AddTo(Stack &stack)
|
||||
TRACE(("usb_uhci: AddTo(): setting up hardware\n"));
|
||||
|
||||
bool found = false;
|
||||
pci_info *item = new pci_info;
|
||||
pci_info *item = new(std::nothrow) pci_info;
|
||||
if (!item) {
|
||||
sPCIModule = NULL;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
|
||||
//class_base = 0C (serial bus) class_sub = 03 (usb) prog_int: 00 (UHCI)
|
||||
if (item->class_base == 0x0C && item->class_sub == 0x03
|
||||
@ -918,7 +1011,14 @@ UHCI::AddTo(Stack &stack)
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci: AddTo(): found at IRQ %u\n", item->u.h0.interrupt_line));
|
||||
UHCI *bus = new UHCI(item, &stack);
|
||||
UHCI *bus = new(std::nothrow) UHCI(item, &stack);
|
||||
if (!bus) {
|
||||
delete item;
|
||||
sPCIModule = NULL;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (bus->InitCheck() < B_OK) {
|
||||
TRACE(("usb_uhci: AddTo(): InitCheck() failed 0x%08x\n", bus->InitCheck()));
|
||||
delete bus;
|
||||
@ -970,8 +1070,11 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, int32 bufferSize)
|
||||
|
||||
result->link_phy = 0;
|
||||
result->link_log = NULL;
|
||||
if (bufferSize <= 0)
|
||||
if (bufferSize <= 0) {
|
||||
result->buffer_log = NULL;
|
||||
result->buffer_phy = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fStack->AllocateChunk(&result->buffer_log, &result->buffer_phy,
|
||||
bufferSize) < B_OK) {
|
||||
@ -991,7 +1094,7 @@ UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor,
|
||||
int32 packetSize = pipe->MaxPacketSize();
|
||||
int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
|
||||
|
||||
bool dataToggle = true;
|
||||
bool dataToggle = pipe->DataToggle();
|
||||
uhci_td *firstDescriptor = NULL;
|
||||
uhci_td *lastDescriptor = *_firstDescriptor;
|
||||
for (int32 i = 0; i < descriptorCount; i++) {
|
||||
@ -1017,6 +1120,7 @@ UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor,
|
||||
firstDescriptor = descriptor;
|
||||
}
|
||||
|
||||
pipe->SetDataToggle(dataToggle);
|
||||
*_firstDescriptor = firstDescriptor;
|
||||
*_lastDescriptor = lastDescriptor;
|
||||
return B_OK;
|
||||
@ -1029,7 +1133,6 @@ UHCI::FreeDescriptor(uhci_td *descriptor)
|
||||
if (!descriptor)
|
||||
return;
|
||||
|
||||
return;
|
||||
if (descriptor->buffer_log) {
|
||||
fStack->FreeChunk(descriptor->buffer_log,
|
||||
(void *)descriptor->buffer_phy, descriptor->buffer_size);
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "usb_p.h"
|
||||
#include "uhci_hardware.h"
|
||||
#include <lock.h>
|
||||
|
||||
struct pci_info;
|
||||
struct pci_module_info;
|
||||
@ -45,10 +46,7 @@ private:
|
||||
uhci_qh *fQueueHead;
|
||||
uhci_td *fStrayDescriptor;
|
||||
uhci_td *fQueueTop;
|
||||
|
||||
// Benaphore locking
|
||||
sem_id fLockSem;
|
||||
int32 fLockAtom;
|
||||
benaphore fLock;
|
||||
};
|
||||
|
||||
|
||||
@ -133,10 +131,7 @@ static pci_module_info *sPCIModule;
|
||||
uint32 fRegisterBase;
|
||||
pci_info *fPCIInfo;
|
||||
Stack *fStack;
|
||||
|
||||
// Benaphore locking
|
||||
sem_id fLockSem;
|
||||
int32 fLockAtom;
|
||||
benaphore fUHCILock;
|
||||
|
||||
// Frame list memory
|
||||
area_id fFrameArea;
|
||||
|
@ -115,6 +115,7 @@ typedef struct
|
||||
#define TD_DEPTH_FIRST 0x4
|
||||
#define TD_TERMINATE 0x1
|
||||
#define TD_ERROR_MASK 0x7e0000
|
||||
#define TD_LINK_MASK 0xfffffff0
|
||||
|
||||
//Represents a Queue Head (QH)
|
||||
|
||||
@ -126,7 +127,6 @@ typedef struct
|
||||
// Software part
|
||||
addr_t this_phy; //The physical pointer to this address
|
||||
void * link_log; //Link to the next TD/QH logical
|
||||
void * element_log; //
|
||||
} uhci_qh;
|
||||
|
||||
#define QH_TERMINATE 0x1
|
||||
@ -143,11 +143,10 @@ typedef struct
|
||||
#define RH_SET_CONFIG 9
|
||||
|
||||
//Descriptors (in usb_request_data->Value)
|
||||
#define RH_DEVICE_DESCRIPTOR ( 1 << 8 )
|
||||
#define RH_CONFIG_DESCRIPTOR ( 2 << 8 )
|
||||
#define RH_INTERFACE_DESCRIPTOR ( 4 << 8 )
|
||||
#define RH_ENDPOINT_DESCRIPTOR ( 5 << 8 )
|
||||
#define RH_HUB_DESCRIPTOR ( 0x29 << 8 )
|
||||
#define RH_DEVICE_DESCRIPTOR (0x01 << 8)
|
||||
#define RH_CONFIG_DESCRIPTOR (0x02 << 8)
|
||||
#define RH_STRING_DESCRIPTOR (0x03 << 8)
|
||||
#define RH_HUB_DESCRIPTOR (0x29 << 8)
|
||||
|
||||
//Hub/Portstatus buffer
|
||||
typedef struct
|
||||
|
@ -19,75 +19,114 @@
|
||||
#endif
|
||||
|
||||
|
||||
usb_device_descriptor uhci_devd =
|
||||
static usb_device_descriptor sUHCIRootHubDevice =
|
||||
{
|
||||
0x12, //Descriptor size
|
||||
USB_DESCRIPTOR_DEVICE, //Type of descriptor
|
||||
0x110, //USB 1.1
|
||||
0x09, //Hub type
|
||||
0, //Subclass
|
||||
0, //Protocol
|
||||
64, //Max packet size
|
||||
0, //Vendor
|
||||
0, //Product
|
||||
0x110, //Version
|
||||
1, 2, 0, //Other data
|
||||
1 //Number of configurations
|
||||
18, // Descriptor length
|
||||
USB_DESCRIPTOR_DEVICE, // Descriptor type
|
||||
0x110, // USB 1.1
|
||||
0x09, // Class (9 = Hub)
|
||||
0, // Subclass
|
||||
0, // Protocol
|
||||
64, // Max packet size on endpoint 0
|
||||
0, // Vendor ID
|
||||
0, // Product ID
|
||||
0x110, // Version
|
||||
1, // Index of manufacturer string
|
||||
2, // Index of product string
|
||||
0, // Index of serial number string
|
||||
1 // Number of configurations
|
||||
};
|
||||
|
||||
|
||||
usb_configuration_descriptor uhci_confd =
|
||||
struct uhci_root_hub_configuration_s {
|
||||
usb_configuration_descriptor configuration;
|
||||
usb_interface_descriptor interface;
|
||||
usb_endpoint_descriptor endpoint;
|
||||
usb_hub_descriptor hub;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
static uhci_root_hub_configuration_s sUHCIRootHubConfig =
|
||||
{
|
||||
0x09, //Size
|
||||
USB_DESCRIPTOR_CONFIGURATION,
|
||||
25, //Total size (taken from BSD source)
|
||||
1, //Number interfaces
|
||||
1, //Value of configuration
|
||||
0, //Number of configuration
|
||||
0x40, //Self powered
|
||||
0 //Max power (0, because of self power)
|
||||
{ // configuration descriptor
|
||||
9, // Descriptor length
|
||||
USB_DESCRIPTOR_CONFIGURATION, // Descriptor type
|
||||
34, // Total length of configuration (including
|
||||
// interface, endpoint and hub descriptors)
|
||||
1, // Number of interfaces
|
||||
1, // Value of this configuration
|
||||
0, // Index of configuration string
|
||||
0x40, // Attributes (0x40 = self powered)
|
||||
0 // Max power (0, since self powered)
|
||||
},
|
||||
|
||||
{ // interface descriptor
|
||||
9, // Descriptor length
|
||||
USB_DESCRIPTOR_INTERFACE, // Descriptor type
|
||||
0, // Interface number
|
||||
0, // Alternate setting
|
||||
1, // Number of endpoints
|
||||
0x09, // Interface class (9 = Hub)
|
||||
0, // Interface subclass
|
||||
0, // Interface protocol
|
||||
0, // Index of interface string
|
||||
},
|
||||
|
||||
{ // endpoint descriptor
|
||||
7, // Descriptor length
|
||||
USB_DESCRIPTOR_ENDPOINT, // Descriptor type
|
||||
USB_REQTYPE_DEVICE_IN | 1, // Endpoint address (first in IN endpoint)
|
||||
0x03, // Attributes (0x03 = interrupt endpoint)
|
||||
8, // Max packet size
|
||||
0xFF // Interval
|
||||
},
|
||||
|
||||
{ // hub descriptor
|
||||
9, // Descriptor length (including
|
||||
// deprecated power control mask)
|
||||
USB_DESCRIPTOR_HUB, // Descriptor type
|
||||
2, // Number of ports
|
||||
0x0000, // Hub characteristics
|
||||
50, // Power on to power good (in 2ms units)
|
||||
0, // Maximum current (in mA)
|
||||
0x00, // Both ports are removable
|
||||
0xff // Depricated power control mask
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
usb_interface_descriptor uhci_intd =
|
||||
{
|
||||
0x09, //Size
|
||||
USB_DESCRIPTOR_INTERFACE,
|
||||
0, //Interface number
|
||||
0, //Alternate setting
|
||||
1, //Num endpoints
|
||||
0x09, //Interface class
|
||||
0, //Interface subclass
|
||||
0, //Interface protocol
|
||||
0, //Interface
|
||||
struct uhci_root_hub_string_s {
|
||||
uint8 length;
|
||||
uint8 descriptor_type;
|
||||
uint16 unicode_string[12];
|
||||
};
|
||||
|
||||
|
||||
usb_endpoint_descriptor uhci_endd =
|
||||
{
|
||||
0x07, //Size
|
||||
USB_DESCRIPTOR_ENDPOINT,
|
||||
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
||||
0x3, // Interrupt
|
||||
8, // Max packet size
|
||||
0xFF // Interval 256
|
||||
};
|
||||
static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
|
||||
{
|
||||
4, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
0x0409 // Supported language IDs (English US)
|
||||
},
|
||||
|
||||
{
|
||||
12, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
'H', 'A', 'I', 'K', 'U', ' ', // Characters
|
||||
'I', 'n', 'c', '.'
|
||||
},
|
||||
|
||||
usb_hub_descriptor uhci_hubd =
|
||||
{
|
||||
0x09, //Including deprecated powerctrlmask
|
||||
USB_DESCRIPTOR_HUB,
|
||||
2, //Number of ports
|
||||
0x02 | 0x01, //Hub characteristics FIXME
|
||||
50, //Power on to power good
|
||||
0, // Current
|
||||
0x00 //Both ports are removable
|
||||
{
|
||||
26, // Descriptor length
|
||||
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||
'U', 'H', 'C', 'I', ' ', 'R', // Characters
|
||||
'o', 'o', 't', 'H', 'u', 'b'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
|
||||
: Hub(uhci, NULL, uhci_devd, devicenum, false)
|
||||
: Hub(uhci, NULL, sUHCIRootHubDevice, devicenum, false)
|
||||
{
|
||||
fUHCI = uhci;
|
||||
}
|
||||
@ -100,14 +139,14 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
|
||||
|
||||
status_t result = B_ERROR;
|
||||
switch(request->Request) {
|
||||
switch (request->Request) {
|
||||
case RH_GET_STATUS:
|
||||
if (request->Index == 0) {
|
||||
// Get the hub status -- everything as 0 means all-right
|
||||
memset(transfer->Buffer(), 0, sizeof(get_status_buffer));
|
||||
memset(transfer->Data(), 0, sizeof(get_status_buffer));
|
||||
result = B_OK;
|
||||
break;
|
||||
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
|
||||
// This port doesn't exist
|
||||
result = EINVAL;
|
||||
break;
|
||||
@ -115,11 +154,11 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
|
||||
// Get port status
|
||||
UpdatePortStatus();
|
||||
memcpy(transfer->Buffer(),
|
||||
memcpy(transfer->Data(),
|
||||
(void *)&fPortStatus[request->Index - 1],
|
||||
transfer->BufferLength());
|
||||
transfer->DataLength());
|
||||
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
*(transfer->ActualLength()) = transfer->DataLength();
|
||||
result = B_OK;
|
||||
break;
|
||||
|
||||
@ -136,37 +175,54 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
case RH_GET_DESCRIPTOR:
|
||||
TRACE(("usb_uhci_roothub: rh_submit_packet GET_DESC: %d\n", request->Value));
|
||||
|
||||
switch (request->Value) {
|
||||
case RH_DEVICE_DESCRIPTOR:
|
||||
memcpy(transfer->Buffer(), (void *)&uhci_devd,
|
||||
transfer->BufferLength());
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
switch (request->Value & 0xff00) {
|
||||
case RH_DEVICE_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(usb_device_descriptor),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
result = B_OK;
|
||||
break;
|
||||
case RH_CONFIG_DESCRIPTOR:
|
||||
memcpy(transfer->Buffer(), (void *)&uhci_confd,
|
||||
transfer->BufferLength());
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
}
|
||||
|
||||
case RH_CONFIG_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(uhci_root_hub_configuration_s),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
result = B_OK;
|
||||
break;
|
||||
case RH_INTERFACE_DESCRIPTOR:
|
||||
memcpy(transfer->Buffer(), (void *)&uhci_intd,
|
||||
transfer->BufferLength());
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
result = B_OK ;
|
||||
break;
|
||||
case RH_ENDPOINT_DESCRIPTOR:
|
||||
memcpy(transfer->Buffer(), (void *)&uhci_endd,
|
||||
transfer->BufferLength());
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
result = B_OK ;
|
||||
break;
|
||||
case RH_HUB_DESCRIPTOR:
|
||||
memcpy(transfer->Buffer(), (void *)&uhci_hubd,
|
||||
transfer->BufferLength());
|
||||
*(transfer->ActualLength()) = transfer->BufferLength();
|
||||
}
|
||||
|
||||
case RH_STRING_DESCRIPTOR: {
|
||||
uint8 index = request->Value & 0x00ff;
|
||||
if (index > 2) {
|
||||
*(transfer->ActualLength()) = 0;
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t length = MIN(sUHCIRootHubStrings[index].length,
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case RH_HUB_DESCRIPTOR: {
|
||||
size_t length = MIN(sizeof(usb_hub_descriptor),
|
||||
transfer->DataLength());
|
||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
||||
length);
|
||||
*(transfer->ActualLength()) = length;
|
||||
result = B_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result = EINVAL;
|
||||
break;
|
||||
@ -183,7 +239,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE no hub changes!\n"));
|
||||
result = EINVAL;
|
||||
break;
|
||||
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
|
||||
// Invalid port number
|
||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE invalid port!\n"));
|
||||
result = EINVAL;
|
||||
@ -217,7 +273,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
TRACE(("usb_uhci_roothub: RH_SET_FEATURE no hub changes!\n"));
|
||||
result = EINVAL;
|
||||
break;
|
||||
} else if (request->Index > uhci_hubd.bNbrPorts) {
|
||||
} else if (request->Index > sUHCIRootHubConfig.hub.bNbrPorts) {
|
||||
// Invalid port number
|
||||
TRACE(("usb_uhci_roothub: RH_SET_FEATURE invalid port!\n"));
|
||||
result = EINVAL;
|
||||
@ -256,7 +312,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
void
|
||||
UHCIRootHub::UpdatePortStatus()
|
||||
{
|
||||
for (int32 i = 0; i < uhci_hubd.bNbrPorts; i++) {
|
||||
for (int32 i = 0; i < sUHCIRootHubConfig.hub.bNbrPorts; i++) {
|
||||
uint16 newStatus = 0;
|
||||
uint16 newChange = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user