Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.
Notices
Welcome to
LinuxQuestions.org , a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free.
Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please
contact us . If you need to reset your password,
click here .
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a
virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month.
Click here for more info.
04-27-2012, 09:40 AM
#1
LQ Newbie
Registered: Apr 2012
Posts: 3
Rep:
sysfs class registration
I want to use the sysclass device module i have registered the class called Dev_Hello and have created the class attribute called enable and its been showing in /sys/class/Dev_Hello/enable but when i do
cat enable i am expecting "enabled" to be displayed on stdout, but i am not able to see anything on the std out and system crashes.
Please guide me...
below is my code:
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/fs.h>
5 #include <linux/device.h>
6 #include <linux/sysdev.h>
7 #include <linux/major.h>
8 #include <asm/uaccess.h>
9 #include <linux/slab.h>
10 #include <linux/cdev.h>
11 #include <linux/kdev_t.h>
12
13
14 #define MAJOR_NUM 200
15 #define DEVICE_NAME "cdev"
16
17 static ssize_t enable_store(struct class *cls, const char *buf, size_t count);
18 static ssize_t enable_show(struct class *cls, char *buf);
19
20 static struct file_operations fops;
21
22 static struct class_attribute class_attr[] = {
23 __ATTR(enable, 0644, enable_show, enable_store),
24 __ATTR_NULL
25 };
26
27 static struct class hello_drv = {
28 .name = "Dev_Hello",
29 .owner = THIS_MODULE,
30 .class_attrs =(struct class_attribute *) &class_attr,
31 };
32
33 static ssize_t enable_show(struct class *cls, char *buf)
34 {
35 char *x[] = {"Enabled", "Disabled"};
36 printk("In enable_show function\n");
37 return sprintf(buf, "%s\n", x[0]);
38 }
39
40 static ssize_t enable_store(struct class *cls, const char *buf, size_t count)
41 {
42 printk("In enable_store function\n");
43 return 1;
44 }
45
46
47 static int hello_init(void)
48 {
49 int status;
50 status = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops);
51 if(status < 0)
52 printk("Registering char driver failed with status = %d\n", status);
53 else
54 printk("Hello World\n");
55
56 status = class_register(&hello_drv);
57 if(status < 0)
58 printk("Registering Class Failed\n");
59
60 return 0;
61 }
62
63 static void hello_exit(void)
64 {
65 class_unregister(&hello_drv);
66 unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
67 printk(" GoodBye, world\n");
68 }
69
70 module_init(hello_init);
71 module_exit(hello_exit);
72 MODULE_LICENSE("GPL");
05-03-2012, 04:15 PM
#2
LQ Newbie
Registered: Mar 2012
Posts: 21
Rep:
Your code works for me. Can you post the output similiar to what I have done below?
Quote:
# insmod class_test.ko
Hello World
# cat /sys/class/Dev_Hello/enable
In enable_show function
Enabled
# rmmod class_test.ko
GoodBye, world
Code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/major.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#define MAJOR_NUM 200
#define DEVICE_NAME "cdev"
static ssize_t enable_store(struct class *cls, const char *buf, size_t count);
static ssize_t enable_show(struct class *cls, char *buf);
static struct file_operations fops;
static struct class_attribute class_attr[] =
{ __ATTR(enable, 0644, enable_show, enable_store), __ATTR_NULL };
static struct class hello_drv =
{ .name = "Dev_Hello", .owner = THIS_MODULE, .class_attrs =
(struct class_attribute *) &class_attr, };
static ssize_t enable_show(struct class *cls, char *buf)
{
char *x[] =
{ "Enabled", "Disabled" };
printk("In enable_show function\n");
return sprintf(buf, "%s\n", x[0]);
}
static ssize_t enable_store(struct class *cls, const char *buf, size_t count)
{
printk("In enable_store function\n");
return 1;
}
static int hello_init(void)
{
int status;
status = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops);
if (status < 0)
printk("Registering char driver failed with status = %d\n", status);
else
printk("Hello World\n");
status = class_register(&hello_drv);
if (status < 0)
printk("Registering Class Failed\n");
return 0;
}
static void hello_exit(void)
{
class_unregister(&hello_drv);
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
printk(" GoodBye, world\n");
}
module_init( hello_init);
module_exit( hello_exit);
MODULE_LICENSE("GPL");
05-03-2012, 10:55 PM
#3
LQ Newbie
Registered: Mar 2012
Posts: 21
Rep:
The parameters in enable_show and enable_store are incorrect. When compiling the module, you get the following warnings:
Quote:
workspace_linux/class_test/class_test.c:21:1: warning: initialization from incompatible pointer type [enabled by default]
workspace_linux/class_test/class_test.c:21:1: warning: (near initialization for ‘class_attr[0].show’) [enabled by default]
workspace_linux/class_test/class_test.c:21:1: warning: initialization from incompatible pointer type [enabled by default]
workspace_linux/class_test/class_test.c:21:1: warning: (near initialization for ‘class_attr[0].store’) [enabled by default]
Fix:
Code:
-static ssize_t enable_store(struct class *cls, const char *buf, size_t count);
+static ssize_t enable_store(struct class *cls, struct class_attribute *attr, const char *buf, size_t count);
-static ssize_t enable_show(struct class *cls, char *buf);
+static ssize_t enable_show(struct class *cls, struct class_attribute *attr, char *buf);
-static ssize_t enable_store(struct class *cls, const char *buf, size_t count)
+static ssize_t enable_store(struct class *cls, struct class_attribute *attr, const char *buf, size_t count)
-static ssize_t enable_show(struct class *cls, char *buf)
+static ssize_t enable_show(struct class *cls, struct class_attribute *attr, char *buf)
Complete Code:
Code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/major.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#define MAJOR_NUM 200
#define DEVICE_NAME "cdev"
static ssize_t enable_store(struct class *cls, struct class_attribute *attr, const char *buf, size_t count);
static ssize_t enable_show(struct class *cls, struct class_attribute *attr, char *buf);
static struct file_operations fops;
static struct class_attribute class_attr[] =
{ __ATTR(enable, 0644, enable_show, enable_store), __ATTR_NULL };
static struct class hello_drv =
{ .name = "Dev_Hello", .owner = THIS_MODULE, .class_attrs =
(struct class_attribute *) &class_attr, };
static ssize_t enable_show(struct class *cls, struct class_attribute *attr, char *buf)
{
char *x[] =
{ "Enabled", "Disabled" };
printk("In enable_show function\n");
return sprintf(buf, "%s\n", x[0]);
}
static ssize_t enable_store(struct class *cls, struct class_attribute *attr, const char *buf, size_t count)
{
printk("In enable_store function\n");
return 1;
}
static int hello_init(void)
{
int status;
status = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops);
if (status < 0)
printk("Registering char driver failed with status = %d\n", status);
else
printk("Hello World\n");
status = class_register(&hello_drv);
if (status < 0)
printk("Registering Class Failed\n");
return 0;
}
static void hello_exit(void)
{
class_unregister(&hello_drv);
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
printk(" GoodBye, world\n");
}
module_init( hello_init);
module_exit( hello_exit);
MODULE_LICENSE("GPL");
05-06-2012, 09:42 PM
#4
LQ Newbie
Registered: Apr 2012
Posts: 3
Original Poster
Rep:
engr04,
Thanks it worked for me after your changes
05-08-2012, 09:00 AM
#5
LQ Newbie
Registered: Apr 2012
Posts: 3
Original Poster
Rep:
Hi,
Further continuing my previous code i am registering a class in "static int hello_init(void)" function and adding to the linked list and in
"static void hello_exit(void)" function i am trying to find the device from the list in the class using "class_find_device(&hello_drv, NULL, tmp, match_entry)" and un-registering all the devices from the calss and finally unregistering the class.
When i do insmod it works fine
But rmmod displays the message "killed" and the driver is not removed
messages are as below:
$>insmod hello.ko
$> rmmod hello.ko
killed
Please guide me i have copied my whole code.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/major.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#define MAJOR_NUM 200
#define DEVICE_NAME "cdev"
static int enable = 0;
struct hello_dev {
struct list_head list;
int device_open;
dev_t tev;
char name[10];
char buff[50];
};
static struct hello_dev mylist;
static struct hello_dev ref[4];
static ssize_t export_store(struct class *cls,struct class_attribute *attr, const char *buf, size_t count);
static ssize_t export_show(struct class *cls, struct class_attribute *attr, char *buf);
static ssize_t dev_attr_show(struct device *dev, struct device_attribute *attr, char *buf) ;
static ssize_t dev_attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size);
static ssize_t hello_read(struct file *, char *, size_t, loff_t *);
static ssize_t hello_write(struct file *, const char *, size_t, loff_t *);
static long hello_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param);
static int hello_open(struct inode *, struct file *);
static int hello_release(struct inode *, struct file *);
static DEVICE_ATTR(Devattr, 0644, dev_attr_show, dev_attr_store);
static struct file_operations fops = {
.open = hello_open,
.read = hello_read,
.write = hello_write,
.release = hello_release,
.unlocked_ioctl = hello_ioctl
};
static struct class_attribute class_attr[] = {
__ATTR(export, 0644, export_show, export_store),
__ATTR_NULL,
};
static const struct attribute *Device_attrs[] = {
&dev_attr_Devattr.attr,
NULL,
};
static const struct attribute_group Device_attr_group = {
.attrs = (struct attribute **) Device_attrs,
};
static struct class hello_drv = {
.name = "Dev_Hello",
.owner = THIS_MODULE,
.class_attrs = (struct class_attribute *) &class_attr,
};
static ssize_t dev_attr_show(struct device *dev, struct device_attribute *attr, char *buf)
{
char *x[] = {"Disabled", "Enabled"};
return sprintf(buf, "%s\n", x[enable]);
return 0;
}
static ssize_t dev_attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
sscanf(buf, "%du", &enable);
return size;
}
static ssize_t export_show(struct class *cls, struct class_attribute *attr, char *buf)
{
char *x[] = {"Disabled", "Enabled"};
return sprintf(buf, "%s\n", x[enable]);
}
static ssize_t export_store(struct class *cls,struct class_attribute *attr, const char *buf, size_t count)
{
sscanf(buf, "%du", &enable);
return count;
}
static int hello_open(struct inode *inode, struct file *file)
{
struct hello_dev *hdev;
struct device *dev;
int status;
int count = 0;
hdev = &ref[iminor(inode)];
if((hdev->device_open) || (count >=3))
{
printk(KERN_INFO "Device Already Open\n Cannot open more devices");
return -EBUSY;
}
else if(count < 3)
{
count++;
hdev->device_open = 1;
file->private_data = hdev;
dev = device_create(&hello_drv, NULL, MKDEV(imajor(inode),iminor(inode)), NULL, "%s%d", "hdev", (int)count);
if(dev)
{
status = sysfs_create_group(&dev->kobj, &Device_attr_group);
if(status != 0)
printk("error creating sysfs_group\n");
return 0 ;
}
printk(KERN_INFO"Device opened\n");
try_module_get(THIS_MODULE);
}
return 0;
}
static int hello_release(struct inode *inode, struct file *file)
{
struct hello_dev *hdev;
hdev = (struct hello_dev *)file->private_data;
hdev->device_open = 0;
device_destroy(&hello_drv, MKDEV(imajor(inode), iminor(inode)));
// class_unregister(&hello_drv);
// unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
printk(" GoodBye, world\n");
module_put(THIS_MODULE);
return 0;
}
static int hello_read(struct file *flip, char __user *buffer, size_t length, loff_t *offset)
{
int status;
struct hello_dev *hdev;
hdev = (struct hello_dev *)flip->private_data;
status = copy_to_user(buffer, hdev->buff, length);
if(status)
{
printk("Copy to user unsuccessful\n No: of bytes not copied = %d\n", status);
status = length - status;
}
else
{
printk("Device read\n");
}
return status;
}
static int hello_write(struct file *flip, const char * buffer, size_t length, loff_t * offset)
{
int count;
struct hello_dev *hdev;
hdev = (struct hello_dev *)flip->private_data;
memset(hdev->buff, '\0', length);
count = copy_from_user(hdev->buff, buffer, length);
printk("Device Write Done\n");
count = length - count;
return count;
}
long hello_ioctl(struct file *flip,unsigned int ioctl_num,unsigned long ioctl_param)
{
switch(ioctl_num)
{
case 0:
printk("IOCTL : CASE 0:");
break;
case 1:
printk("IOCTL : CASE 1:");
break;
default:
printk(KERN_ALERT"Unknown IOCTL number\n");
break;
}
return 0;
}
static int hello_init(void)
{
int status;
struct device *dev;
int count = 0;
int i;
struct list_head *pos, *q;
struct hello_dev *tmp;
// struct hello_dev mylist;
INIT_LIST_HEAD(&mylist.list);
for(i=0; i<4;i++)
{
ref[i].device_open = 0;
}
status = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops);
if(status < 0)
printk("Registering char driver failed with status = %d\n", status);
else
printk("Hello World\n");
status = class_register(&hello_drv);
if(status < 0)
printk("Registering Class Failed\n");
tmp = (struct hello_dev *)kmalloc(sizeof(struct hello_dev), GFP_KERNEL);
tmp->device_open = 1;
tmp->tev = MKDEV(MAJOR_NUM, count);
list_add(&(tmp->list), &(mylist.list));
dev = device_create(&hello_drv, NULL, MKDEV(MAJOR_NUM,count), NULL, "%s%d", "hdev", (int) count);
count++;
if(dev)
{
status = sysfs_create_group(&dev->kobj, &Device_attr_group);
if(status != 0)
printk("error creating sysfs_group\n");
}
list_for_each(pos, &mylist.list)
{
tmp = list_entry(pos, struct hello_dev, list);
printk("device_open = %d dev_t = 0x%X \n ", tmp->device_open, tmp->tev);
}
return 0;
}
static int match_entry(struct device *dev, void *data)
{
dev_t *devt = data;
return dev->devt == *devt;
// return dev_get_drvdata(dev) == data;
}
static void hello_exit(void)
{
struct hello_dev *tmp;
struct device *dev;
struct list_head *pos, *q;
list_for_each(pos, &mylist.list)
{
tmp = list_entry(pos, struct hello_dev, list);
dev = class_find_device(&hello_drv, NULL, tmp, match_entry);
if(dev)
device_unregister(dev);
else
printk("Den Is NULL");
list_del(pos);
kfree(tmp);
}
class_unregister(&hello_drv);
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
printk(" GoodBye, world\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
05-10-2012, 09:06 PM
#6
LQ Newbie
Registered: Mar 2012
Posts: 21
Rep:
I didn't try to compile your code, but it looks like you are missing the sysfs_remove_group to unregister your sysfs_create_group.
All times are GMT -5. The time now is 06:54 PM .
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know .
Latest Threads
LQ News