示例#1
0
static void notify_handler(acpi_handle handle, u32 event, void *context)
{
	struct platform_device *device = context;
	struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
	unsigned int val = !(event & 1); /* Even=press, Odd=release */
	const struct key_entry *ke_rel;
	bool autorelease;

	if (priv->wakeup_mode) {
		if (sparse_keymap_entry_from_scancode(priv->input_dev, event)) {
			pm_wakeup_hard_event(&device->dev);
			return;
		}
		goto out_unknown;
	}

	/*
	 * Even press events are autorelease if there is no corresponding odd
	 * release event, or if the odd event is KE_IGNORE.
	 */
	ke_rel = sparse_keymap_entry_from_scancode(priv->input_dev, event | 1);
	autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);

	if (sparse_keymap_report_event(priv->input_dev, event, val, autorelease))
		return;

out_unknown:
	dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
}
示例#2
0
文件: gb-wmi.c 项目: ivzave/gb-wmi
static void gb_wmi_notify(u32 value, void* context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object* obj;
	acpi_status status;
	int code;
	
	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_err("Bad event status 0x%x\n", status);
		return;
	}
	
	obj = (union acpi_object*)response.pointer;
	if (!obj) {
		pr_info("Could not get response pointer\n");
		return;
	}

	if (obj->type == ACPI_TYPE_BUFFER) {
		int eventcode = obj->buffer.pointer[0];
		struct key_entry* key = sparse_keymap_entry_from_scancode(gb_wmi_input_dev, eventcode);
		pr_info("Buffer received: %x %x \n", obj->buffer.length, obj->buffer.pointer[0], obj->buffer.pointer[1]);
		if (key)
			sparse_keymap_report_entry(gb_wmi_input_dev, key, 1, true);
	}
	else
		pr_info("Unknown event\n");
	
	
	kfree(obj);
}
示例#3
0
static void msi_wmi_notify(u32 value, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	struct key_entry *key;
	union acpi_object *obj;
	acpi_status status;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_info("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;

	if (obj && obj->type == ACPI_TYPE_INTEGER) {
		int eventcode = obj->integer.value;
		pr_debug("Eventcode: 0x%x\n", eventcode);
		key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
				eventcode);
		if (!key) {
			pr_info("Unknown key pressed - %x\n", eventcode);
			goto msi_wmi_notify_exit;
		}

		if (event_wmi->quirk_last_pressed) {
			ktime_t cur = ktime_get_real();
			ktime_t diff = ktime_sub(cur, last_pressed);
			/* Ignore event if any event happened in a 50 ms
			   timeframe -> Key press may result in 10-20 GPEs */
			if (ktime_to_us(diff) < 1000 * 50) {
				pr_debug("Suppressed key event 0x%X - "
					 "Last press was %lld us ago\n",
					 key->code, ktime_to_us(diff));
				goto msi_wmi_notify_exit;
			}
			last_pressed = cur;
		}

		if (key->type == KE_KEY &&
		/* Brightness is served via acpi video driver */
		(backlight ||
		(key->code != MSI_KEY_BRIGHTNESSUP &&
		key->code != MSI_KEY_BRIGHTNESSDOWN))) {
			pr_debug("Send key: 0x%X - Input layer keycode: %d\n",
				 key->code, key->keycode);
			sparse_keymap_report_entry(msi_wmi_input_dev, key, 1,
						   true);
		}
	} else
		pr_info("Unknown event received\n");

msi_wmi_notify_exit:
	kfree(response.pointer);
}
/**
 * sparse_keymap_report_event - report event corresponding to given scancode
 * @dev: Input device using sparse keymap
 * @code: Scan code
 * @value: Value that should be reported (ignored by %KE_SW entries)
 * @autorelease: Signals whether release event should be emitted for %KE_KEY
 *	entries right after reporting press event, ignored by all other
 *	entries
 *
 * This function is used to perform lookup in an input device using sparse
 * keymap and report corresponding event. Returns %true if lookup was
 * successful and %false otherwise.
 */
bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
				unsigned int value, bool autorelease)
{
	const struct key_entry *ke =
		sparse_keymap_entry_from_scancode(dev, code);

	if (ke) {
		sparse_keymap_report_entry(dev, ke, value, autorelease);
		return true;
	}

	return false;
}
static int sparse_keymap_getkeycode(struct input_dev *dev,
				    unsigned int scancode,
				    unsigned int *keycode)
{
	const struct key_entry *key =
			sparse_keymap_entry_from_scancode(dev, scancode);

	if (key && key->type == KE_KEY) {
		*keycode = key->keycode;
		return 0;
	}

	return -EINVAL;
}
示例#6
0
static void msi_wmi_notify(u32 value, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	static struct key_entry *key;
	union acpi_object *obj;
	ktime_t cur;

	wmi_get_event_data(value, &response);

	obj = (union acpi_object *)response.pointer;

	if (obj && obj->type == ACPI_TYPE_INTEGER) {
		int eventcode = obj->integer.value;
		dprintk("Eventcode: 0x%x\n", eventcode);
		key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
				eventcode);
		if (key) {
			ktime_t diff;
			cur = ktime_get_real();
			diff = ktime_sub(cur, last_pressed[key->code -
					KEYCODE_BASE]);
			/* Ignore event if the same event happened in a 50 ms
			   timeframe -> Key press may result in 10-20 GPEs */
			if (ktime_to_us(diff) < 1000 * 50) {
				dprintk("Suppressed key event 0x%X - "
					"Last press was %lld us ago\n",
					 key->code, ktime_to_us(diff));
				return;
			}
			last_pressed[key->code - KEYCODE_BASE] = cur;

			if (key->type == KE_KEY &&
			/* Brightness is served via acpi video driver */
			(!acpi_video_backlight_support() ||
			(key->code != MSI_WMI_BRIGHTNESSUP &&
			key->code != MSI_WMI_BRIGHTNESSDOWN))) {
				dprintk("Send key: 0x%X - "
					"Input layer keycode: %d\n", key->code,
					 key->keycode);
				sparse_keymap_report_entry(msi_wmi_input_dev,
						key, 1, true);
			}
		} else
			printk(KERN_INFO "Unknown key pressed - %x\n",
			       eventcode);
	} else
		printk(KERN_INFO DRV_PFX "Unknown event received\n");
	kfree(response.pointer);
}
示例#7
0
static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
					const struct input_keymap_entry *ke)
{
	struct key_entry *key;
	unsigned int scancode;

	if (ke->flags & INPUT_KEYMAP_BY_INDEX)
		key = sparse_keymap_entry_by_index(dev, ke->index);
	else if (input_scancode_to_scalar(ke, &scancode) == 0)
		key = sparse_keymap_entry_from_scancode(dev, scancode);
	else
		key = NULL;

	return key;
}
示例#8
0
/**
 * sparse_keymap_report_event - report event corresponding to given scancode
 * @dev: Input device using sparse keymap
 * @code: Scan code
 * @value: Value that should be reported (ignored by %KE_SW entries)
 * @autorelease: Signals whether release event should be emitted for %KE_KEY
 *	entries right after reporting press event, ignored by all other
 *	entries
 *
 * This function is used to perform lookup in an input device using sparse
 * keymap and report corresponding event. Returns %true if lookup was
 * successful and %false otherwise.
 */
bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
				unsigned int value, bool autorelease)
{
	const struct key_entry *ke =
		sparse_keymap_entry_from_scancode(dev, code);
	struct key_entry unknown_ke;

	if (ke) {
		sparse_keymap_report_entry(dev, ke, value, autorelease);
		return true;
	}

	/* Report an unknown key event as a debugging aid */
	unknown_ke.type = KE_KEY;
	unknown_ke.code = code;
	unknown_ke.keycode = KEY_UNKNOWN;
	sparse_keymap_report_entry(dev, &unknown_ke, value, true);

	return false;
}
示例#9
0
static int sparse_keymap_setkeycode(struct input_dev *dev,
				    unsigned int scancode,
				    unsigned int keycode)
{
	struct key_entry *key;
	int old_keycode;

	if (dev->keycode) {
		key = sparse_keymap_entry_from_scancode(dev, scancode);
		if (key && key->type == KE_KEY) {
			old_keycode = key->keycode;
			key->keycode = keycode;
			set_bit(keycode, dev->keybit);
			if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
				clear_bit(old_keycode, dev->keybit);
			return 0;
		}
	}

	return -EINVAL;
}
/*
 * Because we communicate with the MSP430 using I2C, and all I2C calls
 * in Linux sleep, we use a threaded IRQ handler.  The IRQ itself is
 * active low, but we go through the GPIO controller so we can trigger
 * on falling edges and not worry about enabling/disabling the IRQ in
 * the keypress handling path.
 */
