LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Nugget: 1 of n : GEtting started with USB communication via VISA

USB is a serial bus protocol which has very little to do with classic “serial” communication such as RS-232 or RS-422. Getting to terms with USB for the first time can be daunting if you don't happen to have a background in similar protocols.

I have therefore decided to write a nugget (it's almost more of a blog to be honest) about my first steps in USB interfacing which were at times painful and frustrating. I have no background in USB or PCI (which is apparently somewhat more similar to USB than “classic” serial)

In order to get a feel for what exactly USB is, and how it works, the official USB 2.0 Specification is an essential read. I personally didn't understand everything in it, but even becoming familiar with the range of different options helps in understanding USB communication at a later point. Sometimes it is already of benefit to know exactly how lost you are..... The (650 page) specification can be downloaded HERE.

There are basically four defined modes of communication defined in the USB 2.0 specification:

  1. Control Transfers

  2. Interrupt transfers

  3. Bulk transfer

  4. Isochronous

There are specific classes of devices defined in order to try to bring some structure to the huge number of possible devices possible. These classes include:

  1. Audio

  2. Communications and CDC Control

  3. HID (Human Interface Device)

  4. Physical

  5. Image

  6. Printer

  7. Mass Storage

  8. Hub

  9. CDC-Data

  10. Smart Card

  11. Content Security

  12. Video

  13. Personal Healthcare

  14. Diagnostic Device

  15. Wireless Controller

  16. Miscellaneous

  17. Application Specific

  18. Vendor Specific

Each class has requirements on which types of communication must be supported and also regarding the format of the data exchanged with the host. Even touching on the surface of these class definitions would be way beyond this nugget.

We will be taking a relatively simple example of a HID device: a mouse.



--To be continued--


Message Edited by Intaris on 07-14-2008 11:24 AM
Message 1 of 104
(63,040 Views)
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><meta name="GENERATOR" content="OpenOffice.org 2.4 (Win32)">

Although interfacing with a mouse is a relatively easy task, we will look first at some details of the USB protocol. The best way to visualise this is by using a USB logger. Under Windows, 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.

Introducing a USB sniffer at this stage may be deemed overkill, especially for something relatively simple such a mouse, but it is a valuable tool which can be used for almost ANY USB device, especially devices for which you may not have an API description... (i.e. reverse-engineering).  The biggest advantage, however is the ability to see what data is being sent and received when using ANY driver, not just VISA as we will be doing later.

By attaching the device to the host computer and running such program, we can observe the communication between any program accessing the device and the device itself. A simple example is a standard mouse. By attaching a second mouse to the computer (recording one mouse but controlling the software with another allows cleaner recorded data) and telling the software to monitor the communication we can observe what is going on.

The following was recorded using a standard Microsoft mouse (installed with a standard Microsoft driver) when clicking and releasing the left-click button of the mouse:

000053: Bulk or Interrupt Transfer (DOWN), 25.06.2008 10:58:14.172 +0.0

Pipe Handle: 0x8a56490c (Endpoint Address: 0x81)

Get 0x4 bytes from the device


000054: Bulk or Interrupt Transfer (UP), 25.06.2008 10:58:44.968 +30.796. Status: 0x00000000

Pipe Handle: 0x8a56490c (Endpoint Address: 0x81)

Get 0x4 bytes from the device

01 00 00 00 <- Data received


000055: Bulk or Interrupt Transfer (DOWN), 25.06.2008 10:58:44.968 +0.0

Pipe Handle: 0x8a56490c (Endpoint Address: 0x81)

Get 0x4 bytes from the device


000056: Bulk or Interrupt Transfer (UP), 25.06.2008 10:58:45.125 +0.156. Status: 0x00000000

Pipe Handle: 0x8a56490c (Endpoint Address: 0x81)

Get 0x4 bytes from the device

00 00 00 00 <-- Data received


000057: Bulk or Interrupt Transfer (DOWN), 25.06.2008 10:58:45.125 +0.0

Pipe Handle: 0x8a56490c (Endpoint Address: 0x81)

Get 0x4 bytes from the device

The first thing to note is that the communication taking place is noted as “Bulk or Interrupt”. Since we're interfacing with a HID device, we know it's Interrupt. The data sent via Interrupt is called a Report. The entire report structure and it's determination is sufficient for a whole chapter in itself, so I won't go into more details here.

Interrupt transfers are designed to allow a device (in this case a mouse) to send data “unsolicited”* to the host. While the actual time of the communication is decided by the device and not the host, the host must first declare itself ready to listen to the device. Once this is done, the host is waiting for a response from the device (which may or may not come depending on whether the device is in use or not). This preparation for receiving an interrupt from the device is what we see in the commands 000053, 000055 and 000057 shown above. We can see from the direction of the communication (DOWN) that it is a communication from host to device. It is basically declaring itself ready for the receipt of a Report.

The other two entries (000054 and 000056) are the Reports sent to the host from the device upon interaction with the mouse. The timing data for transfer number 54 shows us that the data was received 30.796 seconds after we told the device we were ready to receive data. We see that the Reports are each 4 Bytes long.

After receiving a Report, the host must tell the device again that it is ready to receive, otherwise no further communication will take place. This is why we see that the communication listed under 000055 and 000057 are sent to the device immediately after receiving the data from the device.

So how do we implement this in LabVIEW?

*My understanding is that it's actually a hardware-driven polling, not a classic interrupt....


Message 2 of 104
(63,020 Views)
In Part 1 and 2 we have had a very brief introduction into finding out how a device works over USB. We have observed that a mouse sends data to the host via Report, that the Reports are 4 Bytes long and that each Report received is preceeded by a notice message from the host that it is listening.

Now we will implement something like this in LabVIEW:

NI has a good example called Interruptusb.vi which can be found HERE.

We need to install a VISA RAW driver for our desired device. A guide as to how to enable VISA RAW access to a device can be found HERE. After creating a VISA RAW device driver for the mouse we want to interface with, we can see how this software correlates with the data communication we have observed above.

Please note that a mouse isntalled as a VISA RAW device will NOT be used as a system mouse. To make things easier on yourself, attach a second mouse (or a third and fourth if you like – it should be possible to attach and interface to several mice simultaneously and independently).

After choosing the correct VISA device from the front-panel control (Your device descriptor may differ) and running the VI we end up with the following result (For a simple left-click and release):


We see that the Report returned is 4 Bytes long (Just as in the examples above). What we don't see is the second Report. This is because the VI does not continuously read from the device. It waits for a single event and then exits. If we want to create a VI which records data until we want it to stop, we must change the Block diagram from


this


to

this


Note that we have placed the while loop around the three middle functions. These functions are responsible for

  1. Notifying the device that is can start sending Reports

  2. Reading the data sent in the Report

  3. Disposing of the particular event.


If we run the monitoring software when using this method of interfacing with the Mouse, we should see exactly the same as we have previously observed. If we run the moniroting software before the VI we will see additional communication at the beginning of our log which is the initialisation of the device by VISA (To be dealt with on a later date).

We have now successfully interfaced with a USB mouse over VISA. The modified VI shown can be downloaded HERE.

But how do we transform this into something useful? What does the data we are receiving mean?

Hint: Anyone who does what is outlined here should pretty quickly grasp what the data means by playing around with it a bit........




Message Edited by Intaris on 07-14-2008 11:29 AM

Message Edited by Intaris on 07-14-2008 11:29 AM

Message Edited by Intaris on 07-14-2008 11:34 AM
Message 3 of 104
(63,017 Views)

Now that we have the data, we need to find out what it means and what we can do with it.

By playing around with the software we have previously created we can pretty quickly find out what the different data is. The first Byte is a bit array of the buttons pressed. 0 means no buttons pressed, 1 means button 1 pressed, 2 button two, 3 button 1&2 together and so on. I don't think an explanation of this is really necessary.....

The second two bytes are each a value for the relative movement of the mouse in X and Y directions. Since we have an 8-bit Integer for this, our range of movement is -127 to 127 with 0 being no movement.

If we have a mouse with a scroll wheel, chances are that the scroll wheel movement is reflected in the fourth Byte.

In order to better understand the data being sent by the mouse we should look at the specification of the HID class of USB devices. A document detailing what the HID class comprises is to be found here. Each device class has pre-defined functions which are used to allow for a certain level of generalisation between similar devices from different manufacturers. A mouse will, on most operating systems, work without a vendor-specific driver albeit without some functionality. This is because it adheres to the base HID mouse class.

The HID mouse class defines the Interrupt packet as follows (All HID mice must adhere to this format of the first 4 Bytes – further Bytes are possible, but their correct interpretation is not guaranteed):


Byte

Bits

Description

0

0

Button 1

0

1

Button 2

0

2

Button 3

0

4-7

Device Specific

1

0-7

X-Displacement

2

0-7

Y-Displacement

3+

0-7

Vendor specific


So we see that without any other information about the device, we can only assume that we have three buttons (even though they may not be physically present, or more buttons may actually be present) and an X and Y displacement value. As to the meaning of any other values in the data packet, we need further information about the device. The lack of a standard data entry for a scroll wheel is certainly something which contributes to the fact that not all scroll wheels work with the default (non vendor-specific) drivers delivered with Windows. Or as to why the fourth and fifth buttons of my Logitech MX518 don't always work with default Linux drivers......

Joysticks, keyboards, gamepads and a whole host of other devices can be interfaced with using basically the same code as shown here. The data being returned by the device is of course different in each case. Some devices also return multiple reports with an index number to let the software know which data is currently being reported.

I hope to return to this topic at a later date to delve deeper into the depths of the HID specification, but for now it's enough to say that without more coding (quite a lot more I fear) we must be content in adapting our code to each specific device on order to be able to interpret the data.

I am already working on a second part covering a different transfer type (Control Transfer). The topic of control transfers is a big one with a lot of corrollary information which is required to make sense of it all, so it might take a while......

In the mean time, here's a little program I whipped up using the information shown here......

An example of a little mouse component is here.

Shane.


PS: A generic mouse driver would be possible using LVOOP, allowing for the support of multiple models. How would go about this? What would the base-class look like? How would you interface to the host program? How would you handle other HID classes (Joysticks, touchscreen panels and so on)?

PPS: The code shown here may be useful as an introduction to USB, but can anyone think of any actual application which can benefit from a non-system pointing device or keyboard?



Message Edited by Intaris on 07-14-2008 11:34 AM
Download All
Message 4 of 104
(63,009 Views)
As usual, I have trouble limiting the size of my posts.....

This is meant as a very small introduction to USB. The great thing about using USB over VISA is that the same code will run on Linux, Mac or Windows.

I have also developed custom drivers from reverse-engineering a DLL simply be recording the USB communication.  That way I was able to run the software under Linux.

Depending on the feedback to this nugget, I may delve further into the HID class, or cover some of the Control transfer specifics of USB communication.

Personally, I'm still learning about USB, but I thought the work was frustrating enough to warrant sharing what little I know with others.  If I can save anybody even a fraction of the hassle I had getting the most basic USB communication up and running then I'm happy.

All feedback appreciated - especially critique.

Shane.


Message Edited by Intaris on 07-14-2008 11:40 AM
Message 5 of 104
(63,004 Views)

Bravo, Bravo!!!

I've never needed to do low-level USB comms before.  I was once curious and started poking around at it anyway.  Then I turned out the lights, shut the door, and backed away very quietly...

Thanks for sharing your findings.  Your posts help to make it all seem comprehensible without demanding hours and hours of study.  Not yet comprehendED but at least comprehensIBLE.  This thread will be the first place I turn if ever I decide to poke around with USB again.

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 6 of 104
(62,965 Views)
Kevin posted "Bravo, Bravo!!!"
 
I have to agree.
 
Before reading this Nugget I have looked to the vendor to provide some sort of driver, usially a dll. In at least one case I said
"Forget this USB interface, we'll;
 
1)use the serial port
2) Sell the customer a USB to serial converter
3) Write enough LV just to get the data we are after.
 
