這一個簡單的驅動示範了如何使用parport來建立你自己的並口驅動。
/*<br /> Demenstration of how to build your parport related<br /> driver upon parport moudle.<br />Author: Joseph Yang @ dslab<br />Mail: ganggexiongqi@gmail.com<br />Date: 06-30-2011<br />*/<br />#include <linux/module.h><br />#include <linux/parport.h><br />/*<br />struct parport_driver {<br /> const char *name;//textual name of your driver<br /> void (*attach) (struct parport *); // used for new port handling<br /> void (*detach) (struct parport *); // handle ports going away due<br /> //to a low-level driver unloading<br /> struct parport_driver *next;<br />};<br />*/<br />struct pardevice * pdev = NULL;<br />void par_test_attach(struct parport* parport);<br />void par_test_detach(struct parport* parport);<br />static struct parport_driver par_test_driver = {<br />.name = "par_test_driver",<br /> .attach = par_test_attach,<br />.detach = par_test_detach,<br />};<br />//typedef int (*preempt_func) (void *handle);<br />/* No-preempt parport */<br />int par_test_preempt(void* handle)<br />{<br />return 1;<br />}<br />void par_test_attach(struct parport* parport)<br />{<br /> pdev = parport_register_device(parport,<br />"dev_name_proc",//device name under /proc<br /> par_test_preempt,<br />NULL,<br />NULL,<br />0,<br />NULL<br />);<br /> if (!pdev) {<br />printk("Bad parport device register!/n");<br />}<br />printk("%s called/n", __func__);<br />}<br />void par_test_detach(struct parport* parport)<br />{<br /> parport_unregister_device(pdev);<br /> printk("%s called /n", __func__);<br />}<br />int __init par_test_init(void)<br />{<br /> if (parport_register_driver(&par_test_driver)) {<br />printk(KERN_ERR "Bad Parport Register/n");<br />return -EIO;<br />}<br />return 0;<br />}<br />void __exit par_test_cleanup(void)<br />{<br /> /* Stop notifications. */<br />parport_unregister_driver (&par_test_driver);<br />}<br />module_init(par_test_init);<br />module_exit(par_test_cleanup);<br />MODULE_LICENSE("GPL");
這個例子,展示了kobject 的使用。
/*<br /> This module shows how to create a simple subdirectory in sysfs called<br /> /sys/class/par In that directory one file called "par0" is created.<br />*/<br />#include <linux/cdev.h><br />#include <linux/module.h><br />#include <linux/kobject.h><br />#include <linux/device.h><br />#include <linux/kdev_t.h><br />//#include <linux/types.h><br />#include <linux/fs.h><br />#include <linux/slab.h><br />static int data; // store the value passed by the user<br />static dev_t dev_number;<br />static struct kobject *my_kobj;<br />static struct class * my_class;<br />static ssize_t my_kobj_show(struct kobject *kobj, struct kobj_attribute *attr,<br /> char *buf)<br />{<br /> printk("%s called /n", __func__);<br /> return sprintf(buf, "%d/n", data);<br />}<br />static ssize_t my_kobj_store(struct kobject *kobj, struct kobj_attribute *attr,<br /> const char *buf, size_t count)<br />{<br /> printk("%s called /n", __func__);<br /> sscanf(buf, "%du", &data);<br /> return count;<br />}<br />static struct kobj_attribute my_kobj_attribute =<br /> __ATTR(par0, 0666, my_kobj_show, my_kobj_store);<br />static struct attribute *attrs[] = {<br />&my_kobj_attribute.attr,<br />NULL<br />};<br />/*<br /> Parent sysfs show() method. Calls the show() method<br /> corresponding to the individual sysfs file<br /> */<br />static ssize_t s_kobj_show (struct kobject *kobj, struct<br />attribute *a, char *buf)<br />{<br />int ret;<br />struct kobj_attribute* attr = container_of(a, struct kobj_attribute, attr);<br />printk("%s called /n", __func__);<br />ret = attr->show ? attr->show(kobj, attr, buf) : -EIO;<br />return ret;<br />}<br />/*<br /> Parent sysfs store() method. Calls the store() method<br /> corresponding to the individual sysfs file<br /> */<br />static ssize_t s_kobj_store (struct kobject *kobj, struct<br />attribute *a, const char *buf, size_t count)<br />{<br />int ret;<br />struct kobj_attribute* attr = container_of(a, struct kobj_attribute, attr);<br />printk("%s called /n", __func__);<br />ret = attr->store ? attr->store(kobj, attr, buf, count) : -EIO;<br />return ret;<br />}<br />/*<br /> Sysfs operations structure<br />*/<br />static struct sysfs_ops sysfs_ops = {<br />.show = s_kobj_show,<br />.store = s_kobj_store,<br />};<br />/*<br />struct sysfs_ops {<br /> ssize_t (*show)(struct kobject *, struct attribute *,char *);<br /> ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);<br />};<br />*/<br />/*<br /> This describes the kobject.<br />*/<br />static struct kobj_type my_kobj_ktype = {<br />.sysfs_ops = &sysfs_ops,<br />.default_attrs = attrs,<br />};<br />static int __init my_kobj_init(void)<br />{<br /> struct device *c_d;<br />int retval;<br /> /*<br /> Create the pardevice class - /sys/class/mypardev<br />*/<br />my_class = class_create(THIS_MODULE, "mypardev");<br />if (IS_ERR(my_class))<br /> printk("Bad class create/n");<br /> /*<br /> Allocate device number<br /> */<br /> retval = alloc_chrdev_region(&dev_number, 0/*minor*/,<br />1/*dev nums*/,"my_parport");<br />if (retval < 0) {<br /> printk (KERN_WARNING "my_parport: alloc major error!/n");<br /> goto class_destroy;<br />}<br />/*<br /> Create the led class device - /sys/class/pardev/par0<br />*/<br />c_d = device_create(my_class, NULL, dev_number,<br /> NULL, "par0");<br /> // void kobject_init(struct kobject *kobj, struct kobj_type *ktype);<br /> my_kobj = kzalloc(sizeof(*my_kobj), GFP_KERNEL);<br /> if (!my_kobj) {<br /> retval = -ENOMEM;<br /> goto device_destroy;<br /> }<br /> kobject_init(my_kobj, &my_kobj_ktype);//initialize that kobject<br /> // int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);<br /> kobject_add(my_kobj, &c_d->kobj, "control");//register the kobject with sysfs<br /> printk("%s called /n", __func__);<br /> return 0;<br />device_destroy:<br /> device_destroy(my_class, MKDEV(MAJOR(dev_number), 0));<br />class_destroy:<br />class_destroy(my_class);<br />unregister_chrdev_region(dev_number, 1);<br />return retval;<br />}<br />static void __exit my_kobj_exit(void)<br />{<br />kobject_put(my_kobj);<br /> device_destroy(my_class, MKDEV(MAJOR(dev_number), 0));<br />class_destroy(my_class);<br />unregister_chrdev_region(dev_number, 1);<br /> printk("%s called /n", __func__);<br />}</p><p>module_init(my_kobj_init);<br />module_exit(my_kobj_exit);<br />MODULE_LICENSE("GPL");<br />
把上面的兩部分合起來,就是一個綜合的利用kobject 通過在/sys/class 下建立檔案來控制
並口裝置的例子。