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