Re: [PATCH 3/3] Add 3G rfkill sysfs file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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),
> +		&params
> +	};
> +	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


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux