1 int class_device_register(struct class_device *class_dev) 2 { 3 /* [cgw]: 初始化一个struct class_device */ 4 class_device_initialize(class_dev); 5 /* [cgw]: 添加一个struct class_device */ 6 return class_device_add(class_dev); 7 } 8 9 /** 10 * class_device_create - creates a class device and registers it with sysfs 11 * @cls: pointer to the struct class that this device should be registered to. 12 * @parent: pointer to the parent struct class_device of this new device, if any. 13 * @devt: the dev_t for the char device to be added. 14 * @device: a pointer to a struct device that is assiociated with this class device. 15 * @fmt: string for the class device's name 16 * 17 * This function can be used by char device classes. A struct 18 * class_device will be created in sysfs, registered to the specified 19 * class. 20 * A "dev" file will be created, showing the dev_t for the device, if 21 * the dev_t is not 0,0. 22 * If a pointer to a parent struct class_device is passed in, the newly 23 * created struct class_device will be a child of that device in sysfs. 24 * The pointer to the struct class_device will be returned from the 25 * call. Any further sysfs files that might be required can be created 26 * using this pointer. 27 * 28 * Note: the struct class passed to this function must have previously 29 * been created with a call to class_create(). 30 */ 31 struct class_device *class_device_create(struct class *cls, 32 struct class_device *parent, 33 dev_t devt, 34 struct device *device, 35 const char *fmt, ...) 36 { 37 va_list args; 38 struct class_device *class_dev = NULL; 39 int retval = -ENODEV; 40 41 /* [cgw]: cls为空或错误 */ 42 if (cls == NULL || IS_ERR(cls)) 43 goto error; 44 45 /* [cgw]: 分配sizeof(*class_dev)字节大小的内存空间 */ 46 class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL); 47 /* [cgw]: 分配失败 */ 48 if (!class_dev) { 49 retval = -ENOMEM; 50 goto error; 51 } 52 53 /* [cgw]: 分配设备号 */ 54 class_dev->devt = devt; 55 /* [cgw]: 分配一个struct device */ 56 class_dev->dev = device; 57 /* [cgw]: 分配一个struct class */ 58 class_dev->class = cls; 59 /* [cgw]: 分配一个parent struct class_device */ 60 class_dev->parent = parent; 61 /* [cgw]: 分配release方法 */ 62 class_dev->release = class_device_create_release; 63 /* [cgw]: 分配uevent方法 */ 64 class_dev->uevent = class_device_create_uevent; 65 66 va_start(args, fmt); 67 /* [cgw]: 把args格式化到字符串fmt中,填装到class_dev->class_id */ 68 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args); 69 va_end(args); 70 /* [cgw]: 注册一个class_dev */ 71 retval = class_device_register(class_dev); 72 if (retval) 73 goto error; 74 75 return class_dev; 76 77 error: 78 /* [cgw]: 释放class_dev的内存空间 */ 79 kfree(class_dev); 80 return ERR_PTR(retval); 81 } 82 83 void class_device_del(struct class_device *class_dev) 84 { 85 struct class *parent_class = class_dev->class; 86 struct class_device *parent_device = class_dev->parent; 87 struct class_interface *class_intf; 88 89 /* [cgw]: parent_class不为空 */ 90 if (parent_class) { 91 /* [cgw]: 获取信号量 */ 92 down(&parent_class->sem); 93 /* [cgw]: 删除class_dev->node节点 */ 94 list_del_init(&class_dev->node); 95 /* [cgw]: 历遍class_intf->node链表,直到回到parent_class->interfaces节点 */ 96 list_for_each_entry(class_intf, &parent_class->interfaces, node) 97 /* [cgw]: class_intf->remove指针不为空 */ 98 if (class_intf->remove) 99 /* [cgw]: 调用remove方法 */ 100 class_intf->remove(class_dev, class_intf); 101 /* [cgw]: 释放信号量 */ 102 up(&parent_class->sem); 103 } 104 105 /* [cgw]: class_dev->dev指针不为空 */ 106 if (class_dev->dev) { 107 /* [cgw] : 从class_dev->dev->kobj对象目录下删除一个名字为 108 * class_dev->class->name+class_dev->kobj->k_name的链表 109 */ 110 remove_deprecated_class_device_links(class_dev); 111 /* [cgw]: class_dev->kobj目录下,删除名为device的链表 */ 112 sysfs_remove_link(&class_dev->kobj, "device"); 113 } 114 /* [cgw]: class_dev->kobj目录下,删除名为subsystem的链表 */ 115 sysfs_remove_link(&class_dev->kobj, "subsystem"); 116 117 /* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->uevent_attr->attr 118 * 属性文件 119 */ 120 class_device_remove_file(class_dev, &class_dev->uevent_attr); 121 /* [cgw]: class_dev->devt_attr指针不为空 */ 122 if (class_dev->devt_attr) 123 /* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->devt_attr->attr 124 * 属性文件 125 */ 126 class_device_remove_file(class_dev, class_dev->devt_attr); 127 /* [cgw]: 历遍class_dev->class->class_dev_attrs[]数组,如果该属性名字不为空, 128 * 则对应地删除一个属性文件 129 */ 130 class_device_remove_attrs(class_dev); 131 /* [cgw]: 历遍class_dev->groups[],删除所有属性组 */ 132 class_device_remove_groups(class_dev); 133 134 /* [cgw]: 通知用户空间,产生一个KOBJ_REMOVE事件 */ 135 kobject_uevent(&class_dev->kobj, KOBJ_REMOVE); 136 /* [cgw]: 删除kobj对象目录,从kset链表中删除class_dev->kobj */ 137 kobject_del(&class_dev->kobj); 138 139 /* [cgw]: parent_device->kobj引用计数-1 */ 140 class_device_put(parent_device); 141 /* [cgw]: parent_class->kobj引用计数-1 */ 142 class_put(parent_class); 143 } 144 145 void class_device_unregister(struct class_device *class_dev) 146 { 147 pr_debug("CLASS: Unregistering class device. ID = '%s'\n", 148 class_dev->class_id); 149 /* [cgw]: 删除struct class_device */ 150 class_device_del(class_dev); 151 /* [cgw]: class_dev->kobj引用计数-1 */ 152 class_device_put(class_dev); 153 } 154 155 /** 156 * class_device_destroy - removes a class device that was created with class_device_create() 157 * @cls: the pointer to the struct class that this device was registered * with. 158 * @devt: the dev_t of the device that was previously registered. 159 * 160 * This call unregisters and cleans up a class device that was created with a 161 * call to class_device_create() 162 */ 163 void class_device_destroy(struct class *cls, dev_t devt) 164 { 165 struct class_device *class_dev = NULL; 166 struct class_device *class_dev_tmp; 167 168 /* [cgw]: 获得信号量 */ 169 down(&cls->sem); 170 /* [cgw]: 返回class_dev_tmp指针,历遍class_dev_tmp链表, 171 * 查找与cls->children相等的节点class_dev_tmp->node 172 */ 173 list_for_each_entry(class_dev_tmp, &cls->children, node) { 174 /* [cgw]: 找到该节点,设备号为devt */ 175 if (class_dev_tmp->devt == devt) { 176 /* [cgw]: class_dev指向class_dev_tmp */ 177 class_dev = class_dev_tmp; 178 break; 179 } 180 } 181 /* [cgw]: 释放信号量 */ 182 up(&cls->sem); 183 184 /* [cgw]: class_dev指针不为空 */ 185 if (class_dev) 186 /* [cgw]: 注销这个class_dev */ 187 class_device_unregister(class_dev); 188 } 189 190 struct class_device * class_device_get(struct class_device *class_dev) 191 { 192 /* [cgw]: class_dev指针不为空 */ 193 if (class_dev) 194 /* [cgw]: class_dev->kobj引用计数+1 195 * 并根据kobj找到包含这个kobj的结构体指针 196 */ 197 return to_class_dev(kobject_get(&class_dev->kobj)); 198 return NULL; 199 } 200 201 void class_device_put(struct class_device *class_dev) 202 { 203 /* [cgw]: class_dev指针不为空 */ 204 if (class_dev) 205 /* [cgw]: class_dev->kobj引用计数-1 */ 206 kobject_put(&class_dev->kobj); 207 } 208 209 210 int class_interface_register(struct class_interface *class_intf) 211 { 212 struct class *parent; 213 struct class_device *class_dev; 214 struct device *dev; 215 216 /* [cgw]: class_intf或class_intf->class指针为空 */ 217 if (!class_intf || !class_intf->class) 218 return -ENODEV; 219 220 /* [cgw]: class_intf->class->subsys->kset.kobj引用计数+1, 221 * parent指向class_intf->class 222 */ 223 parent = class_get(class_intf->class); 224 /* [cgw]: parent指针为空 */ 225 if (!parent) 226 return -EINVAL; 227 228 /* [cgw]: 获取信号量 */ 229 down(&parent->sem); 230 /* [cgw]: 添加一个新节点class_intf->node,位于parent->interfaces节点前 */ 231 list_add_tail(&class_intf->node, &parent->interfaces); 232 233 /* [cgw]: class_intf->add指针不为空 */ 234 if (class_intf->add) { 235 /* [cgw]: 返回class_dev指针,历遍class_dev链表, 236 * 调用每个节点node对应的add方法 237 */ 238 list_for_each_entry(class_dev, &parent->children, node) 239 /* [cgw]: 调用与node (class_dev)对应的add方法 */ 240 class_intf->add(class_dev, class_intf); 241 } 242 243 /* [cgw]: class_intf->add_dev指针不为空 */ 244 if (class_intf->add_dev) { 245 /* [cgw]: 返回dev指针,历遍dev链表, 246 * 调用每个节点node对应的add_dev方法 247 */ 248 list_for_each_entry(dev, &parent->devices, node) 249 /* [cgw]: 调用与node (dev)对应的add_dev方法 */ 250 class_intf->add_dev(dev, class_intf); 251 } 252 /* [cgw]: 释放信号量 */ 253 up(&parent->sem); 254 255 return 0; 256 } 257 258 void class_interface_unregister(struct class_interface *class_intf) 259 { 260 /* [cgw]: parent指针指向class_intf->class */ 261 struct class * parent = class_intf->class; 262 struct class_device *class_dev; 263 struct device *dev; 264 265 /* [cgw]: parent指针为空 */ 266 if (!parent) 267 return; 268 269 /* [cgw]: 获取信号量 */ 270 down(&parent->sem); 271 /* [cgw]: 删除一个节点class_intf->node */ 272 list_del_init(&class_intf->node); 273 /* [cgw]: class_intf->remove指针不为空 */ 274 if (class_intf->remove) { 275 /* [cgw]: 返回class_dev指针,历遍class_dev链表, 276 * 调用每个节点node对应的remove方法 277 */ 278 list_for_each_entry(class_dev, &parent->children, node) 279 /* [cgw]: 调用与node (class_dev)对应的remove方法 */ 280 class_intf->remove(class_dev, class_intf); 281 } 282 283 /* [cgw]: class_intf->remove_dev指针不为空 */ 284 if (class_intf->remove_dev) { 285 /* [cgw]: 返回dev指针,历遍dev链表, 286 * 调用每个节点node对应的remove_dev方法 287 */ 288 list_for_each_entry(dev, &parent->devices, node) 289 /* [cgw]: 调用与node (class_dev)对应的remove_dev方法 */ 290 class_intf->remove_dev(dev, class_intf); 291 } 292 /* [cgw]: 释放信号量 */ 293 up(&parent->sem); 294 295 /* [cgw]: parent->subsys->kobj引用计数-1 */ 296 class_put(parent); 297 } 298 299 int __init classes_init(void) 300 { 301 int retval; 302 303 retval = subsystem_register(&class_subsys); 304 if (retval) 305 return retval; 306 307 /* ick, this is ugly, the things we go through to keep from showing up 308 * in sysfs... */ 309 subsystem_init(&class_obj_subsys); 310 if (!class_obj_subsys.kobj.parent) 311 class_obj_subsys.kobj.parent = &class_obj_subsys.kobj; 312 return 0; 313 } 314 315 EXPORT_SYMBOL_GPL(class_create_file); 316 EXPORT_SYMBOL_GPL(class_remove_file); 317 EXPORT_SYMBOL_GPL(class_register); 318 EXPORT_SYMBOL_GPL(class_unregister); 319 EXPORT_SYMBOL_GPL(class_create); 320 EXPORT_SYMBOL_GPL(class_destroy); 321 322 EXPORT_SYMBOL_GPL(class_device_register); 323 EXPORT_SYMBOL_GPL(class_device_unregister); 324 EXPORT_SYMBOL_GPL(class_device_initialize); 325 EXPORT_SYMBOL_GPL(class_device_add); 326 EXPORT_SYMBOL_GPL(class_device_del); 327 EXPORT_SYMBOL_GPL(class_device_get); 328 EXPORT_SYMBOL_GPL(class_device_put); 329 EXPORT_SYMBOL_GPL(class_device_create); 330 EXPORT_SYMBOL_GPL(class_device_destroy); 331 EXPORT_SYMBOL_GPL(class_device_create_file); 332 EXPORT_SYMBOL_GPL(class_device_remove_file); 333 EXPORT_SYMBOL_GPL(class_device_create_bin_file); 334 EXPORT_SYMBOL_GPL(class_device_remove_bin_file); 335 336 EXPORT_SYMBOL_GPL(class_interface_register); 337 EXPORT_SYMBOL_GPL(class_interface_unregister);