aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLee, Chun-Yi <joeyli.kernel@gmail.com>2010-12-06 21:29:22 -0500
committerMatthew Garrett <mjg@redhat.com>2011-01-07 17:03:48 -0500
commitb3c9092b2fed427d45117d23ceb577ad8dc46a9a (patch)
tree726ab8a4ee2d95672c4dac824d98443b382889aa /drivers/platform
parent3fdca87d10f1d45b1c034da343e68beb082f9b84 (diff)
acer-wmi: Add 3G rfkill sysfs file
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@novell.com> Acked-by: Thomas Renninger <trenn@suse.de> Acked-by: Jiri Benc <jbenc@suse.cz> Acked-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Carlos Corbaho <carlos@strangeworlds.co.uk> Cc: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/acer-wmi.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index a1c6141f463b..85d263349aac 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -85,6 +85,7 @@ MODULE_LICENSE("GPL");
85#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" 85#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
86#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" 86#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
87#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" 87#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
88#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
88 89
89/* 90/*
90 * Acer ACPI event GUIDs 91 * Acer ACPI event GUIDs
@@ -121,6 +122,24 @@ struct event_return_value {
121} __attribute__((packed)); 122} __attribute__((packed));
122 123
123/* 124/*
125 * GUID3 Get Device Status device flags
126 */
127#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
128
129struct wmid3_gds_input_param { /* Get Device Status input parameter */
130 u8 function_num; /* Function Number */
131 u8 hotkey_number; /* Hotkey Number */
132 u16 devices; /* Get Device */
133} __attribute__((packed));
134
135struct wmid3_gds_return_value { /* Get Device Status return value*/
136 u8 error_code; /* Error Code */
137 u8 ec_return_value; /* EC Return Value */
138 u16 devices; /* Current Device Status */
139 u32 reserved;
140} __attribute__((packed));
141
142/*
124 * Interface capability flags 143 * Interface capability flags
125 */ 144 */
126#define ACER_CAP_MAILLED (1<<0) 145#define ACER_CAP_MAILLED (1<<0)
@@ -174,6 +193,7 @@ struct acer_debug {
174 193
175static struct rfkill *wireless_rfkill; 194static struct rfkill *wireless_rfkill;
176static struct rfkill *bluetooth_rfkill; 195static struct rfkill *bluetooth_rfkill;
196static struct rfkill *threeg_rfkill;
177 197
178/* Each low-level interface must define at least some of the following */ 198/* Each low-level interface must define at least some of the following */
179struct wmi_interface { 199struct wmi_interface {
@@ -982,6 +1002,54 @@ static void acer_backlight_exit(void)
982 backlight_device_unregister(acer_backlight_device); 1002 backlight_device_unregister(acer_backlight_device);
983} 1003}
984 1004
1005static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1006{
1007 struct wmid3_gds_return_value return_value;
1008 acpi_status status;
1009 union acpi_object *obj;
1010 struct wmid3_gds_input_param params = {
1011 .function_num = 0x1,
1012 .hotkey_number = 0x01,
1013 .devices = device,
1014 };
1015 struct acpi_buffer input = {
1016 sizeof(struct wmid3_gds_input_param),
1017 &params
1018 };
1019 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1020
1021 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1022 if (ACPI_FAILURE(status))
1023 return status;
1024
1025 obj = output.pointer;
1026
1027 if (!obj)
1028 return AE_ERROR;
1029 else if (obj->type != ACPI_TYPE_BUFFER) {
1030 kfree(obj);
1031 return AE_ERROR;
1032 }
1033 if (obj->buffer.length != 8) {
1034 printk(ACER_WARNING "Unknown buffer length %d\n",
1035 obj->buffer.length);
1036 kfree(obj);
1037 return AE_ERROR;
1038 }
1039
1040 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1041 kfree(obj);
1042
1043 if (return_value.error_code || return_value.ec_return_value)
1044 printk(ACER_WARNING "Get Device Status failed: "
1045 "0x%x - 0x%x\n", return_value.error_code,
1046 return_value.ec_return_value);
1047 else
1048 *value = !!(return_value.devices & device);
1049
1050 return status;
1051}
1052
985/* 1053/*
986 * Rfkill devices 1054 * Rfkill devices
987 */ 1055 */
@@ -1002,6 +1070,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
1002 rfkill_set_sw_state(bluetooth_rfkill, !state); 1070 rfkill_set_sw_state(bluetooth_rfkill, !state);
1003 } 1071 }
1004 1072
1073 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1074 status = wmid3_get_device_status(&state,
1075 ACER_WMID3_GDS_THREEG);
1076 if (ACPI_SUCCESS(status))
1077 rfkill_set_sw_state(threeg_rfkill, !state);
1078 }
1079
1005 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1080 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
1006} 1081}
1007 1082
@@ -1058,6 +1133,19 @@ static int acer_rfkill_init(struct device *dev)
1058 } 1133 }
1059 } 1134 }
1060 1135
1136 if (has_cap(ACER_CAP_THREEG)) {
1137 threeg_rfkill = acer_rfkill_register(dev,
1138 RFKILL_TYPE_WWAN, "acer-threeg",
1139 ACER_CAP_THREEG);
1140 if (IS_ERR(threeg_rfkill)) {
1141 rfkill_unregister(wireless_rfkill);
1142 rfkill_destroy(wireless_rfkill);
1143 rfkill_unregister(bluetooth_rfkill);
1144 rfkill_destroy(bluetooth_rfkill);
1145 return PTR_ERR(threeg_rfkill);
1146 }
1147 }
1148
1061 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1149 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
1062 1150
1063 return 0; 1151 return 0;
@@ -1074,6 +1162,11 @@ static void acer_rfkill_exit(void)
1074 rfkill_unregister(bluetooth_rfkill); 1162 rfkill_unregister(bluetooth_rfkill);
1075 rfkill_destroy(bluetooth_rfkill); 1163 rfkill_destroy(bluetooth_rfkill);
1076 } 1164 }
1165
1166 if (has_cap(ACER_CAP_THREEG)) {
1167 rfkill_unregister(threeg_rfkill);
1168 rfkill_destroy(threeg_rfkill);
1169 }
1077 return; 1170 return;
1078} 1171}
1079 1172
@@ -1084,7 +1177,12 @@ static ssize_t show_bool_threeg(struct device *dev,
1084 struct device_attribute *attr, char *buf) 1177 struct device_attribute *attr, char *buf)
1085{ 1178{
1086 u32 result; \ 1179 u32 result; \
1087 acpi_status status = get_u32(&result, ACER_CAP_THREEG); 1180 acpi_status status;
1181 if (wmi_has_guid(WMID_GUID3))
1182 status = wmid3_get_device_status(&result,
1183 ACER_WMID3_GDS_THREEG);
1184 else
1185 status = get_u32(&result, ACER_CAP_THREEG);
1088 if (ACPI_SUCCESS(status)) 1186 if (ACPI_SUCCESS(status))
1089 return sprintf(buf, "%u\n", result); 1187 return sprintf(buf, "%u\n", result);
1090 return sprintf(buf, "Read error\n"); 1188 return sprintf(buf, "Read error\n");