2 * acpi_button.c - ACPI Button Driver ($Revision: 29 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 #define _COMPONENT ACPI_BUTTON_COMPONENT
32 ACPI_MODULE_NAME ("acpi_button")
35 static int acpi_button_add (struct acpi_device
*device
);
36 static int acpi_button_remove (struct acpi_device
*device
, int type
);
38 static struct acpi_driver acpi_button_driver
= {
40 ACPI_BUTTON_DRIVER_NAME
,
44 "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
45 {acpi_button_add
,acpi_button_remove
}
50 struct acpi_device
*device
; /* Fixed button kludge */
55 struct acpi_device
*power_button
;
56 struct acpi_device
*sleep_button
;
57 struct acpi_device
*lid_button
;
59 /* --------------------------------------------------------------------------
61 -------------------------------------------------------------------------- */
69 struct acpi_button
*button
= (struct acpi_button
*) data
;
71 ACPI_FUNCTION_TRACE("acpi_button_notify");
73 if (!button
|| !button
->device
)
77 case ACPI_BUTTON_NOTIFY_STATUS
:
78 acpi_bus_generate_event(button
->device
, event
, ++button
->pushed
);
81 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
82 "Unsupported event [0x%x]\n", event
));
91 acpi_button_notify_fixed (
94 struct acpi_button
*button
= (struct acpi_button
*) data
;
96 ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
99 return_ACPI_STATUS(AE_BAD_PARAMETER
);
101 acpi_button_notify(button
->handle
, ACPI_BUTTON_NOTIFY_STATUS
, button
);
103 return_ACPI_STATUS(AE_OK
);
109 struct acpi_device
*device
)
112 ACPI_STATUS status
= AE_OK
;
113 struct acpi_button
*button
= NULL
;
115 ACPI_FUNCTION_TRACE("acpi_button_add");
120 button
= ExAllocatePoolWithTag(NonPagedPool
,sizeof(struct acpi_button
), 'IPCA');
123 memset(button
, 0, sizeof(struct acpi_button
));
125 button
->device
= device
;
126 button
->handle
= device
->handle
;
127 acpi_driver_data(device
) = button
;
130 * Determine the button type (via hid), as fixed-feature buttons
131 * need to be handled a bit differently than generic-space.
133 if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_POWER
)) {
134 button
->type
= ACPI_BUTTON_TYPE_POWER
;
135 sprintf(acpi_device_name(device
), "%s",
136 ACPI_BUTTON_DEVICE_NAME_POWER
);
137 sprintf(acpi_device_class(device
), "%s/%s",
138 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_POWER
);
140 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_POWERF
)) {
141 button
->type
= ACPI_BUTTON_TYPE_POWERF
;
142 sprintf(acpi_device_name(device
), "%s",
143 ACPI_BUTTON_DEVICE_NAME_POWERF
);
144 sprintf(acpi_device_class(device
), "%s/%s",
145 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_POWER
);
147 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_SLEEP
)) {
148 button
->type
= ACPI_BUTTON_TYPE_SLEEP
;
149 sprintf(acpi_device_name(device
), "%s",
150 ACPI_BUTTON_DEVICE_NAME_SLEEP
);
151 sprintf(acpi_device_class(device
), "%s/%s",
152 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_SLEEP
);
154 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_SLEEPF
)) {
155 button
->type
= ACPI_BUTTON_TYPE_SLEEPF
;
156 sprintf(acpi_device_name(device
), "%s",
157 ACPI_BUTTON_DEVICE_NAME_SLEEPF
);
158 sprintf(acpi_device_class(device
), "%s/%s",
159 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_SLEEP
);
161 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_LID
)) {
162 button
->type
= ACPI_BUTTON_TYPE_LID
;
163 sprintf(acpi_device_name(device
), "%s",
164 ACPI_BUTTON_DEVICE_NAME_LID
);
165 sprintf(acpi_device_class(device
), "%s/%s",
166 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_LID
);
169 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Unsupported hid [%s]\n",
170 acpi_device_hid(device
)));
176 * Ensure only one button of each type is used.
178 switch (button
->type
) {
179 case ACPI_BUTTON_TYPE_POWER
:
180 case ACPI_BUTTON_TYPE_POWERF
:
182 power_button
= device
;
184 ExFreePoolWithTag(button
, 'IPCA');
188 case ACPI_BUTTON_TYPE_SLEEP
:
189 case ACPI_BUTTON_TYPE_SLEEPF
:
191 sleep_button
= device
;
193 ExFreePoolWithTag(button
, 'IPCA');
197 case ACPI_BUTTON_TYPE_LID
:
201 ExFreePoolWithTag(button
, 'IPCA');
207 switch (button
->type
) {
208 case ACPI_BUTTON_TYPE_POWERF
:
209 status
= AcpiInstallFixedEventHandler (
210 ACPI_EVENT_POWER_BUTTON
,
211 acpi_button_notify_fixed
,
214 case ACPI_BUTTON_TYPE_SLEEPF
:
215 status
= AcpiInstallFixedEventHandler (
216 ACPI_EVENT_SLEEP_BUTTON
,
217 acpi_button_notify_fixed
,
220 case ACPI_BUTTON_TYPE_LID
:
221 status
= AcpiInstallFixedEventHandler (
222 ACPI_BUTTON_TYPE_LID
,
223 acpi_button_notify_fixed
,
227 status
= AcpiInstallNotifyHandler (
235 if (ACPI_FAILURE(status
)) {
236 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
237 "Error installing notify handler\n"));
243 acpi_device_name(device
), acpi_device_bid(device
));
247 ExFreePoolWithTag(button
, 'IPCA');
250 return_VALUE(result
);
255 acpi_button_remove (struct acpi_device
*device
, int type
)
257 ACPI_STATUS status
= 0;
258 struct acpi_button
*button
= NULL
;
260 ACPI_FUNCTION_TRACE("acpi_button_remove");
262 if (!device
|| !acpi_driver_data(device
))
265 button
= acpi_driver_data(device
);
267 /* Unregister for device notifications. */
268 switch (button
->type
) {
269 case ACPI_BUTTON_TYPE_POWERF
:
270 status
= AcpiRemoveFixedEventHandler(
271 ACPI_EVENT_POWER_BUTTON
, acpi_button_notify_fixed
);
273 case ACPI_BUTTON_TYPE_SLEEPF
:
274 status
= AcpiRemoveFixedEventHandler(
275 ACPI_EVENT_SLEEP_BUTTON
, acpi_button_notify_fixed
);
277 case ACPI_BUTTON_TYPE_LID
:
278 status
= AcpiRemoveFixedEventHandler(
279 ACPI_BUTTON_TYPE_LID
, acpi_button_notify_fixed
);
282 status
= AcpiRemoveNotifyHandler(button
->handle
,
283 ACPI_DEVICE_NOTIFY
, acpi_button_notify
);
287 if (ACPI_FAILURE(status
))
288 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
289 "Error removing notify handler\n"));
291 ExFreePoolWithTag(button
, 'IPCA');
298 acpi_button_init (void)
302 ACPI_FUNCTION_TRACE("acpi_button_init");
304 result
= acpi_bus_register_driver(&acpi_button_driver
);
314 acpi_button_exit (void)
316 ACPI_FUNCTION_TRACE("acpi_button_exit");
318 acpi_bus_unregister_driver(&acpi_button_driver
);