Note: I'm listing this problem as it is today, I'm not opposed to changing the implementation (moving the creation of the class to a common area for example) if it makes things easier... I'm just not sure how to do it. :End Note
I've got two linux kernel modules and I'm trying to update the /sys entries for them. Searching around on google and other sources, I've seen lots of code along the lines of:
static dev_t MyDev;
static struct class *c1;
static int __init start_func(void)
{
...
MyDev = MKDEV(nMajor, MINOR_VERSION);
register_chrdev_region(MyDev, 1, MODULE_NAME);
c1 = class_create(THIS_MODULE, "chardrv");
device_create(c1, NULL, MyDev, NULL, MODULE_NAME);
....
And I've verified for my first module this code works, and that it correctly creates a:
/sys/class/chardrv/<MODULE_NAME>
entry. What I'd like to know is how do you create a device in an existing class. In other words, one of my modules created this new chardrv class, now I want my other module to be able to also register its devices under the same class.
I can't call class_create() again (in the second module), because that "chardrv" class already exists...
So I can run a check to see if /sys/class/chardrv exists, and this can help me decide if I need to call class_create() or not, that's not a problem. Lets put some pseudo code in here to clarify:
if ( path "/sys/class/chardrv" does not exist)
new_class = class_create("chardrv")
else
new_class = some how get class "chardrv" handle, or properties, or whatever
device_create(new_class, ...)
So as per this example, if my class already exists, and I just want to add my new device into it from a second module I assume I need to create a class structure and somehow populate it with the correct "chardrv class" attributes then call device_create as before, but I'm not sure how to do that.
To use the device_create
function with the same class, just pass it a pointer to the same class.
Since you want to call device_create
in a different module than the one in which you create the class, you'll need to export the symbol for the pointer to the class. You can use the EXPORT_SYMBOL
macro to do this.
For example:
module1.c:
extern struct class *c1; /* declare as extern */
EXPORT_SYMBOL(c1); /* use EXPORT_SYMBOL to export c1 */
static dev_t mod1_dev;
static int __init start_func(void)
{
...
/* define class here */
c1 = class_create(THIS_MODULE, "chardrv");
/* create first device */
device_create(c1, NULL, mod1_dev, NULL, "mod1_dev");
....
}
module2.c
extern struct class *c1; /* declare as extern */
static dev_t mod2_dev;
static int __init start_func(void)
{
...
/* c1 is defined in module 1 */
/* create second device */
device_create(c1, NULL, mod2_dev, NULL, "mod2_dev");
....
}
Note: You'll need to insert module1 before module2 since the class pointer is defined and exported in module1.
That should create the directories you are expecting:
/sys/class/chardrv/mod1_dev
/sys/class/chardrv/mod2_dev
By the way, if you are getting an Invalid parameters
error when you try to load the second module, you might have to add a KBUILD_EXTRA_SYMBOLS
line to your Makefile.