# Need help with the MCP2210 on Linux with libusb

#### nsaspook

Joined Aug 27, 2009
8,506
- Is "cur_dev" a C++ structure that is being instantiated dynamically?
- Why using the same instance of "buf" and "rbuf" throughout the code?
- Do you need to enumerate all the HID devices, or you can just jump to hid_open() after hid_init()?

Otherwise, the code seems to be straighthforward to me. It resembles what one would do with libusb. The MCP2210 might deserve a class, similar to what I did with the CP2130. Basically, it will be a wrapper around hiddev. I like what I see!

I'll test this. What libraries are you including in your makefile, by the way?
Like I said this is a version of the hidapi test program (the enumeration section is not needed for proper operation) that was modified quickly from a already modified version from the net to make it work the adapter SPI devices. Most of the variables and structure preexisted my modifications.

Original test source code:
https://github.com/libusb/hidapi/tree/master/hidtest

https://github.com/libusb/hidapi/blob/master/udev/69-hid.rules

A wrapper example.
https://github.com/kerrydwong/MCP2210-Library

Note, the compiled code needs root access to the device and need to be run using "sudo". You may need to add the provided udev rule (99-hid.rules) to the /etc/udev/rules.d directory.

https://github.com/kerrydwong/MCP2210-Library/blob/master/99-hid.rules

Last edited:

#### bloguetronica

Joined Apr 27, 2007
1,453
Thanks. Strangely I've created a udev rule, restarted the udev service, and still I can't open the device. However, I can open it when I execute the program as root. Probably the driver needs to be detached.

As for the wrapper, I'm thinking about doing it myself. It will be a Qt wrapper class that will be able to keep the context of a device. Something in the lines of what I did for the CP2130: https://github.com/bloguetronica/cp2130-qt . However, it will be done around hidapi.

Last edited:

#### nsaspook

Joined Aug 27, 2009
8,506
Thanks. Strangely I've created a udev rule, restarted the udev service, and still I can't open the device. However, I can open it when I execute the program as root. Probably the driver needs to be detached.

As for the wrapper, I'm thinking about doing it myself. It will be a Qt wrapper class that will be able to keep the context of a device. Something in the lines of what I did for the CP2130: https://github.com/bloguetronica/cp2130-qt . However, it will be done around hidapi.
The default udev permission is root access only for the hidraw* devices.
You also need a udev rule to change the permission to something more open.

This works for the MCP2210 device on my system to allow non-privileged user programs access.
https://github.com/kerrydwong/MCP2210-Library/blob/master/99-hid.rules

Code:
# This is a sample udev file for HIDAPI devices which changes the permissions
# to 0666 (world readable/writable) for a specified device on Linux systems.

# If you are using the libusb implementation of hidapi (hid-libusb.c), then
# use something like the following line, substituting the VID and PID with
# those of your device. Note that for kernels before 2.6.24, you will need
# to substitute "usb" with "usb_device". It shouldn't hurt to use two lines
# (one each way) for compatibility with older systems.

# HIDAPI/libusb
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", MODE="0666"

# If you are using the hidraw implementation, then do something like the
# following, substituting the VID and PID with your device. Busnum 1 is USB.

# HIDAPI/hidraw
KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", MODE="0666"

# Once done, optionally rename this file for your device, and drop it into
# /etc/udev/rules.d and unplug and re-plug your device. This is all that is
# necessary to see the new permissions. Udev does not have to be restarted.

# Note that the hexadecimal values for VID and PID are case sensitive and
# must be lower case.

# If you think permissions of 0666 are too loose, then see:
# grained permission setting. For example, it might be sufficient to just
# set the group or user owner for specific devices (for example the plugdev
# group on some systems).

#### bloguetronica

Joined Apr 27, 2007
1,453
Thanks, but I've used those rules, and to no avail. Meanwhile. I've been sniffing the USB traffic to the board. Each operation requires two transactions (two request/response pairs). Not bad!

In comparison, the CP2130 does 19 transactions (38 packets) to read the status of 5 GPIOs, setup the chip select, and read the value from the ADC 6 times! So, the MCP2210 does have a tall order to match this.

