Contour ShuttlePRO Linux Woes

Contour's ShuttlePRO v2 multimedia controller surely is a fine piece of hardware which I like very much. However, the device developers at Contour messed up with the USB HID profile for sure. Unfortunately, in Linux this causes shuttle and jog events to get lost from time to time ... so I started to investigate...

When using my brand-new ShuttlePRO v2 I quickly noticed that Kdenlive often misses the fact that the jog dial has returned to its neutral position. Also, when shuttling around, one out of 256 steps gets lost. Of course, that immediately rang a peal of bells, so I started my journey into USB HID, the USB Human Interface Devices, and into Linux event territory. I've to admit: I've never been there before.

Linux Events from the ShuttelPRO v2

After some research, I learned about evtest, the input device event monitor and query tool. So I fired up a console at pointed evtest at my ShuttlePRO v2:
$ evtest /dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00
The evtest tools first spits out some device descriptive data about the ShuttlePRO and then waits for events coming from the device. The interesting (or rather fishy) device data tidbit reads as follows, we will come to this back in a few moments:
  Event type 2 (EV_REL)
    Event code 7 (REL_DIAL)
    Event code 8 (REL_WHEEL)
For the moment, all you need to remember is that the ShuttlePRO says that it is going to use relative events for its jog and shuttle. So far, so good. We cannot say anything bad about this at this time. Now turn the dial one notch CW, and then two notches CCW.
Event: time 1394377996.913628, type 2 (EV_REL), code 7 (REL_DIAL), value 1
Event: time 1394377996.913628, -------------- SYN_REPORT ------------
Event: time 1394378000.185629, type 2 (EV_REL), code 7 (REL_DIAL), value 255
Event: time 1394378000.185629, -------------- SYN_REPORT ------------

Remember that I said turning the shuttle CCW back two notches? But there is no event being reported when the dial reaches position (value) 0 again ... it seems that this event is getting swallowed. No wonder that Kdenlive sometimes does not correctly recognize the ShuttlePRO v2 event ... it doesn't get them at all! But who is the culprit in the whole picture? Let's dive further into the details.

Everything is Relative ... for Contour

One thing that immediately springs to mind: for Thorwald's sake, but why did the developers at Contour program their USB HID so that it reports itself as using relative events for the jog and shuttle? If we look closer at the values that are sent as part of the input events we quickly realize that they are in fact absolute position values.
Event: time 1394378345.761992, type 2 (EV_REL), code 7 (REL_DIAL), value 1
Event: time 1394378345.761992, -------------- SYN_REPORT ------------
Event: time 1394378346.778003, type 2 (EV_REL), code 7 (REL_DIAL), value 2
Event: time 1394378346.778003, -------------- SYN_REPORT ------------
Event: time 1394378347.578004, type 2 (EV_REL), code 7 (REL_DIAL), value 3
Event: time 1394378347.578004, -------------- SYN_REPORT ------------
Event: time 1394378347.985989, type 2 (EV_REL), code 7 (REL_DIAL), value 4
Event: time 1394378347.985989, -------------- SYN_REPORT ------------
Event: time 1394378348.362007, type 2 (EV_REL), code 7 (REL_DIAL), value 5
Event: time 1394378348.362007, -------------- SYN_REPORT ------------
If the ShuttlePRO v2 were indeed reporting relative coordinates, then with each step all we should see would be a value of either 1, that is: +1 CW, or 255, the latter representing -1 or CCW. So Contour messed up the HID self-description of the ShuttlePRO v2. They probably did this also with their other multimedia controller devices, so the ShuttlePRO v1 and ShuttleXpress are probably broken in exactly the same way.

Fixing the ShuttlePRO...?

Unfortunately, pointing fingers at Contour won't buy us a working ShuttlePRO v2. They most probably won't ever fix their mistakes. But since we're dealing with Linux, the power of the source is always with us.

So I dug into the Linux kernel source ... and was lucky to rather quickly find the place where the broken ShuttlePRO v2 trips on Linux' toes. Inside the Linux kernel sources, let's look at drivers/input/input.c, function input_get_disposition. Inside it, we will find this code snippet:
case EV_REL:
  if (is_event_supported(code, dev->relbit, REL_MAX) && value)
    disposition = INPUT_PASS_TO_HANDLERS;
The problem here is that, for good reason, Linux suppresses any relative events that report a zero relative movement. Unfortunately, the Contour devices are broken in this respect, so Linux actually should report any zero relative movement.

Unfortunately, we cannot simply map the relative axes to absolute ones, as this would break all existing software. We would get correct behavior, but no software would make use of this correct behavior. Grrr.

But how to «fix» drivers/input/input.c when it fact it isn't broken? The big issue here is to find a way to fix the misbehavior of a rather unimportant input device in a way that is acceptable to the Linux kernel maintainers. I'll try to find out...