1 /* 2 * Copyright 2013, Jérôme Duval, korli@users.berlios.de. 3 * 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <ACPI.h> 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 15 #define ACPI_AC_MODULE_NAME "drivers/power/acpi_ac/driver_v1" 16 17 #define ACPI_AC_DEVICE_MODULE_NAME "drivers/power/acpi_ac/device_v1" 18 19 /* Base Namespace devices are published to */ 20 #define ACPI_AC_BASENAME "power/acpi_ac/%d" 21 22 // name of pnp generator of path ids 23 #define ACPI_AC_PATHID_GENERATOR "acpi_ac/path_id" 24 25 #define TRACE_AC 26 #ifdef TRACE_AC 27 # define TRACE(x...) dprintf("acpi_ac: " x) 28 #else 29 # define TRACE(x...) 30 #endif 31 #define ERROR(x...) dprintf("acpi_ac: " x) 32 33 static device_manager_info *sDeviceManager; 34 35 36 typedef struct acpi_ns_device_info { 37 device_node *node; 38 acpi_device_module_info *acpi; 39 acpi_device acpi_cookie; 40 uint8 last_status; 41 } acpi_ac_device_info; 42 43 44 static void 45 acpi_ac_notify_handler(acpi_handle device, uint32 value, void *context) 46 { 47 if (value == 0x80) { 48 dprintf("acpi_ac: status changed\n"); 49 } else { 50 dprintf("acpi_ac: unknown notification\n"); 51 } 52 53 } 54 55 56 // #pragma mark - device module API 57 58 59 static status_t 60 acpi_ac_init_device(void *driverCookie, void **cookie) 61 { 62 *cookie = driverCookie; 63 return B_OK; 64 } 65 66 67 static void 68 acpi_ac_uninit_device(void *_cookie) 69 { 70 71 } 72 73 74 static status_t 75 acpi_ac_open(void *_cookie, const char *path, int flags, void** cookie) 76 { 77 acpi_ac_device_info *device = (acpi_ac_device_info *)_cookie; 78 *cookie = device; 79 return B_OK; 80 } 81 82 83 static status_t 84 acpi_ac_read(void* _cookie, off_t position, void *buf, size_t* num_bytes) 85 { 86 acpi_ac_device_info* device = (acpi_ac_device_info*)_cookie; 87 if (*num_bytes < 1) 88 return B_IO_ERROR; 89 90 *((uint8 *)(buf)) = device->last_status; 91 92 *num_bytes = 1; 93 return B_OK; 94 } 95 96 97 static status_t 98 acpi_ac_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) 99 { 100 return B_ERROR; 101 } 102 103 104 static status_t 105 acpi_ac_control(void* _cookie, uint32 op, void* arg, size_t len) 106 { 107 return B_ERROR; 108 } 109 110 111 static status_t 112 acpi_ac_close (void* cookie) 113 { 114 return B_OK; 115 } 116 117 118 static status_t 119 acpi_ac_free (void* cookie) 120 { 121 return B_OK; 122 } 123 124 125 // #pragma mark - driver module API 126 127 128 static float 129 acpi_ac_support(device_node *parent) 130 { 131 const char *bus; 132 uint32 device_type; 133 const char *hid; 134 135 // make sure parent is really the ACPI bus manager 136 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 137 return -1; 138 139 if (strcmp(bus, "acpi")) 140 return 0.0; 141 142 // check whether it's really a device 143 if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, 144 &device_type, false) != B_OK 145 || device_type != ACPI_TYPE_DEVICE) { 146 return 0.0; 147 } 148 149 // check whether it's an ac device 150 if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &hid, 151 false) != B_OK || strcmp(hid, "ACPI0003")) { 152 return 0.0; 153 } 154 155 dprintf("acpi_ac_support ac device found\n"); 156 157 return 0.6; 158 } 159 160 161 static status_t 162 acpi_ac_register_device(device_node *node) 163 { 164 device_attr attrs[] = { 165 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "ACPI AC" }}, 166 { NULL } 167 }; 168 169 return sDeviceManager->register_node(node, ACPI_AC_MODULE_NAME, attrs, 170 NULL, NULL); 171 } 172 173 174 static status_t 175 acpi_ac_init_driver(device_node *node, void **_driverCookie) 176 { 177 acpi_ac_device_info *device; 178 device_node *parent; 179 status_t status; 180 181 device = (acpi_ac_device_info *)calloc(1, sizeof(*device)); 182 if (device == NULL) 183 return B_NO_MEMORY; 184 185 device->node = node; 186 187 parent = sDeviceManager->get_parent_node(node); 188 sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi, 189 (void **)&device->acpi_cookie); 190 sDeviceManager->put_node(parent); 191 192 status = device->acpi->install_notify_handler(device->acpi_cookie, 193 ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, device); 194 if (status != B_OK) { 195 ERROR("can't install notify handler\n"); 196 } 197 198 device->last_status = 0; 199 acpi_data buf; 200 buf.pointer = NULL; 201 buf.length = ACPI_ALLOCATE_BUFFER; 202 if (device->acpi->evaluate_method(device->acpi_cookie, "_PSR", NULL, 203 &buf) != B_OK 204 || buf.pointer == NULL 205 || ((acpi_object_type*)buf.pointer)->object_type != ACPI_TYPE_INTEGER) { 206 ERROR("couldn't get status\n"); 207 } else { 208 acpi_object_type* object = (acpi_object_type*)buf.pointer; 209 device->last_status = object->integer.integer; 210 free(buf.pointer); 211 TRACE("status %d\n", device->last_status); 212 } 213 214 *_driverCookie = device; 215 return B_OK; 216 } 217 218 219 static void 220 acpi_ac_uninit_driver(void *driverCookie) 221 { 222 acpi_ac_device_info *device = (acpi_ac_device_info *)driverCookie; 223 224 device->acpi->remove_notify_handler(device->acpi_cookie, 225 ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler); 226 227 free(device); 228 } 229 230 231 static status_t 232 acpi_ac_register_child_devices(void *driverCookie) 233 { 234 acpi_ac_device_info *device = (acpi_ac_device_info *)driverCookie; 235 int path_id; 236 char name[128]; 237 238 path_id = sDeviceManager->create_id(ACPI_AC_PATHID_GENERATOR); 239 if (path_id < 0) { 240 ERROR("register_child_devices: couldn't create a path_id\n"); 241 return B_ERROR; 242 } 243 244 snprintf(name, sizeof(name), ACPI_AC_BASENAME, path_id); 245 246 return sDeviceManager->publish_device(device->node, name, 247 ACPI_AC_DEVICE_MODULE_NAME); 248 } 249 250 251 module_dependency module_dependencies[] = { 252 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, 253 {} 254 }; 255 256 257 driver_module_info acpi_ac_driver_module = { 258 { 259 ACPI_AC_MODULE_NAME, 260 0, 261 NULL 262 }, 263 264 acpi_ac_support, 265 acpi_ac_register_device, 266 acpi_ac_init_driver, 267 acpi_ac_uninit_driver, 268 acpi_ac_register_child_devices, 269 NULL, // rescan 270 NULL, // removed 271 }; 272 273 274 struct device_module_info acpi_ac_device_module = { 275 { 276 ACPI_AC_DEVICE_MODULE_NAME, 277 0, 278 NULL 279 }, 280 281 acpi_ac_init_device, 282 acpi_ac_uninit_device, 283 NULL, 284 285 acpi_ac_open, 286 acpi_ac_close, 287 acpi_ac_free, 288 acpi_ac_read, 289 acpi_ac_write, 290 NULL, 291 acpi_ac_control, 292 293 NULL, 294 NULL 295 }; 296 297 module_info *modules[] = { 298 (module_info *)&acpi_ac_driver_module, 299 (module_info *)&acpi_ac_device_module, 300 NULL 301 }; 302