It is an apple to oranges comparison but, in the end, I want to use the MCP2210 for a similar purpose. The CP2130 is integrated on the ITUSB2, a USB switch that I've built to test enumeration and read the consumption current of USB devices.

#### nsaspook

Joined Aug 27, 2009
8,506
Thanks, but I've used those rules, and to no avail.
...
It is an apple to oranges comparison but, in the end, I want to use the MCP2210 for a similar purpose. The CP2130 is integrated on the ITUSB2, a USB switch that I've built to test enumeration and read the consumption current of USB devices.
Strange, the rules did this on my system to fix permissions.

Before and after 99-hid.rules update (unplug and re-plug device) hidraw permissions. /dev/hidraw3 is the MCP2210.

Pretty neat device. https://github.com/bloguetronica

Last edited:

#### bloguetronica

Joined Apr 27, 2007
1,453
Well, I've done "sudo service udev restart" and re-connected the device. It usually works that way with the CP2130. I've even gave it 0666 permissions, which should work even better. Tried different rules. I'll have to try this inside a Debian VM, to see if I get a different result.

Nevertheless, thanks for your comment! I'll post the details about the project here, in AAC, pretty soon.

#### nsaspook

Joined Aug 27, 2009
8,506
Thanks for making me bump the work queue on the MCP2210. I finally received a PCB (from jlcpcb) for the TiC12400 24 input chip I built a prototype for.

I hack another quick Linux C demo (with few data/function abstractions to show a few required programming details for proper USB and SPI transfers) to make the TIC12400 control the MCP23S08 on the eval board.

It polls the switch via SPI once after 10 led rolls so it's slow to update switch changes. It's very easy to make it poll faster by changing the processing loop slightly to read the External Interrupt Pin (GP6) Event Status as a flag to update the switch buffer.

https://github.com/nsaspook/daq_gert/tree/p8055/hidapi/linux_test/tictest

Last edited:

#### bloguetronica

Joined Apr 27, 2007
1,453
I have to say that the demo program I've used ("hidapi_test", that is) works fine, until I try to delete the while and for loops with the intent of doing a single transfer to light a combination of LEDs. I've replaced the variables, of course. It compiles fine, but breaks the program on execution, showing a message. It doesn't make sense because the setup part stays the same.

Anyway, good work! If I can make this work, the MCP2210 will be a great replacement for the CP2130. I suspect that the library might be broken, somehow. Or it is the program that is not very editable, because it sure relies on past states.

Last edited:

#### bloguetronica

Joined Apr 27, 2007
1,453
I've discovered what is going on with the permissions. It is not the udev rules per se, but the fact that the file corresponding to the device appears accessible just for the root user. To fix this, in my case, I have to do a "sudo chmod 0666 /dev/hidraw3". This is temporary, though, because the file will disappear once I remove the device.

Additionally, I've removed the udev rules and restarted udev, re-attaching the device once more. Fixed the permission again, and it works. The rules seem to be unnecessary.

Edit: Is there a way to use the libusb implementation instead of the hidraw one? I can't find any info about this. I don't know if it is a compilation option, an include option, a define we must set... The lack of documentation on this is appalling, especially to a new user like me. I think the libusb implementation would solve the issue.

Last edited:

#### nsaspook

Joined Aug 27, 2009
8,506
I've discovered what is going on with the permissions. It is not the udev rules per se, but the fact that the file corresponding to the device appears accessible just for the root user. To fix this, in my case, I have to do a "sudo chmod 0666 /dev/hidraw3". This is temporary, though, because the file will disappear once I remove the device.

Additionally, I've removed the udev rules and restarted udev, re-attaching the device once more. Fixed the permission again, and it works. The rules seem to be unnecessary.

Edit: Is there a way to use the libusb implementation instead of the hidraw one? I can't find any info about this. I don't know if it is a compilation option, an include option, a define we must set... The lack of documentation on this is appalling, especially to a new user like me. I think the libusb implementation would solve the issue.
root@hpdesk:/etc/udev/rules.d# ls -l
total 40
-rw-r--r-- 1 root root 1524 May 22 21:28 99-hid.rules
-rw-r--r-- 1 root root 20919 Apr 5 10:46 99-jlink.rules
-rw-r--r-- 1 root root 961 May 10 16:10 z010_mchp_tools.rules
-rw-r--r-- 1 root root 606 Apr 5 10:45 z011_mchp_jlink.rules
-rw-r--r-- 1 root root 252 May 10 16:10 z012_mchp_efr.rules

