Showing results for 
Search instead for 
Did you mean: 

Nugget: 2 of n : USB Control transfers using VISA


In the first part of my USB nugget(s) I showed some ways to get started with Interrupt transfers using a mouse as an example. Today I'm going to briefly touch on a second type of USB transfer, the Control transfer.

As with the first nugget, the USB 2.0 specification is a must-read (especially chapter 9) when attempting to understand USB communication. The specification can be downloaded HERE. You will also need to install (on Windows at least) a VISA RAW driver for whatever device you wish to use. A guide as to how to enable VISA RAW access to a device can be found HERE.

There are four types of transfer in the USB 2.0 Specification (Paragraph 5.4, Page 36 of the USB spec). Each different sort of transfer has different characteristics in an effort to allow for very different types of devices.

Transfer Type


Used for


Up to 15.8MB/s

Every Device must support these

Used for Enumeration

Extendable : Custom functions



Up to 49MB/s


Guaranteed low latency

Guaranteed throughput

HID (mouse, Keyboard)


Up to 49MB/s

High speed

No Error-correction

Guaranteed bandwidth




Up to 53MB/s

High speed (on unused bus)

Error Correction

Low priority on bus

Test & Measurement

Mass Storage

ALL USB devices MUST support control transfers as this is the method used during enumeration on the bus. A host controller will retrieve vendor ID, Device ID and a host of other information via Control transfers during enumeration. This data is retrievable via a group of standard requests. All devices, irrespective of their current state are required to respond to all of these standard requests. As such, they are ideal for testing whether communication is working or not.

I will focus only on non-compound devices in this nugget. Compound devices are devices which have more than one interface. These could be (in the example of a USB-music player) “HID” interface for any controls and “Audio” interface for music streaming. The device could additionally have a “Mass Storage” Interface for easy data copying. I have not (yet) delved into compound devices so I am unable to offer any useful information on that front.

I will also highlight how USB Control transfers look when using a USB Logger and how many devices use Control transfers for their own communication (with a simple example).

Message Edited by Intaris on 08-05-2008 10:04 AM
Message 1 of 36

For USB Logging, I personally have found the (non-free) “Device Monitoring Studio” (which seems to have been renamed to “USB Monitor”) to be of great help. Other, free programs are available such as “Snoopy Pro”. These programs sit between the Operating system and the device driver and records all communication.

In the examples I will work through, I had the luxury of having a pre-existing working driver for my target device which I could already use in LabVIEW. This enabled me to use a USB logging software to see exactly what was being sent to the device and what was coming back. Since I could already control the device via LabVIEW (Via DLL) I was relatively quickly able to pin-point which commands were tied to which functions.

A quick mention to the “why” of this action if I already had a driver. Apart from “because I could”, I wanted the software to run under Linux. The supplied DLL wouldn't do that..

A sample log of a basic communication may look like the example shown below. Entries 000050 and 000051 belong to a standard request defined within the USB Specification used to get the Device Descriptor (Table 9-3 on Page 250). The second pair (000052 and 000053) are custom device-specific requests which were the target of my investigations. All data needed to implement this call through VISA is presented in an easy-to-understand form.

000050: Get Descriptor Request (DOWN), 09.11.2007 14:35:32.156 +33.156

Descriptor Type: Device

Descriptor Index: 0x0

Transfer Buffer Size: 0x12 bytes

000051: Control Transfer (UP), 09.11.2007 14:35:36.781 +4.625. Status: 0x00000000

Pipe Handle: 0x88df4020

12 01 00 01 00 00 00 40 61 06 00 29 00 00 00 00 .......@a..)....

00 01 ..

Setup Packet

80 06 00 01 00 00 12 00 .......

Recipient: Device

Request Type: Standard

Direction: Device->Host

Request: 0x6 (GET_DESCRIPTOR)

Value: 0x100

Index: 0x0

Length: 0x12

000052: Vendor-Specific Request (DOWN), 09.11.2007 14:35:36.781 +0.0

Destination: Other

Reserved Bits: 0

Request: 0x4

Value: 0x1c8

Get 0x8 bytes from the device

000053: Control Transfer (UP), 09.11.2007 14:35:36.781 +0.0. Status: 0x00000000

Pipe Handle: 0x88df4020

62 31 30 34 37 31 30 32 b1047102

Setup Packet

