On Wednesday 13 October 2010 04:47:42 Lee, Chun-Yi wrote: > Add 3G rfkill sysfs file for provide userland to control 3G device > on/off by using WMI method. > > Signed-off-by: Lee, Chun-Yi <jlee@xxxxxxxxxx> > --- > drivers/platform/x86/acer-wmi.c | 101 > ++++++++++++++++++++++++++++++++++++++- 1 files changed, 100 > insertions(+), 1 deletions(-) > > diff --git a/drivers/platform/x86/acer-wmi.c > b/drivers/platform/x86/acer-wmi.c index a28a775..150e0e3 100644 > --- a/drivers/platform/x86/acer-wmi.c > +++ b/drivers/platform/x86/acer-wmi.c > @@ -136,6 +136,26 @@ struct lm_return_value { > } __attribute__((packed)); > > /* > + * GUID3 Get Device Status device flags > + */ > +#define ACER_WMID_GUID3_GDS_WIRELESS (1<<0) /* WiFi */ > +#define ACER_WMID_GUID3_GDS_THREEG (1<<6) /* 3G */ These two don't seem to be used? > +#define ACER_WMID_GUID3_GDS_BLUETOOTH (1<<11) /* BT */ > + > +struct guid3_gds_input_param { /* Get Device Status input parameter */ > + u8 function_num; /* Function Number */ > + u8 hotkey_number; /* Hotkey Number */ > + u16 devices; /* Get Device */ > +} __attribute__((packed)); > + > +struct guid3_gds_return_value { /* Get Device Status return value*/ > + u8 error_code; /* Error Code */ > + u8 ec_return_value; /* EC Return Value */ > + u16 devices; /* Current Device Status */ > + u32 reserved; > +} __attribute__((packed)); > + > +/* > * Interface capability flags > */ > #define ACER_CAP_MAILLED (1<<0) > @@ -192,6 +212,7 @@ struct acer_debug { > > static struct rfkill *wireless_rfkill; > static struct rfkill *bluetooth_rfkill; > +static struct rfkill *threeg_rfkill; > > /* Each low-level interface must define at least some of the following */ > struct wmi_interface { > @@ -1000,6 +1021,54 @@ static void acer_backlight_exit(void) > backlight_device_unregister(acer_backlight_device); > } > > +static acpi_status acer_wmi_get_device_status(u32 *value, u16 device) Can you rename this to something like WMID3? This name is just too generic. > +{ > + struct guid3_gds_return_value return_value; > + acpi_status status; > + union acpi_object *obj; > + struct guid3_gds_input_param params = { > + .function_num = 0x1, > + .hotkey_number = 0x01, > + .devices = device, > + }; > + struct acpi_buffer input = { > + sizeof(struct guid3_gds_input_param), > + ¶ms > + }; > + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > + > + status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); > + if (ACPI_FAILURE(status)) > + return status; > + > + obj = output.pointer; > + > + if (!obj) > + return -EINVAL; > + else if (obj->type != ACPI_TYPE_BUFFER) { > + kfree(obj); > + return -EINVAL; > + } > + if (obj->buffer.length != 8) { > + printk(ACER_WARNING "Unknown buffer length %d\n", > + obj->buffer.length); > + kfree(obj); > + return -EINVAL; > + } > + > + return_value = *((struct guid3_gds_return_value *)obj->buffer.pointer); > + kfree(obj); > + > + if (return_value.error_code || return_value.ec_return_value) > + printk(ACER_WARNING "Get Device Status failed: " > + "0x%x - 0x%x\n", return_value.error_code, > + return_value.ec_return_value); > + else > + *value = !!(return_value.devices & device); > + > + return status; > +} > + > /* > * Rfkill devices > */ > @@ -1020,6 +1089,13 @@ static void acer_rfkill_update(struct work_struct > *ignored) rfkill_set_sw_state(bluetooth_rfkill, !state); > } > > + if (has_cap(ACER_CAP_BLUETOOTH) && wmi_has_guid(WMID_GUID3)) { > + status = acer_wmi_get_device_status(&state, > + ACER_WMID_GUID3_GDS_THREEG); > + if (ACPI_SUCCESS(status)) > + rfkill_set_sw_state(bluetooth_rfkill, !state); > + } > + > schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); > } > > @@ -1076,6 +1152,19 @@ static int acer_rfkill_init(struct device *dev) > } > } > > + if (has_cap(ACER_CAP_THREEG)) { Have you figured out a way of detecting if 3G is available on the platform? As this still requires the user to pass in a module parameter to enable it. (And enabling unconditionally won't work, as older machines don't even have the relevant WMI methods and just give nasty ACPI tracebacks). > + threeg_rfkill = acer_rfkill_register(dev, > + RFKILL_TYPE_WWAN, "acer-threeg", > + ACER_CAP_THREEG); > + if (IS_ERR(threeg_rfkill)) { > + rfkill_unregister(wireless_rfkill); > + rfkill_destroy(wireless_rfkill); > + rfkill_unregister(bluetooth_rfkill); > + rfkill_destroy(bluetooth_rfkill); > + return PTR_ERR(threeg_rfkill); > + } > + } > + > schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); > > return 0; > @@ -1092,6 +1181,11 @@ static void acer_rfkill_exit(void) > rfkill_unregister(bluetooth_rfkill); > rfkill_destroy(bluetooth_rfkill); > } > + > + if (has_cap(ACER_CAP_THREEG)) { > + rfkill_unregister(threeg_rfkill); > + rfkill_destroy(threeg_rfkill); > + } > return; > } > > @@ -1102,7 +1196,12 @@ static ssize_t show_bool_threeg(struct device *dev, > struct device_attribute *attr, char *buf) > { > u32 result; \ > - acpi_status status = get_u32(&result, ACER_CAP_THREEG); > + acpi_status status; > + if (wmi_has_guid(WMID_GUID3)) > + status = acer_wmi_get_device_status(&result, > + ACER_WMID_GUID3_GDS_THREEG); > + else > + status = get_u32(&result, ACER_CAP_THREEG); > if (ACPI_SUCCESS(status)) > return sprintf(buf, "%u\n", result); > return sprintf(buf, "Read error\n"); -- E-Mail: carlos@xxxxxxxxxxxxxxxxxxx Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html