root/drivers/platform/x86/hp-wmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. encode_outsize_for_pvsz
  2. hp_wmi_perform_query
  3. hp_wmi_read_int
  4. hp_wmi_hw_state
  5. hp_wmi_bios_2008_later
  6. hp_wmi_bios_2009_later
  7. hp_wmi_enable_hotkeys
  8. hp_wmi_set_block
  9. hp_wmi_get_sw_state
  10. hp_wmi_get_hw_state
  11. hp_wmi_rfkill2_set_block
  12. hp_wmi_rfkill2_refresh
  13. display_show
  14. hddtemp_show
  15. als_show
  16. dock_show
  17. tablet_show
  18. postcode_show
  19. als_store
  20. postcode_store
  21. hp_wmi_notify
  22. hp_wmi_input_setup
  23. hp_wmi_input_destroy
  24. hp_wmi_rfkill_setup
  25. hp_wmi_rfkill2_setup
  26. hp_wmi_bios_setup
  27. hp_wmi_bios_remove
  28. hp_wmi_resume_handler
  29. hp_wmi_init
  30. hp_wmi_exit

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

/* [<][>][^][v][top][bottom][index][help] */