Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | |
| 2 | Device Interfaces |
| 3 | |
| 4 | Introduction |
| 5 | ~~~~~~~~~~~~ |
| 6 | |
| 7 | Device interfaces are the logical interfaces of device classes that correlate |
| 8 | directly to userspace interfaces, like device nodes. |
| 9 | |
| 10 | Each device class may have multiple interfaces through which you can |
| 11 | access the same device. An input device may support the mouse interface, |
| 12 | the 'evdev' interface, and the touchscreen interface. A SCSI disk would |
| 13 | support the disk interface, the SCSI generic interface, and possibly a raw |
| 14 | device interface. |
| 15 | |
| 16 | Device interfaces are registered with the class they belong to. As devices |
| 17 | are added to the class, they are added to each interface registered with |
| 18 | the class. The interface is responsible for determining whether the device |
| 19 | supports the interface or not. |
| 20 | |
| 21 | |
| 22 | Programming Interface |
| 23 | ~~~~~~~~~~~~~~~~~~~~~ |
| 24 | |
| 25 | struct device_interface { |
| 26 | char * name; |
| 27 | rwlock_t lock; |
| 28 | u32 devnum; |
| 29 | struct device_class * devclass; |
| 30 | |
| 31 | struct list_head node; |
| 32 | struct driver_dir_entry dir; |
| 33 | |
| 34 | int (*add_device)(struct device *); |
| 35 | int (*add_device)(struct intf_data *); |
| 36 | }; |
| 37 | |
| 38 | int interface_register(struct device_interface *); |
| 39 | void interface_unregister(struct device_interface *); |
| 40 | |
| 41 | |
| 42 | An interface must specify the device class it belongs to. It is added |
| 43 | to that class's list of interfaces on registration. |
| 44 | |
| 45 | |
| 46 | Interfaces can be added to a device class at any time. Whenever it is |
| 47 | added, each device in the class is passed to the interface's |
| 48 | add_device callback. When an interface is removed, each device is |
| 49 | removed from the interface. |
| 50 | |
| 51 | |
| 52 | Devices |
| 53 | ~~~~~~~ |
| 54 | Once a device is added to a device class, it is added to each |
| 55 | interface that is registered with the device class. The class |
| 56 | is expected to place a class-specific data structure in |
| 57 | struct device::class_data. The interface can use that (along with |
| 58 | other fields of struct device) to determine whether or not the driver |
| 59 | and/or device support that particular interface. |
| 60 | |
| 61 | |
| 62 | Data |
| 63 | ~~~~ |
| 64 | |
| 65 | struct intf_data { |
| 66 | struct list_head node; |
| 67 | struct device_interface * intf; |
| 68 | struct device * dev; |
| 69 | u32 intf_num; |
| 70 | }; |
| 71 | |
| 72 | int interface_add_data(struct interface_data *); |
| 73 | |
| 74 | The interface is responsible for allocating and initializing a struct |
| 75 | intf_data and calling interface_add_data() to add it to the device's list |
| 76 | of interfaces it belongs to. This list will be iterated over when the device |
| 77 | is removed from the class (instead of all possible interfaces for a class). |
| 78 | This structure should probably be embedded in whatever per-device data |
| 79 | structure the interface is allocating anyway. |
| 80 | |
| 81 | Devices are enumerated within the interface. This happens in interface_add_data() |
| 82 | and the enumerated value is stored in the struct intf_data for that device. |
| 83 | |
| 84 | sysfs |
| 85 | ~~~~~ |
| 86 | Each interface is given a directory in the directory of the device |
| 87 | class it belongs to: |
| 88 | |
| 89 | Interfaces get a directory in the class's directory as well: |
| 90 | |
| 91 | class/ |
| 92 | `-- input |
| 93 | |-- devices |
| 94 | |-- drivers |
| 95 | |-- mouse |
| 96 | `-- evdev |
| 97 | |
| 98 | When a device is added to the interface, a symlink is created that points |
| 99 | to the device's directory in the physical hierarchy: |
| 100 | |
| 101 | class/ |
| 102 | `-- input |
| 103 | |-- devices |
| 104 | | `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/ |
| 105 | |-- drivers |
| 106 | | `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/ |
| 107 | |-- mouse |
| 108 | | `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/ |
| 109 | `-- evdev |
| 110 | `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/ |
| 111 | |
| 112 | |
| 113 | Future Plans |
| 114 | ~~~~~~~~~~~~ |
| 115 | A device interface is correlated directly with a userspace interface |
| 116 | for a device, specifically a device node. For instance, a SCSI disk |
| 117 | exposes at least two interfaces to userspace: the standard SCSI disk |
| 118 | interface and the SCSI generic interface. It might also export a raw |
| 119 | device interface. |
| 120 | |
| 121 | Many interfaces have a major number associated with them and each |
| 122 | device gets a minor number. Or, multiple interfaces might share one |
| 123 | major number, and each will receive a range of minor numbers (like in |
| 124 | the case of input devices). |
| 125 | |
| 126 | These major and minor numbers could be stored in the interface |
| 127 | structure. Major and minor allocations could happen when the interface |
| 128 | is registered with the class, or via a helper function. |
| 129 | |