misc: Add oqo-wmi driver for model 2 OQO backlight and rfkill control
Subsystems (3)
PATCH 1/1 misc: Add oqo-wmi driver for model 2 OQO backlight and rfkill control
misc: Add oqo-wmi driver for model 2 OQO backlight and rfkill control
oqo-wmi provides a WMI-based interface to backlight and rfkill control on model 2 OQO devices. It was originally written by Brian Julin (<[email protected]>) - I've ported it to the rfkill layer and tidied it up a little.
drivers/misc/Kconfig +13 -0
@@ -237,6 +237,19 @@ config ICS932S401 This driver can also be built as a module. If so, the module will be called ics932s401. +config OQO_WMI + tristate "OQO WMI extras" + depends on ACPI_WMI + depends on INPUT + depends on RFKILL + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to support rfkill and backlight control on + series 2 OQO handheld devices. + + To compile this driver as a module, choose M here: the module will + be called oqo-wmi. + config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86
drivers/misc/Makefile +1 -0
@@ -16,6 +16,7 @@ obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_ICS932S401) += ics932s401.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o +obj-$(CONFIG_OQO_WMI) += oqo-wmi.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
drivers/misc/oqo-wmi.c new file +941 -0
941 lines not on this page · raw message
Signature · 1 line
Matthew Garrett | [email protected]
Len Brown
reviewerneeds a MAINTAINERS entry.
-Len
Quoted 1 line · Len Brown
needs a
MAINTAINERSentry.
If it were to be set to me it would have to be S: Odd Fixes. I don't know if this is on Matthew's redhat-official "pile of laptops"...
Either way I've marked the webpage hosting the original code as depricated and added a link to linux-acpi's home. I'll have to test the new patch too at some point but not this weekend.
--
Brian
Quoted 6 lines · Brian S. Julin
Quoted 1 line · Len Brown
needs a
MAINTAINERSentry.If it were to be set to me it would have to be S: Odd Fixes. I don't know if this
is on Matthew's redhat-official "pile of laptops"...
Somewhat. There's some work to be done on getting X to work out the LVDS sizing correctly, but other than that I think I get to play with it for now...
Quoted 3 lines
Either way I've marked the webpage hosting the original code as depricated and added a link to linux-acpi's home. I'll have to test the new patch too at some point but not this weekend.
Cool, thanks. I'll have more time to work on the hardware the week after next.
Signature · 1 line
Matthew Garrett | [email protected]
PATCH 1/1 misc: Add oqo-wmi driver for model 2 OQO backlight and rfkill control
oqo-wmi provides a WMI-based interface to backlight and rfkill control on model 2 OQO devices. It was originally written by Brian Julin (<[email protected]>) - I've ported it to the rfkill layer and tidied it up a little.
---
I've added a MAINTAINERS entry - I'm happy to look after this for now, if Brian doesn't have any objections.
MAINTAINERS +5 -0
@@ -3233,6 +3233,11 @@ L: [email protected] W: http://www.nongnu.org/orinoco/ S: Maintained +OQO WMI EXTRAS DRIVER +P: Matthew Garrett +M: [email protected] +S: Maintained + P54 WIRELESS DRIVER P: Michael Wu M: [email protected]
drivers/misc/Kconfig +13 -0
@@ -237,6 +237,19 @@ config ICS932S401 This driver can also be built as a module. If so, the module will be called ics932s401. +config OQO_WMI + tristate "OQO WMI extras" + depends on ACPI_WMI + depends on INPUT + depends on RFKILL + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to support rfkill and backlight control on + series 2 OQO handheld devices. + + To compile this driver as a module, choose M here: the module will + be called oqo-wmi. + config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86
drivers/misc/Makefile +1 -0
@@ -16,6 +16,7 @@ obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_ICS932S401) += ics932s401.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o +obj-$(CONFIG_OQO_WMI) += oqo-wmi.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
drivers/misc/oqo-wmi.c new file +941 -0
941 lines not on this page · raw message
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 4 lines · Matthew Garrett
oqo-wmi provides a WMI-based interface to backlight and rfkill control on model 2 OQO devices. It was originally written by Brian Julin (<[email protected]>) - I've ported it to the rfkill layer and tidied it up a little.
Some general comments below.
Quoted 12 lines
drivers/misc/oqo-wmi.c new file +12
-0+/* Some of this code is left like in acer-wmi so we can add the older +Model 01 and any future models more easily, but we should not expect +it to be as complicated as Acer given each model is a leap rather than +a subtle variant on the last, so we aren't using "quirks" perse. Not +sure if there is any real difference for our purposes between the o2 +and e2. +*/ +struct oqo_model { +const char *model; +u16 model_subs; +}; +#define MODEL_SUB_OQO_O2_SMB0 3
drivers/misc/oqo-wmi.c line 103
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ +static struct oqo_model oqo_models[] = { + { + .model ="Model 2" , + .model_subs =MODEL_SUB_OQO_O2_SMB0 , + }, + {} +}; + +static struct oqo_model *model;
With "like in acer-wmi" you mean that this whole model stuff currently serves no purpose? If we don't access the model variable yet, I think it shouldn't be there.
Quoted 1 line
+static int
dmi_matched(const struct dmi_system_id *dmi)
__init
drivers/misc/oqo-wmi.c line 193
Quoted 12 lines
drivers/misc/oqo-wmi.c new file +12
-0+{ + model = dmi->driver_data; +/* +* Detect which ACPI-WMI interface we're using. +*/ +if (wmi_has_guid (OQO_O2_AMW0_GUID )) + interface = &AMW0_interface; + +return 0 ; +} + +static struct dmi_system_id oqo_dmis[] = {
__initdata
And i think const is also possible.
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+static acpi_status oqo_read_kine (int *good,s16 *x,s16 *y,s16 *z, +u16 *lumin) +{ +u8 hiregs[4 ] = {OQO_O2_SMB0_ACCEL_XHI , +OQO_O2_SMB0_ACCEL_YHI ,
drivers/misc/oqo-wmi.c line 480
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+OQO_O2_SMB0_ACCEL_ZHI , + OQO_O2_SMB0_LUMIN_HI + }; +u8 loregs[4 ] = {OQO_O2_SMB0_ACCEL_XLO , +OQO_O2_SMB0_ACCEL_YLO , +OQO_O2_SMB0_ACCEL_ZLO , +OQO_O2_SMB0_LUMIN_LO + }; + +short ax[4 ] = {ABS_X ,ABS_Y ,ABS_Z ,ABS_MISC };
Uhm, I think these three variables could be static and const.
drivers/misc/oqo-wmi.c line 544
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+ *x = (u16 ) res[0 ]; + *y = (u16 ) res[1 ]; + *z = (u16 ) res[2 ]; + *lumin = (u16 ) res[3 ]; +return status;
This return could be dropped, just let it fall-through.
Quoted 33 lines
drivers/misc/oqo-wmi.c new file +30
-0+leave: +return status; +} +static int __devinit oqo_kine_init (void ) +{ +int err; + + oqo_kine =input_allocate_device (); +if (!oqo_kine) +return -ENOMEM ; + + oqo_kine->name ="OQO embedded accelerometer" ; + oqo_kine->phys ="platform:oqo-wmi:kine" ; + oqo_kine->id.bustype =0 ; + oqo_kine->id.vendor =0 ; + oqo_kine->id.product =2 ; + oqo_kine->id.version =0 ; + oqo_kine->evbit[0 ] =BIT_MASK (EV_ABS ); +set_bit (ABS_X , oqo_kine->absbit); +set_bit (ABS_Y , oqo_kine->absbit); +set_bit (ABS_Z , oqo_kine->absbit); +set_bit (ABS_MISC , oqo_kine->absbit); + oqo_kine->absmin[ABS_X ] = + oqo_kine->absmin[ABS_Y ] = + oqo_kine->absmin[ABS_Z ] = oqo_kine->absmin[ABS_MISC ] =-32768 ; + oqo_kine->absmax[ABS_X ] = + oqo_kine->absmax[ABS_Y ] = + oqo_kine->absmax[ABS_Z ] = oqo_kine->absmax[ABS_MISC ] =32767 ; + +memcpy (oqo_kine->dev.bus_id,"kine" ,4 );
drivers/misc/oqo-wmi.c line 605
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ + oqo_kine_polled =input_allocate_polled_device (); +if (!oqo_kine_polled) { + err = -ENOMEM ; + goto bail0; + } + + oqo_kine_polled->poll = oqo_kine_poll; + oqo_kine_polled->poll_interval =250 ; + oqo_kine_polled->input = oqo_kine;
input_allocate_polled_device() allocates ->input for us, you must remove the input_allocate_device() above and shift the code around.
drivers/misc/oqo-wmi.c line 642
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+static void __devexit oqo_kine_fini(void) +{ +smwrite_u8 (OQO_O2_SMB0_ACCEL_POLL_ITVL , orig.kine_itvl); +input_unregister_polled_device (oqo_kine_polled); +input_free_polled_device (oqo_kine_polled);
Uhm, I wonder if this is the right order. First unregister and then do the smwrite_u8() to prevent the device from reverting our write?
drivers/misc/oqo-wmi.c line 792
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+static int __devinit oqo_platform_probe (struct platform_device *device) +{ +int err; +int i; +char *troubleok ="trouble, but continuing.\n" ;
This variable seems needless, just append the message to the printk() calls.
Quoted 24 lines
drivers/misc/oqo-wmi.c new file +24
-0+ +memset (oqo_sn,0 ,OQO_O2_SMB0_SERIAL_LEN +1 ); +for (i =0 ; i <OQO_O2_SMB0_SERIAL_LEN ; i++) { + err =oqo_smbus_getb (OQO_O2_SMB0_SERIAL_START + i, oqo_sn + i); +if (err) { +printk (OQO_ERR "Serial number check failed.\n" ); +return err; + } + } +printk (OQO_INFO "Found OQO with serial number %s.\n" , oqo_sn); + + err =oqo_backlight_init (&device->dev); +if (err) +printk (OQO_ERR "Backlight init %s" , troubleok); + + err =oqo_rfkill_init (&device->dev); +if (err) +printk (OQO_ERR "RFKill init %s" , troubleok); + +/* LID does not work at all yet, and this may be taken +care of by ACPI. +*/ + orig.lid_wakes =smread_u8 (OQO_O2_SMB0_LID_WAKES_ADDR ); + orig.lid_wakes &=OQO_O2_SMB0_LID_WAKES_MASK ;
drivers/misc/oqo-wmi.c line 826
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ orig.lid_wakes = curr.lid_wakes = !!orig.lid_wakes; +if (orig.lid_wakes <0 ) { +printk (OQO_ERR "Wake on LID event %s" , troubleok); + }else { +printk (OQO_INFO "Wake on LID is %s.\n" , + (orig.lid_wakes ?"on" :"off" )); + } + + err =oqo_kine_init (); +return err;
Uhm, if oqo_kine_init() fails, does our caller take care of unregistering the backlight and rfkill devices?
drivers/misc/oqo-wmi.c line 833
Quoted 7 lines
drivers/misc/oqo-wmi.c new file +7
-0+} + +static int oqo_platform_remove (struct platform_device *device) +{ +oqo_backlight_fini (); +oqo_rfkill_fini (); +oqo_kine_fini ();
These three functions are marked __devexit, I suspect this will cause section mismatches.
drivers/misc/oqo-wmi.c line 843
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ +return 0 ; +} + +#ifdef CONFIG_PM + +static int oqo_platform_suspend (struct platform_device *dev,pm_message_t state) +{ +if (!interface) +return -ENOMEM ;
Interface should be always set once the module has been loaded successfully.
drivers/misc/oqo-wmi.c line 856
Quoted 13 lines
drivers/misc/oqo-wmi.c new file +13
-0+ +/* This sticks during boot so do not turn it entirely off */ +if (oqo_backlight_device) { + curr.bl_bright =read_brightness (oqo_backlight_device); +smwrite_s16 (OQO_O2_SMB0_BL_HI ,OQO_O2_SMB0_BL_LO ,256 ); + } +return 0 ; +} + +static int oqo_platform_resume (struct platform_device *device) +{ +if (!interface) +return -ENOMEM ;
Likewise.
Quoted 4 lines
drivers/misc/oqo-wmi.c new file +4
-0+ +if (oqo_backlight_device) { +smwrite_s16 (OQO_O2_SMB0_BL_HI , +OQO_O2_SMB0_BL_LO , curr.bl_bright);
drivers/misc/oqo-wmi.c line 921
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +9
-0+ } + +return 0 ; +} + err =platform_device_add (oqo_platform_device); +if (err) { +printk (OQO_ERR "platform_device_add gave %d.\n" , err); +platform_device_put (oqo_platform_device); + goto bail1;
Why not add a bail2 and move platform_device_put() there?
Quoted 7 lines
drivers/misc/oqo-wmi.c new file +7
-0+ } + +return 0 ; + +bail1: +platform_driver_unregister (&oqo_platform_driver); +bail0:
drivers/misc/oqo-wmi.c line 938
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+return err; +} + +static void __exit oqo_wmi_fini(void) +{ +platform_device_del (oqo_platform_device); +platform_driver_unregister (&oqo_platform_driver); + +return ; +}
Needless return at end of function.
Sven
Quoted 7 lines · On Wed, 3 Dec 2008 19:55:37 +0000 Matthew Garrett <[email protected]> wrote:
oqo-wmi provides a WMI-based interface to backlight and rfkill control on model 2 OQO devices. It was originally written by Brian Julin (<[email protected]>) - I've ported it to the rfkill layer and tidied it up a little.
Signed-off-by Matthew Garrett <[email protected]>
Are the attributions and signoffs appropriate here?
drivers/misc/oqo-wmi.c line 55
Quoted 6 lines
...
drivers/misc/oqo-wmi.c new file +3
-0+#include <acpi/acpi_drivers.h> + +MODULE_AUTHOR ("Brian Julin" );
Add yourself?
Quoted 36 lines
drivers/misc/oqo-wmi.c new file +36
-0+MODULE_DESCRIPTION ("OQO UPMC WMI Extras Driver" ); +MODULE_LICENSE ("GPL" ); + +#define OQO_LOGPREFIX "oqo-wmi: " +#define OQO_ERR KERN_ERR OQO_LOGPREFIX +#define OQO_NOTICE KERN_NOTICE OQO_LOGPREFIX +#define OQO_INFO KERN_INFO OQO_LOGPREFIX + +#define OQO_KINE_MAXTRY 3 + +/* Store defined devices globally since we only have one instance. */ +static struct platform_device *oqo_platform_device; +static struct backlight_device *oqo_backlight_device; +static struct rfkill *oqo_rfkill; +static struct input_dev *oqo_kine; +static struct input_polled_dev *oqo_kine_polled; + +/* Likewise store current and original settings globally. */ +struct oqo_settings { +int lid_wakes;/* not sure if ACPI handles/needs help here */ +int kine_itvl; +int bl_bright; +}; + +static struct oqo_settings orig, curr; + +/* Some of this code is left like in acer-wmi so we can add the older +Model 01 and any future models more easily, but we should not expect +it to be as complicated as Acer given each model is a leap rather than +a subtle variant on the last, so we aren't using "quirks" perse. Not +sure if there is any real difference for our purposes between the o2 +and e2. +*/ +struct oqo_model { +const char *model; +u16 model_subs;
drivers/misc/oqo-wmi.c line 101
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+}; +#define MODEL_SUB_OQO_O2_SMB0 3 + +static struct oqo_model oqo_models[] = { + { + .model ="Model 2" , + .model_subs =MODEL_SUB_OQO_O2_SMB0 , + }, + {} +};
Might be able to make this and oqo_dmis[] const. Although that tends to be a pita, easily ignorable..
Quoted 6 lines
drivers/misc/oqo-wmi.c new file +3
-0+static struct oqo_model *model; + +/*
drivers/misc/oqo-wmi.c line 171
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+* Interface type flags +*/ +enum interface_type { +OQO_O2_AMW0 , +}; + +/* Each low-level interface must define at least some of the following */ +struct wmi_interface { +/* The WMI device type */ +u32 type;
Can have type `enum interface_type'.
Quoted 21 lines
drivers/misc/oqo-wmi.c new file +18
-0+}; + +static struct wmi_interface AMW0_interface = { + .type =OQO_O2_AMW0 , +}; + +static acpi_status oqo_smbus_getb (u8 addr,u8 *result) +{ +struct acpi_buffer input, res; +acpi_status status; +union acpi_object *obj; +u32 arg2; + + input.length =4 ; + input.pointer = &arg2; + res.length =ACPI_ALLOCATE_BUFFER ; + res.pointer =NULL ; +
drivers/misc/oqo-wmi.c line 242
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ arg2 = addr; + arg2 <<=8 ; + arg2 |=0x12 ;/* HOSTCMD */ + + status =wmi_evaluate_method (OQO_O2_AMW0_GUID ,1 ,1 , &input, &res); + +if (status !=AE_OK ) +return status; + + obj = (union acpi_object *)res.pointer;
Unneeded and undesirable cast of void*.
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!obj) + return AE_NULL_OBJECT;
AE_NO_MEMORY, perhaps.
drivers/misc/oqo-wmi.c line 249
Quoted 4 lines
drivers/misc/oqo-wmi.c new file +4
-0+if (obj->type !=ACPI_TYPE_BUFFER + || obj->buffer.length !=1 || obj->buffer.pointer ==NULL ) { +kfree (obj); +return AE_TYPE ;
I wish someone had documented all these in include/acpi/acexcep.h.
Quoted 20 lines
drivers/misc/oqo-wmi.c new file +20
-0+ } + *result = ((u8 *) (obj->buffer.pointer))[0 ]; +kfree (obj); +return status; +} + +static acpi_status oqo_smbus_setb (u8 addr,u8 val) +{ +struct acpi_buffer input, res; +acpi_status status; +union acpi_object *obj; +u32 arg2; + + input.length =4 ; + input.pointer = &arg2; + res.length =ACPI_ALLOCATE_BUFFER ; + res.pointer =NULL ; + + arg2 = val; + arg2 <<=8 ;
drivers/misc/oqo-wmi.c line 279
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ arg2 |= addr; + arg2 <<=8 ; + arg2 |=0x12 ;/* HOSTCMD */ + + status =wmi_evaluate_method (OQO_O2_AMW0_GUID ,1 ,2 , &input, &res); + +if (status !=AE_OK ) +return status; + + obj = (union acpi_object *)res.pointer;
unneeded cast
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!obj) + return AE_NULL_OBJECT;
AE_NO_MEMORY?
Quoted 41 lines
drivers/misc/oqo-wmi.c new file +41
-0+if (obj->type !=ACPI_TYPE_INTEGER ) { +kfree (obj); +return AE_TYPE ; + } +kfree (obj); +return status; +} + +/* +* We assume we are the only one using this ...ahem... "lock" on +* the SMBUS because it would be pathetically noneffective otherwise. +* +* Nonzero silly_lock will keep certain ACPI routines away from the +* SMBUS (if they aren't already on it when you call it.) Zero +* silly_lock will let them back on +* +* This is probably useful before sleeping the system, and one +* waits until any ACPI funcs would have long finished before +* proceeding. It seems harmless enough and will work to wrap +* more accesses with it. +*/ +static acpi_status oqo_lock_smbus (int silly_lock) +{ +struct acpi_buffer input, res; +acpi_status status; +union acpi_object *obj; +u32 arg2; + + input.length =4 ; + input.pointer = &arg2; + res.length =ACPI_ALLOCATE_BUFFER ; + res.pointer =NULL ; + + arg2 = !!silly_lock; + + status =wmi_evaluate_method (OQO_O2_AMW0_GUID ,1 ,4 , &input, &res); + +if (status !=AE_OK ) +return status; + + obj = (union acpi_object *)res.pointer;
drivers/misc/oqo-wmi.c line 333
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+if (!obj) +return AE_NULL_OBJECT ; + +if (obj->type !=ACPI_TYPE_INTEGER ) { +kfree (obj); +return AE_TYPE ; + } +kfree (obj); +return status; +}
dittoes
drivers/misc/oqo-wmi.c line 344
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+static int smread_s16 (u8 hi_addr,u8 lo_addr) +{ +s16 ret =-1 ; +acpi_status status; +u8 r; + +/* Keep some ACPI routines off the SMBUS */ + status =oqo_lock_smbus (1 ); +if (ACPI_FAILURE (status)) + goto skip;
Does this mean that we didn't take the lock? If so, will running oqo_lock_smbus(0) be correct?
Quoted 22 lines
drivers/misc/oqo-wmi.c new file +22
-0+ status =oqo_smbus_getb (hi_addr, &r); +if (ACPI_FAILURE (status)) + goto skip; + + ret = r; + ret <<=8 ; + + status =oqo_smbus_getb (lo_addr, &r); +if (ACPI_FAILURE (status)) { + ret =-1 ; + goto skip; + } + + ret |= r; + ret &=0x7fff ; +skip: +/* Let ACPI routines back on the SMBUS */ + status =oqo_lock_smbus (0 ); +if (ACPI_FAILURE (status)) +return -1 ; +return (int )ret; +}
drivers/misc/oqo-wmi.c line 377
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ +static int smwrite_s16 (u8 hi_addr,u8 lo_addr,s16 val) +{ +acpi_status status; +u8 r; +int ret =-1 ; + + status =oqo_lock_smbus (1 ); +if (ACPI_FAILURE (status)) + goto skip;
Ditto
Quoted 17 lines
drivers/misc/oqo-wmi.c new file +17
-0+ r = (val >>8 ) &0x7f ; + status =oqo_smbus_setb (hi_addr, r); +if (ACPI_FAILURE (status)) + goto skip; + + r = val &0xff ; + status =oqo_smbus_setb (lo_addr, r); +if (ACPI_FAILURE (status)) + goto skip; + + ret =0 ; +skip: + status =oqo_lock_smbus (0 ); +if (ACPI_FAILURE (status)) +return -1 ; +return ret; +}
drivers/misc/oqo-wmi.c line 405
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ +static int smread_u8 (u8 addr) +{ +int ret =-1 ; +acpi_status status; +u8 r; + + status =oqo_lock_smbus (1 ); +if (ACPI_FAILURE (status)) + goto skip;
etc..
Quoted 20 lines
drivers/misc/oqo-wmi.c new file +17
-0+ status =oqo_smbus_getb (addr, &r); +if (ACPI_FAILURE (status)) + goto skip; + + ret = r; +skip: + status =oqo_lock_smbus (0 ); +if (ACPI_FAILURE (status)) +return -1 ; +return (int )ret; +} + +static acpi_status oqo_read_kine (int *good,s16 *x,s16 *y,s16 *z, +u16 *lumin) +{ +u8 hiregs[4 ] = {OQO_O2_SMB0_ACCEL_XHI , +OQO_O2_SMB0_ACCEL_YHI ,
drivers/misc/oqo-wmi.c line 480
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+OQO_O2_SMB0_ACCEL_ZHI , + OQO_O2_SMB0_LUMIN_HI + }; +u8 loregs[4 ] = {OQO_O2_SMB0_ACCEL_XLO , +OQO_O2_SMB0_ACCEL_YLO , +OQO_O2_SMB0_ACCEL_ZLO , +OQO_O2_SMB0_LUMIN_LO + }; + +short ax[4 ] = {ABS_X ,ABS_Y ,ABS_Z ,ABS_MISC };
The above arrays will be assembled on the stack each time this function is called (unless the compiler is being particularly smart). If there is a way of making them static const, goodness will ensue.
Quoted 22 lines
drivers/misc/oqo-wmi.c new file +22
-0+u8 realgood =0 ; +u16 res[4 ]; +acpi_status status; +int i; + + *good =0 ; + +/* Routine: Starting with the lo byte, read lo/hi bytes +alternately until two lo byte readings, match. Then +take that reading and combine it with the hi reading +sandwiched between. Errors can still happen when +jittering at wrap boundaries, but should be rare. + +Don't use this for missile guidance. + +Userspace post-processing error detection encouraged. +*/ +for (i =0 ; i <4 ; i++) { +int maxtry; +u32 log; +u8 r, lo, hi; +
drivers/misc/oqo-wmi.c line 512
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ lo = loregs[i]; + hi = hiregs[i]; + log =0 ; + +#define LOGRES (reg) do { \ + status = oqo_smbus_getb(reg, &r); \ + log <<= 8; log |= r; log &= 0xffffff; \ + if (ACPI_FAILURE(status)) \ + goto leave; \ + } while (0)
eww...
Quoted 20 lines
drivers/misc/oqo-wmi.c new file +20
-0+ maxtry =OQO_KINE_MAXTRY +1 ; +while (maxtry) { +LOGRES (lo); +if (maxtry <=OQO_KINE_MAXTRY && + (log >>16 ) == (log &0xff )) { + *(res + i) = log &0xffff ; +break ; + } +LOGRES (hi); + maxtry--; + } + +if (maxtry ==OQO_KINE_MAXTRY ) + realgood |=1 << i; + +if (maxtry) { + *good |=1 << i; +/* JIC CYA: this bit may be reserved */ + res[3 ] &=0x7fff ; +input_report_abs (oqo_kine, ax[i], (s16 ) res[i]);
drivers/misc/oqo-wmi.c line 543
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+ } +/* else we had trouble getting the reading to lock +and we skip reporting this axis. +*/ + } + + *x = (u16 ) res[0 ]; + *y = (u16 ) res[1 ]; + *z = (u16 ) res[2 ]; + *lumin = (u16 ) res[3 ];
Those four casts are unneeded.
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+return status; +leave: +return status; +} +
drivers/misc/oqo-wmi.c line 558
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+/* +* Generic Device (interface-independent) +*/ + +static void oqo_kine_poll (struct input_polled_dev *dev) +{ +s16 x, y, z; +u16 lumin; +int good; +/* struct timeval tv1, tv2; */
?
Quoted 81 lines
drivers/misc/oqo-wmi.c new file +81
-0+if (dev != oqo_kine_polled) +return ; +if (orig.kine_itvl <0 ) +return ; + + x = y = z =0 ; +oqo_read_kine (&good, &x, &y, &z, &lumin); +} + +static int __devinit oqo_kine_init (void ) +{ +int err; + + oqo_kine =input_allocate_device (); +if (!oqo_kine) +return -ENOMEM ; + + oqo_kine->name ="OQO embedded accelerometer" ; + oqo_kine->phys ="platform:oqo-wmi:kine" ; + oqo_kine->id.bustype =0 ; + oqo_kine->id.vendor =0 ; + oqo_kine->id.product =2 ; + oqo_kine->id.version =0 ; + oqo_kine->evbit[0 ] =BIT_MASK (EV_ABS ); +set_bit (ABS_X , oqo_kine->absbit); +set_bit (ABS_Y , oqo_kine->absbit); +set_bit (ABS_Z , oqo_kine->absbit); +set_bit (ABS_MISC , oqo_kine->absbit); + oqo_kine->absmin[ABS_X ] = + oqo_kine->absmin[ABS_Y ] = + oqo_kine->absmin[ABS_Z ] = oqo_kine->absmin[ABS_MISC ] =-32768 ; + oqo_kine->absmax[ABS_X ] = + oqo_kine->absmax[ABS_Y ] = + oqo_kine->absmax[ABS_Z ] = oqo_kine->absmax[ABS_MISC ] =32767 ; + +memcpy (oqo_kine->dev.bus_id,"kine" ,4 ); + + oqo_kine_polled =input_allocate_polled_device (); +if (!oqo_kine_polled) { + err = -ENOMEM ; + goto bail0; + } + + oqo_kine_polled->poll = oqo_kine_poll; + oqo_kine_polled->poll_interval =250 ; + oqo_kine_polled->input = oqo_kine; + + orig.kine_itvl =-1 ;/* prevent callback from running */ + err =input_register_polled_device (oqo_kine_polled); +if (err) { +printk (OQO_ERR "Failed to register OQO kine input\n" ); + goto bail1; + } + +/* This will allow the callback to run now if successful. */ + orig.kine_itvl =smread_u8 (OQO_O2_SMB0_ACCEL_POLL_ITVL ); +smwrite_u8 (OQO_O2_SMB0_ACCEL_POLL_ITVL ,250 ); + curr.kine_itvl =smread_u8 (OQO_O2_SMB0_ACCEL_POLL_ITVL ); +if (orig.kine_itvl <0 || curr.kine_itvl !=250 ) { +printk (OQO_ERR "Test communication with kine sensor failed\n" ); + err = -ENODEV ; + goto bail2; + } + +printk (OQO_INFO "Created OQO kine input.\n" ); +printk (OQO_INFO "Firmware interval %ims, driver interval %ims\n" , + curr.kine_itvl, oqo_kine_polled->poll_interval); +return 0 ; +bail2: +input_unregister_polled_device (oqo_kine_polled); +bail1: +input_free_polled_device (oqo_kine_polled);/* frees oqo_kine */ +return err; +bail0: +input_free_device (oqo_kine); +return err; +} + +static void __devexit oqo_kine_fini(void) +{ +smwrite_u8 (OQO_O2_SMB0_ACCEL_POLL_ITVL , orig.kine_itvl);
drivers/misc/oqo-wmi.c line 650
Quoted 10 lines
drivers/misc/oqo-wmi.c new file +10
-0+input_unregister_polled_device (oqo_kine_polled); +input_free_polled_device (oqo_kine_polled); +} + +/* +* Backlight device +*/ +static int read_brightness (struct backlight_device *bd) +{ +return (int )smread_s16 (OQO_O2_SMB0_BL_HI ,OQO_O2_SMB0_BL_LO );
smread_s16() already returns int.
drivers/misc/oqo-wmi.c line 656
Quoted 6 lines
drivers/misc/oqo-wmi.c new file +6
-0+} + +static int update_bl_status (struct backlight_device *bd) +{ +return smwrite_s16 (OQO_O2_SMB0_BL_HI , +OQO_O2_SMB0_BL_LO , (s16 ) bd->props.brightness);
This driver does quite a lot of casting of things which the compiler will happily do for us. This could be viewed as having documentation benefit, but not much, and it is atypical.
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +2
-0+} +
Yeah Matthew picked up the code before I did a final cleanup, at that
point I was still just waiting for someone(anyone) to test it. So the edges are
rough and there's still some painter's tape stuck to the walls. I guess I can afford some time to shave the fuzzies off, but Matthew and I should coordinate timewise if this all needs to be fixed before it's in a repository -- my opportunities to code are sparse, and his attention is probably a highly contested resource.
Thanks for the review (and Sven in other reply, too) -- a few items I probably would have missed cleaning. Some stuff is the wmi core and sample drivers at least as they were when I coded, and those aren't from me.
Quoted 5 lines · Andrew Morton
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+static int smread_s16 (u8 hi_addr,u8 lo_addr) +{ +s16 ret =-1 ; +acpi_status status; +u8 r;
Quoted 8 lines
drivers/misc/oqo-wmi.c line 344
Quoted 5 lines
drivers/misc/oqo-wmi.c new file +5
-0+ +/* Keep some ACPI routines off the SMBUS */ + status =oqo_lock_smbus (1 ); +if (ACPI_FAILURE (status)) + goto skip;Does this mean that we didn't take the lock? If so, will running
oqo_lock_smbus(0)be correct?
That does this (in DSL) after unpacking arguments and running a switch statement:
Store (BUF1, VFLG)
Return (0x00)
...VFLG being a preallocated RAM value in the ACPI VM. That's all. Famous last words but I really don't see it failing ever, or if it does the ACPI VM's in deep doodoo anyways. At any rate it will not spin.
Really an ACPI doctor is needed to even explain why it's there at all -- there's a real mutex on the SMBUS, and this here is not it.
It seems to just be some sort of badly coded (in DSDT) advisory that keeps the machine awake. I only even bothered to call it because it seemed like safer to do so than not. We should really be the only writer, as ACPI routines merely read it (and only a few of them.) The only access to it is through the WMI interface. Can we just claim exclusivity on using that given this is an omnibus driver?
Quoted 3 lines
This driver does quite a lot of casting of things which the compiler will happily do for us. This could be viewed as having documentation benefit, but not much, and it is atypical.
Yep I know, I'm cast-and-paren trigger happy. Keeps me sane, and has saved my butt a few times, but can be cleaned to match style.
P.S. I think it was Sven that pointed out a
label:
return
IIRC that was due to a cranky GCC warning FWIW.
--
Brian
Len Brown
reviewerMatthew,
this refreshed patch sits in my test tree from about a month ago. I guess i was expecting you to reply to the three comments on it before pushing it upstream.
thanks,
Len Brown, Intel Open Source Technology Center
Quoted 4 lines · Len Brown
Matthew,
this refreshed patch sits in my test tree from about a month ago. I guess i was expecting you to reply to the three comments on it before pushing it upstream.
Ah, sorry, I didn't realise you'd picked it up. I'm still trying to find some time to spend with the hardware to make sure a cleaned up version works correctly.
Signature · 1 line
Matthew Garrett | [email protected]
Len Brown
reviewerQuoted 9 lines
Quoted 5 lines
Matthew,
this refreshed patch sits in my test tree from about a month ago. I guess i was expecting you to reply to the three comments on it before pushing it upstream.Ah, sorry, I didn't realise you'd picked it up. I'm still trying to find some time to spend with the hardware to make sure a cleaned up version works correctly.
No sweat, just wanted you to know that v1 is in acpi test and thus will be in linux-next because of it.
It will patiently wait there until you're ready to refresh it.
cheers,
-Len
Len Brown
reviewerFrom: Matthew Garrett <[email protected]>
Matthew,
Here is the version in my tree -- refreshed to live in drivers/platform/x86/.
cheers,
-Len
oqo-wmi provides a WMI-based interface to backlight and rfkill control on model 2 OQO devices. It was originally written by Brian Julin (<[email protected]>) - I've ported it to the rfkill layer and tidied it up a little.
--- MAINTAINERS | 5 + drivers/platform/x86/Kconfig | 13 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/oqo-wmi.c | 941 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 960 insertions(+), 0 deletions(-) create mode 100644 drivers/platform/x86/oqo-wmi.c
MAINTAINERS +5 -0
@@ -3239,6 +3239,11 @@ M: [email protected] L: [email protected] S: Maintained +OQO WMI EXTRAS DRIVER +P: Matthew Garrett +M: [email protected] +S: Maintained + ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh M: [email protected]
drivers/platform/x86/Kconfig +13 -0
@@ -132,6 +132,19 @@ config MSI_LAPTOP If you have an MSI S270 laptop, say Y or M here. +config OQO_WMI + tristate "OQO WMI extras" + depends on ACPI_WMI + depends on INPUT + depends on RFKILL + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to support rfkill and backlight control on + series 2 OQO handheld devices. + + To compile this driver as a module, choose M here: the module will + be called oqo-wmi. + config PANASONIC_LAPTOP tristate "Panasonic Laptop Extras" depends on INPUT && ACPI
drivers/platform/x86/Makefile +1 -0
@@ -13,6 +13,7 @@ obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o +obj-$(CONFIG_OQO_WMI) += oqo-wmi.o obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o obj-$(CONFIG_ACPI_WMI) += wmi.o
drivers/platform/x86/oqo-wmi.c new file +941 -0
941 lines not on this page · raw message
Signature · 1 line
1.6.1.76.gc123b