USB Human Interface Devices

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
Have any of you ever dealt with these? I'm dealing with a device that has physical bounds. It spins, but when it hits its bounds servos start grinding. Any InputReport requests at this time would return a different value than normal indicating that it's at it's physical limits.

What I'm wondering is, do I specifically have to request an input report to get this value, or can I set something (an interrupt?) to automatically register that value and call a function to stop the device from moving?

Target language would be C++.
 

Modelworks

Lifer
Feb 22, 2007
16,240
7
76
Need a lot more detail. What device are you interfacing too ? What device spins ? What is the program attempting to do ?
 

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
Originally posted by: DarkForceRising
Have any of you ever dealt with these? I'm dealing with a device that has physical bounds. It spins, but when it hits its bounds servos start grinding. Any InputReport requests at this time would return a different value than normal indicating that it's at it's physical limits.

What I'm wondering is, do I specifically have to request an input report to get this value, or can I set something (an interrupt?) to automatically register that value and call a function to stop the device from moving?

Target language would be C++.

Is your embedded device already set up for the HID class? If so, why not use the class standard to communicate? It has specific endpoints and reports implemented and sending bound values is nothing more than sending a 0 or 255 (or 65535 if the field is a word) in any data field of the report.
 

sao123

Lifer
May 27, 2002
12,653
205
106
Originally posted by: Modelworks
Need a lot more detail. What device are you interfacing too ? What device spins ? What is the program attempting to do ?

is the device purely driver driven? or does it have its operating system?
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
The device is actually one of the Dreamcheeky USB driven Nerf Guns you can get online. It has several servos that spin the gun right and left as well as tilt it up and down. It's set up as a HID device, it does not have its own operating system, to my knowledge, and I have the product/vendorIDs. There are several open source programs that interface with this specific device, so I know the different values that are used for commands as well as return values. My problem is that none of the open source programs are in C++ on Windows.

I have a program based off of the Visual C++ 6 program on this site: http://www.lvr.com/hidpage.htm . I've modified the program (it's based around a gui) to be usable in a console type application. I can currently get the modified program to connect and send commands to the nerf gun. I cannot get the program to read values from the gun. Say I send the gun a 'go right' command. It will keep going right until I send 'stop.' For the most part, the gun returns a default value when it's in the middle of moving or not doing anything. Whenever the gun gets to the bounds of it's movement, the servos start grinding and it returns a special value (when queried) signifying that it can't go any further.

As I understand it, with the HID interface I can send commands and get reports from the device. But I actually have to manually tell it to send a command or try to read a report. Which means even if the device hits physical bounds, I have to request a report to see if it's returning one of the special values. What I'd like is to tell it to move right, and then when it's at full right, read an input report. I'd prefer for the program not to have to sit their polling for a report, thus me asking about an interrupt.

Is this any clearer at all?
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
It sounds like it works just like a mouse. When writing event driven programs you'd like to just set an interrupt handler and get control every time the mouse state changes, but like the joystick you have to read it (at the lowest level). Windows wraps that with essentially a low-level loop that is always watching the mouse and keyboard and firing events. So what you probably have to do is either write a timer interrupt to wake up every few ms, check the device, and call and cause and raise an event if the device state has changed, or write a loop that does it.
 
Sep 29, 2004
18,656
67
91
If anyone wants to have fun, a Nintendo Wii can be used on your PC. their are open source libraries for it I think.
 

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
Originally posted by: DarkForceRising
The device is actually one of the Dreamcheeky USB driven Nerf Guns you can get online. It has several servos that spin the gun right and left as well as tilt it up and down. It's set up as a HID device, it does not have its own operating system, to my knowledge, and I have the product/vendorIDs. There are several open source programs that interface with this specific device, so I know the different values that are used for commands as well as return values. My problem is that none of the open source programs are in C++ on Windows.

I have a program based off of the Visual C++ 6 program on this site: http://www.lvr.com/hidpage.htm . I've modified the program (it's based around a gui) to be usable in a console type application. I can currently get the modified program to connect and send commands to the nerf gun. I cannot get the program to read values from the gun. Say I send the gun a 'go right' command. It will keep going right until I send 'stop.' For the most part, the gun returns a default value when it's in the middle of moving or not doing anything. Whenever the gun gets to the bounds of it's movement, the servos start grinding and it returns a special value (when queried) signifying that it can't go any further.

As I understand it, with the HID interface I can send commands and get reports from the device. But I actually have to manually tell it to send a command or try to read a report. Which means even if the device hits physical bounds, I have to request a report to see if it's returning one of the special values. What I'd like is to tell it to move right, and then when it's at full right, read an input report. I'd prefer for the program not to have to sit their polling for a report, thus me asking about an interrupt.

Is this any clearer at all?

Each endpoint on the device is configured for a specific USB mode (control, bulk, interrupt, or isochronous).

I don't deal with HID devices in details as I usually do my own custom classes, but if it has an endpoint configured for interrupt mode and the device uses that endpoint to send servo positions then you're pretty much set.

