KMDF Iso Transfers

I am very excited about WDF. After trying for years to understand all the WDM info, this comes along to make our lives "easier". Well I thought so until I started to read all the chm files and white papers on WDF. I know this is a much better way to do things, but that learning curve is still fairly steep. I want to write a USB driver in WDF. The only references I have found are: OSRUSBFX2 example with the WDF DDK, someone recasting that example a little bit on Code Project(http://www.codeproject.com/system/kmdf_osr_usb_fx2.asp) and the confusing mish-mash of Microsoft white papers and chm files from the WDF DDK and the microsoft website.

Here is what I want to achieve: I have a four endpoints: ISO IN, INT IN, INT OUT, ISO OUT. I would like continuous read (Yeah! Way to go Microsoft!) on the ISO IN and INT IN endpoints. I have one USB Interface. Since USB 2.0 is not supposed to enumerate with iso endpoints active, my Interface 0 / Alternate 0 has no endpoints defined. My Interface 0 / Alternate 1 has 4 defined: 1 - ISO IN (16 bytes), 2 - INT IN (32 bytes), 3 - INT OUT (32 bytes) and 4 - ISO OUT (16 bytes).

The following code was done using step2.c in the osrusbfx2 example and cutting and pasting from the codeproject example and going from there to make changes. This code blue screens. I have commented some stuff out to be added later like EventDeviceD0Exit, etc. I like doing things one step at a time. My goal here is to select the alternate interface so I can initialize the pipes and set up everything else. I am not setting up queues in this example yet. Do I need queues initialized before I can select an alternate interface? Any thing to point me in the correct direction would be appreciated. Sorry the listing is so long, as this is the initial show of this, I want everyone to see what I have going so no assumptions are made.

#include "ntddk.h"
#include "wdf.h"
#include "prototypes.h"
#pragma warning(disable:4200) // suppress nameless struct/union warning
#pragma warning(disable:4201) // suppress nameless struct/union warning
#pragma warning(disable:4214) // suppress bit field types other than int warning
#include "usbdi.h"
#pragma warning(default:4200)
#pragma warning(default:4201)
#pragma warning(default:4214)
#include "wdfusb.h"
#include "initguid.h"

#pragma alloc_text(INIT, DriverEntry) // make DriverEntry disappear after it is done
#pragma alloc_text(PAGE, EvtDevicePrepareHardware)
#pragma alloc_text(PAGE, EvtDeviceAdd)

DEFINE_GUID(GUID_DEVINTERFACE_OURDEVICE, 0xD51F1F7B, 0x44A5, 0x41CB, 0xAE, 0x9, 0xDC, 0xC, 0x2E, 0xBE, 0xB7, 0xC9);
// guid in a different format
//d51f1f7b-44a5-41cb-ae09-dc0c2ebeb7c9

// object context definition all specific instances
typedef struct _DEVICE_CONTEXT
{
WDFUSBDEVICE UsbDevice;
WDFUSBINTERFACE UsbInterface;
WDFQUEUE IoIsoWriteQueue;
WDFQUEUE IoIsoReadQueue;
WDFQUEUE IoIntWriteQueue;
WDFQUEUE IoIntReadQueue;
WDFUSBPIPE UsbInterruptInPipe;
WDFUSBPIPE UsbInterruptOutPipe;
WDFUSBPIPE UsbIsoInPipe;
WDFUSBPIPE UsbIsoOutPipe;

} DEVICE_CONTEXT, *PDEVICE_CONTEXT;

// object context function assignment
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)

/*****************************************************************

DriverEntry --

******************************************************************/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;

KdPrint((_DRIVERNAME"-->DriverEntry\n"));
WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd);

status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
if(!NT_SUCCESS(status))
{
KdPrint((_DRIVERNAME"WdfDriverCreate failed in 'DriverEntry' 0x%x\n", status));
}

KdPrint((_DRIVERNAME"<--DriverEntry\n"));
return status;
}

NTSTATUS EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
NTSTATUS status;
WDFDEVICE device;
PDEVICE_CONTEXT devCtx = NULL;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;

UNREFERENCED_PARAMETER(Driver);
KdPrint((_DRIVERNAME"-->EvtDeviceAdd"));

/*set the callback functions that will be executed on PNP and Power events*/
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
// pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
// pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

/*initialize storage for the device context*/
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

/*create a device instance.*/
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if(!NT_SUCCESS(status))
{
KdPrint((_DRIVERNAME"WdfDeviceCreate failed with status 0x%08x\n", status));
return status;
}

/*set the PNP capabilities of our device. we don't want an annoying
popup if the device is pulled out of the USB slot.*/
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
pnpCapabilities.Removable = WdfTrue;
pnpCapabilities.SurpriseRemovalOK = WdfTrue; // we like surprises :wink:
// pnpCapabilities.NoDisplayInUI = WdfTrue; // this keeps it from appearing in Device Manager
WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);

devCtx = GetDeviceContext(device);
/*
status = CreateQueues(device, devCtx);
if(!NT_SUCCESS(status))
return status;
*/

// create i/o queues here

status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_OURDEVICE, NULL);
if(!NT_SUCCESS(status))
{
KdPrint((_DRIVERNAME"WdfDeviceCreateDeviceInterface failed" " with status 0x%08x\n", status));
return status;
}

KdPrint((_DRIVERNAME"<--EvtDeviceAdd"));
return status;
}

NTSTATUS EvtDevicePrepareHardware(IN WDFDEVICE Device, IN WDFCMRESLIST ResourceList, IN WDFCMRESLIST ResourceListTranslated)
{
NTSTATUS status;
PDEVICE_CONTEXT pDeviceContext;
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
BYTE numEndpoints;
WDFUSBINTERFACE UsbInterface;
WDF_USB_INTERFACE_SETTING_PAIR pairs;

UNREFERENCED_PARAMETER(ResourceList);
UNREFERENCED_PARAMETER(ResourceListTranslated);

KdPrint((_DRIVERNAME"-->EvtDevicePrepareHardware"));
pDeviceContext = GetDeviceContext(Device);

status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->UsbDevice); // create usb device
if(!NT_SUCCESS(status))
{
KdPrint(("WdfUsbTargetDeviceCreate failed in 'EvtDevicePrepareHardware' 0x%x\n", status));
return status;
}

UsbInterface = WdfUsbTargetDeviceGetInterface(pDeviceContext->UsbDevice,0);
numEndpoints = WdfUsbInterfaceGetNumEndpoints(pDeviceContext->UsbInterface,0);
KdPrint(("Number of Endpoints 0x%x\n", numEndpoints));

WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
// WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&configParams, 1, &pairs);

status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES,&configParams);
if(!NT_SUCCESS(status))
{
KdPrint((_DRIVERNAME"WdfUsbTargetDeviceSelectConfig failed in 'EvtDevicePrepareHardware' 0x%x\n", status));
return status;
}
pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; // connect the USB to the object context

KdPrint((_DRIVERNAME"<--EvtDevicePrepareHardware"));
return status;
}