| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 |  | 
 | 2 | The Basic Device Structure | 
 | 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 | 4 |  | 
 | 5 | struct device { | 
 | 6 |         struct list_head g_list; | 
 | 7 |         struct list_head node; | 
 | 8 |         struct list_head bus_list; | 
 | 9 |         struct list_head driver_list; | 
 | 10 |         struct list_head intf_list; | 
 | 11 |         struct list_head children; | 
 | 12 |         struct device   * parent; | 
 | 13 |  | 
 | 14 |         char    name[DEVICE_NAME_SIZE]; | 
 | 15 |         char    bus_id[BUS_ID_SIZE]; | 
 | 16 |  | 
 | 17 |         spinlock_t      lock; | 
 | 18 |         atomic_t        refcount; | 
 | 19 |  | 
 | 20 |         struct bus_type * bus; | 
 | 21 |         struct driver_dir_entry dir; | 
 | 22 |  | 
 | 23 | 	u32		class_num; | 
 | 24 |  | 
 | 25 |         struct device_driver *driver; | 
 | 26 |         void            *driver_data; | 
 | 27 |         void            *platform_data; | 
 | 28 |  | 
 | 29 |         u32             current_state; | 
 | 30 |         unsigned char *saved_state; | 
 | 31 |  | 
 | 32 |         void    (*release)(struct device * dev); | 
 | 33 | }; | 
 | 34 |  | 
 | 35 | Fields  | 
 | 36 | ~~~~~~ | 
 | 37 | g_list:	Node in the global device list. | 
 | 38 |  | 
 | 39 | node:	Node in device's parent's children list. | 
 | 40 |  | 
 | 41 | bus_list: Node in device's bus's devices list. | 
 | 42 |  | 
 | 43 | driver_list:   Node in device's driver's devices list. | 
 | 44 |  | 
 | 45 | intf_list:     List of intf_data. There is one structure allocated for | 
 | 46 | 	       each interface that the device supports. | 
 | 47 |  | 
 | 48 | children:      List of child devices. | 
 | 49 |  | 
 | 50 | parent:        *** FIXME *** | 
 | 51 |  | 
 | 52 | name:	       ASCII description of device.  | 
 | 53 | 	       Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]" | 
 | 54 |  | 
 | 55 | bus_id:	       ASCII representation of device's bus position. This  | 
 | 56 | 	       field should be a name unique across all devices on the | 
 | 57 | 	       bus type the device belongs to.  | 
 | 58 |  | 
 | 59 | 	       Example: PCI bus_ids are in the form of | 
 | 60 | 	       <bus number>:<slot number>.<function number>  | 
 | 61 | 	       This name is unique across all PCI devices in the system. | 
 | 62 |  | 
 | 63 | lock:	       Spinlock for the device.  | 
 | 64 |  | 
 | 65 | refcount:      Reference count on the device. | 
 | 66 |  | 
 | 67 | bus:	       Pointer to struct bus_type that device belongs to. | 
 | 68 |  | 
 | 69 | dir:	       Device's sysfs directory. | 
 | 70 |  | 
 | 71 | class_num:     Class-enumerated value of the device. | 
 | 72 |  | 
 | 73 | driver:	       Pointer to struct device_driver that controls the device. | 
 | 74 |  | 
 | 75 | driver_data:   Driver-specific data. | 
 | 76 |  | 
 | 77 | platform_data: Platform data specific to the device. | 
 | 78 |  | 
