Teensyduino USB Joystick no-data driver problem/workaround

gwideman

Well-known member
Hi all,

This post reports on the Teensy++ 2.0 example Joystick/Complete not working on some machines.

We have the guts of an analog joystick (with switches) wired to the Teensy, running the example code.

When plugged into several different Windows desktops or laptops (mostly Win 7 pro), this works fine, for example as seen in joy.cpl, or using Joystick Tester (http://www.mcrenox.com.ar/downloads/).

However, when plugged into a particular laptop ("The Problem Machine", Lenovo Z575 Win 7 Home), although the Teensy appears in joy.cpl, the Properties window is blank (no graph of X-Y, slides or switches).

Another user also reported this kind of problem: http://forum.pjrc.com/threads/1319-teensy-2-joystick-stopped-working

Joystick Tester on the Problem Machine is similarly without data. Notably, the panel which shows data from the HID Report shows Max axes 6, Number of axes 0, Max buttons 32, Number of buttons 32.

I.e., Windows sees the joystick device, can read its device info, but mysteriously the number of data items actually available is zero.

This is the behavior when the Teensy code is compiled with the Arduino "USB Type" set to "Keyboard + Mouse + Joystick".

If instead we switch USB Type to "Serial + Keyboard + Mouse + Joystick", then the joystick works fine on The Problem Machine.

So is seems that there is something in the config_descriptor or joystick_hid_report_desc, when it's compiled with "K+M+J", that causes The Problem Machine to think there are no data items for the Joystick.

Bear in mind, again, that "K+M+J" works fine when Teensy is plugged into the six different other machines that we tried.

We also tried deleting all the serial code from example Complete (and also the examples that don't use serial), and these moves didn't result in proper behavior on The Problem Machine.

So, we have the workaround of using SUB Type = S+K+M+J, but it's worrisome that just K+M+J didn't work.

Other info:
-----------
These results (K+M+J bad, S+K+M+J good) were obtained after installing Arduino 1.0.4, Teensyduino 1.13 and teensy serial driver onto The Problem Machine. The non-working condition was encountered prior to installing Arduino etc. What we don't know is whether S+K+M+L would have worked with Arduino etc not installed (and/or whether that would prompt Windows to look for a serial driver -- doh!).

----------
Ideas?

-- Graham
 
Joystick no-data problem solved

Issue addressed
---------------
This concerns Teensyduino USB joystick, on a particular "problem machine", showing up in joy.cpl, but with the Properties window displaying blank, as though the joystick contains no analog or digital variables. On other machines the Teensy USB joystick works fine.

Short version of fix
--------------------
Delete from the registry all keys containing VID_16c0.

Explanation
------------
After a lot of inspection of Teensy USB traffic with USBLyzer, I think we have an answer and a fix for the problem. The USB activity during hot-plug indicates that on the problem machine, Windows associates driver mouhid.sys with the joystick. On machines that read the joystick properly, Windows associates the joystick with hidusb.sys.

The registry stores a lot of keys in various places that contain the Vendor Id used by the joystick: VID_16c0. It appears that the function of some of these keys is to remember the result of the first time the device was plugged in, and a driver found. There are separate keys for the different sub device Product Ids corresponding to Mouse, Keyboard, Debug and Joystick, and possibly Serial (depending on the setting for USB type in the Arduino environment), and this info may be stored separately per USB socket.

It seems that if that process decides on the "wrong" driver for some reason (for example, chooses the mouse driver mouhid.sys), then the system will be stuck with that choice in future. This mistaken association could perhaps happen during development with the Teensy, or perhaps due to interrupting the process of finding the right driver during initial plug-in.

In previous attempts to fix this problem, we used USBDeview to view information that Windows was retaining for various USB devices. In USBDeview we deleted all records associated with VID_16c0. This did not resolve the problem, and we wrongly concluded that this meant it wasn't a problem of wrong info being retained.

Prompted by inspecting the USB traffic, we tried to track down how the registry might be directing Windows to use mouhid.sys instead of hidusb.sys. However, there were far too many registry records to look at in detail (evidently more than USBDeview shows). So instead we decided to delete all keys containing VID_16c0 (probably more than a hundred deletions).

This is problematic because some of the sub keys have ownership set to System and are not viewable or deletable by even Admins. To get around this, we discovered that regedit can be launched via psexec http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx so that it runs regedit as the System user:

In a Run-as-admin cmd window :
[path-to-psexec]\psexec.exe -i -s c:\windows\regedit.exe
pause

With all the VID_16c0 keys deleted, when we next plugged in the Teensy joystick, Windows went through the process of finding suitable drivers, and then joy.cpl worked properly.

Hope that helps!

-- Graham
 
Wow, thanks for writing this! It's so rare there's ever any resolution to these strange Windows problems.

Maybe I should look into making the installer able to detect these registry keys and offer an option to delete them?
 
Hi Paul --

Thanks for taking note of this issue and commenting. I really enjoy what you've done with Teensy and the USB functionality, so it's a pleasure to have the opportunity to send a little something back in the way of "troubleshooting from the field".

Yes, I think it would be great to offer a way to delete all registry entries that have resulted from Windows USB driver install process. Putting that in the Teensyduino installer might not be optimum though, as the search process is liable to be s-l-o-w. I had already been considering what I'd write if I encounter this problem again, and I think it would be a separate utility that can perform two related functions:

(a) find and list all the keys that contain VID_16C0 (or allow user to set the VID), so one can monitor the variety and proliferation (or not) of such keys. (Ie: both as diagnostic and learning-about-USB tool.)

(b) Delete them (presumably if run as user System, using psexec or similar).

I should also note that there are additional Teensy-USB-related keys named using a concatenation of VID and PID (ie: without the 'VID_' or 'PID_' prefixes), like this:

HKEY_LOCAL_MACHINE\SYSTEM\[CurrentControlSet|ControlSet00[1|2]]\Control\usbflags\16C004820105

(and one cannot simply search for 16C0, as that will hit a bunch of GUIDs that happen to contain that string).

I'm also thinking that in the interests of reducing the proliferation of keys, and complexity of including multiple subdevices that might not be needed, it would be nice if USB Type could be set to any combo of one or more of Serial, Joystick, Mouse or Keyboard (plus the debug device). That's probably straightforward to address in the C code (add a few additional def values and ifdefs), but I haven't yet seen how these additional choices would get onto the Arduino USB Type menu. Clues?

Hope that helps,

-- Graham
 
Issue addressed
---------------
This concerns Teensyduino USB joystick, on a particular "problem machine", showing up in joy.cpl, but with the Properties window displaying blank, as though the joystick contains no analog or digital variables. On other machines the Teensy USB joystick works fine.

Short version of fix
--------------------
Delete from the registry all keys containing VID_16c0.

Explanation
------------
After a lot of inspection of Teensy USB traffic with USBLyzer, I think we have an answer and a fix for the problem. The USB activity during hot-plug indicates that on the problem machine, Windows associates driver mouhid.sys with the joystick. On machines that read the joystick properly, Windows associates the joystick with hidusb.sys.

The registry stores a lot of keys in various places that contain the Vendor Id used by the joystick: VID_16c0. It appears that the function of some of these keys is to remember the result of the first time the device was plugged in, and a driver found. There are separate keys for the different sub device Product Ids corresponding to Mouse, Keyboard, Debug and Joystick, and possibly Serial (depending on the setting for USB type in the Arduino environment), and this info may be stored separately per USB socket.

It seems that if that process decides on the "wrong" driver for some reason (for example, chooses the mouse driver mouhid.sys), then the system will be stuck with that choice in future. This mistaken association could perhaps happen during development with the Teensy, or perhaps due to interrupting the process of finding the right driver during initial plug-in.

In previous attempts to fix this problem, we used USBDeview to view information that Windows was retaining for various USB devices. In USBDeview we deleted all records associated with VID_16c0. This did not resolve the problem, and we wrongly concluded that this meant it wasn't a problem of wrong info being retained.

Prompted by inspecting the USB traffic, we tried to track down how the registry might be directing Windows to use mouhid.sys instead of hidusb.sys. However, there were far too many registry records to look at in detail (evidently more than USBDeview shows). So instead we decided to delete all keys containing VID_16c0 (probably more than a hundred deletions).

This is problematic because some of the sub keys have ownership set to System and are not viewable or deletable by even Admins. To get around this, we discovered that regedit can be launched via psexec http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx so that it runs regedit as the System user:

In a Run-as-admin cmd window :
[path-to-psexec]\psexec.exe -i -s c:\windows\regedit.exe
pause

With all the VID_16c0 keys deleted, when we next plugged in the Teensy joystick, Windows went through the process of finding suitable drivers, and then joy.cpl worked properly.

Hope that helps!

-- Graham


thank you thank you thank you!!!!! this finally allowed me to get my controls working.
 
You're welcome! Nice to hear that it helped.
Graham

I have experienced this now several times when using different Teensyduino USB Joysticks on a machine.
Thank you Graham, for providing a fix to this problem.

I wonder, however, whether in the meantime additional insights into the origin of the problem have been gathered.

Is there a way to prevent this problem from occurring at all?

Thanks,
cramp
 
Is there a way to prevent this problem from occurring at all?

Thanks,
cramp

Just keep away from Windows. I’ve seen it growing from the beginning. There are plug and play issues not fixed since 1995. If Bill Gates was Japanese, he would have had to commit a ritual suicid for all the crap he brought to market.
 
Hi all, I wanted to post here and thank you for this fix. I have a Thrustmaster racing wheel that has been adapted with a Teensy LC. I had one fail on me (no buttons showing up in the Test tab in joy.cpl), so I purchased a second one. After a few months, I encountered the identical problem, so I knew it had to be something I could address.

Long story short, this fix of deleting the registry keys fixed both of my wheels and both are working again correctly.

Much appreciated!
 
Hi all, I wanted to post here and thank you for this fix. I have a Thrustmaster racing wheel that has been adapted with a Teensy LC. I had one fail on me (no buttons showing up in the Test tab in joy.cpl), so I purchased a second one. After a few months, I encountered the identical problem, so I knew it had to be something I could address.

Long story short, this fix of deleting the registry keys fixed both of my wheels and both are working again correctly.

Much appreciated!

Hey, thanks for the comment!
 
Hello Gents,

Many thanks for posting a solution.

This is a real problem for me because I use Teensy 3.5 to make a professional joystick.
145331871_3962977943714890_8360036559960167996_n.jpg

Nevermind that I have to repeat this procedure each time I have to test a new controller on my laptop, but some of my clients buy several joysticks from me and are experiencing the same problems. (Windows 10)

Running this fix is too complicated for them. If the problem cannot be fixed, would it be possible to have an executable file that would flush VID_16c0 out of the Registry?

Cheers,
Etienne
 
Hi @edemers

First off -- cool project!

> If the problem cannot be fixed, would it be possible to have an executable file
> that would flush VID_16c0 out of the Registry

In principle, maybe. Usually, adding, deleting or revising Registry entries would be easy to write an exe to do.

However, in this case it is problematic because some of the sub keys have ownership set to System and are not viewable or deletable by even Admins. To get around this, we discovered that regedit can be launched via psexec http://technet.microsoft.com/en-us/s.../bb897553.aspx so that it runs regedit as the System user. (See earlier comment.)

So an ordinary exe run by a user, even with Admin permissions, could not do the necessary operations. It might be possible to write an exe to do it, and run via psexec etc, but I have not tried that route.

Graham
 
Hello Graham,

Many thanks for your reply and solution. I am indeed using psexec.exe to delete all the keys as you suggested and it solves the problem but I can't ask a client to do this. Therefore the exe would need to override the regedit restrictions.

Hopefully, there something else can be done like adding a teensy driver or something to prevent this issue.

Cheers,
E.
 
Hi @edemers

First off -- cool project!

Thanks, its my biggest seller. The Teensy allows me to do so much more than regular joystick PCBs which gives my product a huge edge over the competition. So I really hope we can get this sorted out since big companies are starting to have this issue and that is a bit of a let down.

Cheers,
E.
 
A question:

When this problem strikes (you plug in one of your Teensy-based joysticks, and it doesn't work), if you plug in a different one of your joysticks that was never connected to that computer, does that one work, or does it fail too?

Hello Graham,

Hopefully, there something else can be done...

Cheers,
E.

I think we would make a step forward if we at least knew which registry keys were causing the problem.

A brute force way to do that would be to take a snapshot of the registry (using Regedit File > Export) , when things are working properly, and then another snapshot after they stop working properly, and compare.

If you're inclined to help...

1. Are you able to produce this problem at will? Or at least get it to happen within hours or days?

2. Can you do that on a machine where you wouldn't mind running exports of the registry, and sending them to a third party (me) for examination?

It would be completely understandable if you didn't want your registry laundry aired in public.

The alternative is for someone like me to devise some sort of registry reader program, or registry dump reader program, which gathers all data related to VID_16C0, and saves only that for sending to me or whoever. However, that might take longer, where "longer" is not guaranteed to be less than infinity.

Thoughts?

Graham
 
Would it be enough the change the Teensy serial-number? Would Windows detect a "new" joystick?
Then, the USB Codecan be changed to use the EEPROM for that number, perhaps.
 
Hi Graham,

Thanks for the interest.

This actually happened again today. I tried plugging a new Teensy based joystick and joy.cpl went dead.

I proceeded to apply your solution and deleted all the instances of VID_16c0 (and there were many) and then I plugged in my new Teensy based joystick and joy.cpl is alive again.

When the problem occurs, joy.cpl will work for all the older Teensy based joysticks that were previously plugged in. Just not for any new ones. Like there is a limit to the amount of VID_16c0 instances windows can accept.

I saved my registry before and after so I can send it to you. Just let me know where.

The problem is not just the joy.cpl not responding anymore, windows, even though it detects the joystick, just doesn't process it via its generic USB joystick device. This is a problem because none of the software that uses the joystick will work (in my case QGroundControl) until your solution is applied.

That said, I did make a software that uses native HID to get the joystick information out and that always works. Although its great for testing the joystick, it does not solve my problem.

I tried compiling all USB types that supports joystick in the Arduino IDE and it makes no difference.

Hi Frank,

I think the serial numbers are already unique but I can try.

Cheers,
E.
 
Thats the intended trick: With a new serial, Windows should detect it as new, and just don't use the old registry values anymore. If this thesis is right :)
 
Hi Graham,
When the problem occurs, joy.cpl will work for all the older Teensy based joysticks that were previously plugged in. Just not for any new ones. Like there is a limit to the amount of VID_16c0 instances windows can accept.

OK, that's interesting. My previous questions (and Frank's idea too) were based on the idea that Windows might be saving, and later assigning, the driver based on VID, PID and also serial number.

However, if other "new" joysticks (presumably with different Teensys and maybe different serial numbers) exhibit the same issue, but other previously-seen ones do not, then driver assignment can't be unique based on serial, I think.

Hi Graham,

I saved my registry before and after so I can send it to you. Just let me know where.

These are registry exports, right? How big are they, once zipped? Do you have a Google Drive that you could share them on? Perhaps you could use the forum "Private Message" feature to send me details.

Graham
 
Thats the intended trick: With a new serial, Windows should detect it as new, and just don't use the old registry values anymore. If this thesis is right :)

I've just tried it, with my T4, usb-type serial.

I've edited usb_desc:
Code:
void usb_init_serialnumber(void)
{
    char buf[11];
    uint32_t i, num;


    num = HW_OCOTP_MAC0 & 0xFFFFFF[COLOR=#ff0000] - 10000[/COLOR];
    // add extra zero to work around OS-X CDC-ACM driver bug
    if (num < 10000000) num = num * 10;
    ultoa(num, buf, 10);
    for (i=0; i<10; i++) {
        char c = buf[i];
        if (!c) break;
        usb_string_serial_number_default.wString[i] = c;
    }
    usb_string_serial_number_default.bLength = i * 2 + 2;
}
And added the red number.
Windows detected a new device. So, it should work with a joystick, too.

So, if you take that "10000" from the eeprom instead, and change that number every time problems occur, everything will work again.
 
Hi Frank,

Thank you for this.

I commented out the previous void usb_init_serialnumber(void) function and added yours but the compiler has issues with HW_OCOTP_MAC0

Did you define this somewhere at the top?

Cheers,
E.
 
We must have different file versions then.

This is what I have

Code:
void usb_init_serialnumber(void)
{
	char buf[11];
	uint32_t i, num;

	__disable_irq();
#if defined(HAS_KINETIS_FLASH_FTFA) || defined(HAS_KINETIS_FLASH_FTFL)
	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
	FTFL_FCCOB0 = 0x41;
	FTFL_FCCOB1 = 15;
	FTFL_FSTAT = FTFL_FSTAT_CCIF;
	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
	num = *(uint32_t *)&FTFL_FCCOB7;
#elif defined(HAS_KINETIS_FLASH_FTFE)
	kinetis_hsrun_disable();
	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
	*(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
	FTFL_FSTAT = FTFL_FSTAT_CCIF;
	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
	num = *(uint32_t *)&FTFL_FCCOBB;
	kinetis_hsrun_enable();
#endif
	__enable_irq();
	// add extra zero to work around OS-X CDC-ACM driver bug
	if (num < 10000000) num = num * 10;
	ultoa(num, buf, 10);
	for (i=0; i<10; i++) {
		char c = buf[i];
		if (!c) break;
		usb_string_serial_number_default.wString[i] = c;
	}
	usb_string_serial_number_default.bLength = i * 2 + 2;
}
 
Back
Top