2 * Copyright 2008-2013, Jérôme Duval, korli@users.berlios.de.
4 * Distributed under the terms of the MIT License.
10 #include <fs/select_sync_pool.h>
17 #define ACPI_LID_MODULE_NAME "drivers/power/acpi_lid/driver_v1"
19 #define ACPI_LID_DEVICE_MODULE_NAME "drivers/power/acpi_lid/device_v1"
21 #define ACPI_NOTIFY_STATUS_CHANGED 0x80
23 /* Base Namespace devices are published to */
24 #define ACPI_LID_BASENAME "power/acpi_lid/%d"
26 // name of pnp generator of path ids
27 #define ACPI_LID_PATHID_GENERATOR "acpi_lid/path_id"
31 # define TRACE(x...) dprintf("acpi_lid: "x)
35 #define ERROR(x...) dprintf("acpi_lid: "x)
38 static device_manager_info
*sDeviceManager
;
41 typedef struct acpi_ns_device_info
{
43 acpi_device_module_info
*acpi
;
44 acpi_device acpi_cookie
;
47 select_sync_pool
* select_pool
;
48 } acpi_lid_device_info
;
52 acpi_lid_read_status(acpi_lid_device_info
*device
)
56 buf
.length
= ACPI_ALLOCATE_BUFFER
;
57 if (device
->acpi
->evaluate_method(device
->acpi_cookie
, "_LID", NULL
,
59 || buf
.pointer
== NULL
60 || ((acpi_object_type
*)buf
.pointer
)->object_type
!= ACPI_TYPE_INTEGER
) {
61 ERROR("couldn't get status\n");
63 acpi_object_type
* object
= (acpi_object_type
*)buf
.pointer
;
64 device
->last_status
= object
->integer
.integer
;
65 device
->updated
= true;
67 TRACE("status %d\n", device
->last_status
);
73 acpi_lid_notify_handler(acpi_handle _device
, uint32 value
, void *context
)
75 acpi_lid_device_info
*device
= (acpi_lid_device_info
*)context
;
76 if (value
== ACPI_NOTIFY_STATUS_CHANGED
) {
77 TRACE("status changed\n");
78 acpi_lid_read_status(device
);
79 if (device
->select_pool
!= NULL
)
80 notify_select_event_pool(device
->select_pool
, B_SELECT_READ
);
82 ERROR("unknown notification\n");
88 // #pragma mark - device module API
92 acpi_lid_init_device(void *driverCookie
, void **cookie
)
94 *cookie
= driverCookie
;
100 acpi_lid_uninit_device(void *_cookie
)
107 acpi_lid_open(void *_cookie
, const char *path
, int flags
, void** cookie
)
109 acpi_lid_device_info
*device
= (acpi_lid_device_info
*)_cookie
;
116 acpi_lid_read(void* _cookie
, off_t position
, void *buf
, size_t* num_bytes
)
118 acpi_lid_device_info
* device
= (acpi_lid_device_info
*)_cookie
;
122 *((uint8
*)(buf
)) = device
->last_status
;
124 device
->updated
= false;
130 acpi_lid_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
)
137 acpi_lid_control(void* _cookie
, uint32 op
, void* arg
, size_t len
)
144 acpi_lid_select(void *_cookie
, uint8 event
, selectsync
*sync
)
146 acpi_lid_device_info
* device
= (acpi_lid_device_info
*)_cookie
;
148 if (event
!= B_SELECT_READ
)
151 // add the event to the pool
152 status_t error
= add_select_sync_pool_entry(&device
->select_pool
, sync
,
155 ERROR("add_select_sync_pool_entry() failed: %#lx\n", error
);
160 notify_select_event(sync
, event
);
167 acpi_lid_deselect(void *_cookie
, uint8 event
, selectsync
*sync
)
169 acpi_lid_device_info
* device
= (acpi_lid_device_info
*)_cookie
;
171 if (event
!= B_SELECT_READ
)
174 return remove_select_sync_pool_entry(&device
->select_pool
, sync
, event
);
179 acpi_lid_close (void* cookie
)
186 acpi_lid_free (void* cookie
)
192 // #pragma mark - driver module API
196 acpi_lid_support(device_node
*parent
)
202 // make sure parent is really the ACPI bus manager
203 if (sDeviceManager
->get_attr_string(parent
, B_DEVICE_BUS
, &bus
, false))
206 if (strcmp(bus
, "acpi"))
209 // check whether it's really a device
210 if (sDeviceManager
->get_attr_uint32(parent
, ACPI_DEVICE_TYPE_ITEM
,
211 &device_type
, false) != B_OK
212 || device_type
!= ACPI_TYPE_DEVICE
) {
216 // check whether it's a lid device
217 if (sDeviceManager
->get_attr_string(parent
, ACPI_DEVICE_HID_ITEM
, &hid
,
218 false) != B_OK
|| strcmp(hid
, "PNP0C0D")) {
222 dprintf("acpi_lid_support lid device found\n");
229 acpi_lid_register_device(device_node
*node
)
231 device_attr attrs
[] = {
232 { B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, { string
: "ACPI Lid" }},
236 return sDeviceManager
->register_node(node
, ACPI_LID_MODULE_NAME
, attrs
,
242 acpi_lid_init_driver(device_node
*node
, void **_driverCookie
)
244 acpi_lid_device_info
*device
;
248 device
= (acpi_lid_device_info
*)calloc(1, sizeof(*device
));
254 parent
= sDeviceManager
->get_parent_node(node
);
255 sDeviceManager
->get_driver(parent
, (driver_module_info
**)&device
->acpi
,
256 (void **)&device
->acpi_cookie
);
257 sDeviceManager
->put_node(parent
);
259 status
= device
->acpi
->install_notify_handler(device
->acpi_cookie
, ACPI_DEVICE_NOTIFY
,
260 acpi_lid_notify_handler
, device
);
261 if (status
!= B_OK
) {
262 ERROR("can't install notify handler\n");
265 device
->last_status
= 0;
266 device
->updated
= false;
267 device
->select_pool
= NULL
;
269 *_driverCookie
= device
;
275 acpi_lid_uninit_driver(void *driverCookie
)
277 acpi_lid_device_info
*device
= (acpi_lid_device_info
*)driverCookie
;
279 device
->acpi
->remove_notify_handler(device
->acpi_cookie
, ACPI_DEVICE_NOTIFY
,
280 acpi_lid_notify_handler
);
287 acpi_lid_register_child_devices(void *_cookie
)
289 acpi_lid_device_info
*device
= (acpi_lid_device_info
*)_cookie
;
293 path_id
= sDeviceManager
->create_id(ACPI_LID_PATHID_GENERATOR
);
295 ERROR("register_child_devices: couldn't create a path_id\n");
299 snprintf(name
, sizeof(name
), ACPI_LID_BASENAME
, path_id
);
301 return sDeviceManager
->publish_device(device
->node
, name
,
302 ACPI_LID_DEVICE_MODULE_NAME
);
306 module_dependency module_dependencies
[] = {
307 { B_DEVICE_MANAGER_MODULE_NAME
, (module_info
**)&sDeviceManager
},
312 driver_module_info acpi_lid_driver_module
= {
314 ACPI_LID_MODULE_NAME
,
320 acpi_lid_register_device
,
321 acpi_lid_init_driver
,
322 acpi_lid_uninit_driver
,
323 acpi_lid_register_child_devices
,
329 struct device_module_info acpi_lid_device_module
= {
331 ACPI_LID_DEVICE_MODULE_NAME
,
336 acpi_lid_init_device
,
337 acpi_lid_uninit_device
,
351 module_info
*modules
[] = {
352 (module_info
*)&acpi_lid_driver_module
,
353 (module_info
*)&acpi_lid_device_module
,