* 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
@@ -112,7 +112,8 @@ BusManager::FreeAddress(int8 address)
Device * 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) // Check if there is a free entry in the device map (for the device number)
int8 deviceAddress = AllocateAddress(); 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)); TRACE(("USB BusManager: setting device address to %d\n", deviceAddress));
ControlPipe *defaultPipe = _GetDefaultPipe(speed); ControlPipe *defaultPipe = _GetDefaultPipe(speed);
defaultPipe->SetHubInfo(parent->DeviceAddress(), port); defaultPipe->SetHubInfo(hubAddress, hubPort);
if (!defaultPipe) { if (!defaultPipe) {
TRACE_ERROR(("USB BusManager: error getting the default pipe for speed %d\n", (int)speed)); 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 // Create a temporary pipe with the new address
ControlPipe pipe(fRootObject); ControlPipe pipe(fRootObject);
pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, hubAddress,
parent->DeviceAddress(), port); hubPort);
// Get the device descriptor // Get the device descriptor
// Just retrieve the first 8 bytes of the descriptor -> minimum supported // 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) // Create a new instance based on the type (Hub or Device)
if (deviceDescriptor.device_class == 0x09) { if (deviceDescriptor.device_class == 0x09) {
TRACE(("USB BusManager: creating new hub\n")); TRACE(("USB BusManager: creating new hub\n"));
Hub *hub = new(std::nothrow) Hub(parent, port, deviceDescriptor, Hub *hub = new(std::nothrow) Hub(parent, hubAddress, hubPort,
deviceAddress, speed, false); deviceDescriptor, deviceAddress, speed, false);
if (!hub) { if (!hub) {
TRACE_ERROR(("USB BusManager: no memory to allocate hub\n")); TRACE_ERROR(("USB BusManager: no memory to allocate hub\n"));
FreeAddress(deviceAddress); FreeAddress(deviceAddress);
@@ -219,8 +220,8 @@ BusManager::AllocateDevice(Hub *parent, uint8 port, usb_speed speed)
} }
TRACE(("USB BusManager: creating new device\n")); TRACE(("USB BusManager: creating new device\n"));
Device *device = new(std::nothrow) Device(parent, port, deviceDescriptor, Device *device = new(std::nothrow) Device(parent, hubAddress, hubPort,
deviceAddress, speed, false); deviceDescriptor, deviceAddress, speed, false);
if (!device) { if (!device) {
TRACE_ERROR(("USB BusManager: no memory to allocate device\n")); TRACE_ERROR(("USB BusManager: no memory to allocate device\n"));
FreeAddress(deviceAddress); FreeAddress(deviceAddress);
+6 -11
View File
@@ -10,8 +10,9 @@
#include "usb_p.h" #include "usb_p.h"
Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc, Device::Device(Object *parent, int8 hubAddress, uint8 hubPort,
int8 deviceAddress, usb_speed speed, bool isRootHub) usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
bool isRootHub)
: Object(parent), : Object(parent),
fDeviceDescriptor(desc), fDeviceDescriptor(desc),
fInitOK(false), fInitOK(false),
@@ -21,6 +22,7 @@ Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc,
fCurrentConfiguration(NULL), fCurrentConfiguration(NULL),
fSpeed(speed), fSpeed(speed),
fDeviceAddress(deviceAddress), fDeviceAddress(deviceAddress),
fHubAddress(hubAddress),
fHubPort(hubPort) fHubPort(hubPort)
{ {
TRACE(("USB Device %d: creating device\n", fDeviceAddress)); TRACE(("USB Device %d: creating device\n", fDeviceAddress));
@@ -31,11 +33,8 @@ Device::Device(Object *parent, int8 hubPort, usb_device_descriptor &desc,
return; return;
} }
int8 hubAddress = 0;
if (parent->Type() & USB_OBJECT_HUB)
hubAddress = ((Hub *)parent)->DeviceAddress();
fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default, 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 // Get the device descriptor
// We already have a part of it, but we want it all // We already have a part of it, but we want it all
@@ -436,10 +435,6 @@ Device::SetConfigurationAt(uint8 index)
void void
Device::InitEndpoints(int32 interfaceIndex) 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++) { for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
if (interfaceIndex >= 0 && j != (size_t)interfaceIndex) if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
continue; continue;
@@ -475,7 +470,7 @@ Device::InitEndpoints(int32 interfaceIndex)
pipe->InitCommon(fDeviceAddress, pipe->InitCommon(fDeviceAddress,
endpoint->descr->endpoint_address & 0x0f, endpoint->descr->endpoint_address & 0x0f,
fSpeed, direction, endpoint->descr->max_packet_size, fSpeed, direction, endpoint->descr->max_packet_size,
endpoint->descr->interval, hubAddress, fHubPort); endpoint->descr->interval, fHubAddress, fHubPort);
endpoint->handle = pipe->USBID(); endpoint->handle = pipe->USBID();
} }
} }
+26 -12
View File
@@ -11,9 +11,11 @@
#include <stdio.h> #include <stdio.h>
Hub::Hub(Object *parent, int8 hubPort, usb_device_descriptor &desc, Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort,
int8 deviceAddress, usb_speed speed, bool isRootHub) usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
: Device(parent, hubPort, desc, deviceAddress, speed, isRootHub), bool isRootHub)
: Device(parent, hubAddress, hubPort, desc, deviceAddress, speed,
isRootHub),
fInterruptPipe(NULL) fInterruptPipe(NULL)
{ {
TRACE(("USB Hub %d: creating hub\n", DeviceAddress())); TRACE(("USB Hub %d: creating hub\n", DeviceAddress()));
@@ -61,15 +63,15 @@ Hub::Hub(Object *parent, int8 hubPort, usb_device_descriptor &desc,
fHubDescriptor.num_ports = USB_MAX_PORT_COUNT; fHubDescriptor.num_ports = USB_MAX_PORT_COUNT;
} }
Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle); usb_interface_list *list = Configuration()->interface;
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) { Object *object = GetStack()->GetObject(list->active->endpoint[0].handle);
TRACE_ERROR(("USB Hub %d: no interrupt pipe found\n", DeviceAddress())); if (object && (object->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0) {
return;
}
fInterruptPipe = (InterruptPipe *)object; fInterruptPipe = (InterruptPipe *)object;
fInterruptPipe->QueueInterrupt(fInterruptStatus, sizeof(fInterruptStatus), fInterruptPipe->QueueInterrupt(fInterruptStatus,
InterruptCallback, this); sizeof(fInterruptStatus), InterruptCallback, this);
} else {
TRACE_ERROR(("USB Hub %d: no interrupt pipe found\n", DeviceAddress()));
}
// Wait some time before powering up the ports // Wait some time before powering up the ports
if (!isRootHub) if (!isRootHub)
@@ -242,7 +244,19 @@ Hub::Explore(change_item **changeList)
if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED) if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
speed = USB_SPEED_HIGHSPEED; 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) { if (newDevice) {
newDevice->Changed(changeList, true); newDevice->Changed(changeList, true);
+11 -5
View File
@@ -180,7 +180,8 @@ virtual status_t InitCheck();
void FreeAddress(int8 address); void FreeAddress(int8 address);
Device *AllocateDevice(Hub *parent, Device *AllocateDevice(Hub *parent,
uint8 port, usb_speed speed); int8 hubAddress, uint8 hubPort,
usb_speed speed);
void FreeDevice(Device *device); void FreeDevice(Device *device);
virtual status_t Start(); virtual status_t Start();
@@ -270,6 +271,7 @@ virtual uint32 Type() { return USB_OBJECT_PIPE; };
size_t MaxPacketSize() { return fMaxPacketSize; }; size_t MaxPacketSize() { return fMaxPacketSize; };
uint8 Interval() { return fInterval; }; uint8 Interval() { return fInterval; };
// Hub port being the one-based logical port number on the hub
void SetHubInfo(int8 address, uint8 port); void SetHubInfo(int8 address, uint8 port);
int8 HubAddress() { return fHubAddress; }; int8 HubAddress() { return fHubAddress; };
uint8 HubPort() { return fHubPort; }; uint8 HubPort() { return fHubPort; };
@@ -419,7 +421,8 @@ private:
class Device : public Object { class Device : public Object {
public: public:
Device(Object *parent, int8 hubPort, Device(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc, usb_device_descriptor &desc,
int8 deviceAddress, int8 deviceAddress,
usb_speed speed, bool isRootHub); usb_speed speed, bool isRootHub);
@@ -464,7 +467,8 @@ virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize, uint32 *index, size_t bufferSize,
Device *device); Device *device);
int8 HubPort() const { return fHubPort; }; int8 HubAddress() const { return fHubAddress; };
uint8 HubPort() const { return fHubPort; };
// Convenience functions for standard requests // Convenience functions for standard requests
virtual status_t SetFeature(uint16 selector); virtual status_t SetFeature(uint16 selector);
@@ -482,14 +486,16 @@ private:
usb_configuration_info *fCurrentConfiguration; usb_configuration_info *fCurrentConfiguration;
usb_speed fSpeed; usb_speed fSpeed;
int8 fDeviceAddress; int8 fDeviceAddress;
int8 fHubPort; int8 fHubAddress;
uint8 fHubPort;
ControlPipe *fDefaultPipe; ControlPipe *fDefaultPipe;
}; };
class Hub : public Device { class Hub : public Device {
public: public:
Hub(Object *parent, int8 hubPort, Hub(Object *parent, int8 hubAddress,
uint8 hubPort,
usb_device_descriptor &desc, usb_device_descriptor &desc,
int8 deviceAddress, int8 deviceAddress,
usb_speed speed, bool isRootHub); usb_speed speed, bool isRootHub);
+1 -1
View File
@@ -122,7 +122,7 @@ static ehci_root_hub_string_s sEHCIRootHubStrings[3] = {
EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress) 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) sEHCIRootHubDevice, deviceAddress, USB_SPEED_HIGHSPEED, true)
{ {
} }
+1 -1
View File
@@ -124,7 +124,7 @@ static ohci_root_hub_string_s sOHCIRootHubStrings[3] = {
OHCIRootHub::OHCIRootHub(Object *rootObject, int8 deviceAddress) 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) sOHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true)
{ {
} }
+1 -1
View File
@@ -123,7 +123,7 @@ static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress) 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) sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true)
{ {
} }