ACPI devices _HID export through sysfs
Subsystems (2)
PATCH 1/1 ACPI devices _HID export through sysfs
Hi
I recently thought about using coldplug (/etc/hotplug/*.rc) scripts to automagically load modules responsible for ACPI-controlled devices such as button, battery, laptop extras. To accomplish this I wrote a trivial kernel patch which exports the ACPI device _HID and _CID attributes in the corresponding sysfs node. I also wrote a script for /etc/hotplug which scans the /sys tree and loads modules according to HIDs exported.
Patch is an attachment because my mail client has a maximum line length limit. The patch is against 2.6.17.
Signature · 3 lines
| ******* Maciek Grela RV409b ********* | JID: [email protected] | Linux user #319794 ++ There is no spoon ...
drivers/acpi/scan.c +40 -0
@@ -351,11 +351,19 @@ static int acpi_bus_get_wakeup_device_flstatic ssize_t acpi_eject_store (struct acpi_device *device,const char *buf,size_t count); +static ssize_t acpi_hid_show (struct acpi_device *device, +char *buf); + +static ssize_t acpi_cid_show (struct acpi_device *device, +char *buf); +#define ACPI_DEVICE_ATTR (_name,_mode,_show,_store) \ static struct acpi_device_attribute acpi_device_attr_##_name = \ __ATTR(_name, _mode, _show, _store)ACPI_DEVICE_ATTR (eject,0200 ,NULL , acpi_eject_store); +ACPI_DEVICE_ATTR (hid,0400 , acpi_hid_show,NULL ); +ACPI_DEVICE_ATTR (cid,0400 , acpi_cid_show,NULL );/** * setup_sys_fs_device_files - sets up the device files under device namespace
@@ -376,6 +384,15 @@ setup_sys_fs_device_files(struct acpi_de status =acpi_get_handle (dev->handle,"_EJ0" , &temp);if (ACPI_SUCCESS (status)) (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr); + +if ( dev->pnp.cid_list ) { + (*(func)) (&dev->kobj, &acpi_device_attr_cid.attr); + } + +if ( dev->pnp.hardware_id[0 ] !=0 ) { + (*(func)) (&dev->kobj, &acpi_device_attr_hid.attr); + } + }static int acpi_eject_operation (acpi_handle handle,int lockable)
@@ -456,6 +473,29 @@ acpi_eject_store(struct acpi_device *devreturn ret; } +static ssize_t acpi_hid_show (struct acpi_device *device, +char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"%s\n" ,device->pnp.hardware_id); +} + +static ssize_t acpi_cid_show (struct acpi_device *device, +char *buf) +{ +int ret =0 ; +int buflen =PAGE_SIZE ; +int i,w; + +for (i =0 ; i < device->pnp.cid_list->count; i++, ret+=w, buflen-=w, buf+=w ) { + w =snprintf (buf, buflen,"%s " , device->pnp.cid_list->id[i].value); + } + + ret +=snprintf (buf, buflen,"\n" ); + +return ret; +} + +/* -------------------------------------------------------------------------- Performance Management -------------------------------------------------------------------------- */
Quoted 6 lines · On Saturday 08 July 2006 16:24, [email protected] wrote:
I recently thought about using coldplug (
/etc/hotplug/*.rc) scripts to automagically load modules responsible for ACPI-controlled devices such as button, battery, laptop extras. To accomplish this I wrote a trivial kernel patch which exports the ACPI device_HIDand_CIDattributes in the corresponding sysfs node. I also wrote a script for/etc/hotplugwhich scans the /sys tree and loads modules according to HIDs exported.
Funny, I was just thinking about this, too :-) I think it's a good idea to be able to automatically load the correct drivers for ACPI devices.
But I think it'd be better for the kernel to expose ACPI devices to user-space as PNP devices, and to use uevents for PNP devices just like we do for PCI devices. I don't like the idea of having separate user-space stuff for PNPBIOS vs PNPACPI devices.
I don't know very much about udev. Would the following patch, in combination with CONFIG_PNPACPI, be enough to do what you want?
drivers/pnp/driver.c +47 -0
@@ -191,9 +191,56 @@return 0 ; } +static int pnp_uevent (struct device *dev,char **envp,int num_envp, +char *buffer,int buffer_size) +{ +struct pnp_dev *pdev; +struct pnp_id *pos; +int i =0 ; +int length =0 ; +int ids =0 ; +char *id_buffer, *p; + +if (!dev) +return -ENODEV ; + + pdev =to_pnp_dev (dev); +if (!pdev) +return -ENODEV ; + +for (pos = pdev->id; pos; pos = pos->next) + ids++; + + id_buffer =kmalloc (ids *9 ,GFP_KERNEL ); +if (!id_buffer) +return -ENOMEM ; + + p = id_buffer; +for (pos = pdev->id; pos; pos = pos->next) + p +=scnprintf (p,9 ,"%s%c" , pos->id, pos->next ?':' :'\0' ); + +if (add_uevent_var (envp, num_envp, &i, + buffer, buffer_size, &length, +"PNP_ID=%s" , id_buffer)) { +kfree (id_buffer); +return -ENOMEM ; + } + +kfree (id_buffer); + +if (add_uevent_var (envp, num_envp, &i, + buffer, buffer_size, &length, +"PNP_DEVICE_NODE=%s" , dev->bus_id)) +return -ENOMEM ; + + envp[i] =NULL ; +return 0 ; +} +struct bus_type pnp_bus_type = { .name ="pnp" , .match = pnp_bus_match, + .uevent = pnp_uevent, .probe = pnp_device_probe, .remove = pnp_device_remove, .suspend = pnp_bus_suspend,