My system udev rules change the permission to 666 each time the device is plugged in automatically.
KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", MODE="0666"

The device loads the standard hid driver so, NO, there is no libusb implementation unless you write one. the hidraw implementation seems to handle simple SPI sequences pretty well.

I created a MCP2210 DIO board for testing the Linux driver.
16 24vdc capable outputs (MC33996) and 24 24vdc capable inputs (TIC12400).
https://www.mouser.com/datasheet/2/302/MC33996-1126506.pdf

https://github.com/nsaspook/mcp2210/tree/main/linux_test/tictest

#### bloguetronica

Joined Apr 27, 2007
1,453
Probably I'm better off by detaching the driver and just write my own libusb implementation. I set the correct access permissions, but udev just doesn't set the correct permissions for the corresponding virtual file. I suspect that udev and the file corresponding to the HID device are separate things.

These are the rules I'm using:
Code:
# This is a sample udev file for HIDAPI devices which lets unprivileged
# users who are physically present at the system (not remote users) access
# HID devices.

# If you are using the libusb implementation of hidapi (libusb/hid.c), then
# use something like the following line, substituting the VID and PID with

# HIDAPI/libusb
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", TAG+="uaccess"

# If you are using the hidraw implementation (linux/hid.c), then do something
# like the following, substituting the VID and PID with your device.

# HIDAPI/hidraw
KERNEL=="hidraw*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", TAG+="uaccess"

# Once done, optionally rename this file for your application, and drop it into
# /etc/udev/rules.d. Note that these rules must have priorty before 70-uaccess.rules
# for example, name the file /etc/udev/rules.d/69-my-application-hid.rules.
# Then, replug your device or run:

# Note that the hexadecimal values for VID and PID are case sensitive and
# must be lower case.

# TAG+="uaccess" only gives permission to physically present users, which
# is appropriate in most scenarios. If you require remote access to the
# GROUP="plugdev", MODE="660"
# to the end of the udev rule lines, add your user to the plugdev group with:
# then log out and log back in (or restart the system).
I've specified the mode to 0666 as well, but no success.

#### bloguetronica

Joined Apr 27, 2007
1,453
Found a possible workaround. I've used these rules instead:
Code:
# This is a sample udev file for HIDAPI devices which lets unprivileged
# users who are physically present at the system (not remote users) access
# HID devices.

# If you are using the libusb implementation of hidapi (libusb/hid.c), then
# use something like the following line, substituting the VID and PID with

# HIDAPI/libusb
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", MODE="0666", GROUP="plugdev"

# If you are using the hidraw implementation (linux/hid.c), then do something
# like the following, substituting the VID and PID with your device.

# HIDAPI/hidraw
KERNEL=="hidraw*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="00de", MODE="0666", GROUP="plugdev"

# Once done, optionally rename this file for your application, and drop it into
# /etc/udev/rules.d. Note that these rules must have priorty before 70-uaccess.rules
# for example, name the file /etc/udev/rules.d/69-my-application-hid.rules.
# Then, replug your device or run:

# Note that the hexadecimal values for VID and PID are case sensitive and
# must be lower case.

# TAG+="uaccess" only gives permission to physically present users, which
# is appropriate in most scenarios. If you require remote access to the
# GROUP="plugdev", MODE="660"
# to the end of the udev rule lines, add your user to the plugdev group with:
# then log out and log back in (or restart the system).
In addition, I had to add my user to the plugdev group, of course. However, the device file still appears with access permissions only for root. To fix this, I have to type "sudo udevadm trigger" on a terminal each time I plug in the device.

#### nsaspook

Joined Aug 27, 2009
8,506
That sounds like Systemd madness. I'm still a old school sysvinit guy on all my operational systems and try not have the Systemd virus on my stuff.

#### bloguetronica

Joined Apr 27, 2007
1,453
Oh, systemd. That POC! Really, systemd and pulseaudio are the worst that ever happened to Linux. And Lennart Poettering, the developer behind it? That guy shouldn't be allowed to contribute for any major distros, with his attitude.

Last edited: