* Fix off-by-one error in port number which caused full- or lowspeed devices

behind highspeed hubs with multiple transaction translators not to work.
* The parent hub isn't necessarily the one providing the transaction translator
  for a full- or lowspeed device. Therefore we need to inherit the hub/port
  addresses to lower devices unless we are a highspeed hub that might be the
  actual provider of the transaction translator. This logic error caused full-
  and lowspeed devices not to work if they were behind a fullspeed hub that
  itself was behind a highspeed hub.

This fixes bugs #1889 and #2501.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26552 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2008-07-21 22:46:16 +00:00
parent e36b6d3e2c
commit a524312842
7 changed files with 54 additions and 38 deletions

View File

@ -112,7 +112,8 @@ BusManager::FreeAddress(int8 address)
Device *
BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
BusManager::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
usb_speed speed)
{
// Check if there is a free entry in the device map (for the device number)
int8 deviceAddress = AllocateAddress();
@ -123,7 +124,7 @@ BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
TRACE(("USB BusManager: setting device address to %d\n", deviceAddress));
ControlPipe *defaultPipe = _GetDefaultPipe(speed);
defaultPipe->SetHubInfo(parent->DeviceAddress(), port);
defaultPipe->SetHubInfo(hubAddress, hubPort);
if (!defaultPipe) {
TRACE_ERROR(("USB BusManager: error getting the default pipe for speed %d\n", (int)speed));
@ -161,8 +162,8 @@ BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
// Create a temporary pipe with the new address
ControlPipe pipe(fRootObject);
pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0,
parent->DeviceAddress(), port);
pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, hubAddress,
hubPort);
// Get the device descriptor
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
@ -200,8 +201,8 @@ BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
// Create a new instance based on the type (Hub or Device)
if (deviceDescriptor.device_class == 0x09) {
TRACE(("USB BusManager: creating new hub\n"));
Hub *hub = new(std::nothrow) Hub(parent, port, deviceDescriptor,
deviceAddress, speed, false);
Hub *hub = new(std::nothrow) Hub(parent, hubAddress, hubPort,
deviceDescriptor, deviceAddress, speed, false);
if (!hub) {
TRACE_ERROR(("USB BusManager: no memory to allocate hub\n"));
FreeAddress(deviceAddress);
@ -219,8 +220,8 @@ BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
}
TRACE(("USB BusManager: creating new device\n"));
Device *device = new(std::nothrow) Device(parent, port, deviceDescriptor,
deviceAddress, speed, false);
Device *device = new(std::nothrow) Device(parent, hubAddress, hubPort,
deviceDescriptor, deviceAddress, speed, false);
if (!device) {
TRACE_ERROR(("USB BusManager: no memory to allocate device\n"));
FreeAddress(deviceAddress);

View File

@ -10,8 +10,9 @@
#include "usb_p.h"
Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc,
int8 deviceAddress, usb_speed speed, bool isRootHub)
Device::Device(Object *parent, int8 hubAddress, uint8 hubPort,
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
bool isRootHub)
: Object(parent),
fDeviceDescriptor(desc),
fInitOK(false),
@ -21,6 +22,7 @@ Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc,
fCurrentConfiguration(NULL),
fSpeed(speed),
fDeviceAddress(deviceAddress),
fHubAddress(hubAddress),
fHubPort(hubPort)
{
TRACE(("USB Device %d: creating device\n", fDeviceAddress));
@ -31,11 +33,8 @@ Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc,
return;
}
int8 hubAddress = 0;
if (parent->Type() & USB_OBJECT_HUB)
hubAddress = ((Hub *)parent)->DeviceAddress();
fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default,
fDeviceDescriptor.max_packet_size_0, 0, hubAddress, fHubPort);
fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort);
// Get the device descriptor
// We already have a part of it, but we want it all
@ -436,10 +435,6 @@ Device::SetConfigurationAt(uint8 index)
void
Device::InitEndpoints(int32 interfaceIndex)
{
int8 hubAddress = 0;
if (Parent() && (Parent()->Type() & USB_OBJECT_HUB))
hubAddress = ((Hub *)Parent())->DeviceAddress();
for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
continue;
@ -475,7 +470,7 @@ Device::InitEndpoints(int32 interfaceIndex)
pipe->InitCommon(fDeviceAddress,
endpoint->descr->endpoint_address & 0x0f,
fSpeed, direction, endpoint->descr->max_packet_size,
endpoint->descr->interval, hubAddress, fHubPort);
endpoint->descr->interval, fHubAddress, fHubPort);
endpoint->handle = pipe->USBID();
}
}

View File

