| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 |  | 
 | 2 | The Basic Device Structure | 
 | 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 | 4 |  | 
| Wanlong Gao | 63dc355 | 2011-05-05 07:55:37 +0800 | [diff] [blame] | 5 | See the kerneldoc for the struct device. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6 |  | 
 | 7 |  | 
 | 8 | Programming Interface | 
 | 9 | ~~~~~~~~~~~~~~~~~~~~~ | 
 | 10 | The bus driver that discovers the device uses this to register the | 
 | 11 | device with the core: | 
 | 12 |  | 
 | 13 | int device_register(struct device * dev); | 
 | 14 |  | 
 | 15 | The bus should initialize the following fields: | 
 | 16 |  | 
 | 17 |     - parent | 
 | 18 |     - name | 
 | 19 |     - bus_id | 
 | 20 |     - bus | 
 | 21 |  | 
 | 22 | A device is removed from the core when its reference count goes to | 
 | 23 | 0. The reference count can be adjusted using: | 
 | 24 |  | 
 | 25 | struct device * get_device(struct device * dev); | 
 | 26 | void put_device(struct device * dev); | 
 | 27 |  | 
 | 28 | get_device() will return a pointer to the struct device passed to it | 
 | 29 | if the reference is not already 0 (if it's in the process of being | 
 | 30 | removed already). | 
 | 31 |  | 
 | 32 | A driver can access the lock in the device structure using:  | 
 | 33 |  | 
 | 34 | void lock_device(struct device * dev); | 
 | 35 | void unlock_device(struct device * dev); | 
 | 36 |  | 
 | 37 |  | 
 | 38 | Attributes | 
 | 39 | ~~~~~~~~~~ | 
 | 40 | struct device_attribute { | 
| Mike Murphy | 245127d | 2009-02-22 01:17:14 -0500 | [diff] [blame] | 41 | 	struct attribute	attr; | 
 | 42 | 	ssize_t (*show)(struct device *dev, struct device_attribute *attr, | 
 | 43 | 			char *buf); | 
 | 44 | 	ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 
 | 45 | 			 const char *buf, size_t count); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | }; | 
 | 47 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 48 | Attributes of devices can be exported by a device driver through sysfs. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 |  | 
 | 50 | Please see Documentation/filesystems/sysfs.txt for more information | 
 | 51 | on how sysfs works. | 
 | 52 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 53 | As explained in Documentation/kobject.txt, device attributes must be be | 
 | 54 | created before the KOBJ_ADD uevent is generated. The only way to realize | 
 | 55 | that is by defining an attribute group. | 
 | 56 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 | Attributes are declared using a macro called DEVICE_ATTR: | 
 | 58 |  | 
 | 59 | #define DEVICE_ATTR(name,mode,show,store) | 
 | 60 |  | 
 | 61 | Example: | 
 | 62 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 63 | static DEVICE_ATTR(type, 0444, show_type, NULL); | 
 | 64 | static DEVICE_ATTR(power, 0644, show_power, store_power); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 66 | This declares two structures of type struct device_attribute with respective | 
 | 67 | names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be | 
 | 68 | organized as follows into a group: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 70 | static struct attribute *dev_attrs[] = { | 
 | 71 | 	&dev_attr_type.attr, | 
 | 72 | 	&dev_attr_power.attr, | 
 | 73 | 	NULL, | 
 | 74 | }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 76 | static struct attribute_group dev_attr_group = { | 
 | 77 | 	.attrs = dev_attrs, | 
 | 78 | }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 79 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 80 | static const struct attribute_group *dev_attr_groups[] = { | 
 | 81 | 	&dev_attr_group, | 
 | 82 | 	NULL, | 
 | 83 | }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 |  | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 85 | This array of groups can then be associated with a device by setting the | 
 | 86 | group pointer in struct device before device_register() is invoked: | 
 | 87 |  | 
 | 88 |       dev->groups = dev_attr_groups; | 
 | 89 |       device_register(dev); | 
 | 90 |  | 
 | 91 | The device_register() function will use the 'groups' pointer to create the | 
 | 92 | device attributes and the device_unregister() function will use this pointer | 
 | 93 | to remove the device attributes. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 |  | 
| Grant Likely | b22813b | 2009-03-06 14:05:39 -0700 | [diff] [blame] | 95 | Word of warning:  While the kernel allows device_create_file() and | 
 | 96 | device_remove_file() to be called on a device at any time, userspace has | 
 | 97 | strict expectations on when attributes get created.  When a new device is | 
 | 98 | registered in the kernel, a uevent is generated to notify userspace (like | 
 | 99 | udev) that a new device is available.  If attributes are added after the | 
 | 100 | device is registered, then userspace won't get notified and userspace will | 
 | 101 | not know about the new attributes. | 
 | 102 |  | 
 | 103 | This is important for device driver that need to publish additional | 
 | 104 | attributes for a device at driver probe time.  If the device driver simply | 
 | 105 | calls device_create_file() on the device structure passed to it, then | 
| Bart Van Assche | d58cb9c | 2011-08-23 19:27:27 +0200 | [diff] [blame] | 106 | userspace will never be notified of the new attributes. |