Author Topic: Getting Initial Button Settings  (Read 5054 times)

sjt

  • Member
  • ***
  • Posts: 6
Getting Initial Button Settings
« on: June 04, 2017, 01:32:15 pm »
Jan - I've read "USB Complete" so many times, that it's falling apart. Brilliant book, thank you. I could never have started with Hids without the indispensable guidelines you give in there.

I've very substantially developed the Generic Hid to better suit my own purposes, and what I've done so far is all working flawlessly as far as I can see.

However, I'm trying to communicate with devices that have physical toggle switches (not momentary) - in other words, on/off switches that can be set by a human to ANY position or combination of positions BEFORE the HID handle exists. The particular devices I'm interfacing with don't have Output Report capabilities, but they do have feature Report capabilities.

The devices also have LED displays, and what those display depends on the settings of the switches. When a switch position CHANGES, I read the input report, and send back an appropriate Feature Report to update the display settings. That all works just fine - but note the word "Changes".

I can get input reports perfectly OK to check the switch positions at any time, but ONLY if one of those switches (Buttons) has been CHANGED from its initial position AFTER the device has been opened.

What I would like to do is to test the physical setting of those switches (ie buttons) immediately the device is opened, so that I can use those settings as the "on open" setting. From those initial switch positions I want to then send a Feature Report to correctly set the displays at the time the device opens, so that the displays show the correct setting without human intervention. Without being able to do that, the displays are incorrect, until I get the first Input Report when a human changes any of the switches or buttons.

I'm not asking for any code specifically (unless you have some!), but would just like a quick pointer from you please as to the generic steps I need to go through to achieve what I am trying to do.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Getting Initial Button Settings
« Reply #1 on: June 04, 2017, 09:21:45 pm »
To get initial data, the host application can use HidD_GetInputReport to request an Input report using a control transfer. The device firmware must support sending Input report data using a control transfer.

I'm glad to hear you've found USB Complete useful!

sjt

  • Member
  • ***
  • Posts: 6
Re: Getting Initial Button Settings
« Reply #2 on: June 04, 2017, 11:38:15 pm »
Thank you. I've tried that, and I never get a satisfactory response. When I pass the input buffer (correct size!) "HidD_GetInputReport(HidHandle, buffer, buffer.Length)"  always returns "False, and resets the buffer size to 1, with a zero byte in it.

I'll play with it a bit more and see if I can see what silly mistake I must be making.

The book? Yes - fantastic, thanks. I could not have written a single line of what I'm doing now, without the wisdom of the book. I've been around the block a bit on other .net stuff for quite a few years, but this is a new field for me.....

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Getting Initial Button Settings
« Reply #3 on: June 05, 2017, 10:02:11 am »
Use whatever debugging tools you have to verify that the device is seeing the request and to determine how it is responding - should be ACK in Setup stage, data in Data stage, ACK in Status stage.

sjt

  • Member
  • ***
  • Posts: 6
Re: Getting Initial Button Settings
« Reply #4 on: June 05, 2017, 10:13:32 pm »
I don't think I'm clever enough for that. I am only using Visual Studio, managed code for everything I'm doing, as far as possible.

I've tried pretty much everything with this, in case I have buffer sizes wrong. But I don't think so. I put a loop around the HidDGetInputReport call so I could test thousands of options of buffer sizes and buffer lengths, and nothing whatsoever returned a positive result. It always returns a buffer reduced in size to one byte long, with whatever value I had put in the first byte ,still in it.

If instead of that I use either a synchronous or async transfer, it works perfectly OK, but of course doing that needs some sort of human trigger to get the device to send the report first. That's not what I want. However, this feature is "icing on the cake" as far as I'm concerned, and I've given up on it for the time being as it's not important enough to me in the big picture. It does not affect the overall application I'm working on in any significant way - but it would be a "nice to have".

 I'll press on without this feature, and come back to it at some stage in the future if I feel I need to tidy this up.

I must be missing something incredibly basic, but have no idea what that is at the moment.

Thanks for your help.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Getting Initial Button Settings
« Reply #5 on: June 06, 2017, 08:10:23 pm »
All HIDs should support sending Input reports using control transfers, but it's possible your devices do not.

sjt

  • Member
  • ***
  • Posts: 6
Re: Getting Initial Button Settings
« Reply #6 on: June 07, 2017, 06:05:31 pm »
Hi Jan,

That's an interesting thought, so I decided to check that out with other devices - just to make sure that some DO return a report. That had some unintended consequences !

I have 17 HID devices attached to my system, and the app I have written enables me to "play" with any of them interactively. I tested the control transfer option with all of them to see what happens. Using async input reporting, and feature reports where appropriate, I had previously had no problems with any of them - and still don't.

I have set <HandleProcessCorruptedStateExceptionsAttribute> and  <SecurityCritical> on critical methods so that I should be able to trap every expected type of exception in case of any unmanaged code infringements.

When using the HidD_GetInputReport control transfer option  I had all sorts of problems. When used on one device, the entire app crashed with no explanation. I could not trap the exception any way I tried. I have exception handlers for AccessViolation, ComException and "generic" exceptions set, but that particular device error ignored all of those. Yet the same device handles async reports perfectly normally. I have so far not been able to find out what exception is causing this device to behave like this. It's just rogue.

Another device caused an AccessViolationException when attempting to get an input report by control transfer

One device crashed, and I lost all contact with it .....couldn't even detect it till I restarted my system!

Some devices did return an input report, most did not. The fact that any returned a report tells me that if the basic syntax of what I have done is wrong - it can't be too wrong! I've checked as far as I am capable of doing to see if all my variable sizes correctly match what's expected in the API, and I couldn't see any glaring errors. Apart from a couple of minor warnings about Native methods, the VS2017 code analysis reported nothing alarming.

So - right now, I am at a loss.

As another test, I compiled your Generic HID VB.NET app and used it "as is" apart from changing a couple of things that had been written for 32 bit code so that variable lengths matched 64 bit (my OS is 64bit). The HidD_GetInputReport call failed exactly the same in yours as it does in my code by returning a single byte-long input buffer.

So - I'm concluding that this is indeed a device-dependent mystery, probably in the devices' firmware. Coincidentally, all the devices that behave abnormally come from the same manufacturer or stable - so perhaps that's where the problem lies. I'm not a comms expert at all, so am not capable of digging with more sophisticated tools than VS.

I'll get back to this at some time in the future as I can't spare it more time right now. Unfortunately it's bugging me, as these things do. The "icing on the cake" is in danger of consuming more time than I wanted it to; doesn't it always?