evdev_device_is_joystick_or_gamepad(struct evdev_device *device)
{
	enum evdev_device_udev_tags udev_tags;
	bool has_joystick_tags;
	struct libevdev *evdev = device->evdev;
	unsigned int code;

	/* The EVDEV_UDEV_TAG_JOYSTICK is set when a joystick or gamepad button
	 * is found. However, it can not be used to identify joysticks or
	 * gamepads because there are keyboards that also have it. Even worse,
	 * many joysticks also map KEY_* and thus are tagged as keyboards.
	 *
	 * In order to be able to detect joysticks and gamepads and
	 * differentiate them from keyboards, apply the following rules:
	 *
	 *  1. The device is tagged as joystick but not as tablet
	 *  2. The device doesn't have 4 well-known keyboard keys
	 *  3. It has at least 2 joystick buttons
	 *  4. It doesn't have 10 keyboard keys */

	udev_tags = evdev_device_get_udev_tags(device, device->udev_device);
	has_joystick_tags = (udev_tags & EVDEV_UDEV_TAG_JOYSTICK) &&
			    !(udev_tags & EVDEV_UDEV_TAG_TABLET) &&
			    !(udev_tags & EVDEV_UDEV_TAG_TABLET_PAD);

	if (!has_joystick_tags)
		return false;


	unsigned int num_well_known_keys = 0;

	for (size_t i = 0; i < ARRAY_LENGTH(well_known_keyboard_keys); i++) {
		code = well_known_keyboard_keys[i];
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_well_known_keys++;
	}

	if (num_well_known_keys >= 4) /* should not have 4 well-known keys */
		return false;

	unsigned int num_joystick_btns = 0;

	for (code = BTN_JOYSTICK; code < BTN_DIGI; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_joystick_btns++;
	}

	for (code = BTN_TRIGGER_HAPPY; code <= BTN_TRIGGER_HAPPY40; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_joystick_btns++;
	}

	if (num_joystick_btns < 2) /* require at least 2 joystick buttons */
		return false;

	unsigned int num_keys = 0;

	for (code = KEY_ESC; code <= KEY_MICMUTE; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	for (code = KEY_OK; code <= KEY_LIGHTS_TOGGLE; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	for (code = KEY_ALS_TOGGLE; code < BTN_TRIGGER_HAPPY; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	if (num_keys >= 10) /* should not have 10 keyboard keys */
		return false;

	return true;
}
evdev_device_is_joystick_or_gamepad(struct evdev_device *device)
{
	enum evdev_device_udev_tags udev_tags;
	bool has_joystick_tags;
	struct libevdev *evdev = device->evdev;
	unsigned int code;

	 

	udev_tags = evdev_device_get_udev_tags(device, device->udev_device);
	has_joystick_tags = (udev_tags & EVDEV_UDEV_TAG_JOYSTICK) &&
			    !(udev_tags & EVDEV_UDEV_TAG_TABLET) &&
			    !(udev_tags & EVDEV_UDEV_TAG_TABLET_PAD);

	if (!has_joystick_tags)
		return false;


	unsigned int num_well_known_keys = 0;

	for (size_t i = 0; i < ARRAY_LENGTH(well_known_keyboard_keys); i++) {
		code = well_known_keyboard_keys[i];
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_well_known_keys++;
	}

	if (num_well_known_keys >= 4)  
		return false;

	unsigned int num_joystick_btns = 0;

	for (code = BTN_JOYSTICK; code < BTN_DIGI; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_joystick_btns++;
	}

	for (code = BTN_TRIGGER_HAPPY; code <= BTN_TRIGGER_HAPPY40; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code))
			num_joystick_btns++;
	}

	if (num_joystick_btns < 2)  
		return false;

	unsigned int num_keys = 0;

	for (code = KEY_ESC; code <= KEY_MICMUTE; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	for (code = KEY_OK; code <= KEY_LIGHTS_TOGGLE; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	for (code = KEY_ALS_TOGGLE; code < BTN_TRIGGER_HAPPY; code++) {
		if (libevdev_has_event_code(evdev, EV_KEY, code) )
			num_keys++;
	}

	if (num_keys >= 10)  
		return false;

	return true;
}