diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index f60c868bf0..5218096067 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -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); -} diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index 6b1e31ccc7..ae01ad730d 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -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); } diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index d4fc67132f..128c01290c 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -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; }; diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index 217bd9acd5..f2f047ff69 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -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; } diff --git a/src/add-ons/kernel/busses/usb/uhci.h b/src/add-ons/kernel/busses/usb/uhci.h index b35c8b0981..5925d4895f 100644 --- a/src/add-ons/kernel/busses/usb/uhci.h +++ b/src/add-ons/kernel/busses/usb/uhci.h @@ -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); diff --git a/src/add-ons/kernel/busses/usb/uhci_hardware.h b/src/add-ons/kernel/busses/usb/uhci_hardware.h index becc45dbf6..0587e64e4a 100644 --- a/src/add-ons/kernel/busses/usb/uhci_hardware.h +++ b/src/add-ons/kernel/busses/usb/uhci_hardware.h @@ -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