Custom USB device causing mouse pointer to move on Linux.

sagreen83

Active member
I am building a device that emulates an off the shelf USB device. The target system is Linux Mint. I am attempting to build the device in a way that requires zero changes to the host system. i.e. plug and play. This device consists of 4 buttons, 3 pots, 3 LEDs, 2 rotary switches and an encoder. The target system is using EVDEV routines in python. I am using a Teensy 4.1. I do not have access to the off the shelf device.

I have developed custom modifications to the core libraries to support this new device. The target system and software see this device as the off the shelf device that I am trying to emulate and is operating as expected when the controls are moved. i.e. When the pots are turned, sliders move on the screen. When the rotary switches are moved selections change on the screen. When the encoder is moved numbers increment on the target system. That part is working great.

The problem is that I am using X, Y and Z axis for the pots. EVDEV sees these as ABS_X, ABS_Y and ABS_Z. When I move these pots, not only does the system react correctly, but the mouse pointer jumps to X zero on the screen and moves with the pot. Same with the Y axis. Oddly this does not happen in windows. The mouse movement is not desired. I only want the target software to see the movement, not the mouse.

As a start, I'm posting my usb_report_descriptor. I'm assuming at this point that the problem is there.

Code:
static uint8_t console_report_desc[] = {
		0x05, 0x0C,        // Usage Page (Consumer)
		0x09, 0x01,        // Usage (Consumer Control)
		0xA1, 0x01,        // Collection (Application)
		0xA1, 0x02,        //   Collection (Logical)
		0x05, 0x09,        //     Usage Page (Button)
		0x19, 0x01,        //     Usage Minimum (0x01)
		0x29, 0x08,        //     Usage Maximum (0x08)
		0x15, 0x00,        //     Logical Minimum (0)
		0x25, 0x01,        //     Logical Maximum (1)
		0x35, 0x00,        //     Physical Minimum (0)
		0x45, 0x01,        //     Physical Maximum (1)
		0x75, 0x01,        //     Report Size (1)
		0x95, 0x10,        //     Report Count (16)
		0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
		0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
		0x09, 0x01,        //     Usage (Pointer)
		0xA1, 0x00,        //     Collection (Physical)
		0x15, 0x00,        //       Logical Minimum (0)
		0x27, 0xFF, 0xFF, 0x00, 0x00,  //       Logical Maximum (65534)		
		0x75, 0x10,        //       Report Size (16)
		0x95, 0x0B,        //       Report Count (11)
		0x09, 0x30,        //       Usage (X)
		0x09, 0x31,        //       Usage (Y)
		0x09, 0x32,        //       Usage (Z)
		0x09, 0x33,        //       Usage (Rx)
		0x09, 0x34,        //       Usage (Ry)
		0x09, 0x35,        //       Usage (Rz)						
		0x09, 0x36,        //       Usage (Slider)
		0x09, 0x36,        //       Usage (Slider)
		0x09, 0x36,        //       Usage (Slider)
		0x09, 0x36,        //       Usage (Slider)		
		0x09, 0x40,        //       Usage (Vx)		
		0x81, 0x02,        //       Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
		0xC0,              //     End Collection

        // SAG --------- Below is for sending keyboard key codes.
        0x05, 0x07,        //   Usage Page (Key Codes),
        0x75, 0x01,        //   Report Size (1),
        0x95, 0x08,        //   Report Count (8),                
        0x09, 0xE2,        //   Left Alt
        0x09, 0x09,        //   f
        0x09, 0x29,        //   esc
        0x09, 0x28,        //   enter
        0x09, 0x3A,        //   F1
        0x09, 0x3B,        //   F2
        0x09, 0x3C,        //   F3
        0x09, 0x3D,        //   F4
        0x15, 0x00,        //   Logical Minimum (0),
        0x25, 0x01,        //   Logical Maximum (1),
        0x81, 0x02,        //   Input (Data, Variable, Absolute), ;Modifier keys	
		// SAG ------------

		0xC0,              //   End Collection
		0xC0,              // End Collection
};
 
