Thread (6 messages) 6 messages, 3 authors, 2010-10-13

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

From: Carlos Corbacho <hidden>
Date: 2010-10-13 06:42:40
Also in: platform-driver-x86

On Wednesday 13 October 2010 04:47:42 Lee, Chun-Yi wrote:
quoted hunk ↗ jump to hunk
Add 3G rfkill sysfs file for provide userland to control 3G device
on/off by using WMI method.

Signed-off-by: Lee, Chun-Yi <redacted>
---
 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?
quoted hunk ↗ jump to hunk
+#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.
quoted hunk ↗ jump to hunk
+{
+	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).
quoted hunk ↗ jump to hunk
+		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@strangeworlds.co.uk
Web: strangeworlds.co.uk
GPG Key ID: 0x23EE722D
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help