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 <[email protected]>
> ---
> 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: [email protected]
Web: strangeworlds.co.uk
GPG Key ID: 0x23EE722D
--
To unsubscribe from this list: send the line "unsubscribe platform-driver-x86"
in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html