Like Kevin said I'll be coming back to this Nugget when I am handed another USB device that doesn't have a pre-written USB driver.
 
Crazy Idea Time!
 
With Shane's Nugget, a couple of USB robots or missle lanchers, and stategic use of VI server, we could pit our VIs against each other head-to-head. (all I have to do is convince my wife I desrve some robots and a camera to record the action)
 
Ben
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 7 of 104
(62,939 Views)



Like these cool things?  Sorry, I didn't put them in the nugget itself since we're not that far yet.......

I think there's at least one follow-up nugget in this, which direction would you guys want it to go in?

Shane.
Message 8 of 104
(62,921 Views)
Just don't point it at me!

Lynn
Message 9 of 104
(62,916 Views)

I agree that this is great and makes the topic very easy to understand. I'm not sure if I will have the need for using a USB device directly, but it's good to be over the initial hurdle.

More would be great, covering both the other types and working with an actual specific instrument. Also, details about the benefits of using USB (assuming it's not the only interface the device has) and maybe some details about what needs to be done on the VISA side (installing, configuring, deploying, etc.).



Intaris wrote:

can anyone think of any actual application which can benefit from a non-system pointing device or keyboard?


Sure - suppose you want a keypad or a joystick or a mouse which would only work on your application without requiring focus. Setting it up as not as an input device is very useful for that. Incidentally, how do you set such a device not to be recognized by the system?

Second minor point about that code - it has a timeout. Where does that come into play? The transfers you showed don't seem to have it, so I assume it's a VISA thing, but does that mean that if the timeout occurs than the PC (VISA, in this case) just stops listening?


PS: A generic mouse driver would be possible using LVOOP, allowing for the support of multiple models. How would go about this? What would the base-class look like? How would you interface to the host program? How would you handle other HID classes (Joysticks, touchscreen panels and so on)?


Interesting question, and one which the answer to is almost guaranteed to be lacking. Here's a quick thought, and one which only takes interrupts into account, since I don't really know anything about the other types.
 
You would probably want to inherit all devices from a single class (USB Device) just so that you can recognize the device plugged in and create an object for it. Then, you would implement a "read" method in this base class which would get the input of how many bytes to read from one of the inheriting classes by calling the parent implementation. If it's a HID, you can probably create an appropriate user event (hmm, a proper mouse scroll event...) and throw it there. The actual listening would probably be have to be done by a dynamically called VI.
Sorry, no real details at all, but as I said, it's just off the top of my head.

___________________
Try to take over the world!
Message 10 of 104
(62,839 Views)