One of the most helpful aids when first starting out in something new is examples. Cypress forgot this when they introduced their USB Starter Kit. But then for $99 U.S., you can't expect the world. The USB Thermometer Driver and Application was developed under contract by System Solutions firstname.lastname@example.org. The code is not freely available.
What I have done is modified the WDM ISO USB driver distributed with the Windows Device Driver Kit for use with the Cypress Digital Themometer. I've kept it basically the same, so you can actually run the Digital Temperature Application on this driver to see that in-fact it does work! I will cop some flap for this, as the driver isn't really a good example to start with, especially if you know little about WDM Programming, as you will learn some bad habits. I'll point these out.
As the driver is based on copyright material developed by Microsoft, I will not distribute the entire driver. What I will attempt to do, is show you the modifications necessary to change the driver so that it works with the Cypress USB Starter Kit. This hopefully will also give you a better understanding as we work through the example.
The driver is simply the ISO_USB driver featured in the Microsoft DDK with modifications in IsoUsb_CreateDeviceObject so you can talk to the Kernel Mode Device Driver using "\.\\Thermometer_0". This allows the Cypress application to talk to the driver, rather than using the GUID which Microsoft uses in their example.
The IOCTL handler has been totally modified to handle calls from the thermometer application which comes with the Cypress Kit. This allows you to run the Cypress Thermometer Application on this device driver. It includes all the IOCTL Control Code 4 Functions such as Set LED Brightness, Read Thermometer, Read Port, Write Port, Read RAM, Write RAM & Read ROM as per the Cypress Starter Kit User Guide(Ver 0.993) Page 48.
Modifiying the IOCTL Call Handler.
O.K., forget the modifications. We will start the handler for the IRP_MJ_DEVICE_CONTROL from scratch. Delete or rename IOCTLISO.C.
Below is the table of functions we will have to implement. This is simular to the table provided by Cypress for compatibility.
At first glance, you would expect the Cypress USB MCU to send the temperature using an Interrupt transfer periodically. After all, the Cypress USB MCU returns an Endpoint Descriptor for EP1 as type equals Interrupt, Maximum Packet Size of 8 Bytes and an Interrupt Interval of 10mS. The String Descriptor for this Endpoint returns "Endpoint1 10ms Interrupt Pipe".
At this stage you jump straight to the vector table. The 128us timer is not used, the 1024us timer is, and the endpoint1 interrupt is not used. The Interrupt Service Routine for the 1024us interrupt, simply checks for activity, sets the suspend accordantly, helps with the button de-bounce. Maybe the 10mS Temperature Interrupt is done in the main loop?
Jumping to the code for the main loop shows we wait for enumeration, Set the Enumeration LED, Read Temperature, Update Brightness, and Set new Brightness. Maybe it's in the Read Temperature Routine? The Read Temperature Routine firstly initialises the results, reads the temperature from the DS1620 and stores it in the FIFO for Endpoint 1.
So where is the code for the Interrupt Transfer? Good question, you tell me? (Have I overlooked something?)
Now what if we were to implement a couple of functions. Maybe ReadRAM, WriteRAM? We could then check the status of the switch by reading a value in RAM. We could read the temperature, provided the temperature was stored in a RAM Location. Umm, life would be easy. We could change the LED Brightness if we write the brightness to a location and set the Update Brightness Semaphore!
This is what I believe has been done. Please correct me if I'm mistaken!
Figure 1 : Flow Chart of Endpoint1
The documentation for the Cypress kit would suggest there is only one valid IO Control Code, IOCTL 4. All driver functions are called within this IOCTL Code. This is certainly not recommended practice. Microsoft has a macro called CTL_CODE which is defined in DEVIOCTL.H which is included in the Device Driver Kit.
// Macro definition for defining IOCTL and FSCTL function control codes. Note // that function codes 0-2047 are reserved for Microsoft Corporation, and // 2048-4095 are reserved for customers. // #define CTL_CODE( DeviceType, Function, Method, Access ) ( \ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ ) The two least significant bits (Method) map the buffer transfer type which determines how the buffer is passed in IOCTL calls. We need to use Method Buffered, thus both bits must be zero. #define METHOD_BUFFERED 0 #define METHOD_IN_DIRECT 1 #define METHOD_OUT_DIRECT 2 #define METHOD_NEITHER 3
The function defines which function we wish to call. The Kits has used Function 1, thus generating an IOCTL code of 4. The Access Type is FILE_ANY_ACCESS (0x00), and the Device Type is Zero. This is not defined in DEVIOCTL.H and Microsoft has reserved Device Types of 0-32767. We should probably be using something like FILE_DEVICE_UNKNOWN 0x00000022. Likewise Function Codes codes 0-2047 are reserved for Microsoft Corporation, and 2048-4095 are reserved for customers.
On top of the IOCTL4, I have added extra IOCTL Calls to all the descriptors, Get the Status, and Send custom URB_FUNCTION_VENDOR_ENDPOINT Commands, should you wish to later add more Vendor Commands to the firmware.
Download Source Code & Driver