1#include <KernelExport.h>
2#include <Drivers.h>
3#include <Errors.h>
4#include <string.h>
5
6#include <stdio.h>
7#include <stdlib.h>
8
9#include <ACPI.h>
10
11
12#define DISPLAYCONTROLS_MODULE_NAME "drivers/display/display_controls/driver_v1"
13
14#define DISPLAYCONTROLS_DEVICE_MODULE_NAME "drivers/display/display_controls/device_v1"
15
16/* Base Namespace devices are published to */
17#define DISPLAYCONTROLS_BASENAME "display/display_controls/%d"
18
19// name of pnp generator of path ids
20#define DISPLAYCONTROLS_PATHID_GENERATOR "displaycontrols/path_id"
21
22
23#define OS_DISPLAY_SWITCH 0
24#define BIOS_DISPLAY_SWITCH 1
25#define LOCK_DISPLAY_SWITCH 2
26#define NOTIFY_DISPLAY_SWITCH 3
27
28#define OS_BRIGHTNESS_CONTROL (1 << 2)
29#define BIOS_BRIGHTNESS_CONTROL (0 << 2)
30
31static device_manager_info *sDeviceManager;
32static acpi_module_info *sAcpi;
33
34
35typedef struct acpi_ns_device_info {
36	device_node *node;
37	acpi_handle acpi_device;
38} displaycontrols_device_info;
39
40
41//	#pragma mark - device module API
42
43
44static status_t
45displaycontrols_init_device(void *_cookie, void **cookie)
46{
47	device_node *node = (device_node *)_cookie;
48	displaycontrols_device_info *device;
49	device_node *parent;
50
51	acpi_objects arguments;
52	acpi_object_type argument;
53
54	const char *path;
55	dprintf("%s: start.\n", __func__);
56
57
58	device = (displaycontrols_device_info *)calloc(1, sizeof(*device));
59	if (device == NULL)
60		return B_NO_MEMORY;
61
62	device->node = node;
63	if (sDeviceManager->get_attr_string(node, ACPI_DEVICE_PATH_ITEM, &path, false)
64			!= B_OK || sAcpi->get_handle(NULL, path, &device->acpi_device) != B_OK) {
65		dprintf("%s: failed to get acpi node.\n", __func__);
66		return B_ERROR;
67	}
68
69	argument.object_type = ACPI_TYPE_INTEGER;
70	argument.data.integer = BIOS_DISPLAY_SWITCH | BIOS_BRIGHTNESS_CONTROL;
71	arguments.count = 1;
72	arguments.pointer = &argument;
73	if (sAcpi->evaluate_object(&device->acpi_device, "_DOS", &arguments, NULL, 0)
74			!= B_OK)
75		dprintf("%s: failed to set _DOS %s\n", __func__, path);
76
77	dprintf("%s: done.\n", __func__);
78	*cookie = device;
79	return B_OK;
80}
81
82
83static void
84displaycontrols_uninit_device(void *_cookie)
85{
86	displaycontrols_device_info *device = (displaycontrols_device_info *)_cookie;
87	free(device);
88}
89
90
91static status_t
92displaycontrols_open(void *_cookie, const char *path, int flags, void** cookie)
93{
94	displaycontrols_device_info *device = (displaycontrols_device_info *)_cookie;
95	*cookie = device;
96	return B_OK;
97}
98
99
100static status_t
101displaycontrols_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
102{
103	return B_ERROR;
104}
105
106
107static status_t
108displaycontrols_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
109{
110	return B_ERROR;
111}
112
113
114static status_t
115displaycontrols_control(void* _cookie, uint32 op, void* arg, size_t len)
116{
117//	displaycontrols_device_info* device = (displaycontrols_device_info*)_cookie;
118
119	return B_ERROR;
120}
121
122
123static status_t
124displaycontrols_close(void* cookie)
125{
126	return B_OK;
127}
128
129
130static status_t
131displaycontrols_free(void* cookie)
132{
133	return B_OK;
134}
135
136
137//	#pragma mark - driver module API
138
139
140static float
141displaycontrols_support(device_node *parent)
142{
143	acpi_handle handle, method;
144//	acpi_object_type dosType;
145
146	const char *bus;
147	const char *path;
148	uint32 device_type;
149
150	// make sure parent is really the ACPI bus manager
151	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
152		return -1;
153
154	if (strcmp(bus, "acpi"))
155		return 0.0;
156
157	if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_PATH_ITEM, &path, false) != B_OK)
158		return 0.0;
159
160	// check whether it's really a device
161	if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, &device_type, false) != B_OK
162		|| device_type != ACPI_TYPE_DEVICE) {
163		return 0.0;
164	}
165
166
167	if (sAcpi->get_handle(NULL, path, &handle) != B_OK)
168		return 0.0;
169
170	if (sAcpi->get_handle(handle, "_DOD", &method) != B_OK ||
171		sAcpi->get_handle(handle, "_DOS", &method) != B_OK) {// ||
172//		sAcpi->get_type(method, &dosType) != B_OK ||
173//		dosType != ACPI_TYPE_METHOD) {
174		return 0.0;
175	}
176
177	dprintf("%s: found at bus: %s path: %s\n", __func__, bus, path);
178	return 0.6;
179}
180
181
182static status_t
183displaycontrols_register_device(device_node *node)
184{
185	device_attr attrs[] = {
186		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "Display Controls" }},
187		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_KEEP_DRIVER_LOADED }},
188		{ NULL }
189	};
190
191	return sDeviceManager->register_node(node, DISPLAYCONTROLS_MODULE_NAME, attrs, NULL, NULL);
192}
193
194
195static status_t
196displaycontrols_init_driver(device_node *node, void **_driverCookie)
197{
198	*_driverCookie = node;
199	return B_OK;
200}
201
202
203static void
204displaycontrols_uninit_driver(void *driverCookie)
205{
206}
207
208
209static status_t
210displaycontrols_register_child_devices(void *_cookie)
211{
212	device_node *node = (device_node*)_cookie;
213	int path_id;
214	char name[128];
215
216	path_id = sDeviceManager->create_id(DISPLAYCONTROLS_PATHID_GENERATOR);
217	if (path_id < 0) {
218		dprintf("displaycontrols_register_child_devices: couldn't create a path_id\n");
219		return B_ERROR;
220	}
221
222	snprintf(name, sizeof(name), DISPLAYCONTROLS_BASENAME, path_id);
223
224	return sDeviceManager->publish_device(node, name, DISPLAYCONTROLS_DEVICE_MODULE_NAME);
225}
226
227
228module_dependency module_dependencies[] = {
229	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
230	{ B_ACPI_MODULE_NAME, (module_info **)&sAcpi},
231	{}
232};
233
234
235driver_module_info displaycontrols_driver_module = {
236	{
237		DISPLAYCONTROLS_MODULE_NAME,
238		0,
239		NULL
240	},
241
242	displaycontrols_support,
243	displaycontrols_register_device,
244	displaycontrols_init_driver,
245	displaycontrols_uninit_driver,
246	displaycontrols_register_child_devices,
247	NULL,	// rescan
248	NULL,	// removed
249};
250
251
252struct device_module_info displaycontrols_device_module = {
253	{
254		DISPLAYCONTROLS_DEVICE_MODULE_NAME,
255		0,
256		NULL
257	},
258
259	displaycontrols_init_device,
260	displaycontrols_uninit_device,
261	NULL,
262
263	displaycontrols_open,
264	displaycontrols_close,
265	displaycontrols_free,
266	displaycontrols_read,
267	displaycontrols_write,
268	NULL,
269	displaycontrols_control,
270
271	NULL,
272	NULL
273};
274
275module_info *modules[] = {
276	(module_info *)&displaycontrols_driver_module,
277	(module_info *)&displaycontrols_device_module,
278	NULL
279};
280