1 #include "display_adapter.h" 2 3 4 typedef struct acpi_ns_device_info { 5 device_node *node; 6 acpi_handle acpi_device; 7 } displayadapter_device_info; 8 9 10 device_manager_info *gDeviceManager = NULL; 11 acpi_module_info *gAcpi = NULL; 12 13 14 /* 15 16 TODO: ACPI Spec 5 Appendix B: Implement: 17 _DOS Method to control display output switching 18 ( _DOD Method to retrieve information about child output devices 19 - You can already do this by listing child devices ) 20 _ROM Method to retrieve the ROM image for this device 21 _GPD Method for determining which VGA device will post 22 _SPD Method for controlling which VGA device will post 23 _VPO Method for determining the post options 24 25 Display cycling notifications 26 27 */ 28 29 30 // #pragma mark - device module API 31 32 33 static status_t 34 displayadapter_init_device(void *_cookie, void **cookie) 35 { 36 device_node *node = (device_node *)_cookie; 37 displayadapter_device_info *device; 38 // device_node *parent; 39 40 // acpi_objects arguments; 41 // acpi_object_type argument; 42 43 const char *path; 44 dprintf("%s: start.\n", __func__); 45 46 47 device = (displayadapter_device_info *)calloc(1, sizeof(*device)); 48 if (device == NULL) 49 return B_NO_MEMORY; 50 51 device->node = node; 52 if (gDeviceManager->get_attr_string(node, ACPI_DEVICE_PATH_ITEM, &path, 53 false) != B_OK 54 || gAcpi->get_handle(NULL, path, &device->acpi_device) != B_OK) { 55 dprintf("%s: failed to get acpi node.\n", __func__); 56 free(device); 57 return B_ERROR; 58 } 59 /* 60 argument.object_type = ACPI_TYPE_INTEGER; 61 argument.integer.integer = BIOS_DISPLAY_SWITCH | BIOS_BRIGHTNESS_CONTROL; 62 arguments.count = 1; 63 arguments.pointer = &argument; 64 if (gAcpi->evaluate_object(&device->acpi_device, "_DOS", &arguments, NULL, 65 0) != B_OK) 66 dprintf("%s: failed to set _DOS %s\n", __func__, path); 67 68 dprintf("%s: done.\n", __func__); 69 */ 70 *cookie = device; 71 return B_OK; 72 } 73 74 75 static void 76 displayadapter_uninit_device(void *_cookie) 77 { 78 displayadapter_device_info *device = (displayadapter_device_info *)_cookie; 79 free(device); 80 } 81 82 83 static status_t 84 displayadapter_open(void *_cookie, const char *path, int flags, void** cookie) 85 { 86 displayadapter_device_info *device = (displayadapter_device_info *)_cookie; 87 *cookie = device; 88 return B_OK; 89 } 90 91 92 static status_t 93 displayadapter_read(void* _cookie, off_t position, void *buf, size_t* num_bytes) 94 { 95 return B_ERROR; 96 } 97 98 99 static status_t 100 displayadapter_write(void* cookie, off_t position, const void* buffer, 101 size_t* num_bytes) 102 { 103 return B_ERROR; 104 } 105 106 107 static status_t 108 displayadapter_control(void* _cookie, uint32 op, void* arg, size_t len) 109 { 110 // displayadapter_device_info* device = (displayadapter_device_info*)_cookie; 111 112 return B_ERROR; 113 } 114 115 116 static status_t 117 displayadapter_close(void* cookie) 118 { 119 return B_OK; 120 } 121 122 123 static status_t 124 displayadapter_free(void* cookie) 125 { 126 return B_OK; 127 } 128 129 130 // #pragma mark - driver module API 131 132 133 static float 134 displayadapter_support(device_node *parent) 135 { 136 acpi_handle handle, method; 137 // acpi_object_type dosType; 138 139 const char *bus; 140 const char *path; 141 uint32 device_type; 142 143 // make sure parent is really the ACPI bus manager 144 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 145 return -1; 146 147 if (strcmp(bus, "acpi")) 148 return 0.0; 149 150 if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_PATH_ITEM, &path, 151 false) != B_OK) 152 return 0.0; 153 154 // check whether it's really a device 155 if (gDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, 156 &device_type, false) != B_OK 157 || device_type != ACPI_TYPE_DEVICE) { 158 return 0.0; 159 } 160 161 162 if (gAcpi->get_handle(NULL, path, &handle) != B_OK) 163 return 0.0; 164 165 if (gAcpi->get_handle(handle, "_DOD", &method) != B_OK || 166 gAcpi->get_handle(handle, "_DOS", &method) != B_OK) {// || 167 // sAcpi->get_type(method, &dosType) != B_OK || 168 // dosType != ACPI_TYPE_METHOD) { 169 return 0.0; 170 } 171 172 dprintf("%s: found at bus: %s path: %s\n", __func__, bus, path); 173 return 0.6; 174 } 175 176 177 static status_t 178 register_displays(const char *parentName, device_node *node) 179 { 180 acpi_handle acpiHandle; 181 const char *path; 182 device_node *parent = gDeviceManager->get_parent_node(node); 183 if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_PATH_ITEM, &path, 184 false) != B_OK 185 || gAcpi->get_handle(NULL, path, &acpiHandle) != B_OK) { 186 dprintf("%s: failed to get acpi node.\n", __func__); 187 gDeviceManager->put_node(parent); 188 return B_ERROR; 189 } 190 191 //get list of ids from _DOD 192 acpi_object_type *pkgData = (acpi_object_type *)malloc(128); 193 if (pkgData == NULL) 194 return B_ERROR; 195 196 status_t status = gAcpi->evaluate_object(acpiHandle, "_DOD", NULL, pkgData, 197 128); 198 if (status != B_OK || pkgData->object_type != ACPI_TYPE_PACKAGE) { 199 dprintf("%s: fail. %ld %lu\n", __func__, status, pkgData->object_type); 200 free(pkgData); 201 return status; 202 } 203 204 acpi_object_type *displayIDs = pkgData->package.objects; 205 for (uint32 i = 0; i < pkgData->package.count; i++) { 206 dprintf("Display ID = %lld\n", displayIDs[i].integer.integer); 207 } 208 209 acpi_object_type result; 210 acpi_handle child = NULL; 211 while (gAcpi->get_next_object(ACPI_TYPE_DEVICE, acpiHandle, &child) 212 == B_OK) { 213 char name[5] = {0}; 214 //TODO: HARDCODED type. 215 if(gAcpi->get_name(child, 1, name, 5) == B_OK) 216 dprintf("name: %s\n", name); 217 if (gAcpi->evaluate_object(child, "_ADR", NULL, &result, sizeof(result)) 218 != B_OK) 219 continue; 220 221 dprintf("Child _adr %llu\n", result.integer.integer); 222 uint32 i; 223 for (i = 0; i < pkgData->package.count; i++) 224 if (displayIDs[i].integer.integer == result.integer.integer) break; 225 226 if (i == pkgData->package.count) continue; 227 228 device_attr attrs[] = { 229 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = name }}, 230 { B_DEVICE_FLAGS, B_UINT32_TYPE, { .ui32 = B_KEEP_DRIVER_LOADED }}, 231 { NULL } 232 233 }; 234 235 device_node* deviceNode; 236 gDeviceManager->register_node(node, DISPLAY_DEVICE_MODULE_NAME, attrs, 237 NULL, &deviceNode); 238 239 char deviceName[128]; 240 snprintf(deviceName, sizeof(deviceName), "%s/%s", parentName, name); 241 gDeviceManager->publish_device(parent, deviceName, 242 DISPLAY_DEVICE_MODULE_NAME); 243 244 } 245 gDeviceManager->put_node(parent); 246 free(pkgData); 247 return B_OK; 248 } 249 250 251 static status_t 252 displayadapter_register_device(device_node *node) 253 { 254 device_attr attrs[] = { 255 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "Display Adapter" }}, 256 { B_DEVICE_FLAGS, B_UINT32_TYPE, { 257 .ui32 = B_KEEP_DRIVER_LOADED | B_FIND_MULTIPLE_CHILDREN }}, 258 { NULL } 259 }; 260 261 return gDeviceManager->register_node(node, DISPLAYADAPTER_MODULE_NAME, 262 attrs, NULL, NULL); 263 } 264 265 266 static status_t 267 displayadapter_init_driver(device_node *node, void **_driverCookie) 268 { 269 *_driverCookie = node; 270 return B_OK; 271 } 272 273 274 static void 275 displayadapter_uninit_driver(void *driverCookie) 276 { 277 } 278 279 280 static status_t 281 displayadapter_register_child_devices(void *_cookie) 282 { 283 device_node *node = (device_node*)_cookie; 284 285 int path_id = gDeviceManager->create_id(DISPLAYADAPTER_PATHID_GENERATOR); 286 if (path_id < 0) { 287 dprintf("displayadapter_register_child_devices: error creating path\n"); 288 return B_ERROR; 289 } 290 291 char name[128]; 292 snprintf(name, sizeof(name), DISPLAYADAPTER_BASENAME, path_id); 293 status_t status = gDeviceManager->publish_device(node, name, 294 DISPLAYADAPTER_DEVICE_MODULE_NAME); 295 296 if (status == B_OK) 297 register_displays(name, node); 298 299 return status; 300 } 301 302 303 module_dependency module_dependencies[] = { 304 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 305 { B_ACPI_MODULE_NAME, (module_info **)&gAcpi}, 306 {} 307 }; 308 309 310 driver_module_info displayadapter_driver_module = { 311 { 312 DISPLAYADAPTER_MODULE_NAME, 313 0, 314 NULL 315 }, 316 317 displayadapter_support, 318 displayadapter_register_device, 319 displayadapter_init_driver, 320 displayadapter_uninit_driver, 321 displayadapter_register_child_devices, 322 NULL, // rescan 323 NULL, // removed 324 }; 325 326 327 device_module_info displayadapter_device_module = { 328 { 329 DISPLAYADAPTER_DEVICE_MODULE_NAME, 330 0, 331 NULL 332 }, 333 334 displayadapter_init_device, 335 displayadapter_uninit_device, 336 NULL, 337 338 displayadapter_open, 339 displayadapter_close, 340 displayadapter_free, 341 displayadapter_read, 342 displayadapter_write, 343 NULL, 344 displayadapter_control, 345 346 NULL, 347 NULL 348 }; 349 350 351 module_info *modules[] = { 352 (module_info *)&display_device_module, 353 (module_info *)&displayadapter_device_module, 354 (module_info *)&displayadapter_driver_module, 355 NULL 356 }; 357