diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-22 01:21:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-22 12:56:37 -0400 |
commit | f2d86100d95274bd85a36b7b7c0efa9af0d82b2b (patch) | |
tree | 16f4c8f4b917af2616137815e7748f1b4561d72c /drivers/staging | |
parent | bc36e6559c32374b7f9cf18e9461cd51998c41d3 (diff) |
Staging: pcc-acpi: update to latest version
Import the changes from the upstream driver into this version to keep
things up to date.
Cc: Yokota Hiroshi <yokota@netlab.cs.tsukuba.ac.jp>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/pcc-acpi/pcc-acpi.c | 540 |
1 files changed, 309 insertions, 231 deletions
diff --git a/drivers/staging/pcc-acpi/pcc-acpi.c b/drivers/staging/pcc-acpi/pcc-acpi.c index ffda32a10303..e44181ead26d 100644 --- a/drivers/staging/pcc-acpi/pcc-acpi.c +++ b/drivers/staging/pcc-acpi/pcc-acpi.c | |||
@@ -94,20 +94,21 @@ | |||
94 | * | 94 | * |
95 | */ | 95 | */ |
96 | 96 | ||
97 | #define ACPI_PCC_VERSION "0.9" | 97 | #define ACPI_PCC_VERSION "0.9+hy" |
98 | 98 | ||
99 | #include <linux/version.h> | 99 | #include <acpi/acpi_bus.h> |
100 | #include <acpi/acpi_drivers.h> | ||
101 | #include <asm/uaccess.h> | ||
102 | #include <linux/ctype.h> | ||
103 | #include <linux/init.h> | ||
104 | #include <linux/input.h> | ||
100 | #include <linux/kernel.h> | 105 | #include <linux/kernel.h> |
101 | #include <linux/module.h> | 106 | #include <linux/module.h> |
102 | #include <linux/init.h> | ||
103 | #include <linux/types.h> | ||
104 | #include <linux/proc_fs.h> | 107 | #include <linux/proc_fs.h> |
105 | #include <linux/ctype.h> | ||
106 | #include <linux/seq_file.h> | 108 | #include <linux/seq_file.h> |
107 | #include <asm/uaccess.h> | 109 | #include <linux/slab.h> |
108 | #include <acpi/acpi_bus.h> | 110 | #include <linux/types.h> |
109 | #include <acpi/acpi_drivers.h> | 111 | #include <linux/version.h> |
110 | #include <linux/input.h> | ||
111 | 112 | ||
112 | 113 | ||
113 | /************************************************************************* | 114 | /************************************************************************* |
@@ -152,10 +153,10 @@ static int _open_func_name_(struct inode *inode, struct file *file) \ | |||
152 | #endif | 153 | #endif |
153 | 154 | ||
154 | #define _COMPONENT ACPI_HOTKEY_COMPONENT | 155 | #define _COMPONENT ACPI_HOTKEY_COMPONENT |
155 | ACPI_MODULE_NAME("pcc_acpi") | 156 | ACPI_MODULE_NAME("pcc_acpi"); |
156 | 157 | ||
157 | MODULE_AUTHOR("Hiroshi Miura"); | 158 | MODULE_AUTHOR("Hiroshi Miura, Hiroshi Yokota"); |
158 | MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Lets Note laptops"); | 159 | MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops"); |
159 | MODULE_LICENSE("GPL"); | 160 | MODULE_LICENSE("GPL"); |
160 | 161 | ||
161 | #define LOGPREFIX "pcc_acpi: " | 162 | #define LOGPREFIX "pcc_acpi: " |
@@ -182,7 +183,7 @@ MODULE_LICENSE("GPL"); | |||
182 | * definitions for /proc/ interface | 183 | * definitions for /proc/ interface |
183 | * | 184 | * |
184 | *******************************************************************/ | 185 | *******************************************************************/ |
185 | #define ACPI_PCC_DRIVER_NAME "PCC Extra Driver" | 186 | #define ACPI_PCC_DRIVER_NAME "pcc_acpi" |
186 | #define ACPI_PCC_DEVICE_NAME "PCCExtra" | 187 | #define ACPI_PCC_DEVICE_NAME "PCCExtra" |
187 | #define ACPI_PCC_CLASS "pcc" | 188 | #define ACPI_PCC_CLASS "pcc" |
188 | #define PROC_PCC ACPI_PCC_CLASS | 189 | #define PROC_PCC ACPI_PCC_CLASS |
@@ -196,6 +197,12 @@ MODULE_LICENSE("GPL"); | |||
196 | 197 | ||
197 | #define PROC_STR_MAX_LEN 8 | 198 | #define PROC_STR_MAX_LEN 8 |
198 | 199 | ||
200 | #define BUS_PCC_HOTKEY BUS_I8042 /*0x1a*/ /* FIXME: BUS_I8042? */ | ||
201 | |||
202 | /* Fn+F4/F5 confricts with Shift+F1/F2 */ | ||
203 | /* This hack avoids key number confrict */ | ||
204 | #define PCC_KEYINPUT_MODE (0) | ||
205 | |||
199 | /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent | 206 | /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent |
200 | ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 | 207 | ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 |
201 | */ | 208 | */ |
@@ -209,27 +216,32 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0, | |||
209 | SINF_STICKY_KEY = 0x80, | 216 | SINF_STICKY_KEY = 0x80, |
210 | }; | 217 | }; |
211 | 218 | ||
212 | static int acpi_pcc_hotkey_add(struct acpi_device *device); | 219 | static struct acpi_device_id pcc_device_ids[] = { |
213 | static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); | ||
214 | static int acpi_pcc_hotkey_resume(struct acpi_device *device); | ||
215 | |||
216 | static const struct acpi_device_id pcc_device_ids[] = { | ||
217 | {"MAT0012", 0}, | 220 | {"MAT0012", 0}, |
218 | {"MAT0013", 0}, | 221 | {"MAT0013", 0}, |
219 | {"MAT0018", 0}, | 222 | {"MAT0018", 0}, |
220 | {"MAT0019", 0}, | 223 | {"MAT0019", 0}, |
221 | {"", 0}, | 224 | {"", 0}, |
222 | }; | 225 | }; |
223 | MODULE_DEVICE_TABLE(acpi, pcc_device_ids); | 226 | MODULE_DEVICE_TABLE(acpi, pcc_device_ids); |
224 | 227 | ||
228 | |||
229 | static int __devinit acpi_pcc_hotkey_add(struct acpi_device *device); | ||
230 | static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, int type); | ||
231 | static int acpi_pcc_hotkey_resume(struct acpi_device *device); | ||
232 | |||
233 | |||
225 | static struct acpi_driver acpi_pcc_driver = { | 234 | static struct acpi_driver acpi_pcc_driver = { |
226 | .name = ACPI_PCC_DRIVER_NAME, | 235 | .name = ACPI_PCC_DRIVER_NAME, |
227 | .class = ACPI_PCC_CLASS, | 236 | .class = ACPI_PCC_CLASS, |
228 | .ids = pcc_device_ids, | 237 | .ids = pcc_device_ids, |
229 | .ops = { | 238 | .ops = { |
230 | .add = acpi_pcc_hotkey_add, | 239 | .add = acpi_pcc_hotkey_add, |
231 | .remove = acpi_pcc_hotkey_remove, | 240 | .remove = __devexit_p(acpi_pcc_hotkey_remove), |
241 | #ifdef CONFIG_PM | ||
242 | /*.suspend = acpi_pcc_hotkey_suspend,*/ | ||
232 | .resume = acpi_pcc_hotkey_resume, | 243 | .resume = acpi_pcc_hotkey_resume, |
244 | #endif | ||
233 | }, | 245 | }, |
234 | }; | 246 | }; |
235 | 247 | ||
@@ -248,9 +260,12 @@ struct pcc_keyinput { | |||
248 | int key_mode; | 260 | int key_mode; |
249 | }; | 261 | }; |
250 | 262 | ||
251 | /* -------------------------------------------------------------------------- | 263 | /* ************************************************************************* |
264 | Hotkey driver core | ||
265 | ************************************************************************* */ | ||
266 | /* ------------------------------------------------------------------------- | ||
252 | method access functions | 267 | method access functions |
253 | -------------------------------------------------------------------------- */ | 268 | ------------------------------------------------------------------------- */ |
254 | static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) | 269 | static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) |
255 | { | 270 | { |
256 | union acpi_object in_objs[] = { | 271 | union acpi_object in_objs[] = { |
@@ -263,13 +278,13 @@ static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) | |||
263 | .count = ARRAY_SIZE(in_objs), | 278 | .count = ARRAY_SIZE(in_objs), |
264 | .pointer = in_objs, | 279 | .pointer = in_objs, |
265 | }; | 280 | }; |
266 | acpi_status status = AE_OK; | 281 | acpi_status status; |
267 | 282 | ||
268 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); | 283 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); |
269 | 284 | ||
270 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SSET, ¶ms, NULL); | 285 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SSET, ¶ms, NULL); |
271 | 286 | ||
272 | return_VALUE(status == AE_OK); | 287 | return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); |
273 | } | 288 | } |
274 | 289 | ||
275 | static inline int acpi_pcc_get_sqty(struct acpi_device *device) | 290 | static inline int acpi_pcc_get_sqty(struct acpi_device *device) |
@@ -301,19 +316,20 @@ static int acpi_pcc_retrieve_biosdata(struct acpi_hotkey *hotkey, u32* sinf) | |||
301 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SINF, 0 , &buffer); | 316 | status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SINF, 0 , &buffer); |
302 | if (ACPI_FAILURE(status)) { | 317 | if (ACPI_FAILURE(status)) { |
303 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SINF\n")); | 318 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SINF\n")); |
304 | return_VALUE(0); | 319 | status = AE_ERROR; |
320 | return_VALUE(status); | ||
305 | } | 321 | } |
306 | 322 | ||
307 | hkey = buffer.pointer; | 323 | hkey = buffer.pointer; |
308 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { | 324 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { |
309 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); | 325 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); |
310 | goto end; | 326 | goto free_buffer; |
311 | } | 327 | } |
312 | 328 | ||
313 | if (hotkey->num_sifr < hkey->package.count) { | 329 | if (hotkey->num_sifr < hkey->package.count) { |
314 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "SQTY reports bad SINF length\n")); | 330 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "SQTY reports bad SINF length\n")); |
315 | status = AE_ERROR; | 331 | status = AE_ERROR; |
316 | goto end; | 332 | goto free_buffer; |
317 | } | 333 | } |
318 | 334 | ||
319 | for (i = 0; i < hkey->package.count; i++) { | 335 | for (i = 0; i < hkey->package.count; i++) { |
@@ -322,59 +338,54 @@ static int acpi_pcc_retrieve_biosdata(struct acpi_hotkey *hotkey, u32* sinf) | |||
322 | sinf[i] = element->integer.value; | 338 | sinf[i] = element->integer.value; |
323 | } else { | 339 | } else { |
324 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n")); | 340 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n")); |
341 | status = AE_ERROR; | ||
342 | break; | ||
325 | } | 343 | } |
326 | } | 344 | } |
327 | sinf[hkey->package.count] = -1; | 345 | sinf[hkey->package.count] = -1; |
328 | 346 | ||
329 | end: | 347 | free_buffer: |
330 | kfree(buffer.pointer); | 348 | kfree(buffer.pointer); |
331 | return_VALUE(status == AE_OK); | 349 | return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); |
332 | } | 350 | } |
333 | 351 | ||
334 | static int acpi_pcc_read_sinf_field(struct seq_file *seq, int field) | 352 | static int acpi_pcc_read_sinf_field(struct seq_file *seq, int field) |
335 | { | 353 | { |
336 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private; | 354 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private; |
337 | u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL); | 355 | u32 sinf[hotkey->num_sifr + 1]; |
338 | 356 | ||
339 | ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field"); | 357 | ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field"); |
340 | 358 | ||
341 | if (!sinf) { | 359 | if (ACPI_SUCCESS(acpi_pcc_retrieve_biosdata(hotkey, sinf))) { |
342 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", | ||
343 | sizeof(u32) * hotkey->num_sifr)); | ||
344 | return_VALUE(0); | ||
345 | } | ||
346 | |||
347 | if (acpi_pcc_retrieve_biosdata(hotkey, sinf)) { | ||
348 | seq_printf(seq, "%u\n", sinf[field]); | 360 | seq_printf(seq, "%u\n", sinf[field]); |
349 | } else { | 361 | } else { |
350 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); | 362 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); |
351 | } | 363 | } |
352 | 364 | ||
353 | kfree(sinf); | 365 | return_VALUE(AE_OK); |
354 | return_VALUE(0); | ||
355 | } | 366 | } |
356 | 367 | ||
357 | /* -------------------------------------------------------------------------- | 368 | /* ------------------------------------------------------------------------- |
358 | user interface functions | 369 | user interface functions |
359 | -------------------------------------------------------------------------- */ | 370 | ------------------------------------------------------------------------- */ |
360 | /* read methods */ | 371 | /* read methods */ |
361 | /* Sinf read methods */ | 372 | /* Sinf read methods */ |
362 | #define PCC_SINF_READ_F(_name_, FUNC) \ | 373 | #define PCC_SINF_READ_F(_name_, FUNC) \ |
363 | static int _name_ (struct seq_file *seq, void *offset) \ | 374 | static int _name_ (struct seq_file *seq, void *offset) \ |
364 | { \ | 375 | { \ |
365 | return acpi_pcc_read_sinf_field(seq, (FUNC)); \ | 376 | return_VALUE(ACPI_SUCCESS(acpi_pcc_read_sinf_field(seq, (FUNC))) ? 0 : -EINVAL); \ |
366 | } | 377 | } |
367 | 378 | ||
368 | PCC_SINF_READ_F(acpi_pcc_numbatteries_show, SINF_NUM_BATTERIES); | 379 | PCC_SINF_READ_F(acpi_pcc_numbatteries_show, SINF_NUM_BATTERIES); |
369 | PCC_SINF_READ_F(acpi_pcc_lcdtype_show, SINF_LCD_TYPE); | 380 | PCC_SINF_READ_F(acpi_pcc_lcdtype_show, SINF_LCD_TYPE); |
370 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_max_show, SINF_AC_MAX_BRIGHT); | 381 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_max_show, SINF_AC_MAX_BRIGHT); |
371 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_min_show, SINF_AC_MIN_BRIGHT); | 382 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_min_show, SINF_AC_MIN_BRIGHT); |
372 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_show, SINF_AC_CUR_BRIGHT); | 383 | PCC_SINF_READ_F(acpi_pcc_ac_brightness_show, SINF_AC_CUR_BRIGHT); |
373 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_max_show, SINF_DC_MAX_BRIGHT); | 384 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_max_show, SINF_DC_MAX_BRIGHT); |
374 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_min_show, SINF_DC_MIN_BRIGHT); | 385 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_min_show, SINF_DC_MIN_BRIGHT); |
375 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_show, SINF_DC_CUR_BRIGHT); | 386 | PCC_SINF_READ_F(acpi_pcc_dc_brightness_show, SINF_DC_CUR_BRIGHT); |
376 | PCC_SINF_READ_F(acpi_pcc_brightness_show, SINF_AC_CUR_BRIGHT); | 387 | PCC_SINF_READ_F(acpi_pcc_brightness_show, SINF_AC_CUR_BRIGHT); |
377 | PCC_SINF_READ_F(acpi_pcc_mute_show, SINF_MUTE); | 388 | PCC_SINF_READ_F(acpi_pcc_mute_show, SINF_MUTE); |
378 | 389 | ||
379 | static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) | 390 | static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) |
380 | { | 391 | { |
@@ -383,7 +394,7 @@ static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) | |||
383 | ACPI_FUNCTION_TRACE("acpi_pcc_sticky_key_show"); | 394 | ACPI_FUNCTION_TRACE("acpi_pcc_sticky_key_show"); |
384 | 395 | ||
385 | if (!hotkey || !hotkey->device) { | 396 | if (!hotkey || !hotkey->device) { |
386 | return_VALUE(0); | 397 | return_VALUE(-EINVAL); |
387 | } | 398 | } |
388 | 399 | ||
389 | seq_printf(seq, "%d\n", hotkey->sticky_mode); | 400 | seq_printf(seq, "%d\n", hotkey->sticky_mode); |
@@ -410,8 +421,9 @@ static int acpi_pcc_version_show(struct seq_file *seq, void *offset) | |||
410 | 421 | ||
411 | ACPI_FUNCTION_TRACE("acpi_pcc_version_show"); | 422 | ACPI_FUNCTION_TRACE("acpi_pcc_version_show"); |
412 | 423 | ||
413 | if (!hotkey || !hotkey->device) | 424 | if (!hotkey || !hotkey->device) { |
414 | return 0; | 425 | return_VALUE(-EINVAL); |
426 | } | ||
415 | 427 | ||
416 | seq_printf(seq, "%s version %s\n", ACPI_PCC_DRIVER_NAME, ACPI_PCC_VERSION); | 428 | seq_printf(seq, "%s version %s\n", ACPI_PCC_DRIVER_NAME, ACPI_PCC_VERSION); |
417 | seq_printf(seq, "%li functions\n", hotkey->num_sifr); | 429 | seq_printf(seq, "%li functions\n", hotkey->num_sifr); |
@@ -421,27 +433,28 @@ static int acpi_pcc_version_show(struct seq_file *seq, void *offset) | |||
421 | 433 | ||
422 | /* write methods */ | 434 | /* write methods */ |
423 | static ssize_t acpi_pcc_write_single_flag (struct file *file, | 435 | static ssize_t acpi_pcc_write_single_flag (struct file *file, |
424 | const char __user *buffer, | 436 | const char __user *buffer, |
425 | size_t count, | 437 | size_t count, |
426 | int sinf_func) | 438 | int sinf_func) |
427 | { | 439 | { |
428 | struct seq_file *seq = file->private_data; | 440 | struct seq_file *seq = file->private_data; |
429 | struct acpi_hotkey *hotkey = seq->private; | 441 | struct acpi_hotkey *hotkey = seq->private; |
430 | char write_string[PROC_STR_MAX_LEN]; | 442 | char write_string[PROC_STR_MAX_LEN]; |
431 | u32 val; | 443 | u32 val; |
432 | 444 | ||
433 | ACPI_FUNCTION_TRACE("acpi_pcc_write_single_flag"); | 445 | ACPI_FUNCTION_TRACE("acpi_pcc_write_single_flag"); |
434 | 446 | ||
435 | if (!hotkey || (count > sizeof(write_string) - 1)) { | 447 | if (!hotkey || (count > sizeof(write_string) - 1)) { |
436 | return_VALUE(-EINVAL); | 448 | return_VALUE(-EINVAL); |
437 | } | 449 | } |
438 | 450 | ||
439 | if (copy_from_user(write_string, buffer, count)) { | 451 | if (copy_from_user(write_string, buffer, count)) { |
440 | return_VALUE(-EFAULT); | 452 | return_VALUE(-EFAULT); |
441 | } | 453 | } |
442 | write_string[count] = '\0'; | 454 | write_string[count] = '\0'; |
443 | 455 | ||
444 | if (sscanf(write_string, "%i", &val) == 1 && (val == 0 || val == 1)) { | 456 | if ((sscanf(write_string, "%3i", &val) == 1) && |
457 | (val == 0 || val == 1)) { | ||
445 | acpi_pcc_write_sset(hotkey, sinf_func, val); | 458 | acpi_pcc_write_sset(hotkey, sinf_func, val); |
446 | } | 459 | } |
447 | 460 | ||
@@ -457,53 +470,51 @@ static unsigned long acpi_pcc_write_brightness(struct file *file, const char __u | |||
457 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; | 470 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; |
458 | char write_string[PROC_STR_MAX_LEN]; | 471 | char write_string[PROC_STR_MAX_LEN]; |
459 | u32 bright; | 472 | u32 bright; |
460 | u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL); | 473 | u32 sinf[hotkey->num_sifr + 1]; |
461 | 474 | ||
462 | ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness"); | 475 | ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness"); |
463 | 476 | ||
464 | if (!hotkey || (count > sizeof(write_string) - 1)) | 477 | if (!hotkey || (count > sizeof(write_string) - 1)) { |
465 | return_VALUE(-EINVAL); | 478 | return_VALUE(-EINVAL); |
466 | |||
467 | if (!sinf) { | ||
468 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", | ||
469 | sizeof(u32) * hotkey->num_sifr)); | ||
470 | return_VALUE(-EFAULT); | ||
471 | } | 479 | } |
472 | 480 | ||
473 | if (copy_from_user(write_string, buffer, count)) | 481 | if (copy_from_user(write_string, buffer, count)) { |
474 | return_VALUE(-EFAULT); | 482 | return_VALUE(-EFAULT); |
483 | } | ||
475 | 484 | ||
476 | write_string[count] = '\0'; | 485 | write_string[count] = '\0'; |
477 | 486 | ||
478 | if (!acpi_pcc_retrieve_biosdata(hotkey, sinf)) { | 487 | if (ACPI_FAILURE(acpi_pcc_retrieve_biosdata(hotkey, sinf))) { |
479 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); | 488 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); |
480 | goto end; | 489 | goto end; |
481 | } | 490 | } |
482 | 491 | ||
483 | if (sscanf(write_string, "%i", &bright) == 1 && | 492 | if ((sscanf(write_string, "%4i", &bright) == 1) && |
484 | bright >= sinf[min_index] && bright <= sinf[max_index]) { | 493 | (bright >= sinf[min_index] ) && |
485 | acpi_pcc_write_sset(hotkey, cur_index, bright); | 494 | (bright <= sinf[max_index] )) { |
495 | acpi_pcc_write_sset(hotkey, cur_index, bright); | ||
486 | } | 496 | } |
487 | 497 | ||
488 | end: | 498 | end: |
489 | kfree(sinf); | ||
490 | return_VALUE(count); | 499 | return_VALUE(count); |
491 | } | 500 | } |
492 | 501 | ||
493 | static ssize_t acpi_pcc_write_ac_brightness(struct file *file, const char __user *buffer, | 502 | static ssize_t acpi_pcc_write_ac_brightness(struct file *file, const char __user *buffer, |
494 | size_t count, loff_t *ppos) | 503 | size_t count, loff_t *ppos) |
495 | { | 504 | { |
496 | return acpi_pcc_write_brightness(file, buffer, count, SINF_AC_MIN_BRIGHT, | 505 | return_VALUE(acpi_pcc_write_brightness(file, buffer, count, |
497 | SINF_AC_MAX_BRIGHT, | 506 | SINF_AC_MIN_BRIGHT, |
498 | SINF_AC_CUR_BRIGHT); | 507 | SINF_AC_MAX_BRIGHT, |
508 | SINF_AC_CUR_BRIGHT)); | ||
499 | } | 509 | } |
500 | 510 | ||
501 | static ssize_t acpi_pcc_write_dc_brightness(struct file *file, const char __user *buffer, | 511 | static ssize_t acpi_pcc_write_dc_brightness(struct file *file, const char __user *buffer, |
502 | size_t count, loff_t *ppos) | 512 | size_t count, loff_t *ppos) |
503 | { | 513 | { |
504 | return acpi_pcc_write_brightness(file, buffer, count, SINF_DC_MIN_BRIGHT, | 514 | return_VALUE(acpi_pcc_write_brightness(file, buffer, count, |
505 | SINF_DC_MAX_BRIGHT, | 515 | SINF_DC_MIN_BRIGHT, |
506 | SINF_DC_CUR_BRIGHT); | 516 | SINF_DC_MAX_BRIGHT, |
517 | SINF_DC_CUR_BRIGHT)); | ||
507 | } | 518 | } |
508 | 519 | ||
509 | static ssize_t acpi_pcc_write_no_brightness(struct file *file, const char __user *buffer, | 520 | static ssize_t acpi_pcc_write_no_brightness(struct file *file, const char __user *buffer, |
@@ -518,14 +529,36 @@ static ssize_t acpi_pcc_write_mute (struct file *file, | |||
518 | const char __user *buffer, | 529 | const char __user *buffer, |
519 | size_t count, loff_t *ppos) | 530 | size_t count, loff_t *ppos) |
520 | { | 531 | { |
521 | return acpi_pcc_write_single_flag(file, buffer, count, SINF_MUTE); | 532 | return_VALUE(acpi_pcc_write_single_flag(file, buffer, count, SINF_MUTE)); |
522 | } | 533 | } |
523 | 534 | ||
524 | static ssize_t acpi_pcc_write_sticky_key (struct file *file, | 535 | static ssize_t acpi_pcc_write_sticky_key (struct file *file, |
525 | const char __user *buffer, | 536 | const char __user *buffer, |
526 | size_t count, loff_t *ppos) | 537 | size_t count, loff_t *ppos) |
527 | { | 538 | { |
528 | return acpi_pcc_write_single_flag(file, buffer, count, SINF_STICKY_KEY); | 539 | struct seq_file *seq = (struct seq_file *)file->private_data; |
540 | struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; | ||
541 | char write_string[PROC_STR_MAX_LEN]; | ||
542 | int mode; | ||
543 | |||
544 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sticky_key"); | ||
545 | |||
546 | if (!hotkey || (count > sizeof(write_string) - 1)) { | ||
547 | return_VALUE(-EINVAL); | ||
548 | } | ||
549 | |||
550 | if (copy_from_user(write_string, buffer, count)) { | ||
551 | return_VALUE(-EFAULT); | ||
552 | } | ||
553 | write_string[count] = '\0'; | ||
554 | |||
555 | if ((sscanf(write_string, "%3i", &mode) == 1) && | ||
556 | (mode == 0 || mode == 1)) { | ||
557 | acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, mode); | ||
558 | hotkey->sticky_mode = mode; | ||
559 | } | ||
560 | |||
561 | return_VALUE(count); | ||
529 | } | 562 | } |
530 | 563 | ||
531 | static ssize_t acpi_pcc_write_keyinput(struct file *file, const char __user *buffer, | 564 | static ssize_t acpi_pcc_write_keyinput(struct file *file, const char __user *buffer, |
@@ -539,25 +572,28 @@ static ssize_t acpi_pcc_write_keyinput(struct file *file, const char __user *buf | |||
539 | 572 | ||
540 | ACPI_FUNCTION_TRACE("acpi_pcc_write_keyinput"); | 573 | ACPI_FUNCTION_TRACE("acpi_pcc_write_keyinput"); |
541 | 574 | ||
542 | if (!hotkey || (count > sizeof(write_string) - 1)) | 575 | if (!hotkey || (count > (sizeof(write_string) - 1))) { |
543 | return_VALUE(-EINVAL); | 576 | return_VALUE(-EINVAL); |
577 | } | ||
544 | 578 | ||
545 | if (copy_from_user(write_string, buffer, count)) | 579 | if (copy_from_user(write_string, buffer, count)) { |
546 | return_VALUE(-EFAULT); | 580 | return_VALUE(-EFAULT); |
581 | } | ||
547 | 582 | ||
548 | write_string[count] = '\0'; | 583 | write_string[count] = '\0'; |
549 | 584 | ||
550 | if (sscanf(write_string, "%i", &key_mode) == 1 && (key_mode == 0 || key_mode == 1)) { | 585 | if ((sscanf(write_string, "%4i", &key_mode) == 1) && |
551 | keyinput = (struct pcc_keyinput *)input_get_drvdata(hotkey->input_dev); | 586 | (key_mode == 0 || key_mode == 1)) { |
587 | keyinput = input_get_drvdata(hotkey->input_dev); | ||
552 | keyinput->key_mode = key_mode; | 588 | keyinput->key_mode = key_mode; |
553 | } | 589 | } |
554 | 590 | ||
555 | return_VALUE(count); | 591 | return_VALUE(count); |
556 | } | 592 | } |
557 | 593 | ||
558 | /* -------------------------------------------------------------------------- | 594 | /* ------------------------------------------------------------------------- |
559 | hotkey driver | 595 | hotkey driver |
560 | -------------------------------------------------------------------------- */ | 596 | ------------------------------------------------------------------------- */ |
561 | static void acpi_pcc_generete_keyinput(struct acpi_hotkey *hotkey) | 597 | static void acpi_pcc_generete_keyinput(struct acpi_hotkey *hotkey) |
562 | { | 598 | { |
563 | struct input_dev *hotk_input_dev = hotkey->input_dev; | 599 | struct input_dev *hotk_input_dev = hotkey->input_dev; |
@@ -640,38 +676,38 @@ void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) | |||
640 | return_VOID; | 676 | return_VOID; |
641 | } | 677 | } |
642 | 678 | ||
643 | /* -------------------------------------------------------------------------- | 679 | /* ************************************************************************* |
644 | FS Interface (/proc) | 680 | FS Interface (/proc) |
645 | -------------------------------------------------------------------------- */ | 681 | ************************************************************************* */ |
646 | /* oepn proc file fs*/ | 682 | /* oepn proc file fs*/ |
647 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_open_fs, acpi_pcc_dc_brightness_show); | 683 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_open_fs, acpi_pcc_dc_brightness_show); |
648 | SEQ_OPEN_FS(acpi_pcc_numbatteries_open_fs, acpi_pcc_numbatteries_show); | 684 | SEQ_OPEN_FS(acpi_pcc_numbatteries_open_fs, acpi_pcc_numbatteries_show); |
649 | SEQ_OPEN_FS(acpi_pcc_lcdtype_open_fs, acpi_pcc_lcdtype_show); | 685 | SEQ_OPEN_FS(acpi_pcc_lcdtype_open_fs, acpi_pcc_lcdtype_show); |
650 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_max_open_fs, acpi_pcc_ac_brightness_max_show); | 686 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_max_open_fs, acpi_pcc_ac_brightness_max_show); |
651 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_min_open_fs, acpi_pcc_ac_brightness_min_show); | 687 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_min_open_fs, acpi_pcc_ac_brightness_min_show); |
652 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_open_fs, acpi_pcc_ac_brightness_show); | 688 | SEQ_OPEN_FS(acpi_pcc_ac_brightness_open_fs, acpi_pcc_ac_brightness_show); |
653 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_max_open_fs, acpi_pcc_dc_brightness_max_show); | 689 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_max_open_fs, acpi_pcc_dc_brightness_max_show); |
654 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_min_open_fs, acpi_pcc_dc_brightness_min_show); | 690 | SEQ_OPEN_FS(acpi_pcc_dc_brightness_min_open_fs, acpi_pcc_dc_brightness_min_show); |
655 | SEQ_OPEN_FS(acpi_pcc_brightness_open_fs, acpi_pcc_brightness_show); | 691 | SEQ_OPEN_FS(acpi_pcc_brightness_open_fs, acpi_pcc_brightness_show); |
656 | SEQ_OPEN_FS(acpi_pcc_mute_open_fs, acpi_pcc_mute_show); | 692 | SEQ_OPEN_FS(acpi_pcc_mute_open_fs, acpi_pcc_mute_show); |
657 | SEQ_OPEN_FS(acpi_pcc_version_open_fs, acpi_pcc_version_show); | 693 | SEQ_OPEN_FS(acpi_pcc_version_open_fs, acpi_pcc_version_show); |
658 | SEQ_OPEN_FS(acpi_pcc_keyinput_open_fs, acpi_pcc_keyinput_show); | 694 | SEQ_OPEN_FS(acpi_pcc_keyinput_open_fs, acpi_pcc_keyinput_show); |
659 | SEQ_OPEN_FS(acpi_pcc_sticky_key_open_fs, acpi_pcc_sticky_key_show); | 695 | SEQ_OPEN_FS(acpi_pcc_sticky_key_open_fs, acpi_pcc_sticky_key_show); |
660 | 696 | ||
661 | typedef struct file_operations fops_t; | 697 | typedef struct file_operations fops_t; |
662 | static fops_t acpi_pcc_numbatteries_fops = SEQ_FILEOPS_R (acpi_pcc_numbatteries_open_fs); | 698 | static fops_t acpi_pcc_numbatteries_fops = SEQ_FILEOPS_R (acpi_pcc_numbatteries_open_fs); |
663 | static fops_t acpi_pcc_lcdtype_fops = SEQ_FILEOPS_R (acpi_pcc_lcdtype_open_fs); | 699 | static fops_t acpi_pcc_lcdtype_fops = SEQ_FILEOPS_R (acpi_pcc_lcdtype_open_fs); |
664 | static fops_t acpi_pcc_mute_fops = SEQ_FILEOPS_RW(acpi_pcc_mute_open_fs, acpi_pcc_write_mute); | 700 | static fops_t acpi_pcc_mute_fops = SEQ_FILEOPS_RW(acpi_pcc_mute_open_fs, acpi_pcc_write_mute); |
665 | static fops_t acpi_pcc_ac_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_ac_brightness_open_fs, acpi_pcc_write_ac_brightness); | 701 | static fops_t acpi_pcc_ac_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_ac_brightness_open_fs, acpi_pcc_write_ac_brightness); |
666 | static fops_t acpi_pcc_ac_brightness_max_fops = SEQ_FILEOPS_R(acpi_pcc_ac_brightness_max_open_fs); | 702 | static fops_t acpi_pcc_ac_brightness_max_fops = SEQ_FILEOPS_R (acpi_pcc_ac_brightness_max_open_fs); |
667 | static fops_t acpi_pcc_ac_brightness_min_fops = SEQ_FILEOPS_R(acpi_pcc_ac_brightness_min_open_fs); | 703 | static fops_t acpi_pcc_ac_brightness_min_fops = SEQ_FILEOPS_R (acpi_pcc_ac_brightness_min_open_fs); |
668 | static fops_t acpi_pcc_dc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_dc_brightness_open_fs, acpi_pcc_write_dc_brightness); | 704 | static fops_t acpi_pcc_dc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_dc_brightness_open_fs, acpi_pcc_write_dc_brightness); |
669 | static fops_t acpi_pcc_dc_brightness_max_fops = SEQ_FILEOPS_R(acpi_pcc_dc_brightness_max_open_fs); | 705 | static fops_t acpi_pcc_dc_brightness_max_fops = SEQ_FILEOPS_R (acpi_pcc_dc_brightness_max_open_fs); |
670 | static fops_t acpi_pcc_dc_brightness_min_fops = SEQ_FILEOPS_R(acpi_pcc_dc_brightness_min_open_fs); | 706 | static fops_t acpi_pcc_dc_brightness_min_fops = SEQ_FILEOPS_R (acpi_pcc_dc_brightness_min_open_fs); |
671 | static fops_t acpi_pcc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_brightness_open_fs, acpi_pcc_write_no_brightness); | 707 | static fops_t acpi_pcc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_brightness_open_fs, acpi_pcc_write_no_brightness); |
672 | static fops_t acpi_pcc_sticky_key_fops = SEQ_FILEOPS_RW(acpi_pcc_sticky_key_open_fs, acpi_pcc_write_sticky_key); | 708 | static fops_t acpi_pcc_sticky_key_fops = SEQ_FILEOPS_RW(acpi_pcc_sticky_key_open_fs, acpi_pcc_write_sticky_key); |
673 | static fops_t acpi_pcc_keyinput_fops = SEQ_FILEOPS_RW(acpi_pcc_keyinput_open_fs, acpi_pcc_write_keyinput); | 709 | static fops_t acpi_pcc_keyinput_fops = SEQ_FILEOPS_RW(acpi_pcc_keyinput_open_fs, acpi_pcc_write_keyinput); |
674 | static fops_t acpi_pcc_version_fops = SEQ_FILEOPS_R (acpi_pcc_version_open_fs); | 710 | static fops_t acpi_pcc_version_fops = SEQ_FILEOPS_R (acpi_pcc_version_open_fs); |
675 | 711 | ||
676 | typedef struct _ProcItem | 712 | typedef struct _ProcItem |
677 | { | 713 | { |
@@ -681,37 +717,35 @@ typedef struct _ProcItem | |||
681 | } ProcItem; | 717 | } ProcItem; |
682 | 718 | ||
683 | /* Note: These functions map *exactly* to the SINF/SSET functions */ | 719 | /* Note: These functions map *exactly* to the SINF/SSET functions */ |
684 | ProcItem pcc_proc_items_sifr[] = | 720 | ProcItem acpi_pcc_proc_items_sifr[] = { |
685 | { | 721 | { "num_batteries", &acpi_pcc_numbatteries_fops, S_IRUGO }, |
686 | { "num_batteries", &acpi_pcc_numbatteries_fops, S_IRUGO }, | 722 | { "lcd_type", &acpi_pcc_lcdtype_fops, S_IRUGO }, |
687 | { "lcd_type", &acpi_pcc_lcdtype_fops, S_IRUGO }, | ||
688 | { "ac_brightness_max" , &acpi_pcc_ac_brightness_max_fops,S_IRUGO }, | 723 | { "ac_brightness_max" , &acpi_pcc_ac_brightness_max_fops,S_IRUGO }, |
689 | { "ac_brightness_min" , &acpi_pcc_ac_brightness_min_fops,S_IRUGO }, | 724 | { "ac_brightness_min" , &acpi_pcc_ac_brightness_min_fops,S_IRUGO }, |
690 | { "ac_brightness" , &acpi_pcc_ac_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 725 | { "ac_brightness" , &acpi_pcc_ac_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
691 | { "dc_brightness_max" , &acpi_pcc_dc_brightness_max_fops,S_IRUGO }, | 726 | { "dc_brightness_max" , &acpi_pcc_dc_brightness_max_fops,S_IRUGO }, |
692 | { "dc_brightness_min" , &acpi_pcc_dc_brightness_min_fops,S_IRUGO }, | 727 | { "dc_brightness_min" , &acpi_pcc_dc_brightness_min_fops,S_IRUGO }, |
693 | { "dc_brightness" , &acpi_pcc_dc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 728 | { "dc_brightness" , &acpi_pcc_dc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
694 | { "brightness" , &acpi_pcc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 729 | { "brightness" , &acpi_pcc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
695 | { "mute", &acpi_pcc_mute_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 730 | { "mute", &acpi_pcc_mute_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
696 | { NULL, NULL, 0 }, | 731 | { NULL, NULL, 0 }, |
697 | }; | 732 | }; |
698 | 733 | ||
699 | ProcItem pcc_proc_items[] = | 734 | ProcItem acpi_pcc_proc_items[] = { |
700 | { | ||
701 | { "sticky_key", &acpi_pcc_sticky_key_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 735 | { "sticky_key", &acpi_pcc_sticky_key_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
702 | { "keyinput", &acpi_pcc_keyinput_fops, S_IFREG | S_IRUGO | S_IWUSR }, | 736 | { "keyinput", &acpi_pcc_keyinput_fops, S_IFREG | S_IRUGO | S_IWUSR }, |
703 | { "version", &acpi_pcc_version_fops, S_IRUGO }, | 737 | { "version", &acpi_pcc_version_fops, S_IRUGO }, |
704 | { NULL, NULL, 0 }, | 738 | { NULL, NULL, 0 }, |
705 | }; | 739 | }; |
706 | 740 | ||
707 | static int acpi_pcc_add_device(struct acpi_device *device, | 741 | static int __devinit acpi_pcc_add_device(struct acpi_device *device, |
708 | ProcItem *proc_items, | 742 | ProcItem *proc_items, |
709 | int num) | 743 | int num) |
710 | { | 744 | { |
745 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); | ||
711 | struct proc_dir_entry* proc; | 746 | struct proc_dir_entry* proc; |
712 | ProcItem* item; | 747 | ProcItem* item; |
713 | int i; | 748 | int i; |
714 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); | ||
715 | 749 | ||
716 | for (item = proc_items, i = 0; item->name && i < num; ++item, ++i) { | 750 | for (item = proc_items, i = 0; item->name && i < num; ++item, ++i) { |
717 | proc = create_proc_entry(item->name, item->flag, hotkey->proc_dir_entry); | 751 | proc = create_proc_entry(item->name, item->flag, hotkey->proc_dir_entry); |
@@ -724,16 +758,16 @@ static int acpi_pcc_add_device(struct acpi_device *device, | |||
724 | item--; | 758 | item--; |
725 | remove_proc_entry(item->name, hotkey->proc_dir_entry); | 759 | remove_proc_entry(item->name, hotkey->proc_dir_entry); |
726 | } | 760 | } |
727 | return -ENODEV; | 761 | return_VALUE(-ENODEV); |
728 | } | 762 | } |
729 | } | 763 | } |
730 | return 0; | 764 | return_VALUE(0); |
731 | } | 765 | } |
732 | 766 | ||
733 | static int acpi_pcc_proc_init(struct acpi_device *device) | 767 | static int __devinit acpi_pcc_proc_init(struct acpi_device *device) |
734 | { | 768 | { |
735 | struct proc_dir_entry* acpi_pcc_dir; | 769 | struct proc_dir_entry *acpi_pcc_dir; |
736 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); | 770 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); |
737 | acpi_status status; | 771 | acpi_status status; |
738 | 772 | ||
739 | ACPI_FUNCTION_TRACE("acpi_pcc_proc_init"); | 773 | ACPI_FUNCTION_TRACE("acpi_pcc_proc_init"); |
@@ -748,8 +782,8 @@ static int acpi_pcc_proc_init(struct acpi_device *device) | |||
748 | acpi_pcc_dir->owner = THIS_MODULE; | 782 | acpi_pcc_dir->owner = THIS_MODULE; |
749 | hotkey->proc_dir_entry = acpi_pcc_dir; | 783 | hotkey->proc_dir_entry = acpi_pcc_dir; |
750 | 784 | ||
751 | status = acpi_pcc_add_device(device, pcc_proc_items_sifr, hotkey->num_sifr); | 785 | status = acpi_pcc_add_device(device, acpi_pcc_proc_items_sifr, hotkey->num_sifr); |
752 | status |= acpi_pcc_add_device(device, pcc_proc_items, sizeof(pcc_proc_items)/sizeof(ProcItem)); | 786 | status |= acpi_pcc_add_device(device, acpi_pcc_proc_items, ARRAY_SIZE(acpi_pcc_proc_items)); |
753 | if (unlikely(status)) { | 787 | if (unlikely(status)) { |
754 | remove_proc_entry(PROC_PCC, acpi_root_dir); | 788 | remove_proc_entry(PROC_PCC, acpi_root_dir); |
755 | hotkey->proc_dir_entry = NULL; | 789 | hotkey->proc_dir_entry = NULL; |
@@ -759,9 +793,9 @@ static int acpi_pcc_proc_init(struct acpi_device *device) | |||
759 | return_VALUE(status); | 793 | return_VALUE(status); |
760 | } | 794 | } |
761 | 795 | ||
762 | static void acpi_pcc_remove_device(struct acpi_device *device, | 796 | static void __devexit acpi_pcc_remove_device(struct acpi_device *device, |
763 | ProcItem *proc_items, | 797 | ProcItem *proc_items, |
764 | int num) | 798 | int num) |
765 | { | 799 | { |
766 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); | 800 | struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); |
767 | ProcItem* item; | 801 | ProcItem* item; |
@@ -771,131 +805,165 @@ static void acpi_pcc_remove_device(struct acpi_device *device, | |||
771 | remove_proc_entry(item->name, hotkey->proc_dir_entry); | 805 | remove_proc_entry(item->name, hotkey->proc_dir_entry); |
772 | } | 806 | } |
773 | 807 | ||
774 | return; | 808 | return_VOID; |
809 | } | ||
810 | |||
811 | /* ************************************************************************* | ||
812 | Power Management | ||
813 | ************************************************************************* */ | ||
814 | #ifdef CONFIG_PM | ||
815 | static int acpi_pcc_hotkey_resume(struct acpi_device *device) | ||
816 | { | ||
817 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | ||
818 | acpi_status status = AE_OK; | ||
819 | |||
820 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); | ||
821 | |||
822 | if (device == NULL || hotkey == NULL) { return_VALUE(-EINVAL); } | ||
823 | |||
824 | if (hotkey->num_sifr != 0) { | ||
825 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Sticky mode restore: %d\n", hotkey->sticky_mode)); | ||
826 | |||
827 | status = acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, hotkey->sticky_mode); | ||
828 | } | ||
829 | if (status != AE_OK) { return_VALUE(-EINVAL); } | ||
830 | |||
831 | return_VALUE(0); | ||
775 | } | 832 | } |
833 | #endif | ||
776 | 834 | ||
777 | /* -------------------------------------------------------------------------- | 835 | /* ************************************************************************* |
778 | input init | 836 | Module init/remove |
779 | -------------------------------------------------------------------------- */ | 837 | ************************************************************************* */ |
780 | static int acpi_pcc_init_input(struct acpi_hotkey *hotkey) | 838 | /* ------------------------------------------------------------------------- |
839 | input | ||
840 | ------------------------------------------------------------------------- */ | ||
841 | static int __devinit acpi_pcc_init_input(struct acpi_hotkey *hotkey) | ||
781 | { | 842 | { |
782 | struct input_dev *hotk_input_dev; | 843 | struct input_dev *hotk_input_dev; |
783 | struct pcc_keyinput *pcc_keyinput; | 844 | struct pcc_keyinput *pcc_keyinput; |
845 | int error; | ||
784 | 846 | ||
785 | ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); | 847 | ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); |
786 | 848 | ||
787 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) | ||
788 | hotk_input_dev = input_allocate_device(); | 849 | hotk_input_dev = input_allocate_device(); |
789 | if (!hotk_input_dev) { | ||
790 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate input device for hotkey")); | ||
791 | return_VALUE(-ENOMEM); | ||
792 | } | ||
793 | #else | ||
794 | hotk_input_dev = kcalloc(1, sizeof(struct input_dev),GFP_KERNEL); | ||
795 | if (hotk_input_dev == NULL) { | 850 | if (hotk_input_dev == NULL) { |
796 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); | 851 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate input device for hotkey")); |
797 | return_VALUE(-ENOMEM); | 852 | goto err_input; |
798 | } | 853 | } |
799 | #endif | ||
800 | 854 | ||
801 | pcc_keyinput = kcalloc(1,sizeof(struct pcc_keyinput),GFP_KERNEL); | 855 | pcc_keyinput = kcalloc(1, sizeof(struct pcc_keyinput), GFP_KERNEL); |
802 | 856 | ||
803 | if (pcc_keyinput == NULL) { | 857 | if (pcc_keyinput == NULL) { |
804 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); | 858 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for private data")); |
805 | input_unregister_device(hotk_input_dev); | 859 | goto err_pcc; |
806 | return_VALUE(-ENOMEM); | ||
807 | } | 860 | } |
808 | 861 | ||
809 | hotk_input_dev->evbit[0] = BIT(EV_KEY); | 862 | hotk_input_dev->evbit[0] = BIT(EV_KEY); |
810 | 863 | ||
811 | set_bit(KEY_BRIGHTNESSDOWN, hotk_input_dev->keybit); | 864 | set_bit(KEY_BRIGHTNESSDOWN, hotk_input_dev->keybit); |
812 | set_bit(KEY_BRIGHTNESSUP, hotk_input_dev->keybit); | 865 | set_bit(KEY_BRIGHTNESSUP, hotk_input_dev->keybit); |
813 | set_bit(KEY_MUTE, hotk_input_dev->keybit); | 866 | set_bit(KEY_MUTE, hotk_input_dev->keybit); |
814 | set_bit(KEY_VOLUMEDOWN, hotk_input_dev->keybit); | 867 | set_bit(KEY_VOLUMEDOWN, hotk_input_dev->keybit); |
815 | set_bit(KEY_VOLUMEUP, hotk_input_dev->keybit); | 868 | set_bit(KEY_VOLUMEUP, hotk_input_dev->keybit); |
816 | set_bit(KEY_SLEEP, hotk_input_dev->keybit); | 869 | set_bit(KEY_SLEEP, hotk_input_dev->keybit); |
817 | set_bit(KEY_BATT, hotk_input_dev->keybit); | 870 | set_bit(KEY_BATT, hotk_input_dev->keybit); |
818 | set_bit(KEY_SUSPEND, hotk_input_dev->keybit); | 871 | set_bit(KEY_SUSPEND, hotk_input_dev->keybit); |
819 | 872 | ||
820 | hotk_input_dev->name = ACPI_PCC_DRIVER_NAME; | 873 | hotk_input_dev->name = ACPI_PCC_DRIVER_NAME; |
821 | hotk_input_dev->phys = ACPI_PCC_INPUT_PHYS; | 874 | hotk_input_dev->phys = ACPI_PCC_INPUT_PHYS; |
822 | hotk_input_dev->id.bustype = 0x1a; /* XXX FIXME: BUS_I8042? */ | 875 | hotk_input_dev->id.bustype = BUS_PCC_HOTKEY; |
823 | hotk_input_dev->id.vendor = 0x0001; | 876 | hotk_input_dev->id.vendor = 0x0001; |
824 | hotk_input_dev->id.product = 0x0001; | 877 | hotk_input_dev->id.product = 0x0001; |
825 | hotk_input_dev->id.version = 0x0100; | 878 | hotk_input_dev->id.version = 0x0100; |
826 | 879 | ||
827 | pcc_keyinput->key_mode = 1; /* default on */ | 880 | pcc_keyinput->key_mode = PCC_KEYINPUT_MODE; |
828 | pcc_keyinput->hotkey = hotkey; | 881 | pcc_keyinput->hotkey = hotkey; |
829 | 882 | ||
830 | input_set_drvdata(hotk_input_dev, pcc_keyinput); | 883 | input_set_drvdata(hotk_input_dev, pcc_keyinput); |
831 | 884 | ||
832 | hotkey->input_dev = hotk_input_dev; | 885 | hotkey->input_dev = hotk_input_dev; |
833 | 886 | ||
887 | error = input_register_device(hotk_input_dev); | ||
834 | 888 | ||
835 | input_register_device(hotk_input_dev); | 889 | if (error) { |
890 | goto err_pcc; | ||
891 | } | ||
836 | 892 | ||
837 | return_VALUE(0); | 893 | return_VALUE(0); |
838 | } | ||
839 | 894 | ||
840 | /* -------------------------------------------------------------------------- | 895 | err_pcc: |
841 | module init | 896 | input_unregister_device(hotk_input_dev); |
842 | -------------------------------------------------------------------------- */ | 897 | err_input: |
898 | return_VALUE(-ENOMEM); | ||
899 | } | ||
843 | 900 | ||
844 | static int acpi_pcc_hotkey_resume(struct acpi_device *device) | 901 | static void __devexit acpi_pcc_remove_input(struct acpi_hotkey *hotkey) |
845 | { | 902 | { |
846 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | 903 | struct input_dev *hotk_input_dev; |
847 | acpi_status status = AE_OK; | 904 | struct pcc_keyinput *pcc_keyinput; |
848 | 905 | ||
849 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); | 906 | ACPI_FUNCTION_TRACE("acpi_pcc_remove_input"); |
850 | 907 | ||
851 | if (device == NULL || hotkey == NULL) { return_VALUE(-EINVAL); } | 908 | if (hotkey == NULL) { |
909 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Can't free memory")); | ||
910 | return_VOID; | ||
911 | } | ||
852 | 912 | ||
853 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", hotkey->sticky_mode)); | 913 | hotk_input_dev = hotkey->input_dev; |
914 | pcc_keyinput = input_get_drvdata(hotk_input_dev); | ||
854 | 915 | ||
855 | status = acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, hotkey->sticky_mode); | 916 | input_unregister_device(hotk_input_dev); |
856 | 917 | ||
857 | return_VALUE(status == AE_OK ? 0 : -EINVAL); | 918 | kfree(pcc_keyinput); |
858 | } | 919 | } |
859 | 920 | ||
860 | static int acpi_pcc_hotkey_add (struct acpi_device *device) | 921 | /* ------------------------------------------------------------------------- |
922 | ACPI | ||
923 | ------------------------------------------------------------------------- */ | ||
924 | static int __devinit acpi_pcc_hotkey_add (struct acpi_device *device) | ||
861 | { | 925 | { |
862 | acpi_status status = AE_OK; | 926 | acpi_status status = AE_OK; |
863 | struct acpi_hotkey *hotkey = NULL; | 927 | struct acpi_hotkey *hotkey = NULL; |
864 | int num_sifr, result; | 928 | int sifr_status, num_sifr, result; |
865 | 929 | ||
866 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); | 930 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); |
867 | 931 | ||
868 | if (!device) { | 932 | if (device == NULL) { |
869 | return_VALUE(-EINVAL); | 933 | return_VALUE(-EINVAL); |
870 | } | 934 | } |
871 | 935 | ||
872 | num_sifr = acpi_pcc_get_sqty(device); | 936 | sifr_status = acpi_pcc_get_sqty(device); |
873 | 937 | ||
874 | if (num_sifr > 255) { | 938 | if (sifr_status > 255) { |
875 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); | 939 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); |
876 | return_VALUE(-ENODEV); | 940 | return_VALUE(-ENODEV); |
877 | } | 941 | } |
878 | 942 | ||
879 | hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL); | 943 | if (sifr_status < 0) { |
880 | if (!hotkey) { | 944 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "not support SQTY")); |
945 | num_sifr = 0; | ||
946 | } else { | ||
947 | num_sifr = sifr_status; | ||
948 | } | ||
949 | |||
950 | hotkey = kcalloc(1, sizeof(struct acpi_hotkey), GFP_KERNEL); | ||
951 | if (hotkey == NULL) { | ||
881 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); | 952 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); |
882 | return_VALUE(-ENOMEM); | 953 | return_VALUE(-ENOMEM); |
883 | } | 954 | } |
884 | 955 | ||
885 | memset(hotkey, 0, sizeof(struct acpi_hotkey)); | 956 | hotkey->device = device; |
886 | 957 | hotkey->handle = device->handle; | |
887 | hotkey->device = device; | ||
888 | hotkey->handle = device->handle; | ||
889 | hotkey->num_sifr = num_sifr; | 958 | hotkey->num_sifr = num_sifr; |
890 | acpi_driver_data(device) = hotkey; | 959 | acpi_driver_data(device) = hotkey; |
891 | strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); | 960 | strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); |
892 | strcpy(acpi_device_class(device), ACPI_PCC_CLASS); | 961 | strcpy(acpi_device_class(device), ACPI_PCC_CLASS); |
893 | 962 | ||
894 | status = acpi_install_notify_handler ( | 963 | status = acpi_install_notify_handler(hotkey->handle, |
895 | hotkey->handle, | 964 | ACPI_DEVICE_NOTIFY, |
896 | ACPI_DEVICE_NOTIFY, | 965 | acpi_pcc_hotkey_notify, |
897 | acpi_pcc_hotkey_notify, | 966 | hotkey); |
898 | hotkey); | ||
899 | 967 | ||
900 | if (ACPI_FAILURE(status)) { | 968 | if (ACPI_FAILURE(status)) { |
901 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); | 969 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); |
@@ -904,7 +972,7 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) | |||
904 | } | 972 | } |
905 | 973 | ||
906 | result = acpi_pcc_init_input(hotkey); | 974 | result = acpi_pcc_init_input(hotkey); |
907 | if (result) { | 975 | if (result != 0) { |
908 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing keyinput handler\n")); | 976 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing keyinput handler\n")); |
909 | kfree(hotkey); | 977 | kfree(hotkey); |
910 | return_VALUE(result); | 978 | return_VALUE(result); |
@@ -913,62 +981,72 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) | |||
913 | return_VALUE(acpi_pcc_proc_init(device)); | 981 | return_VALUE(acpi_pcc_proc_init(device)); |
914 | } | 982 | } |
915 | 983 | ||
916 | static int __init acpi_pcc_init(void) | 984 | static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, int type) |
917 | { | ||
918 | int result = 0; | ||
919 | |||
920 | ACPI_FUNCTION_TRACE("acpi_pcc_init"); | ||
921 | |||
922 | if (acpi_disabled) { | ||
923 | return_VALUE(-ENODEV); | ||
924 | } | ||
925 | |||
926 | result = acpi_bus_register_driver(&acpi_pcc_driver); | ||
927 | if (result < 0) { | ||
928 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n")); | ||
929 | return_VALUE(-ENODEV); | ||
930 | } | ||
931 | |||
932 | return_VALUE(0); | ||
933 | } | ||
934 | |||
935 | module_init(acpi_pcc_init); | ||
936 | |||
937 | static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) | ||
938 | { | 985 | { |
939 | acpi_status status = AE_OK; | 986 | acpi_status status = AE_OK; |
940 | struct acpi_hotkey *hotkey = acpi_driver_data(device); | 987 | struct acpi_hotkey *hotkey = acpi_driver_data(device); |
941 | 988 | ||
942 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); | 989 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); |
943 | 990 | ||
944 | if (!device || !hotkey) | 991 | if (!device || !hotkey) { |
945 | return_VALUE(-EINVAL); | 992 | return_VALUE(-EINVAL); |
993 | } | ||
946 | 994 | ||
947 | if (hotkey->proc_dir_entry) { | 995 | if (hotkey->proc_dir_entry) { |
948 | acpi_pcc_remove_device(device, pcc_proc_items_sifr, hotkey->num_sifr); | 996 | acpi_pcc_remove_device(device, acpi_pcc_proc_items_sifr, hotkey->num_sifr); |
949 | acpi_pcc_remove_device(device, pcc_proc_items, sizeof(pcc_proc_items)/sizeof(ProcItem)); | 997 | acpi_pcc_remove_device(device, acpi_pcc_proc_items, ARRAY_SIZE(acpi_pcc_proc_items)); |
950 | remove_proc_entry(PROC_PCC, acpi_root_dir); | 998 | remove_proc_entry(PROC_PCC, acpi_root_dir); |
951 | } | 999 | } |
952 | 1000 | ||
953 | status = acpi_remove_notify_handler(hotkey->handle, | 1001 | status = acpi_remove_notify_handler(hotkey->handle, |
954 | ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify); | 1002 | ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify); |
955 | 1003 | ||
956 | if (ACPI_FAILURE(status)) | 1004 | if (ACPI_FAILURE(status)) { |
957 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); | 1005 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); |
1006 | } | ||
958 | 1007 | ||
959 | input_unregister_device(hotkey->input_dev); | 1008 | acpi_pcc_remove_input(hotkey); |
960 | 1009 | if (hotkey != NULL) { | |
961 | kfree(hotkey); | 1010 | kfree(hotkey); |
1011 | } | ||
962 | return_VALUE(status == AE_OK); | 1012 | return_VALUE(status == AE_OK); |
963 | } | 1013 | } |
964 | 1014 | ||
1015 | /* ********************************************************************* | ||
1016 | Module entry point | ||
1017 | ********************************************************************* */ | ||
1018 | static int __init acpi_pcc_init(void) | ||
1019 | { | ||
1020 | int result; | ||
1021 | |||
1022 | ACPI_FUNCTION_TRACE("acpi_pcc_init"); | ||
1023 | |||
1024 | printk(KERN_INFO LOGPREFIX "loading...\n"); | ||
1025 | |||
1026 | if (acpi_disabled) { | ||
1027 | printk(KERN_INFO LOGPREFIX "ACPI disabled.\n"); | ||
1028 | return_VALUE(-ENODEV); | ||
1029 | } | ||
1030 | |||
1031 | result = acpi_bus_register_driver(&acpi_pcc_driver); | ||
1032 | if (result < 0) { | ||
1033 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n")); | ||
1034 | return_VALUE(-ENODEV); | ||
1035 | } | ||
1036 | |||
1037 | return_VALUE(result); | ||
1038 | } | ||
1039 | |||
965 | static void __exit acpi_pcc_exit(void) | 1040 | static void __exit acpi_pcc_exit(void) |
966 | { | 1041 | { |
967 | ACPI_FUNCTION_TRACE("acpi_pcc_exit"); | 1042 | ACPI_FUNCTION_TRACE("acpi_pcc_exit"); |
968 | 1043 | ||
1044 | printk(KERN_INFO LOGPREFIX "unloading...\n"); | ||
1045 | |||
969 | acpi_bus_unregister_driver(&acpi_pcc_driver); | 1046 | acpi_bus_unregister_driver(&acpi_pcc_driver); |
970 | 1047 | ||
971 | return_VOID; | 1048 | return_VOID; |
972 | } | 1049 | } |
973 | 1050 | ||
1051 | module_init(acpi_pcc_init); | ||
974 | module_exit(acpi_pcc_exit); | 1052 | module_exit(acpi_pcc_exit); |