Sorry, I have mostly looked at a lot of the USB stuff from the other side (i.e. in the USBHost code). I am also not a python person, although I do at times dable with it with things like generating a High Level Analyzer (HLA) for Saleae Logica Analyzer. I know nothing about EVDEV, so again limited knowledge.

Also more of a windows person but do stuff using Ubuntu. So take all of this with a grain of salt.

At least for me, it is sort of hard to know what might be going on, by just seeing your extract of the report descriptor.

Might or might not help to know more about your USB setup on the Teensy.
Is the USB Descriptor setup for just one Interface or multiple? If multiple, what are they? Multiple HID? Or also have Serial or SEREMU...

Are you using default Teensy: vendor and product ID's? Or did you set these to something else?

Are there any special udev rules?

Some of the things I would do if it were me would include things like:

When I plug in the Teensy, what does the commands like dmesg or the journal control commands show about it.

I might also try to get additional information like does: lssub -v
show anything interesting.

Sorry I know not much help.
 
If you 'grab' the event device (using EVIOCGRAB ioctl), the events are consumed by your application. Then, as long as your Python code is running (has the event device 'grabbed'), the events are only seen by your own code. This (using a grabbing application and handling the HID events directly) is the same way you can connect for example different USB keyboards to the same Linux machine, and have the keyboards be completely separate, affecting only the one application.

With Python evdev, use the .grab() method of the evdev.device.InputDevice Python object corresponding to your USB device.

Linux is much less picky about USB HID devices than other OSes. Typically, the hid-generic driver interfaces to all HID devices that do not have their own driver, and attempts to map the inputs as best it can. (If you know the event device path, say /dev/input/event6, then ls -l /dev/input/event6/device/device/driver will tell you the driver name; if it is ../../../../bus/hid/drivers/hid-generic, then it is hid-generic.)
 
Sorry, I have mostly looked at a lot of the USB stuff from the other side (i.e. in the USBHost code). I am also not a python person, although I do at times dable with it with things like generating a High Level Analyzer (HLA) for Saleae Logica Analyzer. I know nothing about EVDEV, so again limited knowledge.

Also more of a windows person but do stuff using Ubuntu. So take all of this with a grain of salt.

At least for me, it is sort of hard to know what might be going on, by just seeing your extract of the report descriptor.

Might or might not help to know more about your USB setup on the Teensy.
Is the USB Descriptor setup for just one Interface or multiple? If multiple, what are they? Multiple HID? Or also have Serial or SEREMU...

Are you using default Teensy: vendor and product ID's? Or did you set these to something else?

Are there any special udev rules?

Some of the things I would do if it were me would include things like:

When I plug in the Teensy, what does the commands like dmesg or the journal control commands show about it.

I might also try to get additional information like does: lssub -v
show anything interesting.

Sorry I know not much help.

Kurt, thanks for the feedback. Sorry, ive been consumed by another project in the last couple days and havent had a chance to gather some of the information you are looking for. Will get back to you

Scott...
 
If you 'grab' the event device (using EVIOCGRAB ioctl), the events are consumed by your application. Then, as long as your Python code is running (has the event device 'grabbed'), the events are only seen by your own code. This (using a grabbing application and handling the HID events directly) is the same way you can connect for example different USB keyboards to the same Linux machine, and have the keyboards be completely separate, affecting only the one application.

With Python evdev, use the .grab() method of the evdev.device.InputDevice Python object corresponding to your USB device.

Linux is much less picky about USB HID devices than other OSes. Typically, the hid-generic driver interfaces to all HID devices that do not have their own driver, and attempts to map the inputs as best it can. (If you know the event device path, say /dev/input/event6, then ls -l /dev/input/event6/device/device/driver will tell you the driver name; if it is ../../../../bus/hid/drivers/hid-generic, then it is hid-generic.)

@Nominal Animal, as always thanks for the input. I'll check out the driver and get back to you.

Scott...
 
Back
Top