1 /* 2 * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com. 3 * Distributed under the terms of the MIT license. 4 */ 5 6 7 #define DRIVER_NAME "wmi_asus" 8 #include "WMIPrivate.h" 9 10 11 #define ACPI_ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66" 12 #define ACPI_ASUS_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" 13 #define ACPI_ASUS_UID_ASUSWMI "ASUSWMI" 14 15 #define ASUS_WMI_METHODID_INIT 0x54494E49 16 #define ASUS_WMI_METHODID_SPEC 0x43455053 17 #define ASUS_WMI_METHODID_SFUN 0x4E554653 18 #define ASUS_WMI_METHODID_DCTS 0x53544344 19 #define ASUS_WMI_METHODID_DSTS 0x53545344 20 #define ASUS_WMI_METHODID_DEVS 0x53564544 21 22 #define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012 23 #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 24 25 26 class WMIAsus { 27 public: 28 WMIAsus(device_node *node); 29 ~WMIAsus(); 30 31 private: 32 status_t _EvaluateMethod(uint32 methodId, uint32 arg0, 33 uint32 arg1, uint32 *returnValue); 34 status_t _GetDevState(uint32 devId, uint32* value); 35 status_t _SetDevState(uint32 devId, uint32 arg, 36 uint32* value); 37 static void _NotifyHandler(acpi_handle handle, 38 uint32 notify, void *context); 39 void _Notify(acpi_handle handle, uint32 notify); 40 private: 41 device_node* fNode; 42 wmi_device_interface* wmi; 43 wmi_device wmi_cookie; 44 uint32 fDstsID; 45 const char* fEventGuidString; 46 }; 47 48 49 50 WMIAsus::WMIAsus(device_node *node) 51 : 52 fNode(node), 53 fDstsID(ASUS_WMI_METHODID_DSTS), 54 fEventGuidString(NULL) 55 { 56 CALLED(); 57 58 device_node *parent; 59 parent = gDeviceManager->get_parent_node(node); 60 gDeviceManager->get_driver(parent, (driver_module_info **)&wmi, 61 (void **)&wmi_cookie); 62 63 gDeviceManager->put_node(parent); 64 65 const char* uid = wmi->get_uid(wmi_cookie); 66 if (uid != NULL && strcmp(uid, ACPI_ASUS_UID_ASUSWMI) == 0) 67 fDstsID = ASUS_WMI_METHODID_DCTS; 68 TRACE("WMIAsus using _UID %s\n", uid); 69 uint32 value; 70 if (_EvaluateMethod(ASUS_WMI_METHODID_INIT, 0, 0, &value) == B_OK) { 71 TRACE("_INIT: %x\n", value); 72 } 73 if (_EvaluateMethod(ASUS_WMI_METHODID_SPEC, 0, 9, &value) == B_OK) { 74 TRACE("_SPEC: %x\n", value); 75 } 76 if (_EvaluateMethod(ASUS_WMI_METHODID_SFUN, 0, 0, &value) == B_OK) { 77 TRACE("_SFUN: %x\n", value); 78 } 79 80 // install event handler 81 if (wmi->install_event_handler(wmi_cookie, ACPI_ASUS_WMI_EVENT_GUID, 82 _NotifyHandler, this) == B_OK) { 83 fEventGuidString = ACPI_ASUS_WMI_EVENT_GUID; 84 } 85 } 86 87 88 WMIAsus::~WMIAsus() 89 { 90 if (fEventGuidString != NULL) 91 wmi->remove_event_handler(wmi_cookie, fEventGuidString); 92 } 93 94 95 status_t 96 WMIAsus::_EvaluateMethod(uint32 methodId, uint32 arg0, uint32 arg1, 97 uint32 *returnValue) 98 { 99 CALLED(); 100 uint32 params[] = { arg0, arg1 }; 101 acpi_data inBuffer = { sizeof(params), params }; 102 acpi_data outBuffer = { ACPI_ALLOCATE_BUFFER, NULL }; 103 status_t status = wmi->evaluate_method(wmi_cookie, 0, methodId, &inBuffer, 104 &outBuffer); 105 if (status != B_OK) 106 return status; 107 108 acpi_object_type* object = (acpi_object_type*)outBuffer.pointer; 109 uint32 result = 0; 110 if (object != NULL) { 111 if (object->object_type == ACPI_TYPE_INTEGER) 112 result = object->integer.integer; 113 free(object); 114 } 115 if (returnValue != NULL) 116 *returnValue = result; 117 118 return B_OK; 119 } 120 121 122 status_t 123 WMIAsus::_GetDevState(uint32 devId, uint32 *value) 124 { 125 return _EvaluateMethod(fDstsID, devId, 0, value); 126 } 127 128 129 status_t 130 WMIAsus::_SetDevState(uint32 devId, uint32 arg, uint32 *value) 131 { 132 return _EvaluateMethod(ASUS_WMI_METHODID_DEVS, devId, arg, value); 133 } 134 135 136 void 137 WMIAsus::_NotifyHandler(acpi_handle handle, uint32 notify, void *context) 138 { 139 WMIAsus* device = (WMIAsus*)context; 140 device->_Notify(handle, notify); 141 } 142 143 144 void 145 WMIAsus::_Notify(acpi_handle handle, uint32 notify) 146 { 147 CALLED(); 148 149 acpi_data response = { ACPI_ALLOCATE_BUFFER, NULL }; 150 wmi->get_event_data(wmi_cookie, notify, &response); 151 152 acpi_object_type* object = (acpi_object_type*)response.pointer; 153 uint32 result = 0; 154 if (object != NULL) { 155 if (object->object_type == ACPI_TYPE_INTEGER) 156 result = object->integer.integer; 157 free(object); 158 } 159 if (result != 0) { 160 if (result == 0xc4 || result == 0xc5) { 161 TRACE("WMIAsus::_Notify() keyboard backlight key\n"); 162 uint32 value; 163 if (_GetDevState(ASUS_WMI_DEVID_KBD_BACKLIGHT, &value) == B_OK) { 164 TRACE("WMIAsus::_Notify() getkeyboard backlight key %" 165 B_PRIx32 "\n", value); 166 value &= 0x7; 167 if (result == 0xc4) { 168 if (value < 3) 169 value++; 170 } else if (value > 0) 171 value--; 172 TRACE("WMIAsus::_Notify() set keyboard backlight key %" 173 B_PRIx32 "\n", value); 174 _SetDevState(ASUS_WMI_DEVID_KBD_BACKLIGHT, value | 0x80, NULL); 175 } 176 } else if (result == 0x6b) { 177 TRACE("WMIAsus::_Notify() touchpad control\n"); 178 } else { 179 TRACE("WMIAsus::_Notify() key 0x%" B_PRIx32 "\n", result); 180 } 181 } 182 } 183 184 185 // #pragma mark - driver module API 186 187 188 static float 189 wmi_asus_support(device_node *parent) 190 { 191 // make sure parent is really a wmi device 192 const char *bus; 193 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 194 return -1; 195 196 if (strcmp(bus, "wmi")) 197 return 0.0; 198 199 // check whether it's an asus wmi device 200 const char *guid; 201 if (gDeviceManager->get_attr_string(parent, WMI_GUID_STRING_ITEM, &guid, 202 false) != B_OK || strcmp(guid, ACPI_ASUS_WMI_MGMT_GUID) != 0) { 203 return 0.0; 204 } 205 206 TRACE("found an asus wmi device\n"); 207 208 return 0.6; 209 } 210 211 212 static status_t 213 wmi_asus_register_device(device_node *node) 214 { 215 CALLED(); 216 device_attr attrs[] = { 217 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "WMI ASUS" }}, 218 { NULL } 219 }; 220 221 return gDeviceManager->register_node(node, WMI_ASUS_DRIVER_NAME, attrs, 222 NULL, NULL); 223 } 224 225 226 static status_t 227 wmi_asus_init_driver(device_node *node, void **driverCookie) 228 { 229 CALLED(); 230 231 WMIAsus* device = new(std::nothrow) WMIAsus(node); 232 if (device == NULL) 233 return B_NO_MEMORY; 234 *driverCookie = device; 235 236 return B_OK; 237 } 238 239 240 static void 241 wmi_asus_uninit_driver(void *driverCookie) 242 { 243 CALLED(); 244 WMIAsus* device = (WMIAsus*)driverCookie; 245 delete device; 246 } 247 248 249 static status_t 250 wmi_asus_register_child_devices(void *cookie) 251 { 252 CALLED(); 253 return B_OK; 254 } 255 256 257 driver_module_info gWMIAsusDriverModule = { 258 { 259 WMI_ASUS_DRIVER_NAME, 260 0, 261 NULL 262 }, 263 264 wmi_asus_support, 265 wmi_asus_register_device, 266 wmi_asus_init_driver, 267 wmi_asus_uninit_driver, 268 wmi_asus_register_child_devices, 269 NULL, // rescan 270 NULL, // removed 271 }; 272 273