I’ve tried several times to create a HID device with configfs using the 4.9 kernel. I’ve configured it with what appear to
be the necessary options (I would list them here, but I can’t remember them all. I can post a kernel configuration file
if I need to). I have the following modules loaded:
usb_f_hid 10893 2 libcomposite 55711 10 usb_f_hid musb_dsps 11548 0 musb_hdrc 123670 1 musb_dsps udc_core 43032 3 musb_hdrc,libcomposite,usb_f_hid phy_am335x 2825 2 phy_generic 6644 1 phy_am335x phy_am335x_control 3300 1 phy_am335x
You can see that the usb_f_hid driver got loaded. I was able to script the following steps:
`
modprobe libcomposite
cd /sys/kernel/config/usb_gadget
mkdir g1
cd g1
echo 0x1234 > idVendor
echo 0x5678 > idProduct
echo 0x0100 > bcdDevice
echo 0x0200 > bcdUSB
mkdir -p strings/0x409
echo “0123456789” > strings/0x409/serialnumber
echo “Manufacturer Inc.” > strings/0x409/manufacturer
echo “My HID Dev” > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo “Config 1: MY HID Cfg” > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
mkdir -p functions/hid.0
echo 1 > functions/hid.0/protocol
echo 1 > functions/hid.0/subclass
echo 9 > functions/hid.0/report_length
cat ~/hid_desc.bin > functions/hid.0/report_desc
ln -s functions/hid.0 configs/c.1
ls /sys/class/udc > UDC
`
The script is dumb and stupid and doesn’t check anything at all because I’m trying to get some basic things working.
So, when the last line is executed, things go awry:
`
[ 104.598213] Unable to handle kernel NULL pointer dereference at virtual address 00000002
[ 104.606375] pgd = dc700000
[ 104.609292] [00000002] *pgd=9b466831, *pte=00000000, *ppte=00000000
[ 104.615656] Internal error: Oops: 17 [#1] SMP ARM
[ 104.620385] Modules linked in: usb_f_hid libcomposite musb_dsps musb_hdrc udc_core phy_am335x phy_generic phy_am335x_control omap_aes omap_sham crypto_engine evdev omap_rng rng_core tps65217_charger omap_wdt musb_am335x uio_pdrv_genirq uio cpufreq_dt cpufreq_conservative cpufreq_userspace cpufreq_ondemand cpufreq_powersave bluetooth
[ 104.650061] CPU: 0 PID: 1141 Comm: ls Not tainted 4.9.0bpw-1-armv7-devel-r9 #4
[ 104.657314] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 104.663435] task: db05e180 task.stack: dc6ec000
[ 104.668091] PC is at alloc_ep_req+0x34/0xa0 [libcomposite]
[ 104.673602] LR is at 0x0
[ 104.676150] pc : [] lr : [<00000000>] psr: a0000013
sp : dc6edd48 ip : 00000000 fp : dc6edd64
[ 104.687679] r10: dc75c51c r9 : 00000100 r8 : dc75c4d0
[ 104.692927] r7 : dc75c4a8 r6 : db41c280 r5 : db352490 r4 : 00000009
[ 104.699483] r3 : 00000000 r2 : ffffffff r1 : 00000000 r0 : db41c280
[ 104.706043] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
[ 104.713209] Control: 10c5387d Table: 9c700019 DAC: 00000051
[ 104.718980] Process ls (pid: 1141, stack limit = 0xdc6ec218)
[ 104.724665] Stack: (0xdc6edd48 to 0xdc6ee000)
[ 104.729048] dd40: 00000001 bf1d0ab4 dc7f8490 00000000 dc6edd9c dc6edd68
[ 104.737268] dd60: bf1cf72c bf1bfb18 db3531f8 c02cc074 00000000 00000001 00000001 dc7f8490
[ 104.745488] dd80: dc75c4a8 bf1cf688 dc7f84e8 dc75c4d0 dc6eddd4 dc6edda0 bf1ba048 bf1cf694
[ 104.753708] dda0: 00000001 dc728e5c dc728e94 db3f9208 00000000 00000200 dc75c4c4 dc75c4a8
[ 104.761928] ddc0: dc7f8490 dc7f84e8 dc6ede1c dc6eddd8 bf1bed30 bf1b9fc0 c120414c dc728e94
[ 104.770148] dde0: bf1c1fc0 dc728de8 db3531c0 dc728e5c dc677011 dc5cc600 dc728de8 dc7f3680
[ 104.778368] de00: dc728de8 bf12d69c 00000000 dc677000 dc6ede3c dc6ede20 bf12af7c bf1beac8
[ 104.786588] de20: 00000000 dc5cc600 bf12d6b0 dc7f3680 dc6ede64 dc6ede40 bf12b414 bf12af44
[ 104.794808] de40: dc7f3680 dc7f3780 dc728c00 dc728d90 00000011 00000000 dc6ede8c dc6ede68
[ 104.803028] de60: bf1bf820 bf12b324 00000011 dc7f3780 dc7f3798 dc6edf70 dc6d5d80 b6fb5000
[ 104.811248] de80: dc6edec4 dc6ede90 c0368890 bf1bf778 dc6edef4 00000051 c0bc2248 c120414c
[ 104.819468] dea0: dc6d5d80 00040900 dc6edf70 dc6edf70 00000011 00000000 dc6edf3c dc6edec8
[ 104.827688] dec0: c02de4e0 c03687a4 00000073 c120a1ec c120414c 00000817 c0bc2094 c02df15c
[ 104.835908] dee0: dc6edfb0 00033318 00000011 00000000 dc6d5d80 00000001 dc6edf3c dc6edf08
[ 104.844128] df00: c02df15c c06a1a1c 00000003 00000022 dc5eb578 00040900 00000011 dc6d5d80
[ 104.852348] df20: b6fb5000 dc6edf70 b6fb5000 dc6ec000 dc6edf6c dc6edf40 c02df41c c02de4a4
[ 104.860568] df40: 00000000 c030191c dc6d5d80 c120414c dc6d5d80 00000011 b6fb5000 dc6ec000
[ 104.868788] df60: dc6edfa4 dc6edf70 c02e061c c02df374 00000000 00000000 00000022 00040900
[ 104.877007] df80: 00000000 00000011 b6fb5000 b6f50b50 00000004 c0108fc4 00000000 dc6edfa8
[ 104.885227] dfa0: c0108e00 c02e05c4 00000011 b6fb5000 00000001 b6fb5000 00000011 00000000
[ 104.893448] dfc0: 00000011 b6fb5000 b6f50b50 00000004 00000011 00000000 00000001 00033338
[ 104.901667] dfe0: 00000000 beb3178c b6eb3c85 b6eeef26 40000030 00000001 00000001 00000000
[ 104.909973] [] (alloc_ep_req [libcomposite]) from [] (hidg_bind+0xa4/0x298 [usb_f_hid])
[ 104.919808] [] (hidg_bind [usb_f_hid]) from [] (usb_add_function+0x94/0x1f4 [libcomposite])
[ 104.930007] [] (usb_add_function [libcomposite]) from [] (configfs_composite_bind+0x274/0x41c [libcomposite])
[ 104.941836] [] (configfs_composite_bind [libcomposite]) from [] (udc_bind_to_driver+0x44/0x108 [udc_core])
[ 104.953345] [] (udc_bind_to_driver [udc_core]) from [] (usb_gadget_probe_driver+0xfc/0x164 [udc_core])
[ 104.964505] [] (usb_gadget_probe_driver [udc_core]) from [] (gadget_dev_desc_UDC_store+0xb4/0xcc [libcomposite])
[ 104.976518] [] (gadget_dev_desc_UDC_store [libcomposite]) from [] (configfs_write_file+0xf8/0x1a4)
[ 104.987277] [] (configfs_write_file) from [] (__vfs_write+0x48/0x144)
[ 104.995501] [] (__vfs_write) from [] (vfs_write+0xb4/0x1bc)
[ 105.002850] [] (vfs_write) from [] (SyS_write+0x64/0xcc)
[ 105.009949] [] (SyS_write) from [] (ret_fast_syscall+0x0/0x3c)
[ 105.017564] Code: ebfda595 e2506000 0a000011 e5953024 (e1d320d2)
[ 105.023806] —[ end trace 6370b9fa6506820e ]—
`
I’ve used the references in the kernel dump above to track the issue to hidg_bind in f_hid.c:
`
static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_ep *ep;
struct f_hidg *hidg = func_to_hidg(f);
struct usb_string *us;
struct device *device;
int status;
dev_t dev;
/* maybe allocate device-global string IDs, and patch descriptors */
us = usb_gstrings_attach(c->cdev, ct_func_strings,
ARRAY_SIZE(ct_func_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
hidg_interface_desc.iInterface = us[CT_FUNC_HID_IDX].id;
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
hidg_interface_desc.bInterfaceNumber = status;
/* allocate instance-specific endpoints */
status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
if (!ep)
goto fail;
hidg->in_ep = ep;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
if (!ep)
goto fail;
hidg->out_ep = ep;
/* preallocate request and buffer */
status = -ENOMEM;
hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length);
`
At this point, I believe hidg->in_ep is “okay”, however the problem comes in at this point in u_f.c:
`
struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = usb_endpoint_dir_out(ep->desc) ?
usb_ep_align(ep, len) : len;
req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
`
At the underlined point, I believe ep->desc is NULL because using the kernel and an arm objdump variant,
I located the assembly that is causing the NULL dereference. Inside of usb_endpoing_dir_out, it tries to
dereference ep->desc, but ep->desc must be NULL otherwise things would likely go swimmingly. The problem
is, I don’t know what would cause ep->desc == NULL? Whatever causes this (and it might be related to
a function called “usb_gadget_ep_match_desc”) I’d like to know because knowing might tell me how to fix
whatever it is I’m doing wrong or maybe patch the code so that things might work.
I’m hoping someone knowledgeable about am335x USB can help here, or maybe let me know what I’m missing
in my HID configuration. The above configuration steps may not work, however, some python code I had previously
also fails to function. It might even be possible that I just need to use the regular HID driver and not one based on
libcomposite.
Thanks for reading this. Hopefully there are some answers.