1/*
2 * Copyright 2008, Haiku, Inc. All Rights Reserved.
3 *
4 * Distributed under the terms of the MIT License.
5 */
6
7#include <KernelExport.h>
8#include <Drivers.h>
9#include <Errors.h>
10#include <string.h>
11
12#include <stdio.h>
13#include <stdlib.h>
14
15#include <ACPI.h>
16#include "acpi_lid.h"
17
18#define ACPI_LID_MODULE_NAME "drivers/power/acpi_lid/driver_v1"
19
20#define ACPI_LID_DEVICE_MODULE_NAME "drivers/power/acpi_lid/device_v1"
21
22/* Base Namespace devices are published to */
23#define ACPI_LID_BASENAME "power/acpi_lid/%d"
24
25// name of pnp generator of path ids
26#define ACPI_LID_PATHID_GENERATOR "acpi_lid/path_id"
27
28static device_manager_info *sDeviceManager;
29
30typedef struct acpi_ns_device_info {
31	device_node *node;
32	acpi_device_module_info *acpi;
33	acpi_device acpi_cookie;
34} acpi_lid_device_info;
35
36
37//	#pragma mark - device module API
38
39
40static status_t
41acpi_lid_init_device(void *_cookie, void **cookie)
42{
43	device_node *node = (device_node *)_cookie;
44	acpi_lid_device_info *device;
45	device_node *parent;
46
47	device = (acpi_lid_device_info *)calloc(1, sizeof(*device));
48	if (device == NULL)
49		return B_NO_MEMORY;
50
51	device->node = node;
52
53	parent = sDeviceManager->get_parent_node(node);
54	sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
55		(void **)&device->acpi_cookie);
56	sDeviceManager->put_node(parent);
57
58	*cookie = device;
59	return B_OK;
60}
61
62
63static void
64acpi_lid_uninit_device(void *_cookie)
65{
66	acpi_lid_device_info *device = (acpi_lid_device_info *)_cookie;
67	free(device);
68}
69
70
71static status_t
72acpi_lid_open(void *_cookie, const char *path, int flags, void** cookie)
73{
74	acpi_lid_device_info *device = (acpi_lid_device_info *)_cookie;
75	*cookie = device;
76	return B_OK;
77}
78
79
80static status_t
81acpi_lid_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
82{
83	return B_ERROR;
84}
85
86
87static status_t
88acpi_lid_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
89{
90	return B_ERROR;
91}
92
93
94static status_t
95acpi_lid_control(void* _cookie, uint32 op, void* arg, size_t len)
96{
97	acpi_lid_device_info* device = (acpi_lid_device_info*)_cookie;
98
99	return B_ERROR;
100}
101
102
103static status_t
104acpi_lid_close (void* cookie)
105{
106	return B_OK;
107}
108
109
110static status_t
111acpi_lid_free (void* cookie)
112{
113	return B_OK;
114}
115
116
117//	#pragma mark - driver module API
118
119
120static float
121acpi_lid_support(device_node *parent)
122{
123	const char *bus;
124	uint32 device_type;
125	const char *hid;
126
127	dprintf("acpi_lid_support\n");
128
129	// make sure parent is really the ACPI bus manager
130	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
131		return -1;
132
133	if (strcmp(bus, "acpi"))
134		return 0.0;
135
136	// check whether it's really a device
137	if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, &device_type, false) != B_OK
138		|| device_type != ACPI_TYPE_DEVICE) {
139		return 0.0;
140	}
141
142	// check whether it's a lid device
143	if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &hid, false) != B_OK
144		|| strcmp(hid, "PNP0C0D")) {
145		return 0.0;
146	}
147
148	return 0.6;
149}
150
151
152static status_t
153acpi_lid_register_device(device_node *node)
154{
155	device_attr attrs[] = {
156		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI Lid" }},
157		{ NULL }
158	};
159
160	return sDeviceManager->register_node(node, ACPI_LID_MODULE_NAME, attrs, NULL, NULL);
161}
162
163
164static status_t
165acpi_lid_init_driver(device_node *node, void **_driverCookie)
166{
167	*_driverCookie = node;
168	return B_OK;
169}
170
171
172static void
173acpi_lid_uninit_driver(void *driverCookie)
174{
175}
176
177
178static status_t
179acpi_lid_register_child_devices(void *_cookie)
180{
181	device_node *node = _cookie;
182	int path_id;
183	char name[128];
184
185	dprintf("acpi_lid_register_child_devices\n");
186
187	path_id = sDeviceManager->create_id(ACPI_LID_PATHID_GENERATOR);
188	if (path_id < 0) {
189		dprintf("acpi_lid_register_child_devices: couldn't create a path_id\n");
190		return B_ERROR;
191	}
192
193	snprintf(name, sizeof(name), ACPI_LID_BASENAME, path_id);
194
195	return sDeviceManager->publish_device(node, name, ACPI_LID_DEVICE_MODULE_NAME);
196}
197
198
199module_dependency module_dependencies[] = {
200	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
201	{}
202};
203
204
205driver_module_info acpi_lid_driver_module = {
206	{
207		ACPI_LID_MODULE_NAME,
208		0,
209		NULL
210	},
211
212	acpi_lid_support,
213	acpi_lid_register_device,
214	acpi_lid_init_driver,
215	acpi_lid_uninit_driver,
216	acpi_lid_register_child_devices,
217	NULL,	// rescan
218	NULL,	// removed
219};
220
221
222struct device_module_info acpi_lid_device_module = {
223	{
224		ACPI_LID_DEVICE_MODULE_NAME,
225		0,
226		NULL
227	},
228
229	acpi_lid_init_device,
230	acpi_lid_uninit_device,
231	NULL,
232
233	acpi_lid_open,
234	acpi_lid_close,
235	acpi_lid_free,
236	acpi_lid_read,
237	acpi_lid_write,
238	NULL,
239	acpi_lid_control,
240
241	NULL,
242	NULL
243};
244
245module_info *modules[] = {
246	(module_info *)&acpi_lid_driver_module,
247	(module_info *)&acpi_lid_device_module,
248	NULL
249};
250