From e31cac6e5afe902f17dd76e174966515dfb7babb Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 31 Aug 2014 22:53:18 +0200 Subject: [PATCH] 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. --- src/add-ons/kernel/bus_managers/usb/usb.cpp | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index 4b9da16afd..fad8645377 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -99,6 +99,44 @@ debug_process_transfer(int argc, char **argv) return debug_run_transfer(pipe, data, length, requestData, 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 @@ -153,6 +191,10 @@ bus_std_ops(int32 op, ...) &debug_process_transfer, "Transfers _usbTransferData with _usbTransferLength" " (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 // Plain R5 workaround, see comment above. shared = create_area("shared usb stack", &address,