If the device is not setup that way, you can still get reports at a periodic rate by polling the device (sampling) at your defined sample rate on the PC and check for servo position.

If you have access to a USB analyzer, post the enumeration details and I'll see if I can help you out. The endpoint descriptors should show 0x01 or 0x03 at byte offset 3 in the data packet for isochronous or interrupt mode.
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
I'll have to try to get enumeration details tomorrow morning.

Edit: Oddly, the example code I had actually had a way to implement timers, which is what I needed, maybe. Unfortunately, I still can't get my modified code to read from the gun, while the example code can. Unless the window needs to be registered for device notifications (unplugged/plugged) to read from the gun, I haven't the faintest idea what's wrong, because my code is pretty much identical.
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
I'm running a program called SourceUSB (trial version). As far as I can tell, it's set up for interrupt mode.

Ran a quick test, and one of the outputs was:
Descriptor Type : ENDPOINT
bmAttributes : Interrupt (0x03)

I'm guessing that means I can use interrupt transfers?

Gah, I got the thing reading correctly. The example code, as far as I could see, never reset a handle for an event, and it still worked, whereas I had to manually reset it.

Edit/Addition:
If I wanted to read from the gun every say, 500 milliseconds, how would I go about doing that? Can anyone point me at documentation for timer based interrupts? The timer that my example used appears to be part of the Cwnd class, which I don't have in a console application.

Alternatively, how can I set up interrupts for changes on the device (since from the top of my post it looks like I can use interrupt transfers) so I don't need to use a timer?
 

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
Originally posted by: DarkForceRising
I'm running a program called SourceUSB (trial version). As far as I can tell, it's set up for interrupt mode.

Ran a quick test, and one of the outputs was:
Descriptor Type : ENDPOINT
bmAttributes : Interrupt (0x03)

I'm guessing that means I can use interrupt transfers?

Gah, I got the thing reading correctly. The example code, as far as I could see, never reset a handle for an event, and it still worked, whereas I had to manually reset it.

Edit/Addition:
If I wanted to read from the gun every say, 500 milliseconds, how would I go about doing that? Can anyone point me at documentation for timer based interrupts? The timer that my example used appears to be part of the Cwnd class, which I don't have in a console application.

Alternatively, how can I set up interrupts for changes on the device (since from the top of my post it looks like I can use interrupt transfers) so I don't need to use a timer?

How do you know the device is using that endpoint to send the data in interest? Just making sure because a device can have multiple endpoints with same type.

If the data is using an endpoint interrupt, the usb device driver will automatically handle that for you. All you have to do add provisions to check/parse the data and take action on it.
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
That was actually the only endpoint that I noticed. I'm really not sure how to go about checking those. I tried a program (noted above), but most of the output means nothing to me.

When you say USB device driver, what exactly are you referring to?
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
I've been unable to find a definitive answer for this: Does the Windows HID library require MFC?

I'm getting royally annoyed at this. I have a full version of Visual Studio 6.0, which has MFC, which appears to be required for HIDs. The version of the Windows DDK I have is apparently too new for 6.0 to support, and VS 2008 Express doesn't come with MFC, I believe. Any ideas how I could work this out? Is there a way to get older DDK versions? Or is there a way to get 2008 Express to support MFC?
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
If older versions of the DDK are around they'll turn up on Google. As for VS2008 and MFC, as far as I can tell you need to buy the lowest tier commercial version to get MFC. Do you need to build, or just need the runtimes?

Btw, my brother sent me one of those DreamCheeky missile launchers as a gag. I can get it to spin around and elevate in Vista, but it won't fire. I downloaded the latest software and got the cool new UI, but when I click fire the sounds play and the client hangs. So if you make better software send me a copy :).
 

DarkForceRising

Senior member
Apr 16, 2005
407
0
71
So currently I'm getting a couple of linker errors. From reading online, it sounds like I may just have to link to the correct libraries. Currently, I'm linking to setupapi.lib, hid.lib, and mfc42ud.lib.

The errors I'm getting are thus:
1>dartgunapp08.obj : error LNK2019: unresolved external symbol "int __stdcall AfxWinInit(struct HINSTANCE__ *,struct HINSTANCE__ *,wchar_t *,int)" (?AfxWinInit@@YGHPAUHINSTANCE__@@0PA_WH@Z) referenced in function _wmain
1>dartgunapp08.obj : error LNK2019: unresolved external symbol "public: __thiscall CWinApp::CWinApp(wchar_t const *)" (??0CWinApp@@QAE@PB_W@Z) referenced in function "void __cdecl `dynamic initializer for 'theApp''(void)" (??__EtheApp@@YAXXZ)

Any idea what I might need to link? Or is this something else?
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
You're either missing a linker reference, or you have incorrect compilation models (i.e. the function name is mangled in one place and not the other). Those functions are fundamental to MFC startup code, so if you are sure you have all the libraries you need, then it might be incorrect compilation.