* Fixed setting configurations (need to use the configuration_value instead of the index of course)

* Fixed reported power status of the UHCI Root Hub
* Added preservation of the SOF_MODIFY register when doing a global reset of the UHC
* Read out the actual length for outgoing transfers too
* Made actual length handling for transfers a bit safer and correct in respect to NULL packets
* Use short packet detect to handle short packets
* First step at implementing the hub interrupt

Since the devices are now configured correctly, some bulk transfers actually work. Also my hub now reports its status correctly.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18506 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2006-08-13 14:48:10 +00:00
parent bfb0aa18d3
commit d83f3c1a45
9 changed files with 139 additions and 80 deletions
@@ -325,7 +325,7 @@ Device::SetConfigurationAt(uint8 index)
status_t result = SendRequest( status_t result = SendRequest(
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
USB_REQUEST_SET_CONFIGURATION, // request USB_REQUEST_SET_CONFIGURATION, // request
index, // value fConfigurations[index].descr->configuration_value, // value
0, // index 0, // index
0, // length 0, // length
NULL, // buffer NULL, // buffer
+26 -21
View File
@@ -34,27 +34,8 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
for (int32 i = 0; i < 8; i++) for (int32 i = 0; i < 8; i++)
fChildren[i] = NULL; fChildren[i] = NULL;
if (fDeviceDescriptor.device_class != 9 if (fDeviceDescriptor.device_class != 9) {
|| fDeviceDescriptor.device_subclass != 0 TRACE(("USB Hub: wrong class! Bailing out\n"));
|| fDeviceDescriptor.device_protocol != 0) {
TRACE(("USB Hub: wrong class/subclass/protocol! Bailing out\n"));
return;
}
if (Configuration()->descr->number_interfaces > 1) {
TRACE(("USB Hub: too many interfaces\n"));
return;
}
fInterruptInterface = Configuration()->interface->active->descr;
if (fInterruptInterface->num_endpoints > 1) {
TRACE(("USB Hub: too many endpoints\n"));
return;
}
fInterruptEndpoint = Configuration()->interface->active->endpoint[0].descr;
if (fInterruptEndpoint->attributes != 0x03) { // interrupt endpoint
TRACE(("USB Hub: Not an interrupt endpoint\n"));
return; return;
} }
@@ -78,6 +59,19 @@ Hub::Hub(BusManager *bus, Device *parent, usb_device_descriptor &desc,
TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable)); TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable));
TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask)); TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask));
Pipe *pipe = (Pipe *)Configuration()->interface->active->endpoint[0].handle;
if (!pipe || pipe->Type() != Pipe::Interrupt) {
TRACE(("USB Hub: no interrupt pipe found\n"));
return;
}
fInterruptPipe = (InterruptPipe *)pipe;
fInterruptPipe->QueueInterrupt(fInterruptStatus, sizeof(fInterruptStatus),
InterruptCallback, this);
// Wait some time before powering up the ports
snooze(USB_DELAY_HUB_POWER_UP);
// Enable port power on all ports // Enable port power on all ports
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, status = SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
@@ -167,6 +161,9 @@ Hub::Explore()
if (result < B_OK) if (result < B_OK)
continue; continue;
if (DeviceAddress() > 1)
TRACE(("USB Hub (%d): port %d: status: 0x%04x; change: 0x%04x\n", DeviceAddress(), i, fPortStatus[i].status, fPortStatus[i].change));
if (fPortStatus[i].change & PORT_STATUS_CONNECTION) { if (fPortStatus[i].change & PORT_STATUS_CONNECTION) {
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
// new device attached! // new device attached!
@@ -230,6 +227,14 @@ Hub::Explore()
} }
void
Hub::InterruptCallback(void *cookie, uint32 status, void *data,
uint32 actualLength)
{
TRACE(("USB Hub: interrupt callback!\n"));
}
status_t status_t
Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
void *data, size_t dataLength, size_t *actualLength) void *data, size_t dataLength, size_t *actualLength)
@@ -13,8 +13,8 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
: fPipe(pipe), : fPipe(pipe),
fData(NULL), fData(NULL),
fDataLength(0), fDataLength(0),
fActualLength(NULL), fActualLengthPointer(NULL),
fOwnActualLength(0), fActualLength(0),
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR), fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
fCallback(NULL), fCallback(NULL),
fCallbackCookie(NULL), fCallbackCookie(NULL),
@@ -22,7 +22,6 @@ Transfer::Transfer(Pipe *pipe, bool synchronous)
fHostPrivate(NULL), fHostPrivate(NULL),
fRequestData(NULL) fRequestData(NULL)
{ {
fActualLength = &fOwnActualLength;
if (synchronous) { if (synchronous) {
fSem = create_sem(0, "USB Transfer"); fSem = create_sem(0, "USB Transfer");
set_sem_owner(fSem, B_SYSTEM_TEAM); set_sem_owner(fSem, B_SYSTEM_TEAM);
@@ -55,7 +54,7 @@ Transfer::SetData(uint8 *data, size_t dataLength)
void void
Transfer::SetActualLength(size_t *actualLength) Transfer::SetActualLength(size_t *actualLength)
{ {
fActualLength = actualLength; fActualLengthPointer = actualLength;
} }
@@ -92,13 +91,16 @@ Transfer::WaitForFinish()
void void
Transfer::Finished(uint32 status) Transfer::Finished(uint32 status, size_t actualLength)
{ {
fStatus = status; fStatus = status;
fActualLength = actualLength;
if (fActualLengthPointer)
*fActualLengthPointer = actualLength;
// Call the callback function ... // Call the callback function ...
if (fCallback) { if (fCallback) {
fCallback(fCallbackCookie, fStatus, fData, *fActualLength); fCallback(fCallbackCookie, fStatus, fData, fActualLength);
return; return;
} }
+9 -6
View File
@@ -361,6 +361,9 @@ virtual status_t GetDescriptor(uint8 descriptorType,
status_t UpdatePortStatus(uint8 index); status_t UpdatePortStatus(uint8 index);
status_t ResetPort(uint8 index); status_t ResetPort(uint8 index);
void Explore(); void Explore();
static void InterruptCallback(void *cookie,
uint32 status, void *data,
uint32 actualLength);
virtual void ReportDevice( virtual void ReportDevice(
usb_support_descriptor *supportDescriptors, usb_support_descriptor *supportDescriptors,
@@ -369,10 +372,10 @@ virtual void ReportDevice(
bool added); bool added);
private: private:
usb_interface_descriptor *fInterruptInterface; InterruptPipe *fInterruptPipe;
usb_endpoint_descriptor *fInterruptEndpoint;
usb_hub_descriptor fHubDescriptor; usb_hub_descriptor fHubDescriptor;
usb_port_status fInterruptStatus[8];
usb_port_status fPortStatus[8]; usb_port_status fPortStatus[8];
Device *fChildren[8]; Device *fChildren[8];
}; };
@@ -405,7 +408,7 @@ public:
size_t DataLength() { return fDataLength; }; size_t DataLength() { return fDataLength; };
void SetActualLength(size_t *actualLength); void SetActualLength(size_t *actualLength);
size_t *ActualLength() { return fActualLength; }; size_t *ActualLength() { return fActualLengthPointer; };
void SetHostPrivate(hostcontroller_priv *priv); void SetHostPrivate(hostcontroller_priv *priv);
hostcontroller_priv *HostPrivate() { return fHostPrivate; }; hostcontroller_priv *HostPrivate() { return fHostPrivate; };
@@ -414,15 +417,15 @@ public:
void *cookie); void *cookie);
status_t WaitForFinish(); status_t WaitForFinish();
void Finished(uint32 status); void Finished(uint32 status, size_t actualLength);
private: private:
// Data that is related to the transfer // Data that is related to the transfer
Pipe *fPipe; Pipe *fPipe;
uint8 *fData; uint8 *fData;
size_t fDataLength; size_t fDataLength;
size_t *fActualLength; size_t *fActualLengthPointer;
size_t fOwnActualLength; size_t fActualLength;
uint32 fStatus; uint32 fStatus;
usb_callback_func fCallback; usb_callback_func fCallback;
@@ -17,6 +17,7 @@
#define USB_MAX_AREAS 8 #define USB_MAX_AREAS 8
#define USB_DELAY_DEVICE_POWER_UP 300000 #define USB_DELAY_DEVICE_POWER_UP 300000
#define USB_DELAY_HUB_POWER_UP 200000
#define USB_DELAY_PORT_RESET 50000 #define USB_DELAY_PORT_RESET 50000
#define USB_DELAY_PORT_RESET_RECOVERY 250000 #define USB_DELAY_PORT_RESET_RECOVERY 250000
#define USB_DELAY_SET_ADDRESS_RETRY 200000 #define USB_DELAY_SET_ADDRESS_RETRY 200000
+71 -23
View File
@@ -751,31 +751,37 @@ UHCI::FinishTransfers()
transfer->queue->RemoveDescriptorChain( transfer->queue->RemoveDescriptorChain(
transfer->first_descriptor, transfer->first_descriptor,
transfer->last_descriptor); transfer->last_descriptor);
FreeDescriptorChain(transfer->first_descriptor); FreeDescriptorChain(transfer->first_descriptor);
transfer->transfer->Finished(callbackStatus); transfer->transfer->Finished(callbackStatus, 0);
transferDone = true; transferDone = true;
break; break;
} }
if (descriptor == transfer->last_descriptor) { // either all descriptors are done, or we have a short packet
if (descriptor == transfer->last_descriptor
|| (descriptor->status & TD_STATUS_ACTLEN_MASK)
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) {
TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy)); TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy));
// we got through without errors so we are finished // we got through without errors so we are finished
transfer->queue->RemoveDescriptorChain( transfer->queue->RemoveDescriptorChain(
transfer->first_descriptor, transfer->first_descriptor,
transfer->last_descriptor); transfer->last_descriptor);
size_t length = 0;
if (transfer->data_descriptor && transfer->incoming) { if (transfer->data_descriptor && transfer->incoming) {
// data to read out // data to read out
size_t length = ReadDescriptorChain( length = ReadDescriptorChain(
transfer->data_descriptor, transfer->data_descriptor,
transfer->transfer->Data(), transfer->transfer->Data(),
transfer->transfer->DataLength()); transfer->transfer->DataLength());
} else {
*(transfer->transfer->ActualLength()) = length; // read the actual length that was sent
length = ReadActualLength(transfer->first_descriptor);
} }
FreeDescriptorChain(transfer->first_descriptor); FreeDescriptorChain(transfer->first_descriptor);
transfer->transfer->Finished(B_OK); transfer->transfer->Finished(B_USB_STATUS_SUCCESS, length);
transferDone = true; transferDone = true;
break; break;
} }
@@ -813,10 +819,14 @@ UHCI::FinishTransfers()
void void
UHCI::GlobalReset() UHCI::GlobalReset()
{ {
uint8 sofValue = ReadReg8(UHCI_SOFMOD);
WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET); WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET);
snooze(100000); snooze(100000);
WriteReg16(UHCI_USBCMD, 0); WriteReg16(UHCI_USBCMD, 0);
snooze(10000); snooze(10000);
WriteReg8(UHCI_SOFMOD, sofValue);
} }
@@ -1077,7 +1087,7 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, int32 bufferSize)
} }
result->this_phy = (addr_t)physicalAddress; result->this_phy = (addr_t)physicalAddress;
result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS; result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS | TD_CONTROL_SPD;
if (pipe->Speed() == Pipe::LowSpeed) if (pipe->Speed() == Pipe::LowSpeed)
result->status |= TD_CONTROL_LOWSPEED; result->status |= TD_CONTROL_LOWSPEED;
@@ -1188,20 +1198,20 @@ UHCI::LinkDescriptors(uhci_td *first, uhci_td *second)
size_t size_t
UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer, UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
int32 bufferSize) size_t bufferLength)
{ {
size_t actualSize = 0; size_t actualLength = 0;
uhci_td *current = topDescriptor; uhci_td *current = topDescriptor;
while (current) { while (current) {
if (!current->buffer_log) if (!current->buffer_log)
break; break;
int32 length = min_c(current->buffer_size, bufferSize); size_t length = min_c(current->buffer_size, bufferLength);
memcpy(current->buffer_log, buffer, length); memcpy(current->buffer_log, buffer, length);
bufferSize -= length; bufferLength -= length;
actualSize += length; actualLength += length;
buffer += length; buffer += length;
if (current->link_phy & TD_TERMINATE) if (current->link_phy & TD_TERMINATE)
@@ -1210,31 +1220,31 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
current = (uhci_td *)current->link_log; current = (uhci_td *)current->link_log;
} }
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualSize)); TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualLength));
return actualSize; return actualLength;
} }
size_t size_t
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer, UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
int32 bufferSize) size_t bufferLength)
{ {
size_t actualSize = 0; size_t actualLength = 0;
uhci_td *current = topDescriptor; uhci_td *current = topDescriptor;
while (current) { while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
if (!current->buffer_log) if (!current->buffer_log)
break; break;
int32 length = (current->status & TD_STATUS_ACTLEN_MASK) + 1; size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
if (length == TD_STATUS_ACTLEN_NULL + 1) if (length == TD_STATUS_ACTLEN_NULL + 1)
length = 0; length = 0;
length = min_c(length, bufferSize); length = min_c(length, bufferLength);
memcpy(buffer, current->buffer_log, length); memcpy(buffer, current->buffer_log, length);
bufferSize -= length; bufferLength -= length;
actualSize += length; actualLength += length;
buffer += length; buffer += length;
if (current->link_phy & TD_TERMINATE) if (current->link_phy & TD_TERMINATE)
@@ -1243,8 +1253,39 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
current = (uhci_td *)current->link_log; current = (uhci_td *)current->link_log;
} }
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualSize)); TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualLength));
return actualSize; return actualLength;
}
size_t
UHCI::ReadActualLength(uhci_td *topDescriptor)
{
size_t actualLength = 0;
uhci_td *current = topDescriptor;
while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
TRACE(("usb_uhci: reading actual length from status 0x%08x\n", current->status));
size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
if (length == TD_STATUS_ACTLEN_NULL + 1)
length = 0;
actualLength += length;
if (current->link_phy & TD_TERMINATE)
break;
current = (uhci_td *)current->link_log;
}
TRACE(("usb_uhci: read actual length (%d bytes)\n", actualLength));
return actualLength;
}
inline void
UHCI::WriteReg8(uint32 reg, uint8 value)
{
sPCIModule->write_io_8(fRegisterBase + reg, value);
} }
@@ -1262,6 +1303,13 @@ UHCI::WriteReg32(uint32 reg, uint32 value)
} }
inline uint8
UHCI::ReadReg8(uint32 reg)
{
return sPCIModule->read_io_8(fRegisterBase + reg);
}
inline uint16 inline uint16
UHCI::ReadReg16(uint32 reg) UHCI::ReadReg16(uint32 reg)
{ {
+5 -2
View File
@@ -119,13 +119,16 @@ static int32 FinishThread(void *data);
uhci_td *second); uhci_td *second);
size_t WriteDescriptorChain(uhci_td *topDescriptor, size_t WriteDescriptorChain(uhci_td *topDescriptor,
const uint8 *buffer, int32 bufferSize); const uint8 *buffer, size_t bufferLength);
size_t ReadDescriptorChain(uhci_td *topDescriptor, size_t ReadDescriptorChain(uhci_td *topDescriptor,
uint8 *buffer, int32 bufferSize); uint8 *buffer, size_t bufferLength);
size_t ReadActualLength(uhci_td *topDescriptor);
// Register functions // Register functions
inline void WriteReg8(uint32 reg, uint8 value);
inline void WriteReg16(uint32 reg, uint16 value); inline void WriteReg16(uint32 reg, uint16 value);
inline void WriteReg32(uint32 reg, uint32 value); inline void WriteReg32(uint32 reg, uint32 value);
inline uint8 ReadReg8(uint32 reg);
inline uint16 ReadReg16(uint32 reg); inline uint16 ReadReg16(uint32 reg);
inline uint32 ReadReg32(uint32 reg); inline uint32 ReadReg32(uint32 reg);
@@ -95,7 +95,7 @@ typedef struct
} uhci_td; } uhci_td;
// Control and Status // Control and Status
#define TD_CONTROL_SHORT_PACKET (1 << 29) #define TD_CONTROL_SPD (1 << 29)
#define TD_CONTROL_3_ERRORS (3 << 27) #define TD_CONTROL_3_ERRORS (3 << 27)
#define TD_CONTROL_LOWSPEED (1 << 26) #define TD_CONTROL_LOWSPEED (1 << 26)
#define TD_CONTROL_ISOCHRONOUS (1 << 25) #define TD_CONTROL_ISOCHRONOUS (1 << 25)
@@ -110,7 +110,7 @@ typedef struct
#define TD_STATUS_ERROR_TIMEOUT (1 << 18) #define TD_STATUS_ERROR_TIMEOUT (1 << 18)
#define TD_STATUS_ERROR_BITSTUFF (1 << 17) #define TD_STATUS_ERROR_BITSTUFF (1 << 17)
#define TD_STATUS_ACTLEN_MASK 0x03ff #define TD_STATUS_ACTLEN_MASK 0x07ff
#define TD_STATUS_ACTLEN_NULL 0x07ff #define TD_STATUS_ACTLEN_NULL 0x07ff
// Token // Token
+16 -19
View File
@@ -135,9 +135,13 @@ UHCIRootHub::UHCIRootHub(UHCI *uhci, int8 devicenum)
status_t status_t
UHCIRootHub::SubmitTransfer(Transfer *transfer) UHCIRootHub::SubmitTransfer(Transfer *transfer)
{ {
if (transfer->TransferPipe()->Type() != Pipe::Control)
return B_ERROR;
usb_request_data *request = transfer->RequestData(); usb_request_data *request = transfer->RequestData();
TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request)); TRACE(("usb_uhci_roothub: rh_submit_packet called. request: %u\n", request->Request));
size_t actualLength = 0;
status_t result = B_ERROR; status_t result = B_ERROR;
switch (request->Request) { switch (request->Request) {
case RH_GET_STATUS: { case RH_GET_STATUS: {
@@ -155,11 +159,9 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
// Get port status // Get port status
UpdatePortStatus(); UpdatePortStatus();
size_t length = MIN(4, transfer->DataLength()); actualLength = MIN(4, transfer->DataLength());
memcpy(transfer->Data(), memcpy(transfer->Data(),
(void *)&fPortStatus[request->Index - 1], length); (void *)&fPortStatus[request->Index - 1], actualLength);
*(transfer->ActualLength()) = length;
result = B_OK; result = B_OK;
break; break;
} }
@@ -179,21 +181,19 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
switch (request->Value & 0xff00) { switch (request->Value & 0xff00) {
case RH_DEVICE_DESCRIPTOR: { case RH_DEVICE_DESCRIPTOR: {
size_t length = MIN(sizeof(usb_device_descriptor), actualLength = MIN(sizeof(usb_device_descriptor),
transfer->DataLength()); transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice, memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
length); actualLength);
*(transfer->ActualLength()) = length;
result = B_OK; result = B_OK;
break; break;
} }
case RH_CONFIG_DESCRIPTOR: { case RH_CONFIG_DESCRIPTOR: {
size_t length = MIN(sizeof(uhci_root_hub_configuration_s), actualLength = MIN(sizeof(uhci_root_hub_configuration_s),
transfer->DataLength()); transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig, memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
length); actualLength);
*(transfer->ActualLength()) = length;
result = B_OK; result = B_OK;
break; break;
} }
@@ -201,26 +201,23 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
case RH_STRING_DESCRIPTOR: { case RH_STRING_DESCRIPTOR: {
uint8 index = request->Value & 0x00ff; uint8 index = request->Value & 0x00ff;
if (index > 2) { if (index > 2) {
*(transfer->ActualLength()) = 0;
result = EINVAL; result = EINVAL;
break; break;
} }
size_t length = MIN(sUHCIRootHubStrings[index].length, actualLength = MIN(sUHCIRootHubStrings[index].length,
transfer->DataLength()); transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index], memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
length); actualLength);
*(transfer->ActualLength()) = length;
result = B_OK; result = B_OK;
break; break;
} }
case RH_HUB_DESCRIPTOR: { case RH_HUB_DESCRIPTOR: {
size_t length = MIN(sizeof(usb_hub_descriptor), actualLength = MIN(sizeof(usb_hub_descriptor),
transfer->DataLength()); transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub, memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
length); actualLength);
*(transfer->ActualLength()) = length;
result = B_OK; result = B_OK;
break; break;
} }
@@ -304,7 +301,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
break; break;
} }
transfer->Finished(result); transfer->Finished(result, actualLength);
return result; return result;
} }
@@ -340,7 +337,7 @@ UHCIRootHub::UpdatePortStatus()
newChange |= PORT_STATUS_RESET; newChange |= PORT_STATUS_RESET;
//The port is automagically powered on //The port is automagically powered on
newStatus |= PORT_POWER; newStatus |= PORT_STATUS_POWER;
if (portStatus & UHCI_PORTSC_LOWSPEED) if (portStatus & UHCI_PORTSC_LOWSPEED)
newStatus |= PORT_STATUS_LOW_SPEED; newStatus |= PORT_STATUS_LOW_SPEED;