Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / ospm / bn.c
1 /*****************************************************************************
2 *
3 * Module Name: bn.c
4 * $Revision: 1.2 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 Andrew Grover
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Plxxe, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include <acpi.h>
27
28 #define _COMPONENT ACPI_BUTTON
29 MODULE_NAME ("bn")
30
31
32 static struct proc_dir_entry *bn_proc_root = NULL;
33
34
35 /*****************************************************************************
36 * Internal Functions
37 *****************************************************************************/
38
39 /*****************************************************************************
40 *
41 * FUNCTION: bn_print
42 *
43 * PARAMETERS: <TBD>
44 *
45 * RETURN: <TBD>
46 *
47 * DESCRIPTION: Prints out information on a specific button.
48 *
49 ****************************************************************************/
50
51 void
52 bn_print (
53 BN_CONTEXT *button)
54 {
55 #ifdef ACPI_DEBUG
56 ACPI_BUFFER buffer;
57 #endif /*ACPI_DEBUG*/
58
59 if (!button) {
60 return;
61 }
62
63 switch (button->type) {
64
65 case BN_TYPE_POWER_BUTTON:
66 case BN_TYPE_POWER_BUTTON_FIXED:
67 acpi_os_printf("Power Button: found\n");
68 break;
69
70 case BN_TYPE_SLEEP_BUTTON:
71 case BN_TYPE_SLEEP_BUTTON_FIXED:
72 acpi_os_printf("Sleep Button: found\n");
73 break;
74
75 case BN_TYPE_LID_SWITCH:
76 acpi_os_printf("Lid Switch: found\n");
77 break;
78 }
79
80 #ifdef ACPI_DEBUG
81 buffer.length = 256;
82 buffer.pointer = acpi_os_callocate(buffer.length);
83 if (!buffer.pointer) {
84 return;
85 }
86
87 /*
88 * Get the full pathname for this ACPI object.
89 */
90 acpi_get_name(button->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
91
92 /*
93 * Print out basic button information.
94 */
95 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
96
97 switch (button->type) {
98
99 case BN_TYPE_POWER_BUTTON:
100 case BN_TYPE_POWER_BUTTON_FIXED:
101 DEBUG_PRINT(ACPI_INFO, ("| PowerButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
102 break;
103
104 case BN_TYPE_SLEEP_BUTTON:
105 case BN_TYPE_SLEEP_BUTTON_FIXED:
106 DEBUG_PRINT(ACPI_INFO, ("| SleepButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
107 break;
108
109 case BN_TYPE_LID_SWITCH:
110 DEBUG_PRINT(ACPI_INFO, ("| LidSwitch[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
111 break;
112 }
113
114 DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
115
116 acpi_os_free(buffer.pointer);
117 #endif /*ACPI_DEBUG*/
118
119 return;
120 }
121
122
123 /****************************************************************************
124 *
125 * FUNCTION: bn_add_device
126 *
127 * PARAMETERS: <TBD>
128 *
129 * RETURN: <TBD>
130 *
131 * DESCRIPTION: <TBD>
132 *
133 ****************************************************************************/
134
135 ACPI_STATUS
136 bn_add_device(
137 BM_HANDLE device_handle,
138 void **context)
139 {
140 ACPI_STATUS status = AE_OK;
141 BM_DEVICE *device = NULL;
142 BN_CONTEXT *button = NULL;
143
144 FUNCTION_TRACE("bn_add_device");
145
146 DEBUG_PRINT(ACPI_INFO, ("Adding button device [0x%02x].\n", device_handle));
147
148 if (!context || *context) {
149 DEBUG_PRINT(ACPI_ERROR, ("Invalid context.\n"));
150 return_ACPI_STATUS(AE_BAD_PARAMETER);
151 }
152
153 /*
154 * Get information on this device.
155 */
156 status = bm_get_device_info( device_handle, &device );
157 if (ACPI_FAILURE(status)) {
158 return_ACPI_STATUS(status);
159 }
160
161 /*
162 * Allocate a new BN_CONTEXT structure.
163 */
164 button = acpi_os_callocate(sizeof(BN_CONTEXT));
165 if (!button) {
166 return_ACPI_STATUS(AE_NO_MEMORY);
167 }
168
169 button->device_handle = device->handle;
170 button->acpi_handle = device->acpi_handle;
171
172 /*
173 * Power Button?
174 * -------------
175 * Either fixed-feature or generic (namespace) types.
176 */
177 if (strncmp(device->id.hid, BN_HID_POWER_BUTTON,
178 sizeof(BM_DEVICE_HID)) == 0) {
179
180 if (device->id.type == BM_TYPE_FIXED_BUTTON) {
181
182 button->type = BN_TYPE_POWER_BUTTON_FIXED;
183
184 /* Register for fixed-feature events. */
185 status = acpi_install_fixed_event_handler(
186 ACPI_EVENT_POWER_BUTTON, bn_notify_fixed,
187 (void*)button);
188 }
189 else {
190 button->type = BN_TYPE_POWER_BUTTON;
191 }
192
193 //proc_mkdir(BN_PROC_POWER_BUTTON, bn_proc_root);
194
195 }
196
197 /*
198 * Sleep Button?
199 * -------------
200 * Either fixed-feature or generic (namespace) types.
201 */
202 else if (strncmp( device->id.hid, BN_HID_SLEEP_BUTTON,
203 sizeof(BM_DEVICE_HID)) == 0) {
204
205 if (device->id.type == BM_TYPE_FIXED_BUTTON) {
206
207 button->type = BN_TYPE_SLEEP_BUTTON_FIXED;
208
209 /* Register for fixed-feature events. */
210 status = acpi_install_fixed_event_handler(
211 ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed,
212 (void*)button);
213 }
214 else {
215 button->type = BN_TYPE_SLEEP_BUTTON;
216 }
217
218 //proc_mkdir(BN_PROC_SLEEP_BUTTON, bn_proc_root);
219 }
220
221 /*
222 * LID Switch?
223 * -----------
224 */
225 else if (strncmp( device->id.hid, BN_HID_LID_SWITCH,
226 sizeof(BM_DEVICE_HID)) == 0) {
227
228 button->type = BN_TYPE_LID_SWITCH;
229
230 //proc_mkdir(BN_PROC_LID_SWITCH, bn_proc_root);
231 }
232
233 *context = button;
234
235 bn_print(button);
236
237 return_ACPI_STATUS(status);
238 }
239
240
241 /****************************************************************************
242 *
243 * FUNCTION: bn_remove_device
244 *
245 * PARAMETERS: <TBD>
246 *
247 * RETURN: <TBD>
248 *
249 * DESCRIPTION: <TBD>
250 *
251 ****************************************************************************/
252
253 ACPI_STATUS
254 bn_remove_device(
255 void **context)
256 {
257 ACPI_STATUS status = AE_OK;
258 BN_CONTEXT *button = NULL;
259
260 FUNCTION_TRACE("bn_remove_device");
261
262 if (!context || !*context) {
263 return_ACPI_STATUS(AE_BAD_PARAMETER);
264 }
265
266 button = (BN_CONTEXT*)*context;
267
268 DEBUG_PRINT(ACPI_INFO, ("Removing button device [0x%02x].\n", button->device_handle));
269
270 /*
271 * Remove the /proc entry for this button.
272 */
273 switch (button->type) {
274
275 case BN_TYPE_POWER_BUTTON:
276 case BN_TYPE_POWER_BUTTON_FIXED:
277 /* Unregister for fixed-feature events. */
278 status = acpi_remove_fixed_event_handler(
279 ACPI_EVENT_POWER_BUTTON, bn_notify_fixed);
280 //remove_proc_entry(BN_PROC_POWER_BUTTON, bn_proc_root);
281 break;
282
283 case BN_TYPE_SLEEP_BUTTON:
284 case BN_TYPE_SLEEP_BUTTON_FIXED:
285 /* Unregister for fixed-feature events. */
286 status = acpi_remove_fixed_event_handler(
287 ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed);
288 //remove_proc_entry(BN_PROC_SLEEP_BUTTON, bn_proc_root);
289 break;
290
291 case BN_TYPE_LID_SWITCH:
292 //remove_proc_entry(BN_PROC_LID_SWITCH, bn_proc_root);
293 break;
294 }
295
296 acpi_os_free(button);
297
298 *context = NULL;
299
300 return_ACPI_STATUS(status);
301 }
302
303
304 /*****************************************************************************
305 * External Functions
306 *****************************************************************************/
307
308 /*****************************************************************************
309 *
310 * FUNCTION: bn_initialize
311 *
312 * PARAMETERS: <none>
313 *
314 * RETURN:
315 *
316 * DESCRIPTION: <TBD>
317 *
318
319 ****************************************************************************/
320
321 ACPI_STATUS
322 bn_initialize (void)
323 {
324 ACPI_STATUS status = AE_OK;
325 BM_DEVICE_ID criteria;
326 BM_DRIVER driver;
327
328 FUNCTION_TRACE("bn_initialize");
329
330 MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
331 MEMSET(&driver, 0, sizeof(BM_DRIVER));
332
333 driver.notify = &bn_notify;
334 driver.request = &bn_request;
335
336 /*
337 * Create button's root /proc entry.
338 */
339 //bn_proc_root = proc_mkdir(BN_PROC_ROOT, bm_proc_root);
340 //if (!bn_proc_root) {
341 // return_ACPI_STATUS(AE_ERROR);
342 // }
343
344 /*
345 * Register for power buttons.
346 */
347 MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON));
348 status = bm_register_driver(&criteria, &driver);
349
350 /*
351 * Register for sleep buttons.
352 */
353 MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON));
354 status = bm_register_driver(&criteria, &driver);
355
356 /*
357 * Register for LID switches.
358 */
359 MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH));
360 status = bm_register_driver(&criteria, &driver);
361
362 if (status == AE_NOT_FOUND)
363 status = AE_OK;
364
365 return_ACPI_STATUS(status);
366 }
367
368
369 /****************************************************************************
370 *
371 * FUNCTION: bn_terminate
372 *
373 * PARAMETERS: <none>
374 *
375 * RETURN: <TBD>
376 *
377 * DESCRIPTION: <TBD>
378 *
379 ****************************************************************************/
380
381 ACPI_STATUS
382 bn_terminate (void)
383 {
384 ACPI_STATUS status = AE_OK;
385 BM_DEVICE_ID criteria;
386 BM_DRIVER driver;
387
388 FUNCTION_TRACE("bn_terminate");
389
390 MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
391 MEMSET(&driver, 0, sizeof(BM_DRIVER));
392
393 driver.notify = &bn_notify;
394 driver.request = &bn_request;
395
396 /*
397 * Unregister for power buttons.
398 */
399 MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON));
400 status = bm_unregister_driver(&criteria, &driver);
401
402 /*
403 * Unregister for sleep buttons.
404 */
405 MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON));
406 status = bm_unregister_driver(&criteria, &driver);
407
408 /*
409 * Unregister for LID switches.
410 */
411 MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH));
412 status = bm_unregister_driver(&criteria, &driver);
413
414 /*
415 * Remove button's root /proc entry.
416 */
417 if (bn_proc_root) {
418 //remove_proc_entry(BN_PROC_ROOT, bm_proc_root);
419 }
420
421 return_ACPI_STATUS(status);
422 }
423
424
425 /****************************************************************************
426 *
427 * FUNCTION: bn_notify_fixed
428 *
429 * PARAMETERS: <none>
430 *
431 * RETURN:
432 *
433 * DESCRIPTION: <TBD>
434 *
435 ****************************************************************************/
436
437 ACPI_STATUS
438 bn_notify_fixed (
439 void *context)
440 {
441 ACPI_STATUS status = AE_OK;
442 BN_CONTEXT *button = NULL;
443
444 FUNCTION_TRACE("bn_notify_fixed");
445
446 if (!context) {
447 return_ACPI_STATUS(AE_BAD_PARAMETER);
448 }
449
450 button = (BN_CONTEXT*)context;
451
452 DbgPrint("Fixed button status change event detected.\n");
453
454 switch (button->type) {
455
456 case BN_TYPE_POWER_BUTTON_FIXED:
457 DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n"));
458 /*bm_generate_event(button->device_handle, BN_PROC_ROOT,
459 BN_PROC_POWER_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/
460 break;
461
462 case BN_TYPE_SLEEP_BUTTON_FIXED:
463 DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n"));
464 /*bm_generate_event(button->device_handle, BN_PROC_ROOT,
465 BN_PROC_SLEEP_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/
466 break;
467
468 default:
469 DEBUG_PRINT(ACPI_INFO, ("Unsupported fixed-feature event detected.\n"));
470 status = AE_SUPPORT;
471 break;
472 }
473
474 return_ACPI_STATUS(status);
475 }
476
477
478 /****************************************************************************
479 *
480 * FUNCTION: bn_notify
481 *
482 * PARAMETERS: <none>
483 *
484 * RETURN:
485 *
486 * DESCRIPTION: <TBD>
487 *
488 ****************************************************************************/
489
490 ACPI_STATUS
491 bn_notify (
492 BM_NOTIFY notify_type,
493 BM_HANDLE device_handle,
494 void **context)
495 {
496 ACPI_STATUS status = AE_OK;
497
498 FUNCTION_TRACE("bn_notify");
499
500 if (!context) {
501 return_ACPI_STATUS(AE_BAD_PARAMETER);
502 }
503
504 switch (notify_type) {
505 case BM_NOTIFY_DEVICE_ADDED:
506 status = bn_add_device(device_handle, context);
507 break;
508
509 case BM_NOTIFY_DEVICE_REMOVED:
510 status = bn_remove_device(context);
511 break;
512
513 case BN_NOTIFY_STATUS_CHANGE:
514 DEBUG_PRINT(ACPI_INFO, ("Button status change event detected.\n"));
515
516 DbgPrint("Button status change event detected.\n");
517
518 if (!context || !*context) {
519 return_ACPI_STATUS(AE_BAD_PARAMETER);
520 }
521
522 switch(((BN_CONTEXT*)*context)->type) {
523
524 case BN_TYPE_POWER_BUTTON:
525 case BN_TYPE_POWER_BUTTON_FIXED:
526 /*bm_generate_event(device_handle, BN_PROC_ROOT,
527 BN_PROC_POWER_BUTTON, notify_type, 0);*/
528 break;
529
530 case BN_TYPE_SLEEP_BUTTON:
531 case BN_TYPE_SLEEP_BUTTON_FIXED:
532 /*bm_generate_event(device_handle, BN_PROC_ROOT,
533 BN_PROC_SLEEP_BUTTON, notify_type, 0);*/
534 break;
535
536 case BN_TYPE_LID_SWITCH:
537 /*bm_generate_event(device_handle, BN_PROC_ROOT,
538 BN_PROC_LID_SWITCH, notify_type, 0);*/
539 break;
540
541 default:
542 status = AE_SUPPORT;
543 break;
544 }
545
546 break;
547
548 default:
549 status = AE_SUPPORT;
550 break;
551 }
552
553 return_ACPI_STATUS(status);
554 }
555
556
557 /****************************************************************************
558 *
559 * FUNCTION: bn_request
560 *
561 * PARAMETERS: <TBD>
562 *
563 * RETURN: <TBD>
564 *
565 * DESCRIPTION: <TBD>
566 *
567 ****************************************************************************/
568
569 ACPI_STATUS
570 bn_request (
571 BM_REQUEST *request,
572 void *context)
573 {
574 ACPI_STATUS status = AE_OK;
575
576 FUNCTION_TRACE("bn_request");
577
578 /*
579 * Must have a valid request structure and context.
580 */
581 if (!request || !context) {
582 return_ACPI_STATUS(AE_BAD_PARAMETER);
583 }
584
585 /*
586 * Handle Request:
587 * ---------------
588 */
589 switch (request->command) {
590
591 default:
592 status = AE_SUPPORT;
593 break;
594 }
595
596 request->status = status;
597
598 return_ACPI_STATUS(status);
599 }