* Fixed data toggle handling. It must be taken after the transfer finished and from the last transmitted transfer descriptor (which in case of a short packet is not neccessarily the last descriptor of the chain)
* Moved convenience endpoint requests from ControlPipe to Pipe With this change, bulk transfers are fairly stable now. See here for evidence: http://haiku.mlotz.ch/haiku-usb01.png ;). Those are pictures from my Canon Digital Ixus 750 downloaded with Exposure using the PTP plugin. I of course navigated Haiku with my USB Logitech iFeel mouse which works nice since some days. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18510 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -55,6 +55,60 @@ Pipe::CancelQueuedTransfers()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::SetFeature(uint16 selector)
|
||||
{
|
||||
if (!fDevice)
|
||||
return B_ERROR;
|
||||
|
||||
return fDevice->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::ClearFeature(uint16 selector)
|
||||
{
|
||||
if (!fDevice)
|
||||
return B_ERROR;
|
||||
|
||||
return fDevice->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
selector,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::GetStatus(uint16 *status)
|
||||
{
|
||||
if (!fDevice)
|
||||
return B_ERROR;
|
||||
|
||||
return fDevice->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_IN,
|
||||
USB_REQUEST_GET_STATUS,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
(void *)status,
|
||||
2,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #pragma mark -
|
||||
//
|
||||
@@ -233,48 +287,3 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ set_feature(const void *object, uint16 selector)
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->SetFeature(selector);
|
||||
return ((Pipe *)object)->SetFeature(selector);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ clear_feature(const void *object, uint16 selector)
|
||||
if (!object)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->ClearFeature(selector);
|
||||
return ((Pipe *)object)->ClearFeature(selector);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ get_status(const void *object, uint16 *status)
|
||||
if (!object || !status)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return ((ControlPipe *)object)->GetStatus(status);
|
||||
return ((Pipe *)object)->GetStatus(status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -167,6 +167,11 @@ virtual void SetDataToggle(bool toggle) { fDataToggle = toggle; };
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
status_t CancelQueuedTransfers();
|
||||
|
||||
// Convenience functions for standard requests
|
||||
virtual status_t SetFeature(uint16 selector);
|
||||
virtual status_t ClearFeature(uint16 selector);
|
||||
virtual status_t GetStatus(uint16 *status);
|
||||
|
||||
protected:
|
||||
Device *fDevice;
|
||||
BusManager *fBus;
|
||||
@@ -269,11 +274,6 @@ virtual void SetDataToggle(bool toggle) {};
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -768,20 +768,24 @@ UHCI::FinishTransfers()
|
||||
transfer->first_descriptor,
|
||||
transfer->last_descriptor);
|
||||
|
||||
size_t length = 0;
|
||||
size_t actualLength = 0;
|
||||
uint8 lastDataToggle = 0;
|
||||
if (transfer->data_descriptor && transfer->incoming) {
|
||||
// data to read out
|
||||
length = ReadDescriptorChain(
|
||||
actualLength = ReadDescriptorChain(
|
||||
transfer->data_descriptor,
|
||||
transfer->transfer->Data(),
|
||||
transfer->transfer->DataLength());
|
||||
transfer->transfer->DataLength(),
|
||||
&lastDataToggle);
|
||||
} else {
|
||||
// read the actual length that was sent
|
||||
length = ReadActualLength(transfer->first_descriptor);
|
||||
actualLength = ReadActualLength(
|
||||
transfer->first_descriptor, &lastDataToggle);
|
||||
}
|
||||
|
||||
FreeDescriptorChain(transfer->first_descriptor);
|
||||
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, length);
|
||||
transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0);
|
||||
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength);
|
||||
transferDone = true;
|
||||
break;
|
||||
}
|
||||
@@ -1152,7 +1156,6 @@ UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor,
|
||||
firstDescriptor = descriptor;
|
||||
}
|
||||
|
||||
pipe->SetDataToggle(dataToggle);
|
||||
*_firstDescriptor = firstDescriptor;
|
||||
*_lastDescriptor = lastDescriptor;
|
||||
return B_OK;
|
||||
@@ -1227,10 +1230,11 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
|
||||
|
||||
size_t
|
||||
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||
size_t bufferLength)
|
||||
size_t bufferLength, uint8 *lastDataToggle)
|
||||
{
|
||||
size_t actualLength = 0;
|
||||
uhci_td *current = topDescriptor;
|
||||
uint8 dataToggle = 0;
|
||||
|
||||
while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
|
||||
if (!current->buffer_log)
|
||||
@@ -1243,9 +1247,10 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||
length = min_c(length, bufferLength);
|
||||
memcpy(buffer, current->buffer_log, length);
|
||||
|
||||
buffer += length;
|
||||
bufferLength -= length;
|
||||
actualLength += length;
|
||||
buffer += length;
|
||||
dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
|
||||
|
||||
if (current->link_phy & TD_TERMINATE)
|
||||
break;
|
||||
@@ -1253,30 +1258,38 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer,
|
||||
current = (uhci_td *)current->link_log;
|
||||
}
|
||||
|
||||
if (lastDataToggle)
|
||||
*lastDataToggle = dataToggle;
|
||||
|
||||
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualLength));
|
||||
return actualLength;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
UHCI::ReadActualLength(uhci_td *topDescriptor)
|
||||
UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle)
|
||||
{
|
||||
size_t actualLength = 0;
|
||||
uhci_td *current = topDescriptor;
|
||||
uint8 dataToggle = 0;
|
||||
|
||||
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;
|
||||
dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
|
||||
|
||||
if (current->link_phy & TD_TERMINATE)
|
||||
break;
|
||||
|
||||
current = (uhci_td *)current->link_log;
|
||||
}
|
||||
|
||||
if (lastDataToggle)
|
||||
*lastDataToggle = dataToggle;
|
||||
|
||||
TRACE(("usb_uhci: read actual length (%d bytes)\n", actualLength));
|
||||
return actualLength;
|
||||
}
|
||||
|
||||
@@ -121,8 +121,10 @@ static int32 FinishThread(void *data);
|
||||
size_t WriteDescriptorChain(uhci_td *topDescriptor,
|
||||
const uint8 *buffer, size_t bufferLength);
|
||||
size_t ReadDescriptorChain(uhci_td *topDescriptor,
|
||||
uint8 *buffer, size_t bufferLength);
|
||||
size_t ReadActualLength(uhci_td *topDescriptor);
|
||||
uint8 *buffer, size_t bufferLength,
|
||||
uint8 *lastDataToggle);
|
||||
size_t ReadActualLength(uhci_td *topDescriptor,
|
||||
uint8 *lastDataToggle);
|
||||
|
||||
// Register functions
|
||||
inline void WriteReg8(uint32 reg, uint8 value);
|
||||
|
||||
@@ -116,7 +116,8 @@ typedef struct
|
||||
// Token
|
||||
#define TD_TOKEN_MAXLEN_SHIFT 21
|
||||
#define TD_TOKEN_NULL_DATA (0x07ff << TD_TOKEN_MAXLEN_SHIFT)
|
||||
#define TD_TOKEN_DATA1 (1 << 19)
|
||||
#define TD_TOKEN_DATA_TOGGLE_SHIFT 19
|
||||
#define TD_TOKEN_DATA1 (1 << TD_TOKEN_DATA_TOGGLE_SHIFT)
|
||||
|
||||
#define TD_TOKEN_SETUP 0x2d
|
||||
#define TD_TOKEN_IN 0x69
|
||||
|
||||
Reference in New Issue
Block a user