@ -11,9 +11,11 @@
#include <stdio.h>
Hub::Hub(Object *parent, int8 hubPort, usb_device_descriptor &desc,
int8 deviceAddress, usb_speed speed, bool isRootHub)
: Device(parent, hubPort, desc, deviceAddress, speed, isRootHub),
Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort,
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
bool isRootHub)
: Device(parent, hubAddress, hubPort, desc, deviceAddress, speed,
isRootHub),
fInterruptPipe(NULL)
{
TRACE(("USB Hub %d: creating hub\n", DeviceAddress()));
@ -61,16 +63,16 @@ Hub::Hub(Object *parent, int8 hubPort, usb_device_descriptor &desc,
fHubDescriptor.num_ports = USB_MAX_PORT_COUNT;
}
Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle);
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) {
usb_interface_list *list = Configuration()->interface;
Object *object = GetStack()->GetObject(list->active->endpoint[0].handle);
if (object && (object->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0) {
fInterruptPipe = (InterruptPipe *)object;
fInterruptPipe->QueueInterrupt(fInterruptStatus,
sizeof(fInterruptStatus), InterruptCallback, this);
} else {
TRACE_ERROR(("USB Hub %d: no interrupt pipe found\n", DeviceAddress()));
return;
}
fInterruptPipe = (InterruptPipe *)object;
fInterruptPipe->QueueInterrupt(fInterruptStatus, sizeof(fInterruptStatus),
InterruptCallback, this);
// Wait some time before powering up the ports
if (!isRootHub)
snooze(USB_DELAY_HUB_POWER_UP);
@ -242,7 +244,19 @@ Hub::Explore(change_item **changeList)
if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
speed = USB_SPEED_HIGHSPEED;
Device *newDevice = GetBusManager()->AllocateDevice(this, i, speed);
// either let the device inherit our addresses (if we are
// already potentially using a transaction translator) or set
// ourselfs as the hub when we might become the transaction
// translator for the device.
int8 hubAddress = HubAddress();
uint8 hubPort = HubPort();
if (Speed() == USB_SPEED_HIGHSPEED) {
hubAddress = DeviceAddress();
hubPort = i + 1;
}
Device *newDevice = GetBusManager()->AllocateDevice(this,
hubAddress, hubPort, speed);
if (newDevice) {
newDevice->Changed(changeList, true);

View File

@ -180,7 +180,8 @@ virtual status_t InitCheck();
void FreeAddress(int8 address);
Device *AllocateDevice(Hub *parent,
uint8 port, usb_speed speed);
int8 hubAddress, uint8 hubPort,
usb_speed speed);
void FreeDevice(Device *device);
virtual status_t Start();
@ -270,6 +271,7 @@ virtual uint32 Type() { return USB_OBJECT_PIPE; };
size_t MaxPacketSize() { return fMaxPacketSize; };
uint8 Interval() { return fInterval; };
// Hub port being the one-based logical port number on the hub
void SetHubInfo(int8 address, uint8 port);
int8 HubAddress() { return fHubAddress; };
uint8 HubPort() { return fHubPort; };
@ -419,7 +421,8 @@ private:
class Device : public Object {
public:
Device(Object *parent, int8 hubPort,
Device(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc,
int8 deviceAddress,
usb_speed speed, bool isRootHub);
@ -464,7 +467,8 @@ virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize,
Device *device);
int8 HubPort() const { return fHubPort; };
int8 HubAddress() const { return fHubAddress; };
uint8 HubPort() const { return fHubPort; };
// Convenience functions for standard requests
virtual status_t SetFeature(uint16 selector);
@ -482,14 +486,16 @@ private:
usb_configuration_info *fCurrentConfiguration;
usb_speed fSpeed;
int8 fDeviceAddress;
int8 fHubPort;
int8 fHubAddress;
uint8 fHubPort;
ControlPipe *fDefaultPipe;
};
class Hub : public Device {
public:
Hub(Object *parent, int8 hubPort,
Hub(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc,
int8 deviceAddress,
usb_speed speed, bool isRootHub);

View File

@ -122,7 +122,7 @@ static ehci_root_hub_string_s sEHCIRootHubStrings[3] = {
EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress)
: Hub(rootObject, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
: Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
sEHCIRootHubDevice, deviceAddress, USB_SPEED_HIGHSPEED, true)
{
}

View File

@ -124,7 +124,7 @@ static ohci_root_hub_string_s sOHCIRootHubStrings[3] = {
OHCIRootHub::OHCIRootHub(Object *rootObject, int8 deviceAddress)
: Hub(rootObject, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
: Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
sOHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true)
{
}

View File

@ -123,7 +123,7 @@ static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress)
: Hub(rootObject, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
: Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true)
{
}