/* * The Dolby button (yes really a Dolby button) causes an ACPI variable to get * set on both press and release. The WMI method checks and clears that flag. * So for a press + release we will get back One from the WMI method either once * (if polling after the release) or twice (polling between press and release). * We ignore events for 0.5s after the first event to avoid reporting 2 presses. */ static void peaq_wmi_poll(struct input_polled_dev *dev) { union acpi_object obj; acpi_status status; u32 dummy = 0; struct acpi_buffer input = { sizeof(dummy), &dummy }; struct acpi_buffer output = { sizeof(obj), &obj }; status = wmi_evaluate_method(PEAQ_DOLBY_BUTTON_GUID, 0, PEAQ_DOLBY_BUTTON_METHOD_ID, &input, &output); if (ACPI_FAILURE(status)) return; if (obj.type != ACPI_TYPE_INTEGER) { dev_err(&peaq_poll_dev->input->dev, "Error WMBC did not return an integer\n"); return; } if (peaq_ignore_events_counter && peaq_ignore_events_counter--) return; if (obj.integer.value) { input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 1); input_sync(peaq_poll_dev->input); input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 0); input_sync(peaq_poll_dev->input); peaq_ignore_events_counter = max(1u, PEAQ_POLL_IGNORE_MS / peaq_poll_dev->poll_interval); } }
static int dell_led_perform_fn(u8 length, u8 result_code, u8 device_id, u8 command, u8 on_time, u8 off_time) { struct bios_args *bios_return; u8 return_code; union acpi_object *obj; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer input; acpi_status status; struct bios_args args; args.length = length; args.result_code = result_code; args.device_id = device_id; args.command = command; args.on_time = on_time; args.off_time = off_time; input.length = sizeof(struct bios_args); input.pointer = &args; status = wmi_evaluate_method(DELL_LED_BIOS_GUID, 1, 1, &input, &output); if (ACPI_FAILURE(status)) return status; obj = output.pointer; if (!obj) return -EINVAL; else if (obj->type != ACPI_TYPE_BUFFER) { kfree(obj); return -EINVAL; } bios_return = ((struct bios_args *)obj->buffer.pointer); return_code = bios_return->result_code; kfree(obj); return return_code; }
static int thinkpad_wmi_simple_call(const char *guid, const char *arg) { const struct acpi_buffer input = { strlen(arg), (char *)arg }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_status status; status = wmi_evaluate_method(guid, 0, 0, &input, &output); if (ACPI_FAILURE(status)) return -EIO; return thinkpad_wmi_extract_error(&output); }
static int thinkpad_wmi_get_bios_selections(const char *item, char **value) { const struct acpi_buffer input = { strlen(item), (char *)item }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_status status; status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID, 0, 0, &input, &output); if (ACPI_FAILURE(status)) return -EIO; return thinkpad_wmi_extract_output_string(&output, value); }
/* * hp_wmi_perform_query * * query: The commandtype (enum hp_wmi_commandtype) * write: The command (enum hp_wmi_command) * buffer: Buffer used as input and/or output * insize: Size of input buffer * outsize: Size of output buffer * * returns zero on success * an HP WMI query specific error code (which is positive) * -EINVAL if the query was not successful at all * -EINVAL if the output buffer size exceeds buffersize * * Note: The buffersize must at least be the maximum of the input and output * size. E.g. Battery info query is defined to have 1 byte input * and 128 byte output. The caller would do: * buffer = kzalloc(128, GFP_KERNEL); * ret = hp_wmi_perform_query(HPWMI_BATTERY_QUERY, HPWMI_READ, buffer, 1, 128) */ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, void *buffer, int insize, int outsize) { int mid; struct bios_return *bios_return; int actual_outsize; union acpi_object *obj; struct bios_args args = { .signature = 0x55434553, .command = command, .commandtype = query, .datasize = insize, .data = 0, }; struct acpi_buffer input = { sizeof(struct bios_args), &args }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; int ret = 0; mid = encode_outsize_for_pvsz(outsize); if (WARN_ON(mid < 0)) return mid; if (WARN_ON(insize > sizeof(args.data))) return -EINVAL; memcpy(&args.data, buffer, insize); wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); obj = output.pointer; if (!obj) return -EINVAL; if (obj->type != ACPI_TYPE_BUFFER) { ret = -EINVAL; goto out_free; } bios_return = (struct bios_return *)obj->buffer.pointer; ret = bios_return->return_code; if (ret) { if (ret != HPWMI_RET_UNKNOWN_CMDTYPE) pr_warn("query 0x%x returned error 0x%x\n", query, ret); goto out_free; } /* Ignore output data of zero size */ if (!outsize) goto out_free; actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); memset(buffer + actual_outsize, 0, outsize - actual_outsize); out_free: kfree(obj); return ret; } static int hp_wmi_read_int(int query) { int val = 0, ret; ret = hp_wmi_perform_query(query, HPWMI_READ, &val, sizeof(val), sizeof(val)); if (ret) return ret < 0 ? ret : -EINVAL; return val; }