I am trying to learn how to write modules and drivers for Linux systems. Similarly to this question I am trying to run a simple "Hello World" module on USB keyboard hot-plug (code below). Even though initializing the module by commands insmode and modprobe seem to work (dmesg shows debugging messages), the module is not loaded upon plugging in the keyboard.

What I did:

  1. Run make to produce hellomodule.ko file.
  2. Copy the hellomodule.ko file to /lib/modules/"my_kernel_version"/
  3. Run depmod -a comand.

After those three steps I have my module added to modules.alias and modules.dep files. It still does not work.

Is this kernels configuration fault or something entirely different?

System: Ubuntu 14.04 LTS; Kernel: 3.14.0

hellomodule.c:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

MODULE_AUTHOR("author");
MODULE_DESCRIPTION("helloworld module\n");
MODULE_LICENSE("GPL");

static struct usb_device_id hello_id_table [] = {
        { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID,
        USB_INTERFACE_SUBCLASS_BOOT,
            USB_INTERFACE_PROTOCOL_KEYBOARD) },
    { } /* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, hello_id_table);

static int hello_probe(struct usb_interface *interface,
    const struct usb_device_id *id)
{
    pr_debug("HelloModule: USB keyboard probe function called\n");
    return 0;
}

static void hello_disconnect(struct usb_interface *interface)
{
    pr_debug("HelloModule: USB keyboard disconnect function called\n");
}

static struct usb_driver hello_driver = {
//.owner =  THIS_MODULE,
.name =     "hello_driver",
.probe =    hello_probe,
.disconnect =   hello_disconnect,
.id_table = hello_id_table
};

static int __init hello_init(void)
{
   int retval = 0;

   pr_debug("HelloModule: Hello World!\n");
   retval = usb_register(&hello_driver);
   if (retval)
       pr_debug("HelloModule: usb_register failed. Error number %d", retval);

   return 0;
}

static void __exit hello_exit(void)
{
    usb_deregister(&hello_driver);
    pr_debug("HelloModule: exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

Makefile:

obj-m := hellomodule.o
CFLAGS_hellomodule.o := -DDEBUG

KDIR  :=  /lib/modules/`uname -r`/build

default:
    make -C $(KDIR) M=$(PWD) modules
clean:
    make -C $(KDIR) M=$(PWD) clean
有帮助吗?

解决方案

I had the same problem. In my case it was caused by the usbhid module being already loaded, since I was using a USB mouse.

If I understand it correctly, in Ubuntu 14.04, the udev rule that loads the proper module(s) when a new device is attached is the following (located in /lib/udev/rules.d/80-drivers.rules):

DRIVER!="?*", ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"

As you can see, kmod load is executed only if the new device has no driver. However, if usbhid is already loaded, the just-attached keyboard already has a driver. Therefore the "hello world" module is not loaded.

A possible solution is to modify/override the udev rule by removing the DRIVER!="?*" condition, thus turning it into:

ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"`.

Another possible workaround is to unload the usbhid module before attaching the keyboard. Of course, that will cause all USB keyboards, mice and other HID class devices to stop working until you attach the new keyboard.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top