C3 04 C8 01 00 00 08 00 Ã.È.....

Recipient: Other

Request Type: Vendor

Direction: Device->Host

Request: 0x4 (Unknown)

Value: 0x1c8

Index: 0x0

Length: 0x8

The data packets (in this case Device to Host) are shown in italicised bold font. The setup Packet is not of interest for us at the moment as VISA takes care of this when we give the correct transmission parameters. The USB transmission parameters used to initiate this transfer is shown at the bottom of each entry (Recipient, Request type and so on). These seven parameters are detailed enough for us to be able to implement the functionality we require.


I personally got stuck at this point for quite a while trying to implement this in LabVIEW. The information IS all in the USB specification, but it required a lot of trial and error on my part to get it working. I want to help others avoid thie trial and error part by sharing with the community how I got this done.

-End Note-.

Message 2 of 36

The key to understanding what these seven values are is listed in Table 9-2 of Paragraph 9.3 of the USB Specification document, reproduced here (hoping I don't get sued for Copyright infringement).

Examining the USB Logger output and Table 9-2 we can find all seven of our USB parameters. Three of the parameters are actually bitmapped into a single value “bmRequestType”. The Direction of the request (Command to device or request from device), What type of request it is (Standard, Class, Vendor) and the intended recipient of the packet (Device, Interface, Endpoint or Other). The other four parameters are passed individually.

The second entry in the table is the “bRequest” entry. Table 9-3 of the USB Specification lists several standard request types. Tables 9_4 and 9_5 are also required in order to fully understand what is going on here.

Table 9_4 lists the Byte values for each of the standard bRequest types. In the case of the bRequest Types “GET_DESCRIPTOR” or “SET_DESCRIPTOR” an additional value is required as to what TYPE of Descriptor is involved. These values are then listed in Table 9_5.

We now have enough Information to understand what the request listed in the USB log above is actually for.

The first three entries;

Recipient: Device

Request Type: Standard

Direction: Device->Host

tell us that we are sending a data packet to the device, making a request for information from the device and that the request is a Standard request.

The following line

Request: 0x6 (GET_DESCRIPTOR)

tells us that the standard Request being executed is a request for a Descriptor. Looking at the entry in Table 9_3 for the Request “GET_DESCRIPTOR” tells us what the last three values mean:

Value: 0x100

Index: 0x0

Length: 0x12

Value represents “Descriptor Type and Descriptor Index”. The first 8 Bytes correspond to the value 1, which from Table 9_5 tells us is the DEVICE Descriptor. The second Byte is zero, telling us that we want the Descriptor at index zero (Some Devices have multiple instances of a certain type of descriptor).

Index represents “Zero or Language ID”. Since this value is zero, we are requesting the default descriptor. Since Descriptors may contain text which is language-dependent, a device can store many different descriptors for different languages if required.

Length represents the “Descriptor Length”. Although we are required to enter a value here, it can often happen that the returned descriptor is longer than the requested length. Since the length of the actual descriptor is contained within the header for the actual descriptor (18 Bytes, 0x12 in Hexadecimal Paragraph 9.6.1, Table 9_8 on Page 261 and onwards of the USB Specification), an initial request for 18 Bytes is normal which can then be followed up with a request for the corrent length of descriptor.

This is jsut a single example of a command which according to the USB specification EVERY USB Device should respond to. As such it can be used to test any early attempts to get USB communication up and running.

I have also implemented a couple of simple enums for the values of the Standard Request Codes and the Descriptor Types as outlined in Tables 9_4 and 9_5.

Now that we know what the various entries in our USB Log are for, we can move over to implementing some communication in LabVIEW.

Message Edited by Intaris on 08-05-2008 10:18 AM
Download All
Message 3 of 36

If we now look at the Connection pane of the respective VISA function we see all these values present also.

- Note - I was initially very confused with the nomenclature “Control IN” and “Control OUT”. I thought it counter-intuitive that the function for sending requests to a device is called “VISA USB Control In” and not “Out”. An example from NI finally sorted me out (Which I unfortunately cannot locate at the moment).

- End of Note -

Assuming we have implemented our RAW driver as outlined in the NI tutorial above, we should be able to choose our device from a VISA control. In the examples shown below, I have connected a second mouse (Microsoft 2-Button mouse with scroll wheel) to my PC and have run the Device driver wizard for VISA. Once this is completed, the device is visible whenever I use a VISA control set to USB devices.

Once we have done this, any devices configured for USB RAW communication via the VISA Driver wizard should be visible.

The first device shown here is a USB Spectrometer I have been communicating with over USB, the second is the MS-Mouse (Vendor ID 0x045E, Product ID 0x0084).

We can then use the VISA Open just like any other VISA resource to open a handle to the device.

Now all we need to do is wire up our request to the device for a device descriptor and we're basically done.

The picture below shows the values needed for a simple device descriptor request using the Vis and controls I have implemented.

We can see that we are doing basically the very same request as originally recorded using the USB Logger program mentioned at the beginning.

As a reminder:

Recipient: Device

Request Type: Standard

Direction: Device->Host

Request: 0x6 (GET_DESCRIPTOR)

Value: 0x100

Index: 0x0

Length: 0x12

The “Index” value is not shown because the default value for the “VISA USB Control In” VI is already zero.

The result of this communication should now be available at the output terminal of our VISA Control In VI. In order to format this into something we might understand, the following code is used:

The Constant “USB _bDescriptor Type 1” is a Typedef representing the data structure of the Device Descriptor as outlined in Table 9_8 of Paragraph 9.6.1 of the USB Specification. The first two Bytes are ignored as they contain information not required by the conversion (Descriptor size and bDescriptor Type). We could incorporate these two Bytes into our Typedef and do away with this step.

In order to convert the received 16-bit values into a LV-Conform format, we perform a Byte Swap on the values “bcdUSB”, idVendor” and “idProduct”.

In the case of the MS Mouse, we get a data structure as follows:

We see the Vendor ID (0x045E) and the Product ID (0x0084) are contained within the Device Descriptor. This is actually the method used by the OS to determine what has actually been attached to the computer.

We also see some other information such as max Packet size (8).

Using this nugget, we have enough information to request other device information also, such as the “Standard Configuration Decsriptor” from the device. This is already implemented in one of the Vis attached.

The functionality highlighted in the USB Logger information at the beginning of this nugget can now easily be implemented in LabVIEW. The device-specific part was a request to a miniature USB spectrometer to retrieve the serial number of the unit. Using the USB Logger (And some good guess-work to work out the format of transferred data) I have been able to implement a pure G (USB via VISA) spectrometer driver for my applications. The program works under Windows and Linux. Should work under Mac too, but I haven't got a mac for testing.

This nugget has truly only scratches the surface of USB Control transfers. For those of you willing to go through the hardships of getting acquainted with USB, I hope the information and Vis posted here help reduce the probability of hair loss in the process.

Please download the code shown below and try experimenting.

Any corrections / Comments are as always more than welcome.


Message Edited by Intaris on 08-05-2008 10:23 AM
Message 4 of 36
I forgot a picture in the last post : the result of formatting the device descriptor:

I haven't gone into depth about the actual data structure of the varying descriptors in the USB spec.

They can be found in Section 9.6 (Page 261 to 274) in the USB Spec.

16-Bit numbers must be byte-swapped before LV can work with them.


Message Edited by Intaris on 08-05-2008 10:34 AM

Message Edited by Intaris on 08-05-2008 10:35 AM
Message 5 of 36

You almost make me WANT to do USB communication. Smiley Very Happy

At least I know that when I do, I'll have where to start.

Try to take over the world!
Message 6 of 36

This is excellent timing... 

I am starting a USB project..  Hope it's okay to ask "general" questions in this thread.  I'll start new thread for specific ones..

Great Nugget! Many Thanks!



Message 7 of 36
@Tst, @JoeLabView

Glad to help.

Re: Questions, fire away.  I think it's important to have general questions in the nugget thread, because I'm only one person with limited time, so I've certainly not covered everything of interest on the topic.  That way, people reading the nugget also get the extra info for "free".


@JoeLabView: Congrats on your Zeal.

Message Edited by Intaris on 08-06-2008 02:36 AM
0 Kudos
Message 8 of 36

Thanks Shane!

I will not be able to give this serious read today since it requires more than the 9 minutes I have available today. Smiley Surprised


Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 9 of 36
This insight to USB using VISA is just great!
Thanks a lot for sharing.

Too bad I don't have a project right now where I could use the information in this nugget Smiley Wink


0 Kudos
Message 10 of 36