Monotype Computer Interface Compatibility Woes

MS Windows

So far, I have been using a MS Windows system to connect to my Monotype computer interface. The software that runs on the computer is written in Java so it can be run on other operating systems without needing to be modified or compiled for that system. All you need is to have a sufficiently new Java installation on the computer.

Moving to Linux

I had recently set up a Linux system (specifically, Ubuntu) and one thing I wanted to try was my computer interface.

After a bit of fiddling around, one change in the Java code, and one change in the firmware on the interface, I got it to work. Sort of. There are some issues, though:

The first is that, as with many other devices, Ubuntu presents the connected USB devices as special files in its file system. By default, only root (the “super user”) can access these files, so for now to get things to work I must use the root account to grant access to these special files to my (unprivileged) user account. Each time the USB is disconnected and reconnected, a fresh special file entry is made, so the permissions must be fixed again.

Ubuntu provides a solution to this problem. There is a specific shell script which is run when changes are made to these special files, and this script runs as root, so it can sniff the new files and, based on what it finds, do things, including setting permissions, to suit. For this interface, code can be added to the script to recognize the Monotype interface and set the required permissions automatically.

The second problem is that the communications seem a bit flaky. At times the Java code is unable to obtain even basic information like the device type. It seems that the code on Linux that is communicating with the USB interface does not do any retrying if there is a transient error. Some analysis reveals that at some level this appears as the standard Linux error code EPIPE, but other USB-specific code is referring to a STALL condition on the interface. For some reason this is not a problem on my Windows systems; perhaps either the transient errors are not occurring, or some code in Windows automatically retries on error. This still needs some investigation.

The final issue, for which I currently have a fix on Linux, is that in the Monotype interface, I am using the code provided in the microcontroller’s built-in ROM to manage the device end of the USB interface. This code, however, only gives me the choice of two USB device classes: Mass Storage (like thumb drives and external hard drives) and Human Interface Devices (like mice, keyboards, and such). Of the two only the HID class really matches my communications requirements.

Having some weird unknown HID plugged in doesn’t bother Windows at all, but on Linux, any plugged-in HID gets “claimed” by the system—whether or not it knows what to do with it—and so my Java code was told it could not access the interface because it was already in use. Fortunately, the USB library I am using (known as ‘libusb’ and its Java wrapper ‘usb4java’) has the ability to claim the interface from the system when necessary.

What about MacOS (Linux but not really) ?

I also want this interface to work on MacOS, and using Java should be able to make this work; MacOS is essentially Linux under the covers.

Unfortunately, based on my reading, MacOS has its hold on HIDs well locked down, and it is essentially impossible to wrest control of an HID from the system.

There is the possibility of using another library called ‘hidapi’, which was originally separate from libusb but now appears to be part of newer versions of libusb. It also appears to be part of newer versions of the usb4java Java wrapper so I should be able to access it from Java. Whereas libusb uses ‘ioctl’ (“I/O Control”) system calls to do its work and so needs to own the interface, hidapi uses ‘read’ and ‘write’ system calls instead. This means the system can keep its hold on the interface, and so, at least in theory, this should work on MacOS as well. The only oddity is that the data for the read and write calls includes an extra byte or two, apparently to tell the system which “endpoint” (a USB concept) to communicate with.

So this solution needs me to find and use a newer usb4java that also supports hidapi, and also to ascertain what these extra bytes really are in the read and write data.

But the real root of the problem is that the Monotype interface is not an HID; it is really a custom device and should not be masquerading as an HID-class device at all. The ROM in the microprocessor is only really providing a thin wrapper for the actual embedded hardware USB controller, and I should be able to make my firmware use this controller directly, and identify itself as a custom-class device.

This may, however, open its own can of worms, for instance making Windows freak out and try (and fail) to find a suitable driver every time you plug in the USB cable. As well, I don’t know if there actually is an official “custom class” to use; if I just pick some random class ID it could turn out to be a real published class (or could become one in the future), with standards that my device does not follow at all.

But I think the latter approach is the better one in the long run, though it could run into a roadblock that requires me to roll back to the HID approach and using hidapi. This approach also means that if I end up having to change which microcontroller I use, I’m not relying on the ROM support and so any microcontroller with a USB interface should suit.

Leave a Reply

Your email address will not be published. Required fields are marked *

*