* Fixed memory leak of Transfers never getting deleted (intentionally until now).
* Reduced the Transfer class to a minimum and removed support for synchronous transfers. The only usage of this is in SendRequest(), which now provides a callback and QueueRequest()s it's request instead. * Clarified semantics of SubmitTransfer(). It returns a status_t indicating wether the transfer was submitted successfully. This includes no information about the outcome. Therefore the UHCI RootHub now reports the status only through the callback and returns B_OK or B_ERROR for SubmitTransfer(). * Added comment to the Transfer class explaining who takes ownership of the Transfer in which cases. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18511 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -125,7 +125,7 @@ status_t
|
|||||||
InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
|
InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
|
||||||
usb_callback_func callback, void *callbackCookie)
|
usb_callback_func callback, void *callbackCookie)
|
||||||
{
|
{
|
||||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
Transfer *transfer = new(std::nothrow) Transfer(this);
|
||||||
if (!transfer)
|
if (!transfer)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -133,9 +133,7 @@ InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
|
|||||||
transfer->SetCallback(callback, callbackCookie);
|
transfer->SetCallback(callback, callbackCookie);
|
||||||
|
|
||||||
status_t result = SubmitTransfer(transfer);
|
status_t result = SubmitTransfer(transfer);
|
||||||
if (result == B_OK || result == EINPROGRESS)
|
if (result < B_OK)
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
delete transfer;
|
delete transfer;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -157,7 +155,7 @@ status_t
|
|||||||
BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
|
BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
|
||||||
void *callbackCookie)
|
void *callbackCookie)
|
||||||
{
|
{
|
||||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
Transfer *transfer = new(std::nothrow) Transfer(this);
|
||||||
if (!transfer)
|
if (!transfer)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -165,9 +163,7 @@ BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
|
|||||||
transfer->SetCallback(callback, callbackCookie);
|
transfer->SetCallback(callback, callbackCookie);
|
||||||
|
|
||||||
status_t result = SubmitTransfer(transfer);
|
status_t result = SubmitTransfer(transfer);
|
||||||
if (result == B_OK || result == EINPROGRESS)
|
if (result < B_OK)
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
delete transfer;
|
delete transfer;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -199,6 +195,13 @@ IsochronousPipe::QueueIsochronous(void *data, size_t dataLength,
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
struct transfer_result_data {
|
||||||
|
sem_id notify_sem;
|
||||||
|
uint32 status;
|
||||||
|
size_t actual_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
ControlPipe::ControlPipe(Device *device, pipeSpeed speed,
|
ControlPipe::ControlPipe(Device *device, pipeSpeed speed,
|
||||||
uint8 endpointAddress, uint32 maxPacketSize)
|
uint8 endpointAddress, uint32 maxPacketSize)
|
||||||
: Pipe(device, Pipe::Default, speed, endpointAddress, maxPacketSize)
|
: Pipe(device, Pipe::Default, speed, endpointAddress, maxPacketSize)
|
||||||
@@ -230,30 +233,43 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
|
|||||||
uint16 index, uint16 length, void *data, size_t dataLength,
|
uint16 index, uint16 length, void *data, size_t dataLength,
|
||||||
size_t *actualLength)
|
size_t *actualLength)
|
||||||
{
|
{
|
||||||
usb_request_data requestData;
|
transfer_result_data transferResult;
|
||||||
requestData.RequestType = requestType;
|
transferResult.notify_sem = create_sem(0, "Send Request Notify Sem");
|
||||||
requestData.Request = request;
|
if (transferResult.notify_sem < B_OK)
|
||||||
requestData.Value = value;
|
return B_NO_MORE_SEMS;
|
||||||
requestData.Index = index;
|
|
||||||
requestData.Length = length;
|
|
||||||
|
|
||||||
Transfer *transfer = new(std::nothrow) Transfer(this, true);
|
status_t result = QueueRequest(requestType, request, value, index, length,
|
||||||
if (!transfer)
|
data, dataLength, SendRequestCallback, &transferResult);
|
||||||
return B_NO_MEMORY;
|
if (result < B_OK) {
|
||||||
|
delete_sem(transferResult.notify_sem);
|
||||||
transfer->SetRequestData(&requestData);
|
|
||||||
transfer->SetData((uint8 *)data, dataLength);
|
|
||||||
transfer->SetActualLength(actualLength);
|
|
||||||
|
|
||||||
status_t result = SubmitTransfer(transfer);
|
|
||||||
if (result == EINPROGRESS)
|
|
||||||
return transfer->WaitForFinish();
|
|
||||||
|
|
||||||
if (result < B_OK)
|
|
||||||
delete transfer;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the sem will be released in the callback after
|
||||||
|
// the result data was filled into the provided struct
|
||||||
|
acquire_sem(transferResult.notify_sem);
|
||||||
|
delete_sem(transferResult.notify_sem);
|
||||||
|
|
||||||
|
if (actualLength)
|
||||||
|
*actualLength = transferResult.actual_length;
|
||||||
|
|
||||||
|
if (transferResult.status == B_USB_STATUS_SUCCESS)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ControlPipe::SendRequestCallback(void *cookie, uint32 status, void *data,
|
||||||
|
size_t actualLength)
|
||||||
|
{
|
||||||
|
transfer_result_data *transferResult = (transfer_result_data *)cookie;
|
||||||
|
transferResult->status = status;
|
||||||
|
transferResult->actual_length = actualLength;
|
||||||
|
release_sem(transferResult->notify_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
||||||
@@ -270,7 +286,7 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
|||||||
requestData->Index = index;
|
requestData->Index = index;
|
||||||
requestData->Length = length;
|
requestData->Length = length;
|
||||||
|
|
||||||
Transfer *transfer = new(std::nothrow) Transfer(this, false);
|
Transfer *transfer = new(std::nothrow) Transfer(this);
|
||||||
if (!transfer) {
|
if (!transfer) {
|
||||||
delete requestData;
|
delete requestData;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -281,9 +297,7 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
|
|||||||
transfer->SetCallback(callback, callbackCookie);
|
transfer->SetCallback(callback, callbackCookie);
|
||||||
|
|
||||||
status_t result = SubmitTransfer(transfer);
|
status_t result = SubmitTransfer(transfer);
|
||||||
if (result == B_OK || result == EINPROGRESS)
|
if (result < B_OK)
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
delete transfer;
|
delete transfer;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,30 +9,22 @@
|
|||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
|
|
||||||
Transfer::Transfer(Pipe *pipe, bool synchronous)
|
Transfer::Transfer(Pipe *pipe)
|
||||||
: fPipe(pipe),
|
: fPipe(pipe),
|
||||||
fData(NULL),
|
fData(NULL),
|
||||||
fDataLength(0),
|
fDataLength(0),
|
||||||
fActualLengthPointer(NULL),
|
|
||||||
fActualLength(0),
|
|
||||||
fStatus(B_USB_STATUS_DRIVER_INTERNAL_ERROR),
|
|
||||||
fCallback(NULL),
|
fCallback(NULL),
|
||||||
fCallbackCookie(NULL),
|
fCallbackCookie(NULL),
|
||||||
fSem(-1),
|
|
||||||
fHostPrivate(NULL),
|
|
||||||
fRequestData(NULL)
|
fRequestData(NULL)
|
||||||
{
|
{
|
||||||
if (synchronous) {
|
|
||||||
fSem = create_sem(0, "USB Transfer");
|
|
||||||
set_sem_owner(fSem, B_SYSTEM_TEAM);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Transfer::~Transfer()
|
Transfer::~Transfer()
|
||||||
{
|
{
|
||||||
if (fSem >= B_OK)
|
// we take ownership of the request data
|
||||||
delete_sem(fSem);
|
if (fRequestData)
|
||||||
|
delete fRequestData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -51,13 +43,6 @@ Transfer::SetData(uint8 *data, size_t dataLength)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Transfer::SetActualLength(size_t *actualLength)
|
|
||||||
{
|
|
||||||
fActualLengthPointer = actualLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Transfer::SetCallback(usb_callback_func callback, void *cookie)
|
Transfer::SetCallback(usb_callback_func callback, void *cookie)
|
||||||
{
|
{
|
||||||
@@ -66,47 +51,9 @@ Transfer::SetCallback(usb_callback_func callback, void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Transfer::SetHostPrivate(hostcontroller_priv *priv)
|
|
||||||
{
|
|
||||||
fHostPrivate = priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Transfer::WaitForFinish()
|
|
||||||
{
|
|
||||||
if (fSem < B_OK)
|
|
||||||
return fSem;
|
|
||||||
|
|
||||||
status_t result = acquire_sem(fSem);
|
|
||||||
if (result < B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (fStatus == B_USB_STATUS_SUCCESS)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Transfer::Finished(uint32 status, size_t actualLength)
|
Transfer::Finished(uint32 status, size_t actualLength)
|
||||||
{
|
{
|
||||||
fStatus = status;
|
if (fCallback)
|
||||||
fActualLength = actualLength;
|
fCallback(fCallbackCookie, status, fData, actualLength);
|
||||||
if (fActualLengthPointer)
|
|
||||||
*fActualLengthPointer = actualLength;
|
|
||||||
|
|
||||||
// Call the callback function ...
|
|
||||||
if (fCallback) {
|
|
||||||
fCallback(fCallbackCookie, fStatus, fData, fActualLength);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... or release the sem
|
|
||||||
if (fSem > B_OK) {
|
|
||||||
release_sem(fSem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,6 +266,9 @@ virtual void SetDataToggle(bool toggle) {};
|
|||||||
uint16 index, uint16 length,
|
uint16 index, uint16 length,
|
||||||
void *data, size_t dataLength,
|
void *data, size_t dataLength,
|
||||||
size_t *actualLength);
|
size_t *actualLength);
|
||||||
|
static void SendRequestCallback(void *cookie,
|
||||||
|
uint32 status, void *data,
|
||||||
|
size_t actualLength);
|
||||||
|
|
||||||
status_t QueueRequest(uint8 requestType,
|
status_t QueueRequest(uint8 requestType,
|
||||||
uint8 request, uint16 value,
|
uint8 request, uint16 value,
|
||||||
@@ -382,20 +385,19 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a forward definition of a struct that is defined in the individual
|
* A Transfer is allocated on the heap and passed to the Host Controller in
|
||||||
* host controller modules
|
* SubmitTransfer(). It is generated for all queued transfers. If queuing
|
||||||
*/
|
* succeds (SubmitTransfer() returns with >= B_OK) the Host Controller takes
|
||||||
struct hostcontroller_priv;
|
* ownership of the Transfer and will delete it as soon as it has called the
|
||||||
|
* set callback function. If SubmitTransfer() failes, the calling function is
|
||||||
|
* responsible for deleting the Transfer.
|
||||||
/*
|
* Also, the transfer takes ownership of the usb_request_data passed to it in
|
||||||
* This class is more like an utility class that performs all functions on
|
* SetRequestData(), but does not take ownership of the data buffer set by
|
||||||
* packets. The class is only used in the bus_manager: the host controllers
|
* SetData().
|
||||||
* receive the internal data structures.
|
|
||||||
*/
|
*/
|
||||||
class Transfer {
|
class Transfer {
|
||||||
public:
|
public:
|
||||||
Transfer(Pipe *pipe, bool synchronous);
|
Transfer(Pipe *pipe);
|
||||||
~Transfer();
|
~Transfer();
|
||||||
|
|
||||||
Pipe *TransferPipe() { return fPipe; };
|
Pipe *TransferPipe() { return fPipe; };
|
||||||
@@ -407,16 +409,9 @@ public:
|
|||||||
uint8 *Data() { return fData; };
|
uint8 *Data() { return fData; };
|
||||||
size_t DataLength() { return fDataLength; };
|
size_t DataLength() { return fDataLength; };
|
||||||
|
|
||||||
void SetActualLength(size_t *actualLength);
|
|
||||||
size_t *ActualLength() { return fActualLengthPointer; };
|
|
||||||
|
|
||||||
void SetHostPrivate(hostcontroller_priv *priv);
|
|
||||||
hostcontroller_priv *HostPrivate() { return fHostPrivate; };
|
|
||||||
|
|
||||||
void SetCallback(usb_callback_func callback,
|
void SetCallback(usb_callback_func callback,
|
||||||
void *cookie);
|
void *cookie);
|
||||||
|
|
||||||
status_t WaitForFinish();
|
|
||||||
void Finished(uint32 status, size_t actualLength);
|
void Finished(uint32 status, size_t actualLength);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -424,16 +419,9 @@ private:
|
|||||||
Pipe *fPipe;
|
Pipe *fPipe;
|
||||||
uint8 *fData;
|
uint8 *fData;
|
||||||
size_t fDataLength;
|
size_t fDataLength;
|
||||||
size_t *fActualLengthPointer;
|
|
||||||
size_t fActualLength;
|
|
||||||
uint32 fStatus;
|
|
||||||
|
|
||||||
usb_callback_func fCallback;
|
usb_callback_func fCallback;
|
||||||
void *fCallbackCookie;
|
void *fCallbackCookie;
|
||||||
|
|
||||||
sem_id fSem;
|
|
||||||
hostcontroller_priv *fHostPrivate;
|
|
||||||
|
|
||||||
// For control transfers
|
// For control transfers
|
||||||
usb_request_data *fRequestData;
|
usb_request_data *fRequestData;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINPROGRESS;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -655,7 +655,7 @@ UHCI::SubmitRequest(Transfer *transfer)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINPROGRESS;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -804,6 +804,7 @@ UHCI::FinishTransfers()
|
|||||||
fLastTransfer = lastTransfer;
|
fLastTransfer = lastTransfer;
|
||||||
|
|
||||||
transfer_data *next = transfer->link;
|
transfer_data *next = transfer->link;
|
||||||
|
delete transfer->transfer;
|
||||||
delete transfer;
|
delete transfer;
|
||||||
transfer = next;
|
transfer = next;
|
||||||
|
|
||||||
|
|||||||
@@ -141,18 +141,20 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
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));
|
||||||
|
|
||||||
|
// ToDo: define better status codes. We should return a request error.
|
||||||
|
uint32 status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||||
size_t actualLength = 0;
|
size_t actualLength = 0;
|
||||||
status_t result = B_ERROR;
|
|
||||||
switch (request->Request) {
|
switch (request->Request) {
|
||||||
case RH_GET_STATUS: {
|
case RH_GET_STATUS: {
|
||||||
if (request->Index == 0) {
|
if (request->Index == 0) {
|
||||||
// Get the hub status -- everything as 0 means all-right
|
// Get the hub status -- everything as 0 means all-right
|
||||||
memset(transfer->Data(), 0, sizeof(get_status_buffer));
|
actualLength = MIN(sizeof(get_status_buffer),
|
||||||
result = B_OK;
|
transfer->DataLength());
|
||||||
|
memset(transfer->Data(), 0, actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
||||||
// This port doesn't exist
|
// This port doesn't exist
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,18 +164,18 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
actualLength = MIN(4, transfer->DataLength());
|
actualLength = MIN(4, transfer->DataLength());
|
||||||
memcpy(transfer->Data(),
|
memcpy(transfer->Data(),
|
||||||
(void *)&fPortStatus[request->Index - 1], actualLength);
|
(void *)&fPortStatus[request->Index - 1], actualLength);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RH_SET_ADDRESS:
|
case RH_SET_ADDRESS:
|
||||||
if (request->Value >= 128) {
|
if (request->Value >= 128) {
|
||||||
result = EINVAL;
|
status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci_roothub: rh_submit_packet RH_ADDRESS: %d\n", request->Value));
|
TRACE(("usb_uhci_roothub: rh_submit_packet RH_ADDRESS: %d\n", request->Value));
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RH_GET_DESCRIPTOR:
|
case RH_GET_DESCRIPTOR:
|
||||||
@@ -185,7 +187,7 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
|
||||||
actualLength);
|
actualLength);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,22 +196,20 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
|
||||||
actualLength);
|
actualLength);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RH_STRING_DESCRIPTOR: {
|
case RH_STRING_DESCRIPTOR: {
|
||||||
uint8 index = request->Value & 0x00ff;
|
uint8 index = request->Value & 0x00ff;
|
||||||
if (index > 2) {
|
if (index > 2)
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
actualLength = 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],
|
||||||
actualLength);
|
actualLength);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,48 +218,41 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
transfer->DataLength());
|
transfer->DataLength());
|
||||||
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
|
||||||
actualLength);
|
actualLength);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
result = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RH_SET_CONFIG:
|
case RH_SET_CONFIG:
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RH_CLEAR_FEATURE: {
|
case RH_CLEAR_FEATURE: {
|
||||||
if (request->Index == 0) {
|
if (request->Index == 0) {
|
||||||
// We don't support any hub changes
|
// We don't support any hub changes
|
||||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE no hub changes!\n"));
|
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE no hub changes!\n"));
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
||||||
// Invalid port number
|
// Invalid port number
|
||||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE invalid port!\n"));
|
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE invalid port!\n"));
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE called. Feature: %u!\n", request->Value));
|
TRACE(("usb_uhci_roothub: RH_CLEAR_FEATURE called. Feature: %u!\n", request->Value));
|
||||||
uint16 status;
|
uint16 portStatus;
|
||||||
switch(request->Value) {
|
switch(request->Value) {
|
||||||
case C_PORT_RESET:
|
case C_PORT_RESET:
|
||||||
fUHCI->SetPortResetChange(request->Index - 1, false);
|
fUHCI->SetPortResetChange(request->Index - 1, false);
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case C_PORT_CONNECTION:
|
case C_PORT_CONNECTION:
|
||||||
status = fUHCI->PortStatus(request->Index - 1);
|
portStatus = fUHCI->PortStatus(request->Index - 1);
|
||||||
result = fUHCI->SetPortStatus(request->Index - 1,
|
if (fUHCI->SetPortStatus(request->Index - 1,
|
||||||
(status & UHCI_PORTSC_DATAMASK) | UHCI_PORTSC_STATCHA);
|
(portStatus & UHCI_PORTSC_DATAMASK)
|
||||||
break;
|
| UHCI_PORTSC_STATCHA) >= B_OK)
|
||||||
default:
|
status = B_USB_STATUS_SUCCESS;
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -269,40 +262,32 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
|||||||
if (request->Index == 0) {
|
if (request->Index == 0) {
|
||||||
// We don't support any hub changes
|
// We don't support any hub changes
|
||||||
TRACE(("usb_uhci_roothub: RH_SET_FEATURE no hub changes!\n"));
|
TRACE(("usb_uhci_roothub: RH_SET_FEATURE no hub changes!\n"));
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
} else if (request->Index > sUHCIRootHubConfig.hub.num_ports) {
|
||||||
// Invalid port number
|
// Invalid port number
|
||||||
TRACE(("usb_uhci_roothub: RH_SET_FEATURE invalid port!\n"));
|
TRACE(("usb_uhci_roothub: RH_SET_FEATURE invalid port!\n"));
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb_uhci_roothub: RH_SET_FEATURE called. Feature: %u!\n", request->Value));
|
TRACE(("usb_uhci_roothub: RH_SET_FEATURE called. Feature: %u!\n", request->Value));
|
||||||
switch(request->Value) {
|
switch(request->Value) {
|
||||||
case PORT_RESET:
|
case PORT_RESET:
|
||||||
result = fUHCI->ResetPort(request->Index - 1);
|
if (fUHCI->ResetPort(request->Index - 1) >= B_OK)
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PORT_POWER:
|
case PORT_POWER:
|
||||||
// the ports are automatically powered
|
// the ports are automatically powered
|
||||||
result = B_OK;
|
status = B_USB_STATUS_SUCCESS;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
result = EINVAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
result = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer->Finished(result, actualLength);
|
transfer->Finished(status, actualLength);
|
||||||
return result;
|
delete transfer;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user