USB: Implement usb_clear_stall kernel debugger command.
It constructs a clear feature request for the endpoint halt selector and sends the request using debug transfers. Clearing a stall condition can be done safely and has one nice side effect: it reinitializes the data toggle to a known state. This command can therefore be used when a pipe is possibly used from userland as well and the data toggle may therefore be out of sync.
This commit is contained in:
@@ -99,6 +99,44 @@ debug_process_transfer(int argc, char **argv)
|
|||||||
return debug_run_transfer(pipe, data, length, requestData,
|
return debug_run_transfer(pipe, data, length, requestData,
|
||||||
argc > 1 && strcmp(argv[1], "cancel") == 0);
|
argc > 1 && strcmp(argv[1], "cancel") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debug_clear_stall(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
|
||||||
|
if (pipe == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
static usb_request_data requestData;
|
||||||
|
|
||||||
|
requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
|
||||||
|
requestData.Request = USB_REQUEST_CLEAR_FEATURE;
|
||||||
|
requestData.Value = USB_FEATURE_ENDPOINT_HALT;
|
||||||
|
requestData.Index = pipe->EndpointAddress()
|
||||||
|
| (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
|
||||||
|
: USB_ENDPOINT_ADDR_DIR_OUT);
|
||||||
|
requestData.Length = 0;
|
||||||
|
|
||||||
|
Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
|
||||||
|
for (int tries = 0; tries < 100; tries++) {
|
||||||
|
status_t result
|
||||||
|
= debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
|
||||||
|
|
||||||
|
if (result == B_DEV_PENDING)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
// clearing a stalled condition resets the data toggle
|
||||||
|
pipe->SetDataToggle(false);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_TIMED_OUT;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -153,6 +191,10 @@ bus_std_ops(int32 op, ...)
|
|||||||
&debug_process_transfer,
|
&debug_process_transfer,
|
||||||
"Transfers _usbTransferData with _usbTransferLength"
|
"Transfers _usbTransferData with _usbTransferLength"
|
||||||
" (and/or _usbRequestData) to pipe _usbPipe");
|
" (and/or _usbRequestData) to pipe _usbPipe");
|
||||||
|
add_debugger_command("usb_clear_stall",
|
||||||
|
&debug_clear_stall,
|
||||||
|
"Tries to issue a clear feature request for the endpoint halt"
|
||||||
|
" feature on pipe _usbPipe");
|
||||||
#elif HAIKU_TARGET_PLATFORM_BEOS
|
#elif HAIKU_TARGET_PLATFORM_BEOS
|
||||||
// Plain R5 workaround, see comment above.
|
// Plain R5 workaround, see comment above.
|
||||||
shared = create_area("shared usb stack", &address,
|
shared = create_area("shared usb stack", &address,
|
||||||
|
|||||||
Reference in New Issue
Block a user