static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
{
	static u16 last_event;
	struct dm355evm_keys *keys = _keys;
	const struct key_entry *ke;
	unsigned int keycode;
	int status;
	u16 event;

	/* For simplicity we ignore INPUT_COUNT and just read
	 * events until we get the "queue empty" indicator.
	 * Reading INPUT_LOW decrements the count.
	 */
	for (;;) {
		status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
		if (status < 0) {
			dev_dbg(keys->dev, "input high err %d\n",
					status);
			break;
		}
		event = status << 8;

		status = dm355evm_msp_read(DM355EVM_MSP_INPUT_LOW);
		if (status < 0) {
			dev_dbg(keys->dev, "input low err %d\n",
					status);
			break;
		}
		event |= status;
		if (event == 0xdead)
			break;

		/* Press and release a button:  two events, same code.
		 * Press and hold (autorepeat), then release: N events
		 * (N > 2), same code.  For RC5 buttons the toggle bits
		 * distinguish (for example) "1-autorepeat" from "1 1";
		 * but PCB buttons don't support that bit.
		 *
		 * So we must synthesize release events.  We do that by
		 * mapping events to a press/release event pair; then
		 * to avoid adding extra events, skip the second event
		 * of each pair.
		 */
		if (event == last_event) {
			last_event = 0;
			continue;
		}
		last_event = event;

		/* ignore the RC5 toggle bit */
		event &= ~0x0800;

		/* find the key, or report it as unknown */
		ke = sparse_keymap_entry_from_scancode(keys->input, event);
		keycode = ke ? ke->keycode : KEY_UNKNOWN;
		dev_dbg(keys->dev,
			"input event 0x%04x--> keycode %d\n",
			event, keycode);

		/* report press + release */
		input_report_key(keys->input, keycode, 1);
		input_sync(keys->input);
		input_report_key(keys->input, keycode, 0);
		input_sync(keys->input);
	}

	return IRQ_HANDLED;
}
示例#11
0
文件: intel-hid.c 项目: Lyude/linux
static void notify_handler(acpi_handle handle, u32 event, void *context)
{
	struct platform_device *device = context;
	struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
	unsigned long long ev_index;

	if (priv->wakeup_mode) {
		/*
		 * Needed for wakeup from suspend-to-idle to work on some
		 * platforms that don't expose the 5-button array, but still
		 * send notifies with the power button event code to this
		 * device object on power button actions while suspended.
		 */
		if (event == 0xce)
			goto wakeup;

		/* Wake up on 5-button array events only. */
		if (event == 0xc0 || !priv->array)
			return;

		if (!sparse_keymap_entry_from_scancode(priv->array, event)) {
			dev_info(&device->dev, "unknown event 0x%x\n", event);
			return;
		}

wakeup:
		pm_wakeup_hard_event(&device->dev);
		return;
	}

	/*
	 * Needed for suspend to work on some platforms that don't expose
	 * the 5-button array, but still send notifies with power button
	 * event code to this device object on power button actions.
	 *
	 * Report the power button press; catch and ignore the button release.
	 */
	if (!priv->array) {
		if (event == 0xce) {
			input_report_key(priv->input_dev, KEY_POWER, 1);
			input_sync(priv->input_dev);
			return;
		}

		if (event == 0xcf)
			return;
	}

	/* 0xC0 is for HID events, other values are for 5 button array */
	if (event != 0xc0) {
		if (!priv->array ||
		    !sparse_keymap_report_event(priv->array, event, 1, true))
			dev_dbg(&device->dev, "unknown event 0x%x\n", event);
		return;
	}

	if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN,
				       &ev_index)) {
		dev_warn(&device->dev, "failed to get event index\n");
		return;
	}

	if (!sparse_keymap_report_event(priv->input_dev, ev_index, 1, true))
		dev_dbg(&device->dev, "unknown event index 0x%llx\n",
			 ev_index);
}