summaryrefslogtreecommitdiff
path: root/UsbDk/UsbTarget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'UsbDk/UsbTarget.cpp')
-rw-r--r--UsbDk/UsbTarget.cpp136
1 files changed, 66 insertions, 70 deletions
diff --git a/UsbDk/UsbTarget.cpp b/UsbDk/UsbTarget.cpp
index 71286ff..0e56761 100644
--- a/UsbDk/UsbTarget.cpp
+++ b/UsbDk/UsbTarget.cpp
@@ -40,6 +40,8 @@ NTSTATUS CWdfUsbInterface::SetAltSetting(ULONG64 AltSettingIdx)
return status;
}
+ ExclusiveLock m_LockedContext(m_PipesLock);
+
m_Pipes.reset();
m_NumPipes = WdfUsbInterfaceGetNumConfiguredPipes(m_Interface);
@@ -67,19 +69,6 @@ NTSTATUS CWdfUsbInterface::SetAltSetting(ULONG64 AltSettingIdx)
return STATUS_SUCCESS;
}
-CWdfUsbPipe *CWdfUsbInterface::FindPipeByEndpointAddress(ULONG64 EndpointAddress)
-{
- for (UCHAR i = 0; i < m_NumPipes; i++)
- {
- if (m_Pipes[i].EndpointAddress() == EndpointAddress)
- {
- return &m_Pipes[i];
- }
- }
-
- return nullptr;
-}
-
NTSTATUS CWdfUsbInterface::Reset(WDFREQUEST Request)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -311,38 +300,20 @@ NTSTATUS CWdfUsbTarget::SetInterfaceAltSetting(ULONG64 InterfaceIdx, ULONG64 Alt
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_USBTARGET, "%!FUNC! setting #%d for interface #%d",
static_cast<UCHAR>(AltSettingIdx), static_cast<UCHAR>(InterfaceIdx));
- //TODO: Stop read/write queue before interface reconfiguration
return m_Interfaces[InterfaceIdx].SetAltSetting(AltSettingIdx);
}
-CWdfUsbPipe *CWdfUsbTarget::FindPipeByEndpointAddress(ULONG64 EndpointAddress)
-{
- CWdfUsbPipe *Pipe = nullptr;
-
- for (UCHAR i = 0; i < m_NumInterfaces; i++)
- {
- Pipe = m_Interfaces[i].FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
- {
- break;
- }
- }
-
- return Pipe;
-}
-
void CWdfUsbTarget::WritePipeAsync(WDFREQUEST Request, ULONG64 EndpointAddress, WDFMEMORY Buffer, PFN_WDF_REQUEST_COMPLETION_ROUTINE Completion)
{
CWdfRequest WdfRequest(Request);
- CWdfUsbPipe *Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
+ if (!DoPipeOperation<CWdfUsbInterface::SharedLock>(EndpointAddress,
+ [&WdfRequest, Buffer, Completion](CWdfUsbPipe &Pipe)
+ {
+ Pipe.WriteAsync(WdfRequest, Buffer, Completion);
+ }))
{
- Pipe->WriteAsync(WdfRequest, Buffer, Completion);
- }
- else
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed because pipe was not found");
WdfRequest.SetStatus(STATUS_NOT_FOUND);
}
}
@@ -351,14 +322,13 @@ void CWdfUsbTarget::ReadPipeAsync(WDFREQUEST Request, ULONG64 EndpointAddress, W
{
CWdfRequest WdfRequest(Request);
- CWdfUsbPipe *Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
- {
- Pipe->ReadAsync(WdfRequest, Buffer, Completion);
- }
- else
+ if (!DoPipeOperation<CWdfUsbInterface::SharedLock>(EndpointAddress,
+ [&WdfRequest, Buffer, Completion](CWdfUsbPipe &Pipe)
+ {
+ Pipe.ReadAsync(WdfRequest, Buffer, Completion);
+ }))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed because pipe was not found");
WdfRequest.SetStatus(STATUS_NOT_FOUND);
}
}
@@ -369,14 +339,13 @@ void CWdfUsbTarget::ReadIsochronousPipeAsync(WDFREQUEST Request, ULONG64 Endpoin
{
CWdfRequest WdfRequest(Request);
- CWdfUsbPipe *Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
+ if (!DoPipeOperation<CWdfUsbInterface::SharedLock>(EndpointAddress,
+ [&WdfRequest, Buffer, PacketSizes, PacketNumber, Completion](CWdfUsbPipe &Pipe)
+ {
+ Pipe.ReadIsochronousAsync(WdfRequest, Buffer, PacketSizes, PacketNumber, Completion);
+ }))
{
- Pipe->ReadIsochronousAsync(WdfRequest, Buffer, PacketSizes, PacketNumber, Completion);
- }
- else
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed because pipe was not found");
WdfRequest.SetStatus(STATUS_NOT_FOUND);
}
}
@@ -387,50 +356,72 @@ void CWdfUsbTarget::WriteIsochronousPipeAsync(WDFREQUEST Request, ULONG64 Endpoi
{
CWdfRequest WdfRequest(Request);
- CWdfUsbPipe *Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
+ if (!DoPipeOperation<CWdfUsbInterface::SharedLock>(EndpointAddress,
+ [&WdfRequest, Buffer, PacketSizes, PacketNumber, Completion](CWdfUsbPipe &Pipe)
+ {
+ Pipe.WriteIsochronousAsync(WdfRequest, Buffer, PacketSizes, PacketNumber, Completion);
+ }))
{
- Pipe->WriteIsochronousAsync(WdfRequest, Buffer, PacketSizes, PacketNumber, Completion);
- }
- else
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed because pipe was not found");
WdfRequest.SetStatus(STATUS_NOT_FOUND);
}
}
NTSTATUS CWdfUsbTarget::AbortPipe(WDFREQUEST Request, ULONG64 EndpointAddress)
{
- auto Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
+ NTSTATUS status;
+
+ //AbortPipe does not require locking because is scheduled sequentially
+ //with SetAltSettings which is only operation that changes pipes array
+
+ if (!DoPipeOperation<CWdfUsbInterface::NeitherLock>(EndpointAddress,
+ [&status, &Request](CWdfUsbPipe &Pipe)
+ {
+ status = Pipe.Abort(Request);
+ }))
{
- return Pipe->Abort(Request);
+ status = STATUS_NOT_FOUND;
}
- else
+
+ if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
- return STATUS_NOT_FOUND;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: %!STATUS!", status);
}
+
+ return status;
}
NTSTATUS CWdfUsbTarget::ResetPipe(WDFREQUEST Request, ULONG64 EndpointAddress)
{
- auto Pipe = FindPipeByEndpointAddress(EndpointAddress);
- if (Pipe != nullptr)
+ NTSTATUS status;
+
+ //AbortPipe does not require locking because is scheduled sequentially
+ //with SetAltSettings which is only operation that changes pipes array
+
+ if (!DoPipeOperation<CWdfUsbInterface::NeitherLock>(EndpointAddress,
+ [&status, &Request](CWdfUsbPipe &Pipe)
+ {
+ status = Pipe.Reset(Request);
+ }))
{
- return Pipe->Reset(Request);
+ status = STATUS_NOT_FOUND;
}
- else
+
+ if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: Pipe 0x%llu not found", EndpointAddress);
- return STATUS_NOT_FOUND;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "%!FUNC! Failed: %!STATUS!", status);
}
+
+ return status;
}
NTSTATUS CWdfUsbTarget::ResetDevice(WDFREQUEST Request)
{
NTSTATUS status = STATUS_SUCCESS;
+ //ResetDevice does not require locking because is scheduled sequentially
+ //with SetAltSettings which is only operation that changes pipes array
+
for (UCHAR i = 0; i < m_NumInterfaces; i++)
{
auto currentStatus = m_Interfaces[i].Reset(Request);
@@ -468,3 +459,8 @@ NTSTATUS CWdfUsbTarget::ControlTransferAsync(CWdfRequest &WdfRequest, PWDF_USB_C
return status;
}
+
+void CWdfUsbTarget::TracePipeNotFoundError(ULONG64 EndpointAddress)
+{
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_USBTARGET, "Pipe %llu not found", EndpointAddress);
+}