|
@@ -85,6 +85,7 @@ MODULE_LICENSE("GPL");
|
|
#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
|
|
#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
|
|
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
|
|
#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
|
|
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
|
|
#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
|
|
|
|
+#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
|
|
|
|
|
|
/*
|
|
/*
|
|
* Acer ACPI event GUIDs
|
|
* Acer ACPI event GUIDs
|
|
@@ -120,6 +121,24 @@ struct event_return_value {
|
|
u32 reserved;
|
|
u32 reserved;
|
|
} __attribute__((packed));
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * GUID3 Get Device Status device flags
|
|
|
|
+ */
|
|
|
|
+#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
|
|
|
|
+
|
|
|
|
+struct wmid3_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 wmid3_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
|
|
* Interface capability flags
|
|
*/
|
|
*/
|
|
@@ -174,6 +193,7 @@ struct acer_debug {
|
|
|
|
|
|
static struct rfkill *wireless_rfkill;
|
|
static struct rfkill *wireless_rfkill;
|
|
static struct rfkill *bluetooth_rfkill;
|
|
static struct rfkill *bluetooth_rfkill;
|
|
|
|
+static struct rfkill *threeg_rfkill;
|
|
|
|
|
|
/* Each low-level interface must define at least some of the following */
|
|
/* Each low-level interface must define at least some of the following */
|
|
struct wmi_interface {
|
|
struct wmi_interface {
|
|
@@ -982,6 +1002,54 @@ static void acer_backlight_exit(void)
|
|
backlight_device_unregister(acer_backlight_device);
|
|
backlight_device_unregister(acer_backlight_device);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static acpi_status wmid3_get_device_status(u32 *value, u16 device)
|
|
|
|
+{
|
|
|
|
+ struct wmid3_gds_return_value return_value;
|
|
|
|
+ acpi_status status;
|
|
|
|
+ union acpi_object *obj;
|
|
|
|
+ struct wmid3_gds_input_param params = {
|
|
|
|
+ .function_num = 0x1,
|
|
|
|
+ .hotkey_number = 0x01,
|
|
|
|
+ .devices = device,
|
|
|
|
+ };
|
|
|
|
+ struct acpi_buffer input = {
|
|
|
|
+ sizeof(struct wmid3_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 AE_ERROR;
|
|
|
|
+ else if (obj->type != ACPI_TYPE_BUFFER) {
|
|
|
|
+ kfree(obj);
|
|
|
|
+ return AE_ERROR;
|
|
|
|
+ }
|
|
|
|
+ if (obj->buffer.length != 8) {
|
|
|
|
+ printk(ACER_WARNING "Unknown buffer length %d\n",
|
|
|
|
+ obj->buffer.length);
|
|
|
|
+ kfree(obj);
|
|
|
|
+ return AE_ERROR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return_value = *((struct wmid3_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
|
|
* Rfkill devices
|
|
*/
|
|
*/
|
|
@@ -1002,6 +1070,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
|
|
rfkill_set_sw_state(bluetooth_rfkill, !state);
|
|
rfkill_set_sw_state(bluetooth_rfkill, !state);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
|
|
|
|
+ status = wmid3_get_device_status(&state,
|
|
|
|
+ ACER_WMID3_GDS_THREEG);
|
|
|
|
+ if (ACPI_SUCCESS(status))
|
|
|
|
+ rfkill_set_sw_state(threeg_rfkill, !state);
|
|
|
|
+ }
|
|
|
|
+
|
|
schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
|
|
schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1058,6 +1133,19 @@ static int acer_rfkill_init(struct device *dev)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (has_cap(ACER_CAP_THREEG)) {
|
|
|
|
+ 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));
|
|
schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1074,6 +1162,11 @@ static void acer_rfkill_exit(void)
|
|
rfkill_unregister(bluetooth_rfkill);
|
|
rfkill_unregister(bluetooth_rfkill);
|
|
rfkill_destroy(bluetooth_rfkill);
|
|
rfkill_destroy(bluetooth_rfkill);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (has_cap(ACER_CAP_THREEG)) {
|
|
|
|
+ rfkill_unregister(threeg_rfkill);
|
|
|
|
+ rfkill_destroy(threeg_rfkill);
|
|
|
|
+ }
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1084,7 +1177,12 @@ static ssize_t show_bool_threeg(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
{
|
|
u32 result; \
|
|
u32 result; \
|
|
- acpi_status status = get_u32(&result, ACER_CAP_THREEG);
|
|
|
|
|
|
+ acpi_status status;
|
|
|
|
+ if (wmi_has_guid(WMID_GUID3))
|
|
|
|
+ status = wmid3_get_device_status(&result,
|
|
|
|
+ ACER_WMID3_GDS_THREEG);
|
|
|
|
+ else
|
|
|
|
+ status = get_u32(&result, ACER_CAP_THREEG);
|
|
if (ACPI_SUCCESS(status))
|
|
if (ACPI_SUCCESS(status))
|
|
return sprintf(buf, "%u\n", result);
|
|
return sprintf(buf, "%u\n", result);
|
|
return sprintf(buf, "Read error\n");
|
|
return sprintf(buf, "Read error\n");
|