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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 #include <acpi_drivers.h>
37 #define _COMPONENT ACPI_BUTTON_COMPONENT
38 ACPI_MODULE_NAME ("acpi_button")
41 static int acpi_button_add (struct acpi_device
*device
);
42 static int acpi_button_remove (struct acpi_device
*device
, int type
);
44 static struct acpi_driver acpi_button_driver
= {
45 .name
= ACPI_BUTTON_DRIVER_NAME
,
46 .class = ACPI_BUTTON_CLASS
,
47 .ids
= "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
49 .add
= acpi_button_add
,
50 .remove
= acpi_button_remove
,
56 struct acpi_device
*device
; /* Fixed button kludge */
60 /* --------------------------------------------------------------------------
62 -------------------------------------------------------------------------- */
70 struct acpi_button
*button
= (struct acpi_button
*) data
;
72 ACPI_FUNCTION_TRACE("acpi_button_notify");
74 if (!button
|| !button
->device
)
78 case ACPI_BUTTON_NOTIFY_STATUS
:
79 acpi_bus_generate_event(button
->device
, event
, ++button
->pushed
);
82 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
83 "Unsupported event [0x%x]\n", event
));
92 acpi_button_notify_fixed (
95 struct acpi_button
*button
= (struct acpi_button
*) data
;
97 ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
100 return_ACPI_STATUS(AE_BAD_PARAMETER
);
102 acpi_button_notify(button
->handle
, ACPI_BUTTON_NOTIFY_STATUS
, button
);
104 return_ACPI_STATUS(AE_OK
);
110 struct acpi_device
*device
)
113 ACPI_STATUS status
= AE_OK
;
114 struct acpi_button
*button
= NULL
;
116 static struct acpi_device
*power_button
;
117 static struct acpi_device
*sleep_button
;
118 static struct acpi_device
*lid_button
;
120 ACPI_FUNCTION_TRACE("acpi_button_add");
125 button
= ExAllocatePool(NonPagedPool
,sizeof(struct acpi_button
));
128 memset(button
, 0, sizeof(struct acpi_button
));
130 button
->device
= device
;
131 button
->handle
= device
->handle
;
132 acpi_driver_data(device
) = button
;
135 * Determine the button type (via hid), as fixed-feature buttons
136 * need to be handled a bit differently than generic-space.
138 if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_POWER
)) {
139 button
->type
= ACPI_BUTTON_TYPE_POWER
;
140 sprintf(acpi_device_name(device
), "%s",
141 ACPI_BUTTON_DEVICE_NAME_POWER
);
142 sprintf(acpi_device_class(device
), "%s/%s",
143 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_POWER
);
145 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_POWERF
)) {
146 button
->type
= ACPI_BUTTON_TYPE_POWERF
;
147 sprintf(acpi_device_name(device
), "%s",
148 ACPI_BUTTON_DEVICE_NAME_POWERF
);
149 sprintf(acpi_device_class(device
), "%s/%s",
150 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_POWER
);
152 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_SLEEP
)) {
153 button
->type
= ACPI_BUTTON_TYPE_SLEEP
;
154 sprintf(acpi_device_name(device
), "%s",
155 ACPI_BUTTON_DEVICE_NAME_SLEEP
);
156 sprintf(acpi_device_class(device
), "%s/%s",
157 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_SLEEP
);
159 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_SLEEPF
)) {
160 button
->type
= ACPI_BUTTON_TYPE_SLEEPF
;
161 sprintf(acpi_device_name(device
), "%s",
162 ACPI_BUTTON_DEVICE_NAME_SLEEPF
);
163 sprintf(acpi_device_class(device
), "%s/%s",
164 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_SLEEP
);
166 else if (!strcmp(acpi_device_hid(device
), ACPI_BUTTON_HID_LID
)) {
167 button
->type
= ACPI_BUTTON_TYPE_LID
;
168 sprintf(acpi_device_name(device
), "%s",
169 ACPI_BUTTON_DEVICE_NAME_LID
);
170 sprintf(acpi_device_class(device
), "%s/%s",
171 ACPI_BUTTON_CLASS
, ACPI_BUTTON_SUBCLASS_LID
);
174 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Unsupported hid [%s]\n",
175 acpi_device_hid(device
)));
181 * Ensure only one button of each type is used.
183 switch (button
->type
) {
184 case ACPI_BUTTON_TYPE_POWER
:
185 case ACPI_BUTTON_TYPE_POWERF
:
187 power_button
= device
;
193 case ACPI_BUTTON_TYPE_SLEEP
:
194 case ACPI_BUTTON_TYPE_SLEEPF
:
196 sleep_button
= device
;
202 case ACPI_BUTTON_TYPE_LID
:
212 switch (button
->type
) {
213 case ACPI_BUTTON_TYPE_POWERF
:
214 status
= AcpiInstallFixedEventHandler (
215 ACPI_EVENT_POWER_BUTTON
,
216 acpi_button_notify_fixed
,
219 case ACPI_BUTTON_TYPE_SLEEPF
:
220 status
= AcpiInstallFixedEventHandler (
221 ACPI_EVENT_SLEEP_BUTTON
,
222 acpi_button_notify_fixed
,
225 case ACPI_BUTTON_TYPE_LID
:
226 status
= AcpiInstallFixedEventHandler (
227 ACPI_BUTTON_TYPE_LID
,
228 acpi_button_notify_fixed
,
232 status
= AcpiInstallNotifyHandler (
240 if (ACPI_FAILURE(status
)) {
241 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
242 "Error installing notify handler\n"));
248 acpi_device_name(device
), acpi_device_bid(device
));
255 return_VALUE(result
);
260 acpi_button_remove (struct acpi_device
*device
, int type
)
262 ACPI_STATUS status
= 0;
263 struct acpi_button
*button
= NULL
;
265 ACPI_FUNCTION_TRACE("acpi_button_remove");
267 if (!device
|| !acpi_driver_data(device
))
270 button
= acpi_driver_data(device
);
272 /* Unregister for device notifications. */
273 switch (button
->type
) {
274 case ACPI_BUTTON_TYPE_POWERF
:
275 status
= AcpiRemoveFixedEventHandler(
276 ACPI_EVENT_POWER_BUTTON
, acpi_button_notify_fixed
);
278 case ACPI_BUTTON_TYPE_SLEEPF
:
279 status
= AcpiRemoveFixedEventHandler(
280 ACPI_EVENT_SLEEP_BUTTON
, acpi_button_notify_fixed
);
282 case ACPI_BUTTON_TYPE_LID
:
283 status
= AcpiRemoveFixedEventHandler(
284 ACPI_BUTTON_TYPE_LID
, acpi_button_notify_fixed
);
287 status
= AcpiRemoveNotifyHandler(button
->handle
,
288 ACPI_DEVICE_NOTIFY
, acpi_button_notify
);
292 if (ACPI_FAILURE(status
))
293 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
294 "Error removing notify handler\n"));
303 acpi_button_init (void)
307 ACPI_FUNCTION_TRACE("acpi_button_init");
309 result
= acpi_bus_register_driver(&acpi_button_driver
);
319 acpi_button_exit (void)
321 ACPI_FUNCTION_TRACE("acpi_button_exit");
323 acpi_bus_unregister_driver(&acpi_button_driver
);