channels/smartcard: add async irp processing

This commit is contained in:
Marc-André Moreau 2014-04-05 17:51:13 -04:00
parent 2aa248853a
commit 9de2a85f6a
5 changed files with 82 additions and 17 deletions

View File

@ -90,9 +90,11 @@ IRP* irp_new(DEVMAN* devman, wStream* s)
Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */ Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */
Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */ Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */
irp->cancelled = FALSE;
irp->Complete = irp_complete; irp->Complete = irp_complete;
irp->Discard = irp_free; irp->Discard = irp_free;
irp->thread = NULL;
irp->cancelled = FALSE;
return irp; return irp;
} }

View File

@ -34,6 +34,8 @@
#include "smartcard_main.h" #include "smartcard_main.h"
#define SMARTCARD_ASYNC_IRP 1
static void smartcard_free(DEVICE* device) static void smartcard_free(DEVICE* device)
{ {
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
@ -94,25 +96,16 @@ void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
irp->Discard(irp); irp->Discard(irp);
} }
static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) void* smartcard_process_irp_worker_proc(IRP* irp)
{ {
void* key; SMARTCARD_DEVICE* smartcard;
key = (void*) (size_t) irp->CompletionId; smartcard = (SMARTCARD_DEVICE*) irp->device;
ListDictionary_Add(smartcard->OutstandingIrps, key, irp);
switch (irp->MajorFunction) smartcard_irp_device_control(smartcard, irp);
{
case IRP_MJ_DEVICE_CONTROL:
smartcard_irp_device_control(smartcard, irp);
break;
default: ExitThread(0);
fprintf(stderr, "MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction); return NULL;
irp->IoStatus = STATUS_NOT_SUPPORTED;
smartcard_complete_irp(smartcard, irp);
break;
}
} }
/** /**
@ -120,6 +113,55 @@ static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
* http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html * http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html
*/ */
void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
void* key;
BOOL asyncIrp = FALSE;
UINT32 ioControlCode = 0;
key = (void*) (size_t) irp->CompletionId;
ListDictionary_Add(smartcard->OutstandingIrps, key, irp);
if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
{
smartcard_irp_device_control_peek_io_control_code(smartcard, irp, &ioControlCode);
#ifdef SMARTCARD_ASYNC_IRP
if (!ioControlCode)
return;
switch (ioControlCode)
{
case SCARD_IOCTL_TRANSMIT:
case SCARD_IOCTL_STATUSA:
case SCARD_IOCTL_STATUSW:
case SCARD_IOCTL_GETSTATUSCHANGEA:
case SCARD_IOCTL_GETSTATUSCHANGEW:
asyncIrp = TRUE;
break;
}
#endif
if (!asyncIrp)
{
smartcard_irp_device_control(smartcard, irp);
}
else
{
irp->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) smartcard_process_irp_worker_proc,
irp, 0, NULL);
}
}
else
{
fprintf(stderr, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
irp->MajorFunction, irp->MinorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
smartcard_complete_irp(smartcard, irp);
}
}
static void* smartcard_thread_func(void* arg) static void* smartcard_thread_func(void* arg)
{ {
IRP* irp; IRP* irp;

View File

@ -100,8 +100,10 @@ struct _SMARTCARD_DEVICE
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE; typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp); void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp);
void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp);
void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp); void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp);
void smartcard_irp_device_control_peek_io_control_code(SMARTCARD_DEVICE* smartcard, IRP* irp, UINT32* ioControlCode);
#include "smartcard_pack.h" #include "smartcard_pack.h"

View File

@ -1871,6 +1871,23 @@ finish:
return status; return status;
} }
void smartcard_irp_device_control_peek_io_control_code(SMARTCARD_DEVICE* smartcard, IRP* irp, UINT32* ioControlCode)
{
*ioControlCode = 0;
if (Stream_GetRemainingLength(irp->input) < 32)
{
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return;
}
Stream_Seek_UINT32(irp->input); /* OutputBufferLength (4 bytes) */
Stream_Seek_UINT32(irp->input); /* InputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, *ioControlCode); /* IoControlCode (4 bytes) */
Stream_Rewind(irp->input, (4 + 4 + 4));
}
void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp) void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
{ {
UINT32 result; UINT32 result;

View File

@ -342,9 +342,11 @@ struct _IRP
UINT32 IoStatus; UINT32 IoStatus;
wStream* output; wStream* output;
BOOL cancelled;
pcIRPResponse Complete; pcIRPResponse Complete;
pcIRPResponse Discard; pcIRPResponse Discard;
HANDLE thread;
BOOL cancelled;
}; };
struct _DEVMAN struct _DEVMAN