Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.19-rc1 1036 lines 25 kB view raw
1/* 2 * HP WMI hotkeys 3 * 4 * Copyright (C) 2008 Red Hat <mjg@redhat.com> 5 * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi> 6 * 7 * Portions based on wistron_btns.c: 8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> 10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 */ 26 27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 28 29#include <linux/kernel.h> 30#include <linux/module.h> 31#include <linux/init.h> 32#include <linux/slab.h> 33#include <linux/types.h> 34#include <linux/input.h> 35#include <linux/input/sparse-keymap.h> 36#include <linux/platform_device.h> 37#include <linux/acpi.h> 38#include <linux/rfkill.h> 39#include <linux/string.h> 40 41MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>"); 42MODULE_DESCRIPTION("HP laptop WMI hotkeys driver"); 43MODULE_LICENSE("GPL"); 44 45MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C"); 46MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); 47 48#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" 49#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4" 50 51enum hp_wmi_radio { 52 HPWMI_WIFI = 0x0, 53 HPWMI_BLUETOOTH = 0x1, 54 HPWMI_WWAN = 0x2, 55 HPWMI_GPS = 0x3, 56}; 57 58enum hp_wmi_event_ids { 59 HPWMI_DOCK_EVENT = 0x01, 60 HPWMI_PARK_HDD = 0x02, 61 HPWMI_SMART_ADAPTER = 0x03, 62 HPWMI_BEZEL_BUTTON = 0x04, 63 HPWMI_WIRELESS = 0x05, 64 HPWMI_CPU_BATTERY_THROTTLE = 0x06, 65 HPWMI_LOCK_SWITCH = 0x07, 66 HPWMI_LID_SWITCH = 0x08, 67 HPWMI_SCREEN_ROTATION = 0x09, 68 HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A, 69 HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B, 70 HPWMI_PROXIMITY_SENSOR = 0x0C, 71 HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D, 72 HPWMI_PEAKSHIFT_PERIOD = 0x0F, 73 HPWMI_BATTERY_CHARGE_PERIOD = 0x10, 74}; 75 76struct bios_args { 77 u32 signature; 78 u32 command; 79 u32 commandtype; 80 u32 datasize; 81 u32 data; 82}; 83 84enum hp_wmi_commandtype { 85 HPWMI_DISPLAY_QUERY = 0x01, 86 HPWMI_HDDTEMP_QUERY = 0x02, 87 HPWMI_ALS_QUERY = 0x03, 88 HPWMI_HARDWARE_QUERY = 0x04, 89 HPWMI_WIRELESS_QUERY = 0x05, 90 HPWMI_BATTERY_QUERY = 0x07, 91 HPWMI_BIOS_QUERY = 0x09, 92 HPWMI_FEATURE_QUERY = 0x0b, 93 HPWMI_HOTKEY_QUERY = 0x0c, 94 HPWMI_FEATURE2_QUERY = 0x0d, 95 HPWMI_WIRELESS2_QUERY = 0x1b, 96 HPWMI_POSTCODEERROR_QUERY = 0x2a, 97}; 98 99enum hp_wmi_command { 100 HPWMI_READ = 0x01, 101 HPWMI_WRITE = 0x02, 102 HPWMI_ODM = 0x03, 103}; 104 105enum hp_wmi_hardware_mask { 106 HPWMI_DOCK_MASK = 0x01, 107 HPWMI_TABLET_MASK = 0x04, 108}; 109 110struct bios_return { 111 u32 sigpass; 112 u32 return_code; 113}; 114 115enum hp_return_value { 116 HPWMI_RET_WRONG_SIGNATURE = 0x02, 117 HPWMI_RET_UNKNOWN_COMMAND = 0x03, 118 HPWMI_RET_UNKNOWN_CMDTYPE = 0x04, 119 HPWMI_RET_INVALID_PARAMETERS = 0x05, 120}; 121 122enum hp_wireless2_bits { 123 HPWMI_POWER_STATE = 0x01, 124 HPWMI_POWER_SOFT = 0x02, 125 HPWMI_POWER_BIOS = 0x04, 126 HPWMI_POWER_HARD = 0x08, 127}; 128 129#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \ 130 != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) 131#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) 132 133struct bios_rfkill2_device_state { 134 u8 radio_type; 135 u8 bus_type; 136 u16 vendor_id; 137 u16 product_id; 138 u16 subsys_vendor_id; 139 u16 subsys_product_id; 140 u8 rfkill_id; 141 u8 power; 142 u8 unknown[4]; 143}; 144 145/* 7 devices fit into the 128 byte buffer */ 146#define HPWMI_MAX_RFKILL2_DEVICES 7 147 148struct bios_rfkill2_state { 149 u8 unknown[7]; 150 u8 count; 151 u8 pad[8]; 152 struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES]; 153}; 154 155static const struct key_entry hp_wmi_keymap[] = { 156 { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } }, 157 { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } }, 158 { KE_KEY, 0x20e6, { KEY_PROG1 } }, 159 { KE_KEY, 0x20e8, { KEY_MEDIA } }, 160 { KE_KEY, 0x2142, { KEY_MEDIA } }, 161 { KE_KEY, 0x213b, { KEY_INFO } }, 162 { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } }, 163 { KE_KEY, 0x216a, { KEY_SETUP } }, 164 { KE_KEY, 0x231b, { KEY_HELP } }, 165 { KE_END, 0 } 166}; 167 168static struct input_dev *hp_wmi_input_dev; 169static struct platform_device *hp_wmi_platform_dev; 170 171static struct rfkill *wifi_rfkill; 172static struct rfkill *bluetooth_rfkill; 173static struct rfkill *wwan_rfkill; 174 175struct rfkill2_device { 176 u8 id; 177 int num; 178 struct rfkill *rfkill; 179}; 180 181static int rfkill2_count; 182static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; 183 184/* map output size to the corresponding WMI method id */ 185static inline int encode_outsize_for_pvsz(int outsize) 186{ 187 if (outsize > 4096) 188 return -EINVAL; 189 if (outsize > 1024) 190 return 5; 191 if (outsize > 128) 192 return 4; 193 if (outsize > 4) 194 return 3; 195 if (outsize > 0) 196 return 2; 197 return 1; 198} 199 200/* 201 * hp_wmi_perform_query 202 * 203 * query: The commandtype (enum hp_wmi_commandtype) 204 * write: The command (enum hp_wmi_command) 205 * buffer: Buffer used as input and/or output 206 * insize: Size of input buffer 207 * outsize: Size of output buffer 208 * 209 * returns zero on success 210 * an HP WMI query specific error code (which is positive) 211 * -EINVAL if the query was not successful at all 212 * -EINVAL if the output buffer size exceeds buffersize 213 * 214 * Note: The buffersize must at least be the maximum of the input and output 215 * size. E.g. Battery info query is defined to have 1 byte input 216 * and 128 byte output. The caller would do: 217 * buffer = kzalloc(128, GFP_KERNEL); 218 * ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128) 219 */ 220static int hp_wmi_perform_query(int query, enum hp_wmi_command command, 221 void *buffer, int insize, int outsize) 222{ 223 int mid; 224 struct bios_return *bios_return; 225 int actual_outsize; 226 union acpi_object *obj; 227 struct bios_args args = { 228 .signature = 0x55434553, 229 .command = command, 230 .commandtype = query, 231 .datasize = insize, 232 .data = 0, 233 }; 234 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 235 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 236 int ret = 0; 237 238 mid = encode_outsize_for_pvsz(outsize); 239 if (WARN_ON(mid < 0)) 240 return mid; 241 242 if (WARN_ON(insize > sizeof(args.data))) 243 return -EINVAL; 244 memcpy(&args.data, buffer, insize); 245 246 wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); 247 248 obj = output.pointer; 249 250 if (!obj) 251 return -EINVAL; 252 253 if (obj->type != ACPI_TYPE_BUFFER) { 254 ret = -EINVAL; 255 goto out_free; 256 } 257 258 bios_return = (struct bios_return *)obj->buffer.pointer; 259 ret = bios_return->return_code; 260 261 if (ret) { 262 if (ret != HPWMI_RET_UNKNOWN_CMDTYPE) 263 pr_warn("query 0x%x returned error 0x%x\n", query, ret); 264 goto out_free; 265 } 266 267 /* Ignore output data of zero size */ 268 if (!outsize) 269 goto out_free; 270 271 actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); 272 memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); 273 memset(buffer + actual_outsize, 0, outsize - actual_outsize); 274 275out_free: 276 kfree(obj); 277 return ret; 278} 279 280static int hp_wmi_read_int(int query) 281{ 282 int val = 0, ret; 283 284 ret = hp_wmi_perform_query(query, HPWMI_READ, &val, 285 sizeof(val), sizeof(val)); 286 287 if (ret) 288 return ret < 0 ? ret : -EINVAL; 289 290 return val; 291} 292 293static int hp_wmi_hw_state(int mask) 294{ 295 int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); 296 297 if (state < 0) 298 return state; 299 300 return !!(state & mask); 301} 302 303static int __init hp_wmi_bios_2008_later(void) 304{ 305 int state = 0; 306 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state, 307 sizeof(state), sizeof(state)); 308 if (!ret) 309 return 1; 310 311 return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; 312} 313 314static int __init hp_wmi_bios_2009_later(void) 315{ 316 int state = 0; 317 int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state, 318 sizeof(state), sizeof(state)); 319 if (!ret) 320 return 1; 321 322 return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO; 323} 324 325static int __init hp_wmi_enable_hotkeys(void) 326{ 327 int value = 0x6e; 328 int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, HPWMI_WRITE, &value, 329 sizeof(value), 0); 330 331 return ret <= 0 ? ret : -EINVAL; 332} 333 334static int hp_wmi_set_block(void *data, bool blocked) 335{ 336 enum hp_wmi_radio r = (enum hp_wmi_radio) data; 337 int query = BIT(r + 8) | ((!blocked) << r); 338 int ret; 339 340 ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, 341 &query, sizeof(query), 0); 342 343 return ret <= 0 ? ret : -EINVAL; 344} 345 346static const struct rfkill_ops hp_wmi_rfkill_ops = { 347 .set_block = hp_wmi_set_block, 348}; 349 350static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 351{ 352 int mask = 0x200 << (r * 8); 353 354 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 355 356 /* TBD: Pass error */ 357 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 358 359 return !(wireless & mask); 360} 361 362static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 363{ 364 int mask = 0x800 << (r * 8); 365 366 int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 367 368 /* TBD: Pass error */ 369 WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); 370 371 return !(wireless & mask); 372} 373 374static int hp_wmi_rfkill2_set_block(void *data, bool blocked) 375{ 376 int rfkill_id = (int)(long)data; 377 char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; 378 int ret; 379 380 ret = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_WRITE, 381 buffer, sizeof(buffer), 0); 382 383 return ret <= 0 ? ret : -EINVAL; 384} 385 386static const struct rfkill_ops hp_wmi_rfkill2_ops = { 387 .set_block = hp_wmi_rfkill2_set_block, 388}; 389 390static int hp_wmi_rfkill2_refresh(void) 391{ 392 struct bios_rfkill2_state state; 393 int err, i; 394 395 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 396 0, sizeof(state)); 397 if (err) 398 return err; 399 400 for (i = 0; i < rfkill2_count; i++) { 401 int num = rfkill2[i].num; 402 struct bios_rfkill2_device_state *devstate; 403 devstate = &state.device[num]; 404 405 if (num >= state.count || 406 devstate->rfkill_id != rfkill2[i].id) { 407 pr_warn("power configuration of the wireless devices unexpectedly changed\n"); 408 continue; 409 } 410 411 rfkill_set_states(rfkill2[i].rfkill, 412 IS_SWBLOCKED(devstate->power), 413 IS_HWBLOCKED(devstate->power)); 414 } 415 416 return 0; 417} 418 419static ssize_t display_show(struct device *dev, struct device_attribute *attr, 420 char *buf) 421{ 422 int value = hp_wmi_read_int(HPWMI_DISPLAY_QUERY); 423 if (value < 0) 424 return value; 425 return sprintf(buf, "%d\n", value); 426} 427 428static ssize_t hddtemp_show(struct device *dev, struct device_attribute *attr, 429 char *buf) 430{ 431 int value = hp_wmi_read_int(HPWMI_HDDTEMP_QUERY); 432 if (value < 0) 433 return value; 434 return sprintf(buf, "%d\n", value); 435} 436 437static ssize_t als_show(struct device *dev, struct device_attribute *attr, 438 char *buf) 439{ 440 int value = hp_wmi_read_int(HPWMI_ALS_QUERY); 441 if (value < 0) 442 return value; 443 return sprintf(buf, "%d\n", value); 444} 445 446static ssize_t dock_show(struct device *dev, struct device_attribute *attr, 447 char *buf) 448{ 449 int value = hp_wmi_hw_state(HPWMI_DOCK_MASK); 450 if (value < 0) 451 return value; 452 return sprintf(buf, "%d\n", value); 453} 454 455static ssize_t tablet_show(struct device *dev, struct device_attribute *attr, 456 char *buf) 457{ 458 int value = hp_wmi_hw_state(HPWMI_TABLET_MASK); 459 if (value < 0) 460 return value; 461 return sprintf(buf, "%d\n", value); 462} 463 464static ssize_t postcode_show(struct device *dev, struct device_attribute *attr, 465 char *buf) 466{ 467 /* Get the POST error code of previous boot failure. */ 468 int value = hp_wmi_read_int(HPWMI_POSTCODEERROR_QUERY); 469 if (value < 0) 470 return value; 471 return sprintf(buf, "0x%x\n", value); 472} 473 474static ssize_t als_store(struct device *dev, struct device_attribute *attr, 475 const char *buf, size_t count) 476{ 477 u32 tmp = simple_strtoul(buf, NULL, 10); 478 int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp, 479 sizeof(tmp), sizeof(tmp)); 480 if (ret) 481 return ret < 0 ? ret : -EINVAL; 482 483 return count; 484} 485 486static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, 487 const char *buf, size_t count) 488{ 489 long unsigned int tmp2; 490 int ret; 491 u32 tmp; 492 493 ret = kstrtoul(buf, 10, &tmp2); 494 if (!ret && tmp2 != 1) 495 ret = -EINVAL; 496 if (ret) 497 goto out; 498 499 /* Clear the POST error code. It is kept until until cleared. */ 500 tmp = (u32) tmp2; 501 ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, 502 sizeof(tmp), sizeof(tmp)); 503 504out: 505 if (ret) 506 return ret < 0 ? ret : -EINVAL; 507 508 return count; 509} 510 511static DEVICE_ATTR_RO(display); 512static DEVICE_ATTR_RO(hddtemp); 513static DEVICE_ATTR_RW(als); 514static DEVICE_ATTR_RO(dock); 515static DEVICE_ATTR_RO(tablet); 516static DEVICE_ATTR_RW(postcode); 517 518static void hp_wmi_notify(u32 value, void *context) 519{ 520 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 521 u32 event_id, event_data; 522 union acpi_object *obj; 523 acpi_status status; 524 u32 *location; 525 int key_code; 526 527 status = wmi_get_event_data(value, &response); 528 if (status != AE_OK) { 529 pr_info("bad event status 0x%x\n", status); 530 return; 531 } 532 533 obj = (union acpi_object *)response.pointer; 534 535 if (!obj) 536 return; 537 if (obj->type != ACPI_TYPE_BUFFER) { 538 pr_info("Unknown response received %d\n", obj->type); 539 kfree(obj); 540 return; 541 } 542 543 /* 544 * Depending on ACPI version the concatenation of id and event data 545 * inside _WED function will result in a 8 or 16 byte buffer. 546 */ 547 location = (u32 *)obj->buffer.pointer; 548 if (obj->buffer.length == 8) { 549 event_id = *location; 550 event_data = *(location + 1); 551 } else if (obj->buffer.length == 16) { 552 event_id = *location; 553 event_data = *(location + 2); 554 } else { 555 pr_info("Unknown buffer length %d\n", obj->buffer.length); 556 kfree(obj); 557 return; 558 } 559 kfree(obj); 560 561 switch (event_id) { 562 case HPWMI_DOCK_EVENT: 563 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 564 input_report_switch(hp_wmi_input_dev, SW_DOCK, 565 hp_wmi_hw_state(HPWMI_DOCK_MASK)); 566 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 567 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 568 hp_wmi_hw_state(HPWMI_TABLET_MASK)); 569 input_sync(hp_wmi_input_dev); 570 break; 571 case HPWMI_PARK_HDD: 572 break; 573 case HPWMI_SMART_ADAPTER: 574 break; 575 case HPWMI_BEZEL_BUTTON: 576 key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); 577 if (key_code < 0) 578 break; 579 580 if (!sparse_keymap_report_event(hp_wmi_input_dev, 581 key_code, 1, true)) 582 pr_info("Unknown key code - 0x%x\n", key_code); 583 break; 584 case HPWMI_WIRELESS: 585 if (rfkill2_count) { 586 hp_wmi_rfkill2_refresh(); 587 break; 588 } 589 590 if (wifi_rfkill) 591 rfkill_set_states(wifi_rfkill, 592 hp_wmi_get_sw_state(HPWMI_WIFI), 593 hp_wmi_get_hw_state(HPWMI_WIFI)); 594 if (bluetooth_rfkill) 595 rfkill_set_states(bluetooth_rfkill, 596 hp_wmi_get_sw_state(HPWMI_BLUETOOTH), 597 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 598 if (wwan_rfkill) 599 rfkill_set_states(wwan_rfkill, 600 hp_wmi_get_sw_state(HPWMI_WWAN), 601 hp_wmi_get_hw_state(HPWMI_WWAN)); 602 break; 603 case HPWMI_CPU_BATTERY_THROTTLE: 604 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n"); 605 break; 606 case HPWMI_LOCK_SWITCH: 607 break; 608 case HPWMI_LID_SWITCH: 609 break; 610 case HPWMI_SCREEN_ROTATION: 611 break; 612 case HPWMI_COOLSENSE_SYSTEM_MOBILE: 613 break; 614 case HPWMI_COOLSENSE_SYSTEM_HOT: 615 break; 616 case HPWMI_PROXIMITY_SENSOR: 617 break; 618 case HPWMI_BACKLIT_KB_BRIGHTNESS: 619 break; 620 case HPWMI_PEAKSHIFT_PERIOD: 621 break; 622 case HPWMI_BATTERY_CHARGE_PERIOD: 623 break; 624 default: 625 pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data); 626 break; 627 } 628} 629 630static int __init hp_wmi_input_setup(void) 631{ 632 acpi_status status; 633 int err, val; 634 635 hp_wmi_input_dev = input_allocate_device(); 636 if (!hp_wmi_input_dev) 637 return -ENOMEM; 638 639 hp_wmi_input_dev->name = "HP WMI hotkeys"; 640 hp_wmi_input_dev->phys = "wmi/input0"; 641 hp_wmi_input_dev->id.bustype = BUS_HOST; 642 643 __set_bit(EV_SW, hp_wmi_input_dev->evbit); 644 645 /* Dock */ 646 val = hp_wmi_hw_state(HPWMI_DOCK_MASK); 647 if (!(val < 0)) { 648 __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); 649 input_report_switch(hp_wmi_input_dev, SW_DOCK, val); 650 } 651 652 /* Tablet mode */ 653 val = hp_wmi_hw_state(HPWMI_TABLET_MASK); 654 if (!(val < 0)) { 655 __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); 656 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); 657 } 658 659 err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); 660 if (err) 661 goto err_free_dev; 662 663 /* Set initial hardware state */ 664 input_sync(hp_wmi_input_dev); 665 666 if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) 667 hp_wmi_enable_hotkeys(); 668 669 status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); 670 if (ACPI_FAILURE(status)) { 671 err = -EIO; 672 goto err_free_dev; 673 } 674 675 err = input_register_device(hp_wmi_input_dev); 676 if (err) 677 goto err_uninstall_notifier; 678 679 return 0; 680 681 err_uninstall_notifier: 682 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 683 err_free_dev: 684 input_free_device(hp_wmi_input_dev); 685 return err; 686} 687 688static void hp_wmi_input_destroy(void) 689{ 690 wmi_remove_notify_handler(HPWMI_EVENT_GUID); 691 input_unregister_device(hp_wmi_input_dev); 692} 693 694static void cleanup_sysfs(struct platform_device *device) 695{ 696 device_remove_file(&device->dev, &dev_attr_display); 697 device_remove_file(&device->dev, &dev_attr_hddtemp); 698 device_remove_file(&device->dev, &dev_attr_als); 699 device_remove_file(&device->dev, &dev_attr_dock); 700 device_remove_file(&device->dev, &dev_attr_tablet); 701 device_remove_file(&device->dev, &dev_attr_postcode); 702} 703 704static int __init hp_wmi_rfkill_setup(struct platform_device *device) 705{ 706 int err, wireless; 707 708 wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); 709 if (wireless < 0) 710 return wireless; 711 712 err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_WRITE, &wireless, 713 sizeof(wireless), 0); 714 if (err) 715 return err; 716 717 if (wireless & 0x1) { 718 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 719 RFKILL_TYPE_WLAN, 720 &hp_wmi_rfkill_ops, 721 (void *) HPWMI_WIFI); 722 if (!wifi_rfkill) 723 return -ENOMEM; 724 rfkill_init_sw_state(wifi_rfkill, 725 hp_wmi_get_sw_state(HPWMI_WIFI)); 726 rfkill_set_hw_state(wifi_rfkill, 727 hp_wmi_get_hw_state(HPWMI_WIFI)); 728 err = rfkill_register(wifi_rfkill); 729 if (err) 730 goto register_wifi_error; 731 } 732 733 if (wireless & 0x2) { 734 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 735 RFKILL_TYPE_BLUETOOTH, 736 &hp_wmi_rfkill_ops, 737 (void *) HPWMI_BLUETOOTH); 738 if (!bluetooth_rfkill) { 739 err = -ENOMEM; 740 goto register_bluetooth_error; 741 } 742 rfkill_init_sw_state(bluetooth_rfkill, 743 hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); 744 rfkill_set_hw_state(bluetooth_rfkill, 745 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 746 err = rfkill_register(bluetooth_rfkill); 747 if (err) 748 goto register_bluetooth_error; 749 } 750 751 if (wireless & 0x4) { 752 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 753 RFKILL_TYPE_WWAN, 754 &hp_wmi_rfkill_ops, 755 (void *) HPWMI_WWAN); 756 if (!wwan_rfkill) { 757 err = -ENOMEM; 758 goto register_wwan_error; 759 } 760 rfkill_init_sw_state(wwan_rfkill, 761 hp_wmi_get_sw_state(HPWMI_WWAN)); 762 rfkill_set_hw_state(wwan_rfkill, 763 hp_wmi_get_hw_state(HPWMI_WWAN)); 764 err = rfkill_register(wwan_rfkill); 765 if (err) 766 goto register_wwan_error; 767 } 768 769 return 0; 770 771register_wwan_error: 772 rfkill_destroy(wwan_rfkill); 773 wwan_rfkill = NULL; 774 if (bluetooth_rfkill) 775 rfkill_unregister(bluetooth_rfkill); 776register_bluetooth_error: 777 rfkill_destroy(bluetooth_rfkill); 778 bluetooth_rfkill = NULL; 779 if (wifi_rfkill) 780 rfkill_unregister(wifi_rfkill); 781register_wifi_error: 782 rfkill_destroy(wifi_rfkill); 783 wifi_rfkill = NULL; 784 return err; 785} 786 787static int __init hp_wmi_rfkill2_setup(struct platform_device *device) 788{ 789 struct bios_rfkill2_state state; 790 int err, i; 791 792 err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, 793 0, sizeof(state)); 794 if (err) 795 return err < 0 ? err : -EINVAL; 796 797 if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { 798 pr_warn("unable to parse 0x1b query output\n"); 799 return -EINVAL; 800 } 801 802 for (i = 0; i < state.count; i++) { 803 struct rfkill *rfkill; 804 enum rfkill_type type; 805 char *name; 806 switch (state.device[i].radio_type) { 807 case HPWMI_WIFI: 808 type = RFKILL_TYPE_WLAN; 809 name = "hp-wifi"; 810 break; 811 case HPWMI_BLUETOOTH: 812 type = RFKILL_TYPE_BLUETOOTH; 813 name = "hp-bluetooth"; 814 break; 815 case HPWMI_WWAN: 816 type = RFKILL_TYPE_WWAN; 817 name = "hp-wwan"; 818 break; 819 case HPWMI_GPS: 820 type = RFKILL_TYPE_GPS; 821 name = "hp-gps"; 822 break; 823 default: 824 pr_warn("unknown device type 0x%x\n", 825 state.device[i].radio_type); 826 continue; 827 } 828 829 if (!state.device[i].vendor_id) { 830 pr_warn("zero device %d while %d reported\n", 831 i, state.count); 832 continue; 833 } 834 835 rfkill = rfkill_alloc(name, &device->dev, type, 836 &hp_wmi_rfkill2_ops, (void *)(long)i); 837 if (!rfkill) { 838 err = -ENOMEM; 839 goto fail; 840 } 841 842 rfkill2[rfkill2_count].id = state.device[i].rfkill_id; 843 rfkill2[rfkill2_count].num = i; 844 rfkill2[rfkill2_count].rfkill = rfkill; 845 846 rfkill_init_sw_state(rfkill, 847 IS_SWBLOCKED(state.device[i].power)); 848 rfkill_set_hw_state(rfkill, 849 IS_HWBLOCKED(state.device[i].power)); 850 851 if (!(state.device[i].power & HPWMI_POWER_BIOS)) 852 pr_info("device %s blocked by BIOS\n", name); 853 854 err = rfkill_register(rfkill); 855 if (err) { 856 rfkill_destroy(rfkill); 857 goto fail; 858 } 859 860 rfkill2_count++; 861 } 862 863 return 0; 864fail: 865 for (; rfkill2_count > 0; rfkill2_count--) { 866 rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill); 867 rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill); 868 } 869 return err; 870} 871 872static int __init hp_wmi_bios_setup(struct platform_device *device) 873{ 874 int err; 875 876 /* clear detected rfkill devices */ 877 wifi_rfkill = NULL; 878 bluetooth_rfkill = NULL; 879 wwan_rfkill = NULL; 880 rfkill2_count = 0; 881 882 if (hp_wmi_rfkill_setup(device)) 883 hp_wmi_rfkill2_setup(device); 884 885 err = device_create_file(&device->dev, &dev_attr_display); 886 if (err) 887 goto add_sysfs_error; 888 err = device_create_file(&device->dev, &dev_attr_hddtemp); 889 if (err) 890 goto add_sysfs_error; 891 err = device_create_file(&device->dev, &dev_attr_als); 892 if (err) 893 goto add_sysfs_error; 894 err = device_create_file(&device->dev, &dev_attr_dock); 895 if (err) 896 goto add_sysfs_error; 897 err = device_create_file(&device->dev, &dev_attr_tablet); 898 if (err) 899 goto add_sysfs_error; 900 err = device_create_file(&device->dev, &dev_attr_postcode); 901 if (err) 902 goto add_sysfs_error; 903 return 0; 904 905add_sysfs_error: 906 cleanup_sysfs(device); 907 return err; 908} 909 910static int __exit hp_wmi_bios_remove(struct platform_device *device) 911{ 912 int i; 913 cleanup_sysfs(device); 914 915 for (i = 0; i < rfkill2_count; i++) { 916 rfkill_unregister(rfkill2[i].rfkill); 917 rfkill_destroy(rfkill2[i].rfkill); 918 } 919 920 if (wifi_rfkill) { 921 rfkill_unregister(wifi_rfkill); 922 rfkill_destroy(wifi_rfkill); 923 } 924 if (bluetooth_rfkill) { 925 rfkill_unregister(bluetooth_rfkill); 926 rfkill_destroy(bluetooth_rfkill); 927 } 928 if (wwan_rfkill) { 929 rfkill_unregister(wwan_rfkill); 930 rfkill_destroy(wwan_rfkill); 931 } 932 933 return 0; 934} 935 936static int hp_wmi_resume_handler(struct device *device) 937{ 938 /* 939 * Hardware state may have changed while suspended, so trigger 940 * input events for the current state. As this is a switch, 941 * the input layer will only actually pass it on if the state 942 * changed. 943 */ 944 if (hp_wmi_input_dev) { 945 if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) 946 input_report_switch(hp_wmi_input_dev, SW_DOCK, 947 hp_wmi_hw_state(HPWMI_DOCK_MASK)); 948 if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) 949 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 950 hp_wmi_hw_state(HPWMI_TABLET_MASK)); 951 input_sync(hp_wmi_input_dev); 952 } 953 954 if (rfkill2_count) 955 hp_wmi_rfkill2_refresh(); 956 957 if (wifi_rfkill) 958 rfkill_set_states(wifi_rfkill, 959 hp_wmi_get_sw_state(HPWMI_WIFI), 960 hp_wmi_get_hw_state(HPWMI_WIFI)); 961 if (bluetooth_rfkill) 962 rfkill_set_states(bluetooth_rfkill, 963 hp_wmi_get_sw_state(HPWMI_BLUETOOTH), 964 hp_wmi_get_hw_state(HPWMI_BLUETOOTH)); 965 if (wwan_rfkill) 966 rfkill_set_states(wwan_rfkill, 967 hp_wmi_get_sw_state(HPWMI_WWAN), 968 hp_wmi_get_hw_state(HPWMI_WWAN)); 969 970 return 0; 971} 972 973static const struct dev_pm_ops hp_wmi_pm_ops = { 974 .resume = hp_wmi_resume_handler, 975 .restore = hp_wmi_resume_handler, 976}; 977 978static struct platform_driver hp_wmi_driver = { 979 .driver = { 980 .name = "hp-wmi", 981 .pm = &hp_wmi_pm_ops, 982 }, 983 .remove = __exit_p(hp_wmi_bios_remove), 984}; 985 986static int __init hp_wmi_init(void) 987{ 988 int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); 989 int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 990 int err; 991 992 if (!bios_capable && !event_capable) 993 return -ENODEV; 994 995 if (event_capable) { 996 err = hp_wmi_input_setup(); 997 if (err) 998 return err; 999 } 1000 1001 if (bios_capable) { 1002 hp_wmi_platform_dev = 1003 platform_device_register_simple("hp-wmi", -1, NULL, 0); 1004 if (IS_ERR(hp_wmi_platform_dev)) { 1005 err = PTR_ERR(hp_wmi_platform_dev); 1006 goto err_destroy_input; 1007 } 1008 1009 err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); 1010 if (err) 1011 goto err_unregister_device; 1012 } 1013 1014 return 0; 1015 1016err_unregister_device: 1017 platform_device_unregister(hp_wmi_platform_dev); 1018err_destroy_input: 1019 if (event_capable) 1020 hp_wmi_input_destroy(); 1021 1022 return err; 1023} 1024module_init(hp_wmi_init); 1025 1026static void __exit hp_wmi_exit(void) 1027{ 1028 if (wmi_has_guid(HPWMI_EVENT_GUID)) 1029 hp_wmi_input_destroy(); 1030 1031 if (hp_wmi_platform_dev) { 1032 platform_device_unregister(hp_wmi_platform_dev); 1033 platform_driver_unregister(&hp_wmi_driver); 1034 } 1035} 1036module_exit(hp_wmi_exit);