Hi Martin. To an end user, writing "0" to enable the device & "1" to disable it sounds counter-intuitive, especially when the sysfs entry is called "cdpower". Is there a reason to not flip that? Regards, Karthik On Tue, Jan 13, 2009 at 11:32 AM, Martin Lucina <mato@xxxxxxxxxx> wrote: > Hello, > > attached is a patch to the panasonic-laptop driver to enable power > management (i.e. on/off) of the built-in optical drive. It creates a > sysfs interface /sys/devices/platform/panasonic/cdpower which can be > either queried or written to. Writing "0" enables the device, "1" > disables it. > > This code is based on reading the existing code[1][2], > examining the DSDT on my CF-W4 system and experimentation. > > The presence of the CF-Y series in the DMI table is based on the > assumption that this method works on recent CF-Yx models. > > I have a few questions I'd like to clear up before actually submitting > this for inclusion: > > 1) Is a platform device the right way to do this? > > 2) Rather than checking the DMI system vendor and product name would it > be a better approach to simply check for the presence of the \_SB.FBAY() > and \_SB.STAT() ACPI methods and enable the platform device on any > (Panasonic) system where these are present? This would seem like a > more future-proof approach. > > 3) Please advise on the correct way to propagate an error result from > the functions that call the ACPI methods {get,set}optd_power_state() to > userspace in the sysfs interface. I couldn't find a straightforward > example anywhere. > > Thanks! > > -mato > > [1] Referenced here http://www.da-cha.jp/letsnote as "A patch to handle > CD on/off button(need to merge)" (now a dead link) > [2] http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/panasonic_acpi/, > see the 20070907 version ("includes small hack for CD-ROM drive") > > --- > > --- linux-2.6.28/drivers/misc/panasonic-laptop.c.orig 2009-01-13 17:01:53.327106958 +0100 > +++ linux-2.6.28/drivers/misc/panasonic-laptop.c 2009-01-13 17:04:04.911106197 +0100 > @@ -24,6 +24,8 @@ > *--------------------------------------------------------------------------- > * > * ChangeLog: > + * Jan.13, 2009 Martin Lucina <mato@xxxxxxxxxx> > + * -v0.96 add support for optical drive power in Y and W series > * Sep.23, 2008 Harald Welte <laforge@xxxxxxxxxxxx> > * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to > * drivers/misc/panasonic-laptop.c > @@ -127,6 +129,8 @@ > #include <acpi/acpi_bus.h> > #include <acpi/acpi_drivers.h> > #include <linux/input.h> > +#include <linux/platform_device.h> > +#include <linux/dmi.h> > > > #ifndef ACPI_HOTKEY_COMPONENT > @@ -219,6 +223,7 @@ struct pcc_acpi { > struct acpi_device *device; > struct input_dev *input_dev; > struct backlight_device *backlight; > + struct platform_device *platform; > int keymap[KEYMAP_SIZE]; > }; > > @@ -226,6 +231,27 @@ struct pcc_keyinput { > struct acpi_hotkey *hotkey; > }; > > +/* known models with optical drive */ > +static struct dmi_system_id pcc_platform_dmi_table[] = { > + { > + .ident = "Panasonic Toughbook W Series", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, > + "Matsushita Electric Industrial Co.,Ltd."), > + DMI_MATCH(DMI_PRODUCT_NAME, "CF-W"), > + }, > + }, > + { > + .ident = "Panasonic Toughbook Y Series", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, > + "Matsushita Electric Industrial Co.,Ltd."), > + DMI_MATCH(DMI_PRODUCT_NAME, "CF-Y"), > + }, > + }, > + { } > +}; > + > /* method access functions */ > static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val) > { > @@ -360,6 +386,63 @@ static struct backlight_ops pcc_backligh > .update_status = bl_set_status, > }; > > +/* get optical driver power state */ > + > +static int get_optd_power_state(void) > +{ > + acpi_status status; > + unsigned long long state; > + int result; > + > + status = acpi_evaluate_integer(NULL, "\\_SB.STAT", NULL, &state); > + if (ACPI_FAILURE(status)) { > + result = -EIO; > + goto out; > + } > + switch (state) { > + case 0: /* power off */ > + result = 1; > + break; > + case 0x0f: /* power on */ > + result = 0; > + break; > + default: > + result = -EIO; > + break; > + } > +out: > + return result; > +} > + > +/* set optical drive power state */ > + > +static int set_optd_power_state(int new_state) > +{ > + int state, result; > + acpi_status status; > + > + state = get_optd_power_state(); > + if (new_state == state) > + return 0; > + > + result = 0; > + switch (new_state) { > + case 0: /* power on */ > + status = acpi_evaluate_object (NULL, "\\_SB.FBAY", NULL, NULL); > + if (ACPI_FAILURE(status)) > + result = -EIO; > + break; > + case 1: /* power off */ > + status = acpi_evaluate_object (NULL, "\\_SB.CDDI", NULL, NULL); > + if (ACPI_FAILURE(status)) > + result = -EIO; > + break; > + default: > + result = -EINVAL; > + break; > + } > + return result; > +} > > /* sysfs user interface functions */ > > @@ -427,10 +510,29 @@ static ssize_t set_sticky(struct device > return count; > } > > +static ssize_t show_cdpower(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + return snprintf(buf, PAGE_SIZE, "%d\n", get_optd_power_state()); > +} > + > +static ssize_t set_cdpower(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + int value; > + > + if (count) { > + value = simple_strtoul(buf, NULL, 10); > + set_optd_power_state (value); > + } > + return count; > +} > + > static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL); > static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL); > static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL); > static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky); > +static DEVICE_ATTR(cdpower, S_IRUGO | S_IWUSR, show_cdpower, set_cdpower); > > static struct attribute *pcc_sysfs_entries[] = { > &dev_attr_numbatt.attr, > @@ -691,8 +793,26 @@ static int acpi_pcc_hotkey_add(struct ac > if (result) > goto out_backlight; > > + /* platform device initialization */ > + if (!dmi_check_system(pcc_platform_dmi_table)) { > + pcc->platform = NULL; > + goto out_no_optd; > + } > + pcc->platform = platform_device_register_simple("panasonic", -1, > + NULL, 0); > + if (IS_ERR(pcc->platform)) { > + result = PTR_ERR(pcc->platform); > + goto out_backlight; > + } > + result = device_create_file(&pcc->platform->dev, &dev_attr_cdpower); > + if (result) > + goto out_platform; > + > +out_no_optd: > return 0; > > +out_platform: > + platform_device_unregister(pcc->platform); > out_backlight: > backlight_device_unregister(pcc->backlight); > out_notify: > @@ -738,6 +858,11 @@ static int acpi_pcc_hotkey_remove(struct > if (!device || !pcc) > return -EINVAL; > > + if (pcc->platform) { > + device_remove_file(&pcc->platform->dev, &dev_attr_cdpower); > + platform_device_unregister(pcc->platform); > + } > + > sysfs_remove_group(&device->dev.kobj, &pcc_attr_group); > > backlight_device_unregister(pcc->backlight); > -- > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html