3

OS: Ubuntu 18.04.3
Kernel: 5.3.8


Hi guys :)
I'm trying to create bunch of HID gadgets by using configfs.
It was successful until setting up fourth gadget,
but kernel emits error message during creation of fifth gadget.
Error message was as below.

# 4 successive gadget creation
g_mouse1 : /dev/hidg0
g_mouse2 : /dev/hidg1
g_mouse3 : /dev/hidg2
g_kbd1 : /dev/hidg3
# error occured
mkdir: cannot create directory ‘/config/usb_gadget/g_kbd2/functions/hid.usb0’: No such device

It seems like HID function cannot be created anymore.
So my question is
"Is the number of gadget limited?" and
"If user can adjust limit, how could it be?"


According to further research,
I found out that mass_storage function can be created up to 5,
midi function can be created more than 10.
So the specific limit exists for each USB classes.
However, my project requires beyond HID class' limitation.
Does anyone know the way to manipulate those limits?


Thanks for @mosvy!

Problem solved by this way.

  1. Change a value of HIDG_MINORS in /usr/src/linux-$(uname -r)/drivers/usb/gadget/function/f_hid.c.
  2. Recompile kernel module /usr/src/linux-$(uname -r)/drivers/usb/gadget.
    Kernel Modules which need to be updated are as follows.
    • udc_core
    • libcomposite
    • usb_f_hid

Now you can create HID gadget up to HIDG_MINORS

1 Answer 1

4

Yes, you can only create 4 HID gadgets, and it's a hard-coded limit: the only way to bypass it is by modifying the code and recompiling the usb_f_hid.ko module.

This limitation has to do with how Linux allocates dynamic major/minor numbers for the /dev/hidg# devices.

From drivers/usb/gadget/function/f_hid.c:

#define HIDG_MINORS     4

static inline int hidg_get_minor(void)
{
    ...
        if (ret >= HIDG_MINORS) {
                ida_simple_remove(&hidg_ida, ret);
                ret = -ENODEV;

static struct usb_function_instance *hidg_alloc_inst(void)
{
    ...
                status = ghid_setup(NULL, HIDG_MINORS);

int ghid_setup(struct usb_gadget *g, int count)
{
    ...
        status = alloc_chrdev_region(&dev, 0, count, "hidg");

Similar limitations exists for other gadgets which create device nodes (/dev/g_printer# = printer, /dev/ttyGS# = gser + obex + acm, etc).

1
  • Thanks a lot @mosvy!! I recompiled that kernel source then it worked like a charm
    – jmiry
    Nov 25, 2019 at 9:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .