diff options
-rw-r--r-- | drivers/acpi/button.c | 140 |
1 files changed, 44 insertions, 96 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index d73c94b8441d..9195deba9d94 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * acpi_button.c - ACPI Button Driver ($Revision: 30 $) | 2 | * button.c - ACPI Button Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
@@ -41,17 +41,13 @@ | |||
41 | 41 | ||
42 | #define ACPI_BUTTON_SUBCLASS_POWER "power" | 42 | #define ACPI_BUTTON_SUBCLASS_POWER "power" |
43 | #define ACPI_BUTTON_HID_POWER "PNP0C0C" | 43 | #define ACPI_BUTTON_HID_POWER "PNP0C0C" |
44 | #define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)" | 44 | #define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button" |
45 | #define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)" | ||
46 | #define ACPI_BUTTON_TYPE_POWER 0x01 | 45 | #define ACPI_BUTTON_TYPE_POWER 0x01 |
47 | #define ACPI_BUTTON_TYPE_POWERF 0x02 | ||
48 | 46 | ||
49 | #define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" | 47 | #define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" |
50 | #define ACPI_BUTTON_HID_SLEEP "PNP0C0E" | 48 | #define ACPI_BUTTON_HID_SLEEP "PNP0C0E" |
51 | #define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)" | 49 | #define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button" |
52 | #define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)" | ||
53 | #define ACPI_BUTTON_TYPE_SLEEP 0x03 | 50 | #define ACPI_BUTTON_TYPE_SLEEP 0x03 |
54 | #define ACPI_BUTTON_TYPE_SLEEPF 0x04 | ||
55 | 51 | ||
56 | #define ACPI_BUTTON_SUBCLASS_LID "lid" | 52 | #define ACPI_BUTTON_SUBCLASS_LID "lid" |
57 | #define ACPI_BUTTON_HID_LID "PNP0C0D" | 53 | #define ACPI_BUTTON_HID_LID "PNP0C0D" |
@@ -95,7 +91,6 @@ static struct acpi_driver acpi_button_driver = { | |||
95 | }; | 91 | }; |
96 | 92 | ||
97 | struct acpi_button { | 93 | struct acpi_button { |
98 | struct acpi_device *device; /* Fixed button kludge */ | ||
99 | unsigned int type; | 94 | unsigned int type; |
100 | struct input_dev *input; | 95 | struct input_dev *input; |
101 | char phys[32]; /* for input device */ | 96 | char phys[32]; /* for input device */ |
@@ -126,14 +121,10 @@ static struct proc_dir_entry *acpi_button_dir; | |||
126 | 121 | ||
127 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) | 122 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) |
128 | { | 123 | { |
129 | struct acpi_button *button = seq->private; | 124 | struct acpi_device *device = seq->private; |
130 | |||
131 | if (!button || !button->device) | ||
132 | return 0; | ||
133 | 125 | ||
134 | seq_printf(seq, "type: %s\n", | 126 | seq_printf(seq, "type: %s\n", |
135 | acpi_device_name(button->device)); | 127 | acpi_device_name(device)); |
136 | |||
137 | return 0; | 128 | return 0; |
138 | } | 129 | } |
139 | 130 | ||
@@ -144,14 +135,11 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file) | |||
144 | 135 | ||
145 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | 136 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) |
146 | { | 137 | { |
147 | struct acpi_button *button = seq->private; | 138 | struct acpi_device *device = seq->private; |
148 | acpi_status status; | 139 | acpi_status status; |
149 | unsigned long long state; | 140 | unsigned long long state; |
150 | 141 | ||
151 | if (!button || !button->device) | 142 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); |
152 | return 0; | ||
153 | |||
154 | status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state); | ||
155 | seq_printf(seq, "state: %s\n", | 143 | seq_printf(seq, "state: %s\n", |
156 | ACPI_FAILURE(status) ? "unsupported" : | 144 | ACPI_FAILURE(status) ? "unsupported" : |
157 | (state ? "open" : "closed")); | 145 | (state ? "open" : "closed")); |
@@ -169,24 +157,17 @@ static struct proc_dir_entry *acpi_lid_dir; | |||
169 | 157 | ||
170 | static int acpi_button_add_fs(struct acpi_device *device) | 158 | static int acpi_button_add_fs(struct acpi_device *device) |
171 | { | 159 | { |
160 | struct acpi_button *button = acpi_driver_data(device); | ||
172 | struct proc_dir_entry *entry = NULL; | 161 | struct proc_dir_entry *entry = NULL; |
173 | struct acpi_button *button; | ||
174 | |||
175 | if (!device || !acpi_driver_data(device)) | ||
176 | return -EINVAL; | ||
177 | |||
178 | button = acpi_driver_data(device); | ||
179 | 162 | ||
180 | switch (button->type) { | 163 | switch (button->type) { |
181 | case ACPI_BUTTON_TYPE_POWER: | 164 | case ACPI_BUTTON_TYPE_POWER: |
182 | case ACPI_BUTTON_TYPE_POWERF: | ||
183 | if (!acpi_power_dir) | 165 | if (!acpi_power_dir) |
184 | acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, | 166 | acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, |
185 | acpi_button_dir); | 167 | acpi_button_dir); |
186 | entry = acpi_power_dir; | 168 | entry = acpi_power_dir; |
187 | break; | 169 | break; |
188 | case ACPI_BUTTON_TYPE_SLEEP: | 170 | case ACPI_BUTTON_TYPE_SLEEP: |
189 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
190 | if (!acpi_sleep_dir) | 171 | if (!acpi_sleep_dir) |
191 | acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, | 172 | acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, |
192 | acpi_button_dir); | 173 | acpi_button_dir); |
@@ -210,8 +191,7 @@ static int acpi_button_add_fs(struct acpi_device *device) | |||
210 | /* 'info' [R] */ | 191 | /* 'info' [R] */ |
211 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, | 192 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, |
212 | S_IRUGO, acpi_device_dir(device), | 193 | S_IRUGO, acpi_device_dir(device), |
213 | &acpi_button_info_fops, | 194 | &acpi_button_info_fops, device); |
214 | acpi_driver_data(device)); | ||
215 | if (!entry) | 195 | if (!entry) |
216 | return -ENODEV; | 196 | return -ENODEV; |
217 | 197 | ||
@@ -219,8 +199,7 @@ static int acpi_button_add_fs(struct acpi_device *device) | |||
219 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 199 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
220 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, | 200 | entry = proc_create_data(ACPI_BUTTON_FILE_STATE, |
221 | S_IRUGO, acpi_device_dir(device), | 201 | S_IRUGO, acpi_device_dir(device), |
222 | &acpi_button_state_fops, | 202 | &acpi_button_state_fops, device); |
223 | acpi_driver_data(device)); | ||
224 | if (!entry) | 203 | if (!entry) |
225 | return -ENODEV; | 204 | return -ENODEV; |
226 | } | 205 | } |
@@ -250,15 +229,16 @@ static int acpi_button_remove_fs(struct acpi_device *device) | |||
250 | /* -------------------------------------------------------------------------- | 229 | /* -------------------------------------------------------------------------- |
251 | Driver Interface | 230 | Driver Interface |
252 | -------------------------------------------------------------------------- */ | 231 | -------------------------------------------------------------------------- */ |
253 | static int acpi_lid_send_state(struct acpi_button *button) | 232 | static int acpi_lid_send_state(struct acpi_device *device) |
254 | { | 233 | { |
234 | struct acpi_button *button = acpi_driver_data(device); | ||
255 | unsigned long long state; | 235 | unsigned long long state; |
256 | acpi_status status; | 236 | acpi_status status; |
257 | 237 | ||
258 | status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, | 238 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); |
259 | &state); | ||
260 | if (ACPI_FAILURE(status)) | 239 | if (ACPI_FAILURE(status)) |
261 | return -ENODEV; | 240 | return -ENODEV; |
241 | |||
262 | /* input layer checks if event is redundant */ | 242 | /* input layer checks if event is redundant */ |
263 | input_report_switch(button->input, SW_LID, !state); | 243 | input_report_switch(button->input, SW_LID, !state); |
264 | input_sync(button->input); | 244 | input_sync(button->input); |
@@ -270,9 +250,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
270 | struct acpi_button *button = acpi_driver_data(device); | 250 | struct acpi_button *button = acpi_driver_data(device); |
271 | struct input_dev *input; | 251 | struct input_dev *input; |
272 | 252 | ||
273 | if (!button || !button->device) | ||
274 | return; | ||
275 | |||
276 | switch (event) { | 253 | switch (event) { |
277 | case ACPI_FIXED_HARDWARE_EVENT: | 254 | case ACPI_FIXED_HARDWARE_EVENT: |
278 | event = ACPI_BUTTON_NOTIFY_STATUS; | 255 | event = ACPI_BUTTON_NOTIFY_STATUS; |
@@ -280,7 +257,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
280 | case ACPI_BUTTON_NOTIFY_STATUS: | 257 | case ACPI_BUTTON_NOTIFY_STATUS: |
281 | input = button->input; | 258 | input = button->input; |
282 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 259 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
283 | acpi_lid_send_state(button); | 260 | acpi_lid_send_state(device); |
284 | } else { | 261 | } else { |
285 | int keycode = test_bit(KEY_SLEEP, input->keybit) ? | 262 | int keycode = test_bit(KEY_SLEEP, input->keybit) ? |
286 | KEY_SLEEP : KEY_POWER; | 263 | KEY_SLEEP : KEY_POWER; |
@@ -291,43 +268,35 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
291 | input_sync(input); | 268 | input_sync(input); |
292 | } | 269 | } |
293 | 270 | ||
294 | acpi_bus_generate_proc_event(button->device, event, | 271 | acpi_bus_generate_proc_event(device, event, ++button->pushed); |
295 | ++button->pushed); | ||
296 | break; | 272 | break; |
297 | default: | 273 | default: |
298 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 274 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
299 | "Unsupported event [0x%x]\n", event)); | 275 | "Unsupported event [0x%x]\n", event)); |
300 | break; | 276 | break; |
301 | } | 277 | } |
302 | |||
303 | return; | ||
304 | } | 278 | } |
305 | 279 | ||
306 | static int acpi_button_resume(struct acpi_device *device) | 280 | static int acpi_button_resume(struct acpi_device *device) |
307 | { | 281 | { |
308 | struct acpi_button *button; | 282 | struct acpi_button *button = acpi_driver_data(device); |
309 | if (!device) | 283 | |
310 | return -EINVAL; | 284 | if (button->type == ACPI_BUTTON_TYPE_LID) |
311 | button = acpi_driver_data(device); | 285 | return acpi_lid_send_state(device); |
312 | if (button && button->type == ACPI_BUTTON_TYPE_LID) | ||
313 | return acpi_lid_send_state(button); | ||
314 | return 0; | 286 | return 0; |
315 | } | 287 | } |
316 | 288 | ||
317 | static int acpi_button_add(struct acpi_device *device) | 289 | static int acpi_button_add(struct acpi_device *device) |
318 | { | 290 | { |
319 | int error; | ||
320 | struct acpi_button *button; | 291 | struct acpi_button *button; |
321 | struct input_dev *input; | 292 | struct input_dev *input; |
322 | 293 | char *hid, *name, *class; | |
323 | if (!device) | 294 | int error; |
324 | return -EINVAL; | ||
325 | 295 | ||
326 | button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); | 296 | button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); |
327 | if (!button) | 297 | if (!button) |
328 | return -ENOMEM; | 298 | return -ENOMEM; |
329 | 299 | ||
330 | button->device = device; | ||
331 | device->driver_data = button; | 300 | device->driver_data = button; |
332 | 301 | ||
333 | button->input = input = input_allocate_device(); | 302 | button->input = input = input_allocate_device(); |
@@ -336,40 +305,29 @@ static int acpi_button_add(struct acpi_device *device) | |||
336 | goto err_free_button; | 305 | goto err_free_button; |
337 | } | 306 | } |
338 | 307 | ||
339 | /* | 308 | hid = acpi_device_hid(device); |
340 | * Determine the button type (via hid), as fixed-feature buttons | 309 | name = acpi_device_name(device); |
341 | * need to be handled a bit differently than generic-space. | 310 | class = acpi_device_class(device); |
342 | */ | 311 | |
343 | if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) { | 312 | if (!strcmp(hid, ACPI_BUTTON_HID_POWER) || |
313 | !strcmp(hid, ACPI_BUTTON_HID_POWERF)) { | ||
344 | button->type = ACPI_BUTTON_TYPE_POWER; | 314 | button->type = ACPI_BUTTON_TYPE_POWER; |
345 | strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_POWER); | 315 | strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER); |
346 | sprintf(acpi_device_class(device), "%s/%s", | 316 | sprintf(class, "%s/%s", |
347 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); | ||
348 | } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { | ||
349 | button->type = ACPI_BUTTON_TYPE_POWERF; | ||
350 | strcpy(acpi_device_name(device), | ||
351 | ACPI_BUTTON_DEVICE_NAME_POWERF); | ||
352 | sprintf(acpi_device_class(device), "%s/%s", | ||
353 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); | 317 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); |
354 | } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { | 318 | } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) || |
319 | !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) { | ||
355 | button->type = ACPI_BUTTON_TYPE_SLEEP; | 320 | button->type = ACPI_BUTTON_TYPE_SLEEP; |
356 | strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_SLEEP); | 321 | strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP); |
357 | sprintf(acpi_device_class(device), "%s/%s", | 322 | sprintf(class, "%s/%s", |
358 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); | ||
359 | } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) { | ||
360 | button->type = ACPI_BUTTON_TYPE_SLEEPF; | ||
361 | strcpy(acpi_device_name(device), | ||
362 | ACPI_BUTTON_DEVICE_NAME_SLEEPF); | ||
363 | sprintf(acpi_device_class(device), "%s/%s", | ||
364 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); | 323 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); |
365 | } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { | 324 | } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) { |
366 | button->type = ACPI_BUTTON_TYPE_LID; | 325 | button->type = ACPI_BUTTON_TYPE_LID; |
367 | strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_LID); | 326 | strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); |
368 | sprintf(acpi_device_class(device), "%s/%s", | 327 | sprintf(class, "%s/%s", |
369 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); | 328 | ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); |
370 | } else { | 329 | } else { |
371 | printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", | 330 | printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); |
372 | acpi_device_hid(device)); | ||
373 | error = -ENODEV; | 331 | error = -ENODEV; |
374 | goto err_free_input; | 332 | goto err_free_input; |
375 | } | 333 | } |
@@ -378,10 +336,9 @@ static int acpi_button_add(struct acpi_device *device) | |||
378 | if (error) | 336 | if (error) |
379 | goto err_free_input; | 337 | goto err_free_input; |
380 | 338 | ||
381 | snprintf(button->phys, sizeof(button->phys), | 339 | snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid); |
382 | "%s/button/input0", acpi_device_hid(device)); | ||
383 | 340 | ||
384 | input->name = acpi_device_name(device); | 341 | input->name = name; |
385 | input->phys = button->phys; | 342 | input->phys = button->phys; |
386 | input->id.bustype = BUS_HOST; | 343 | input->id.bustype = BUS_HOST; |
387 | input->id.product = button->type; | 344 | input->id.product = button->type; |
@@ -389,13 +346,11 @@ static int acpi_button_add(struct acpi_device *device) | |||
389 | 346 | ||
390 | switch (button->type) { | 347 | switch (button->type) { |
391 | case ACPI_BUTTON_TYPE_POWER: | 348 | case ACPI_BUTTON_TYPE_POWER: |
392 | case ACPI_BUTTON_TYPE_POWERF: | ||
393 | input->evbit[0] = BIT_MASK(EV_KEY); | 349 | input->evbit[0] = BIT_MASK(EV_KEY); |
394 | set_bit(KEY_POWER, input->keybit); | 350 | set_bit(KEY_POWER, input->keybit); |
395 | break; | 351 | break; |
396 | 352 | ||
397 | case ACPI_BUTTON_TYPE_SLEEP: | 353 | case ACPI_BUTTON_TYPE_SLEEP: |
398 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
399 | input->evbit[0] = BIT_MASK(EV_KEY); | 354 | input->evbit[0] = BIT_MASK(EV_KEY); |
400 | set_bit(KEY_SLEEP, input->keybit); | 355 | set_bit(KEY_SLEEP, input->keybit); |
401 | break; | 356 | break; |
@@ -410,7 +365,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
410 | if (error) | 365 | if (error) |
411 | goto err_remove_fs; | 366 | goto err_remove_fs; |
412 | if (button->type == ACPI_BUTTON_TYPE_LID) | 367 | if (button->type == ACPI_BUTTON_TYPE_LID) |
413 | acpi_lid_send_state(button); | 368 | acpi_lid_send_state(device); |
414 | 369 | ||
415 | if (device->wakeup.flags.valid) { | 370 | if (device->wakeup.flags.valid) { |
416 | /* Button's GPE is run-wake GPE */ | 371 | /* Button's GPE is run-wake GPE */ |
@@ -422,9 +377,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
422 | device->wakeup.state.enabled = 1; | 377 | device->wakeup.state.enabled = 1; |
423 | } | 378 | } |
424 | 379 | ||
425 | printk(KERN_INFO PREFIX "%s [%s]\n", | 380 | printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); |
426 | acpi_device_name(device), acpi_device_bid(device)); | ||
427 | |||
428 | return 0; | 381 | return 0; |
429 | 382 | ||
430 | err_remove_fs: | 383 | err_remove_fs: |
@@ -438,17 +391,11 @@ static int acpi_button_add(struct acpi_device *device) | |||
438 | 391 | ||
439 | static int acpi_button_remove(struct acpi_device *device, int type) | 392 | static int acpi_button_remove(struct acpi_device *device, int type) |
440 | { | 393 | { |
441 | struct acpi_button *button; | 394 | struct acpi_button *button = acpi_driver_data(device); |
442 | |||
443 | if (!device || !acpi_driver_data(device)) | ||
444 | return -EINVAL; | ||
445 | |||
446 | button = acpi_driver_data(device); | ||
447 | 395 | ||
448 | acpi_button_remove_fs(device); | 396 | acpi_button_remove_fs(device); |
449 | input_unregister_device(button->input); | 397 | input_unregister_device(button->input); |
450 | kfree(button); | 398 | kfree(button); |
451 | |||
452 | return 0; | 399 | return 0; |
453 | } | 400 | } |
454 | 401 | ||
@@ -459,6 +406,7 @@ static int __init acpi_button_init(void) | |||
459 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | 406 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); |
460 | if (!acpi_button_dir) | 407 | if (!acpi_button_dir) |
461 | return -ENODEV; | 408 | return -ENODEV; |
409 | |||
462 | result = acpi_bus_register_driver(&acpi_button_driver); | 410 | result = acpi_bus_register_driver(&acpi_button_driver); |
463 | if (result < 0) { | 411 | if (result < 0) { |
464 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | 412 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); |