| David Brownell | 4109aca | 2005-05-16 17:19:55 -0700 | [diff] [blame] | 79 | 	       Example:  for devices on custom boards, as typical of embedded | 
 | 80 | 	       and SOC based hardware, Linux often uses platform_data to point | 
 | 81 | 	       to board-specific structures describing devices and how they | 
 | 82 | 	       are wired.  That can include what ports are available, chip | 
 | 83 | 	       variants, which GPIO pins act in what additional roles, and so | 
 | 84 | 	       on.  This shrinks the "Board Support Packages" (BSPs) and | 
 | 85 | 	       minimizes board-specific #ifdefs in drivers. | 
 | 86 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | current_state: Current power state of the device. | 
 | 88 |  | 
 | 89 | saved_state:   Pointer to saved state of the device. This is usable by | 
 | 90 | 	       the device driver controlling the device. | 
 | 91 |  | 
 | 92 | release:       Callback to free the device after all references have  | 
 | 93 | 	       gone away. This should be set by the allocator of the  | 
 | 94 | 	       device (i.e. the bus driver that discovered the device). | 
 | 95 |  | 
 | 96 |  | 
 | 97 | Programming Interface | 
 | 98 | ~~~~~~~~~~~~~~~~~~~~~ | 
 | 99 | The bus driver that discovers the device uses this to register the | 
 | 100 | device with the core: | 
 | 101 |  | 
 | 102 | int device_register(struct device * dev); | 
 | 103 |  | 
 | 104 | The bus should initialize the following fields: | 
 | 105 |  | 
 | 106 |     - parent | 
 | 107 |     - name | 
 | 108 |     - bus_id | 
 | 109 |     - bus | 
 | 110 |  | 
 | 111 | A device is removed from the core when its reference count goes to | 
 | 112 | 0. The reference count can be adjusted using: | 
 | 113 |  | 
 | 114 | struct device * get_device(struct device * dev); | 
 | 115 | void put_device(struct device * dev); | 
 | 116 |  | 
 | 117 | get_device() will return a pointer to the struct device passed to it | 
 | 118 | if the reference is not already 0 (if it's in the process of being | 
 | 119 | removed already). | 
 | 120 |  | 
 | 121 | A driver can access the lock in the device structure using:  | 
 | 122 |  | 
 | 123 | void lock_device(struct device * dev); | 
 | 124 | void unlock_device(struct device * dev); | 
 | 125 |  | 
 | 126 |  | 
 | 127 | Attributes | 
 | 128 | ~~~~~~~~~~ | 
 | 129 | struct device_attribute { | 
| Mike Murphy | 245127d | 2009-02-22 01:17:14 -0500 | [diff] [blame] | 130 | 	struct attribute	attr; | 
 | 131 | 	ssize_t (*show)(struct device *dev, struct device_attribute *attr, | 
 | 132 | 			char *buf); | 
 | 133 | 	ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 
 | 134 | 			 const char *buf, size_t count); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 135 | }; | 
 | 136 |  | 
 | 137 | Attributes of devices can be exported via drivers using a simple | 
 | 138 | procfs-like interface.  | 
 | 139 |  | 
 | 140 | Please see Documentation/filesystems/sysfs.txt for more information | 
 | 141 | on how sysfs works. | 
 | 142 |  | 
 | 143 | Attributes are declared using a macro called DEVICE_ATTR: | 
 | 144 |  | 
 | 145 | #define DEVICE_ATTR(name,mode,show,store) | 
 | 146 |  | 
 | 147 | Example: | 
 | 148 |  | 
 | 149 | DEVICE_ATTR(power,0644,show_power,store_power); | 
 | 150 |  | 
 | 151 | This declares a structure of type struct device_attribute named | 
 | 152 | 'dev_attr_power'. This can then be added and removed to the device's | 
 | 153 | directory using: | 
 | 154 |  | 
 | 155 | int device_create_file(struct device *device, struct device_attribute * entry); | 
 | 156 | void device_remove_file(struct device * dev, struct device_attribute * attr); | 
 | 157 |  | 
 | 158 | Example: | 
 | 159 |  | 
 | 160 | device_create_file(dev,&dev_attr_power); | 
 | 161 | device_remove_file(dev,&dev_attr_power); | 
 | 162 |  | 
 | 163 | The file name will be 'power' with a mode of 0644 (-rw-r--r--). | 
 | 164 |  | 
| Grant Likely | b22813b | 2009-03-06 14:05:39 -0700 | [diff] [blame] | 165 | Word of warning:  While the kernel allows device_create_file() and | 
 | 166 | device_remove_file() to be called on a device at any time, userspace has | 
 | 167 | strict expectations on when attributes get created.  When a new device is | 
 | 168 | registered in the kernel, a uevent is generated to notify userspace (like | 
 | 169 | udev) that a new device is available.  If attributes are added after the | 
 | 170 | device is registered, then userspace won't get notified and userspace will | 
 | 171 | not know about the new attributes. | 
 | 172 |  | 
 | 173 | This is important for device driver that need to publish additional | 
 | 174 | attributes for a device at driver probe time.  If the device driver simply | 
 | 175 | calls device_create_file() on the device structure passed to it, then | 
 | 176 | userspace will never be notified of the new attributes.  Instead, it should | 
 | 177 | probably use class_create() and class->dev_attrs to set up a list of | 
 | 178 | desired attributes in the modules_init function, and then in the .probe() | 
 | 179 | hook, and then use device_create() to create a new device as a child | 
 | 180 | of the probed device.  The new device will generate a new uevent and | 
 | 181 | properly advertise the new attributes to userspace. | 
 | 182 |  | 
 | 183 | For example, if a driver wanted to add the following attributes: | 
 | 184 | struct device_attribute mydriver_attribs[] = { | 
 | 185 | 	__ATTR(port_count, 0444, port_count_show), | 
 | 186 | 	__ATTR(serial_number, 0444, serial_number_show), | 
 | 187 | 	NULL | 
 | 188 | }; | 
 | 189 |  | 
 | 190 | Then in the module init function is would do: | 
 | 191 | 	mydriver_class = class_create(THIS_MODULE, "my_attrs"); | 
 | 192 | 	mydriver_class.dev_attr = mydriver_attribs; | 
 | 193 |  | 
 | 194 | And assuming 'dev' is the struct device passed into the probe hook, the driver | 
 | 195 | probe function would do something like: | 
 | 196 | 	create_device(&mydriver_class, dev, chrdev, &private_data, "my_name"); |