diff --git a/packages/apps/jelos-gamepad/package.mk b/packages/apps/jelos-gamepad/package.mk index d921fb824..09635d3d2 100644 --- a/packages/apps/jelos-gamepad/package.mk +++ b/packages/apps/jelos-gamepad/package.mk @@ -8,7 +8,7 @@ PKG_DEPENDS_TARGET="toolchain" PKG_TOOLCHAIN="make" GET_HANDLER_SUPPORT="git" -case ${DEVOCE} in +case ${DEVICE} in RK3588-ACE) PKG_PATCH_DIRS+=" ${DEVICE}" ;; diff --git a/packages/apps/jelos-gamepad/patches/RK3588-ACE/000-jelos-gamepad.patch b/packages/apps/jelos-gamepad/patches/RK3588-ACE/000-jelos-gamepad.patch index 643235cf3..a05242412 100644 --- a/packages/apps/jelos-gamepad/patches/RK3588-ACE/000-jelos-gamepad.patch +++ b/packages/apps/jelos-gamepad/patches/RK3588-ACE/000-jelos-gamepad.patch @@ -1,6 +1,15 @@ diff -rupN rinputer2.orig/main.c rinputer2/main.c ---- rinputer2.orig/main.c 2024-02-22 18:08:36.307753030 +0000 -+++ rinputer2/main.c 2024-02-23 20:00:20.626534557 +0000 +--- rinputer2.orig/main.c 2024-03-02 16:34:18.582729256 +0000 ++++ rinputer2/main.c 2024-03-02 23:08:29.187330115 +0000 +@@ -123,7 +123,7 @@ void *worker(void *data) + { + case EV_KEY: + ioctl(my_device->infd, EVIOCGBIT(EV_KEY, sizeof(codes)), &codes); +- ++ + // dividing by 8 because all values + // are stored as bits, not bytes + if((codes[BTN_SOUTH / 8]) & 1) @@ -144,6 +144,9 @@ void *worker(void *data) if((codes[ABS_X / 8]) & 1) useful = 1; @@ -11,36 +20,32 @@ diff -rupN rinputer2.orig/main.c rinputer2/main.c struct input_absinfo tmp; for(int tmp_code = ABS_X; tmp_code < ABS_HAT3Y; tmp_code++) { -@@ -240,7 +243,7 @@ int rescan_devices(struct rinputer_devic - continue; - - // let's not make a loop -- if(strncmp("Rinputer", name, 8) == 0) -+ if(strncmp("gameforce_ace_gamepad", name, 8) == 0) +@@ -244,7 +247,7 @@ int rescan_devices(struct rinputer_devic continue; // ignore steam-created controllers // they have this name, with a digit at the end -@@ -316,10 +319,10 @@ int main(void) +- if(strncmp("Microsoft X-Box 360 pad ", name, 24) == 0) ++ if(strncmp("Microsoft X-Box 360 pad", name, 24) == 0) + continue; + + tmpdev = calloc(1, sizeof(struct rinputer_device)); +@@ -316,7 +319,7 @@ int main(void) ioctl(outfd, UI_SET_EVBIT, EV_KEY); - //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_UP); // dpad up -- //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_DOWN); // dpad down -- //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_LEFT); // dpad left -- //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_RIGHT); // dpad right -+ ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_UP); // dpad up -+ ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_DOWN); // dpad down -+ ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_LEFT); // dpad left -+ ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_RIGHT); // dpad right ++ //ioctl(outfd, UI_SET_KEYBITUI_SET_KEYBIT, BTN_DPAD_UP); // dpad up + //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_DOWN); // dpad down + //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_LEFT); // dpad left + //ioctl(outfd, UI_SET_KEYBIT, BTN_DPAD_RIGHT); // dpad right +@@ -328,9 +331,12 @@ int main(void) - ioctl(outfd, UI_SET_KEYBIT, BTN_NORTH); // x - ioctl(outfd, UI_SET_KEYBIT, BTN_SOUTH); // b -@@ -329,8 +332,11 @@ int main(void) ioctl(outfd, UI_SET_KEYBIT, BTN_TL); // L1 ioctl(outfd, UI_SET_KEYBIT, BTN_TR); // R1 - +- - ioctl(outfd, UI_SET_KEYBIT, BTN_TR2); // L2 - ioctl(outfd, UI_SET_KEYBIT, BTN_TL2); // R2 ++ + //ioctl(outfd, UI_SET_KEYBIT, BTN_TR2); // L2 + //ioctl(outfd, UI_SET_KEYBIT, BTN_TL2); // R2 + @@ -49,23 +54,27 @@ diff -rupN rinputer2.orig/main.c rinputer2/main.c ioctl(outfd, UI_SET_KEYBIT, BTN_SELECT); ioctl(outfd, UI_SET_KEYBIT, BTN_START); -@@ -350,15 +356,15 @@ int main(void) - setup_abs(outfd, ABS_RZ); +@@ -340,8 +346,8 @@ int main(void) + ioctl(outfd, UI_SET_EVBIT, EV_ABS); - // dpad -- setup_abs(outfd, ABS_HAT0X); -- setup_abs(outfd, ABS_HAT0Y); -+ //setup_abs(outfd, ABS_HAT0X); -+ //setup_abs(outfd, ABS_HAT0Y); + // analogs +- setup_abs(outfd, ABS_X); +- setup_abs(outfd, ABS_Y); ++ //setup_abs(outfd, ABS_X); ++ //setup_abs(outfd, ABS_Y); + setup_abs(outfd, ABS_RX); + setup_abs(outfd, ABS_RY); +@@ -356,9 +362,9 @@ int main(void) // maybe we should pretend to be xbox gamepad? memset(&usetup, 0, sizeof(usetup)); usetup.id.bustype = BUS_USB; - usetup.id.vendor = 0x1234; +- usetup.id.vendor = 0x1234; - usetup.id.product = 0x5678; - strcpy(usetup.name, "Rinputer"); -+ usetup.id.product = 0x8765; -+ strcpy(usetup.name, "gameforce_ace_gamepad"); ++ usetup.id.vendor = 0x045e; ++ usetup.id.product = 0x028e; ++ strcpy(usetup.name, "Microsoft X-Box 360 pad"); ioctl(outfd, UI_DEV_SETUP, &usetup); ioctl(outfd, UI_DEV_CREATE); diff --git a/projects/Rockchip/devices/RK3588-ACE/linux/linux.aarch64.conf b/projects/Rockchip/devices/RK3588-ACE/linux/linux.aarch64.conf index e88555d75..9f7db614a 100644 --- a/projects/Rockchip/devices/RK3588-ACE/linux/linux.aarch64.conf +++ b/projects/Rockchip/devices/RK3588-ACE/linux/linux.aarch64.conf @@ -2979,6 +2979,7 @@ CONFIG_USB_NET_RNDIS_WLAN=y CONFIG_INPUT=y CONFIG_INPUT_LEDS=y CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_SPARSEKMAP is not set # CONFIG_INPUT_MATRIXKMAP is not set diff --git a/projects/Rockchip/patches/linux/RK3588-ACE/000-gameforce-ace.patch b/projects/Rockchip/patches/linux/RK3588-ACE/000-gameforce-ace.patch index ebababfb2..01ba41347 100644 --- a/projects/Rockchip/patches/linux/RK3588-ACE/000-gameforce-ace.patch +++ b/projects/Rockchip/patches/linux/RK3588-ACE/000-gameforce-ace.patch @@ -268,7 +268,7 @@ diff -rupN linux.orig/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts lin + }; + + // lqb : 手柄GPIO按键 -+ gpio-keys-control { ++ gpio-keys { + status = "okay"; + compatible = "gpio-keys"; + diff --git a/projects/Rockchip/patches/linux/RK3588-ACE/006-dpad-hat.patch b/projects/Rockchip/patches/linux/RK3588-ACE/006-dpad-hat.patch new file mode 100644 index 000000000..86f3c17ac --- /dev/null +++ b/projects/Rockchip/patches/linux/RK3588-ACE/006-dpad-hat.patch @@ -0,0 +1,974 @@ +diff -rupN linux.orig/drivers/input/Kconfig linux/drivers/input/Kconfig +--- linux.orig/drivers/input/Kconfig 2024-03-02 17:57:02.760204687 +0000 ++++ linux/drivers/input/Kconfig 2024-03-02 18:09:13.825975926 +0000 +@@ -51,6 +51,14 @@ config INPUT_FF_MEMLESS + To compile this driver as a module, choose M here: the + module will be called ff-memless. + ++config INPUT_POLLDEV ++ tristate "Polled input device skeleton" ++ help ++ Say Y here if you are using a driver for an input ++ device that periodically polls hardware state. This ++ option is only useful for out-of-tree drivers since ++ in-tree drivers select it automatically. ++ + config INPUT_SPARSEKMAP + tristate "Sparse keymap support library" + help +diff -rupN linux.orig/drivers/input/Makefile linux/drivers/input/Makefile +--- linux.orig/drivers/input/Makefile 2024-03-02 17:57:02.760204687 +0000 ++++ linux/drivers/input/Makefile 2024-03-02 18:07:53.627958774 +0000 +@@ -10,6 +10,7 @@ input-core-y := input.o input-compat.o i + input-core-y += touchscreen.o + + obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o ++obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o + obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o + obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o + obj-$(CONFIG_INPUT_VIVALDIFMAP) += vivaldi-fmap.o +diff -rupN linux.orig/drivers/input/input-polldev.c linux/drivers/input/input-polldev.c +--- linux.orig/drivers/input/input-polldev.c 1970-01-01 00:00:00.000000000 +0000 ++++ linux/drivers/input/input-polldev.c 2024-03-02 18:07:18.547098087 +0000 +@@ -0,0 +1,362 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Generic implementation of a polled input device ++ ++ * Copyright (c) 2007 Dmitry Torokhov ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++MODULE_AUTHOR("Dmitry Torokhov "); ++MODULE_DESCRIPTION("Generic implementation of a polled input device"); ++MODULE_LICENSE("GPL v2"); ++ ++static void input_polldev_queue_work(struct input_polled_dev *dev) ++{ ++ unsigned long delay; ++ ++ delay = msecs_to_jiffies(dev->poll_interval); ++ if (delay >= HZ) ++ delay = round_jiffies_relative(delay); ++ ++ queue_delayed_work(system_freezable_wq, &dev->work, delay); ++} ++ ++static void input_polled_device_work(struct work_struct *work) ++{ ++ struct input_polled_dev *dev = ++ container_of(work, struct input_polled_dev, work.work); ++ ++ dev->poll(dev); ++ input_polldev_queue_work(dev); ++} ++ ++static int input_open_polled_device(struct input_dev *input) ++{ ++ struct input_polled_dev *dev = input_get_drvdata(input); ++ ++ if (dev->open) ++ dev->open(dev); ++ ++ /* Only start polling if polling is enabled */ ++ if (dev->poll_interval > 0) { ++ dev->poll(dev); ++ input_polldev_queue_work(dev); ++ } ++ ++ return 0; ++} ++ ++static void input_close_polled_device(struct input_dev *input) ++{ ++ struct input_polled_dev *dev = input_get_drvdata(input); ++ ++ cancel_delayed_work_sync(&dev->work); ++ ++ if (dev->close) ++ dev->close(dev); ++} ++ ++/* SYSFS interface */ ++ ++static ssize_t input_polldev_get_poll(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct input_polled_dev *polldev = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", polldev->poll_interval); ++} ++ ++static ssize_t input_polldev_set_poll(struct device *dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct input_polled_dev *polldev = dev_get_drvdata(dev); ++ struct input_dev *input = polldev->input; ++ unsigned int interval; ++ int err; ++ ++ err = kstrtouint(buf, 0, &interval); ++ if (err) ++ return err; ++ ++ if (interval < polldev->poll_interval_min) ++ return -EINVAL; ++ ++ if (interval > polldev->poll_interval_max) ++ return -EINVAL; ++ ++ mutex_lock(&input->mutex); ++ ++ polldev->poll_interval = interval; ++ ++ if (input->users) { ++ cancel_delayed_work_sync(&polldev->work); ++ if (polldev->poll_interval > 0) ++ input_polldev_queue_work(polldev); ++ } ++ ++ mutex_unlock(&input->mutex); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(poll, S_IRUGO | S_IWUSR, input_polldev_get_poll, ++ input_polldev_set_poll); ++ ++ ++static ssize_t input_polldev_get_max(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct input_polled_dev *polldev = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", polldev->poll_interval_max); ++} ++ ++static DEVICE_ATTR(max, S_IRUGO, input_polldev_get_max, NULL); ++ ++static ssize_t input_polldev_get_min(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct input_polled_dev *polldev = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", polldev->poll_interval_min); ++} ++ ++static DEVICE_ATTR(min, S_IRUGO, input_polldev_get_min, NULL); ++ ++static struct attribute *sysfs_attrs[] = { ++ &dev_attr_poll.attr, ++ &dev_attr_max.attr, ++ &dev_attr_min.attr, ++ NULL ++}; ++ ++static struct attribute_group input_polldev_attribute_group = { ++ .attrs = sysfs_attrs ++}; ++ ++static const struct attribute_group *input_polldev_attribute_groups[] = { ++ &input_polldev_attribute_group, ++ NULL ++}; ++ ++/** ++ * input_allocate_polled_device - allocate memory for polled device ++ * ++ * The function allocates memory for a polled device and also ++ * for an input device associated with this polled device. ++ */ ++struct input_polled_dev *input_allocate_polled_device(void) ++{ ++ struct input_polled_dev *dev; ++ ++ dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL); ++ if (!dev) ++ return NULL; ++ ++ dev->input = input_allocate_device(); ++ if (!dev->input) { ++ kfree(dev); ++ return NULL; ++ } ++ ++ return dev; ++} ++EXPORT_SYMBOL(input_allocate_polled_device); ++ ++struct input_polled_devres { ++ struct input_polled_dev *polldev; ++}; ++ ++static int devm_input_polldev_match(struct device *dev, void *res, void *data) ++{ ++ struct input_polled_devres *devres = res; ++ ++ return devres->polldev == data; ++} ++ ++static void devm_input_polldev_release(struct device *dev, void *res) ++{ ++ struct input_polled_devres *devres = res; ++ struct input_polled_dev *polldev = devres->polldev; ++ ++ dev_dbg(dev, "%s: dropping reference/freeing %s\n", ++ __func__, dev_name(&polldev->input->dev)); ++ ++ input_put_device(polldev->input); ++ kfree(polldev); ++} ++ ++static void devm_input_polldev_unregister(struct device *dev, void *res) ++{ ++ struct input_polled_devres *devres = res; ++ struct input_polled_dev *polldev = devres->polldev; ++ ++ dev_dbg(dev, "%s: unregistering device %s\n", ++ __func__, dev_name(&polldev->input->dev)); ++ input_unregister_device(polldev->input); ++ ++ /* ++ * Note that we are still holding extra reference to the input ++ * device so it will stick around until devm_input_polldev_release() ++ * is called. ++ */ ++} ++ ++/** ++ * devm_input_allocate_polled_device - allocate managed polled device ++ * @dev: device owning the polled device being created ++ * ++ * Returns prepared &struct input_polled_dev or %NULL. ++ * ++ * Managed polled input devices do not need to be explicitly unregistered ++ * or freed as it will be done automatically when owner device unbinds ++ * from * its driver (or binding fails). Once such managed polled device ++ * is allocated, it is ready to be set up and registered in the same ++ * fashion as regular polled input devices (using ++ * input_register_polled_device() function). ++ * ++ * If you want to manually unregister and free such managed polled devices, ++ * it can be still done by calling input_unregister_polled_device() and ++ * input_free_polled_device(), although it is rarely needed. ++ * ++ * NOTE: the owner device is set up as parent of input device and users ++ * should not override it. ++ */ ++struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev) ++{ ++ struct input_polled_dev *polldev; ++ struct input_polled_devres *devres; ++ ++ devres = devres_alloc(devm_input_polldev_release, sizeof(*devres), ++ GFP_KERNEL); ++ if (!devres) ++ return NULL; ++ ++ polldev = input_allocate_polled_device(); ++ if (!polldev) { ++ devres_free(devres); ++ return NULL; ++ } ++ ++ polldev->input->dev.parent = dev; ++ polldev->devres_managed = true; ++ ++ devres->polldev = polldev; ++ devres_add(dev, devres); ++ ++ return polldev; ++} ++EXPORT_SYMBOL(devm_input_allocate_polled_device); ++ ++/** ++ * input_free_polled_device - free memory allocated for polled device ++ * @dev: device to free ++ * ++ * The function frees memory allocated for polling device and drops ++ * reference to the associated input device. ++ */ ++void input_free_polled_device(struct input_polled_dev *dev) ++{ ++ if (dev) { ++ if (dev->devres_managed) ++ WARN_ON(devres_destroy(dev->input->dev.parent, ++ devm_input_polldev_release, ++ devm_input_polldev_match, ++ dev)); ++ input_put_device(dev->input); ++ kfree(dev); ++ } ++} ++EXPORT_SYMBOL(input_free_polled_device); ++ ++/** ++ * input_register_polled_device - register polled device ++ * @dev: device to register ++ * ++ * The function registers previously initialized polled input device ++ * with input layer. The device should be allocated with call to ++ * input_allocate_polled_device(). Callers should also set up poll() ++ * method and set up capabilities (id, name, phys, bits) of the ++ * corresponding input_dev structure. ++ */ ++int input_register_polled_device(struct input_polled_dev *dev) ++{ ++ struct input_polled_devres *devres = NULL; ++ struct input_dev *input = dev->input; ++ int error; ++ ++ if (dev->devres_managed) { ++ devres = devres_alloc(devm_input_polldev_unregister, ++ sizeof(*devres), GFP_KERNEL); ++ if (!devres) ++ return -ENOMEM; ++ ++ devres->polldev = dev; ++ } ++ ++ input_set_drvdata(input, dev); ++ INIT_DELAYED_WORK(&dev->work, input_polled_device_work); ++ ++ if (!dev->poll_interval) ++ dev->poll_interval = 500; ++ if (!dev->poll_interval_max) ++ dev->poll_interval_max = dev->poll_interval; ++ ++ input->open = input_open_polled_device; ++ input->close = input_close_polled_device; ++ ++ input->dev.groups = input_polldev_attribute_groups; ++ ++ error = input_register_device(input); ++ if (error) { ++ devres_free(devres); ++ return error; ++ } ++ ++ /* ++ * Take extra reference to the underlying input device so ++ * that it survives call to input_unregister_polled_device() ++ * and is deleted only after input_free_polled_device() ++ * has been invoked. This is needed to ease task of freeing ++ * sparse keymaps. ++ */ ++ input_get_device(input); ++ ++ if (dev->devres_managed) { ++ dev_dbg(input->dev.parent, "%s: registering %s with devres.\n", ++ __func__, dev_name(&input->dev)); ++ devres_add(input->dev.parent, devres); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(input_register_polled_device); ++ ++/** ++ * input_unregister_polled_device - unregister polled device ++ * @dev: device to unregister ++ * ++ * The function unregisters previously registered polled input ++ * device from input layer. Polling is stopped and device is ++ * ready to be freed with call to input_free_polled_device(). ++ */ ++void input_unregister_polled_device(struct input_polled_dev *dev) ++{ ++ if (dev->devres_managed) ++ WARN_ON(devres_destroy(dev->input->dev.parent, ++ devm_input_polldev_unregister, ++ devm_input_polldev_match, ++ dev)); ++ ++ input_unregister_device(dev->input); ++} ++EXPORT_SYMBOL(input_unregister_polled_device); +diff -rupN linux.orig/drivers/input/keyboard/gpio_keys.c linux/drivers/input/keyboard/gpio_keys.c +--- linux.orig/drivers/input/keyboard/gpio_keys.c 2024-03-02 17:57:02.768204942 +0000 ++++ linux/drivers/input/keyboard/gpio_keys.c 2024-03-02 22:59:30.386988471 +0000 +@@ -8,7 +8,6 @@ + + #include + +-#include + #include + #include + #include +@@ -30,6 +29,29 @@ + #include + #include + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int dbg_enable = 0; ++ ++#define DBG(args...) \ ++ do { \ ++ if (dbg_enable) { \ ++ pr_info(args); \ ++ } \ ++ } while(0) ++ ++ + struct gpio_button_data { + const struct gpio_keys_button *button; + struct input_dev *input; +@@ -37,11 +59,10 @@ struct gpio_button_data { + + unsigned short *code; + +- struct hrtimer release_timer; ++ struct timer_list release_timer; + unsigned int release_delay; /* in msecs, for IRQ-only buttons */ + + struct delayed_work work; +- struct hrtimer debounce_timer; + unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ + + unsigned int irq; +@@ -50,7 +71,7 @@ struct gpio_button_data { + bool disabled; + bool key_pressed; + bool suspended; +- bool debounce_use_hrtimer; ++ + }; + + struct gpio_keys_drvdata { +@@ -58,50 +79,24 @@ struct gpio_keys_drvdata { + struct input_dev *input; + struct mutex disable_lock; + unsigned short *keymap; ++ ++// struct iio_channel *channelx; ++// struct iio_channel *channely; ++// struct iio_channel *channelz; ++// struct iio_channel *channelrz; ++// int num_joystick; ++ ++ unsigned char now_data[4]; ++ int raw_data[4]; ++ ++// int last_bra; ++// int last_gas; ++ + struct gpio_button_data data[]; + }; + +-/* +- * SYSFS interface for enabling/disabling keys and switches: +- * +- * There are 4 attributes under /sys/devices/platform/gpio-keys/ +- * keys [ro] - bitmap of keys (EV_KEY) which can be +- * disabled +- * switches [ro] - bitmap of switches (EV_SW) which can be +- * disabled +- * disabled_keys [rw] - bitmap of keys currently disabled +- * disabled_switches [rw] - bitmap of switches currently disabled +- * +- * Userland can change these values and hence disable event generation +- * for each key (or switch). Disabling a key means its interrupt line +- * is disabled. +- * +- * For example, if we have following switches set up as gpio-keys: +- * SW_DOCK = 5 +- * SW_CAMERA_LENS_COVER = 9 +- * SW_KEYPAD_SLIDE = 10 +- * SW_FRONT_PROXIMITY = 11 +- * This is read from switches: +- * 11-9,5 +- * Next we want to disable proximity (11) and dock (5), we write: +- * 11,5 +- * to file disabled_switches. Now proximity and dock IRQs are disabled. +- * This can be verified by reading the file disabled_switches: +- * 11,5 +- * If we now want to enable proximity (11) switch we write: +- * 5 +- * to disabled_switches. +- * +- * We can disable only those keys which don't allow sharing the irq. +- */ ++//static unsigned char abs_date[]={128,128,128,128}; + +-/** +- * get_n_events_by_type() - returns maximum number of events per @type +- * @type: type of button (%EV_KEY, %EV_SW) +- * +- * Return value of this function can be used to allocate bitmap +- * large enough to hold all bits for given type. +- */ + static int get_n_events_by_type(int type) + { + BUG_ON(type != EV_SW && type != EV_KEY); +@@ -111,7 +106,7 @@ static int get_n_events_by_type(int type + + /** + * get_bm_events_by_type() - returns bitmap of supported events per @type +- * @dev: input device from which bitmap is retrieved ++ * @input: input device from which bitmap is retrieved + * @type: type of button (%EV_KEY, %EV_SW) + * + * Return value of this function can be used to allocate bitmap +@@ -125,18 +120,6 @@ static const unsigned long *get_bm_event + return (type == EV_KEY) ? dev->keybit : dev->swbit; + } + +-static void gpio_keys_quiesce_key(void *data) +-{ +- struct gpio_button_data *bdata = data; +- +- if (!bdata->gpiod) +- hrtimer_cancel(&bdata->release_timer); +- else if (bdata->debounce_use_hrtimer) +- hrtimer_cancel(&bdata->debounce_timer); +- else +- cancel_delayed_work_sync(&bdata->work); +-} +- + /** + * gpio_keys_disable_button() - disables given GPIO button + * @bdata: button data for button to be disabled +@@ -157,7 +140,12 @@ static void gpio_keys_disable_button(str + * Disable IRQ and associated timer/work structure. + */ + disable_irq(bdata->irq); +- gpio_keys_quiesce_key(bdata); ++ ++ if (bdata->gpiod) ++ cancel_delayed_work_sync(&bdata->work); ++ else ++ del_timer_sync(&bdata->release_timer); ++ + bdata->disabled = true; + } + } +@@ -247,7 +235,7 @@ static ssize_t gpio_keys_attr_store_help + ssize_t error; + int i; + +- bits = bitmap_alloc(n_events, GFP_KERNEL); ++ bits = bitmap_zalloc(n_events, GFP_KERNEL); + if (!bits) + return -ENOMEM; + +@@ -363,16 +351,28 @@ static struct attribute *gpio_keys_attrs + }; + ATTRIBUTE_GROUPS(gpio_keys); + ++static void other_key_report(struct input_dev *input,unsigned int code ,int state,int value){ ++ if(state) ++ { ++ printk("11111111111other_key_report code = %d,state = %d,value = %d\n",code,state,value); ++ input_report_abs(input, code,value); ++ } ++ else{ ++ input_report_abs(input, code,0); ++ printk("00000000000other_key_report code = %d,state = %d,value = %d\n",code,state,value); ++ } ++} ++ + static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) + { + const struct gpio_keys_button *button = bdata->button; + struct input_dev *input = bdata->input; + unsigned int type = button->type ?: EV_KEY; + int state; ++ unsigned short code = 0; ++ state = gpiod_get_value_cansleep(bdata->gpiod); + +- state = bdata->debounce_use_hrtimer ? +- gpiod_get_value(bdata->gpiod) : +- gpiod_get_value_cansleep(bdata->gpiod); ++ printk("func = %s lqbirq state = %d,code = %d\n",__func__,state,*bdata->code); + if (state < 0) { + dev_err(input->dev.parent, + "failed to get gpio state: %d\n", state); +@@ -382,18 +382,23 @@ static void gpio_keys_gpio_report_event( + if (type == EV_ABS) { + if (state) + input_event(input, type, button->code, button->value); ++ printk("lqbirq type == EV_ABS"); + } else { +- input_event(input, type, *bdata->code, state); ++ code = *bdata->code; ++ if(code < BTN_DPAD_UP || code > BTN_DPAD_RIGHT){ ++ input_event(input, type, *bdata->code, state); ++ } ++ else if( code == BTN_DPAD_UP ){ ++ other_key_report(input,ABS_HAT0Y,state,-1); ++ }else if(code == BTN_DPAD_DOWN){ ++ other_key_report(input,ABS_HAT0Y,state,1); ++ }else if(code == BTN_DPAD_LEFT){ ++ other_key_report(input,ABS_HAT0X,state,-1); ++ }else if(code == BTN_DPAD_RIGHT){ ++ other_key_report(input,ABS_HAT0X,state,1); ++ } + } +-} +- +-static void gpio_keys_debounce_event(struct gpio_button_data *bdata) +-{ +- gpio_keys_gpio_report_event(bdata); +- input_sync(bdata->input); +- +- if (bdata->button->wakeup) +- pm_relax(bdata->input->dev.parent); ++ input_sync(input); + } + + static void gpio_keys_gpio_work_func(struct work_struct *work) +@@ -401,17 +406,10 @@ static void gpio_keys_gpio_work_func(str + struct gpio_button_data *bdata = + container_of(work, struct gpio_button_data, work.work); + +- gpio_keys_debounce_event(bdata); +-} +- +-static enum hrtimer_restart gpio_keys_debounce_timer(struct hrtimer *t) +-{ +- struct gpio_button_data *bdata = +- container_of(t, struct gpio_button_data, debounce_timer); +- +- gpio_keys_debounce_event(bdata); ++ gpio_keys_gpio_report_event(bdata); + +- return HRTIMER_NORESTART; ++ if (bdata->button->wakeup) ++ pm_relax(bdata->input->dev.parent); + } + + static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) +@@ -419,7 +417,7 @@ static irqreturn_t gpio_keys_gpio_isr(in + struct gpio_button_data *bdata = dev_id; + + BUG_ON(irq != bdata->irq); +- ++ DBG("lqbirq func = %s\n,irq = %d\n",__func__,irq); + if (bdata->button->wakeup) { + const struct gpio_keys_button *button = bdata->button; + +@@ -435,33 +433,25 @@ static irqreturn_t gpio_keys_gpio_isr(in + } + } + +- if (bdata->debounce_use_hrtimer) { +- hrtimer_start(&bdata->debounce_timer, +- ms_to_ktime(bdata->software_debounce), +- HRTIMER_MODE_REL); +- } else { +- mod_delayed_work(system_wq, +- &bdata->work, +- msecs_to_jiffies(bdata->software_debounce)); +- } ++ mod_delayed_work(system_wq, ++ &bdata->work, ++ msecs_to_jiffies(bdata->software_debounce)); + + return IRQ_HANDLED; + } + +-static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t) ++static void gpio_keys_irq_timer(struct timer_list *t) + { +- struct gpio_button_data *bdata = container_of(t, +- struct gpio_button_data, +- release_timer); ++ struct gpio_button_data *bdata = from_timer(bdata, t, release_timer); + struct input_dev *input = bdata->input; +- ++ unsigned long flags; ++ spin_lock_irqsave(&bdata->lock, flags); + if (bdata->key_pressed) { + input_event(input, EV_KEY, *bdata->code, 0); + input_sync(input); + bdata->key_pressed = false; + } +- +- return HRTIMER_NORESTART; ++ spin_unlock_irqrestore(&bdata->lock, flags); + } + + static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) +@@ -471,9 +461,9 @@ static irqreturn_t gpio_keys_irq_isr(int + unsigned long flags; + + BUG_ON(irq != bdata->irq); ++ DBG("func = %s,lqbjoystick irq = %d\n",__func__,irq); + + spin_lock_irqsave(&bdata->lock, flags); +- + if (!bdata->key_pressed) { + if (bdata->button->wakeup) + pm_wakeup_event(bdata->input->dev.parent, 0); +@@ -491,14 +481,22 @@ static irqreturn_t gpio_keys_irq_isr(int + } + + if (bdata->release_delay) +- hrtimer_start(&bdata->release_timer, +- ms_to_ktime(bdata->release_delay), +- HRTIMER_MODE_REL_HARD); ++ mod_timer(&bdata->release_timer, ++ jiffies + msecs_to_jiffies(bdata->release_delay)); + out: + spin_unlock_irqrestore(&bdata->lock, flags); + return IRQ_HANDLED; + } + ++static void gpio_keys_quiesce_key(void *data) ++{ ++ struct gpio_button_data *bdata = data; ++ if (bdata->gpiod) ++ cancel_delayed_work_sync(&bdata->work); ++ else ++ del_timer_sync(&bdata->release_timer); ++} ++ + static int gpio_keys_setup_key(struct platform_device *pdev, + struct input_dev *input, + struct gpio_keys_drvdata *ddata, +@@ -568,20 +566,13 @@ static int gpio_keys_setup_key(struct pl + if (error < 0) + bdata->software_debounce = + button->debounce_interval; +- +- /* +- * If reading the GPIO won't sleep, we can use a +- * hrtimer instead of a standard timer for the software +- * debounce, to reduce the latency as much as possible. +- */ +- bdata->debounce_use_hrtimer = +- !gpiod_cansleep(bdata->gpiod); + } + + if (button->irq) { + bdata->irq = button->irq; + } else { + irq = gpiod_to_irq(bdata->gpiod); ++ + if (irq < 0) { + error = irq; + dev_err(dev, +@@ -594,10 +585,6 @@ static int gpio_keys_setup_key(struct pl + + INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); + +- hrtimer_init(&bdata->debounce_timer, +- CLOCK_REALTIME, HRTIMER_MODE_REL); +- bdata->debounce_timer.function = gpio_keys_debounce_timer; +- + isr = gpio_keys_gpio_isr; + irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + +@@ -632,9 +619,7 @@ static int gpio_keys_setup_key(struct pl + } + + bdata->release_delay = button->debounce_interval; +- hrtimer_init(&bdata->release_timer, +- CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); +- bdata->release_timer.function = gpio_keys_irq_timer; ++ timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0); + + isr = gpio_keys_irq_isr; + irqflags = 0; +@@ -804,9 +789,12 @@ static int gpio_keys_probe(struct platfo + struct fwnode_handle *child = NULL; + struct gpio_keys_drvdata *ddata; + struct input_dev *input; ++ ++ int value; ++ enum iio_chan_type type; + int i, error; + int wakeup = 0; +- ++ DBG("lqb func = %s\n",__func__); + if (!pdata) { + pdata = gpio_keys_get_devtree_pdata(dev); + if (IS_ERR(pdata)) +@@ -819,6 +807,7 @@ static int gpio_keys_probe(struct platfo + dev_err(dev, "failed to allocate state\n"); + return -ENOMEM; + } ++ dev_set_drvdata(&pdev->dev,ddata); + + ddata->keymap = devm_kcalloc(dev, + pdata->nbuttons, sizeof(ddata->keymap[0]), +@@ -831,6 +820,15 @@ static int gpio_keys_probe(struct platfo + dev_err(dev, "failed to allocate input device\n"); + return -ENOMEM; + } ++ //error = input_setup_polling(input, adc_joystick_poll); ++ //if (error) { ++ // dev_err(dev, "Unable to set up polling: %d\n", error); ++ // return error; ++ //} ++ //if (!device_property_read_u32(dev, "poll-interval", &value)) ++ //{ ++ // input_set_poll_interval(input, value); ++ //} + + ddata->pdata = pdata; + ddata->input = input; +@@ -839,21 +837,57 @@ static int gpio_keys_probe(struct platfo + platform_set_drvdata(pdev, ddata); + input_set_drvdata(input, ddata); + +- input->name = pdata->name ? : pdev->name; +- input->phys = "gpio-keys/input0"; ++// input->name = "Microsoft X-Box 360 pad"; ++ input->name = "gpio-keys-control"; ++ + input->dev.parent = dev; + input->open = gpio_keys_open; + input->close = gpio_keys_close; + + input->id.bustype = BUS_HOST; +- input->id.vendor = 0x0001; +- input->id.product = 0x0001; +- input->id.version = 0x0100; ++// input->id.bustype = BUS_USB; ++ ++ input->id.vendor = 0x0003; ++ input->id.product = 0x0003; ++ ++// input->id.vendor = 0x045e; ++// input->id.product = 0x0032; ++// input->id.product = 0x0b13; ++ ++ input->id.version = 0x0110; + + input->keycode = ddata->keymap; + input->keycodesize = sizeof(ddata->keymap[0]); + input->keycodemax = pdata->nbuttons; + ++ __set_bit(EV_ABS, input->evbit); ++// __set_bit(ABS_BRAKE, input->absbit); ++// __set_bit(ABS_THROTTLE, input->absbit); ++ __set_bit(ABS_HAT0Y, input->absbit); ++ __set_bit(ABS_HAT0X, input->absbit); ++// __set_bit(ABS_X, input->absbit); ++// __set_bit(ABS_Y, input->absbit); ++// __set_bit(ABS_RX, input->absbit); ++// __set_bit(ABS_RY, input->absbit); ++// __set_bit(ABS_RZ, input->absbit); ++// __set_bit(ABS_Z, input->absbit); ++ ++// __set_bit(BTN_TL2, input->keybit); ++// __set_bit(BTN_TR2, input->keybit); ++ ++// input_set_abs_params(input, ABS_X, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_RX, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_RY, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_Y, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_Z, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_RZ, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_BRAKE, 0, 255, 0, 15); ++// input_set_abs_params(input, ABS_THROTTLE, 0, 255, 0, 15); ++ //0xff : up , 0x01 : down ++ input_set_abs_params(input, ABS_HAT0Y, -1, 1, 0, 0); ++ //0xff : left , 0x01 : right ++ input_set_abs_params(input, ABS_HAT0X, -1, 1, 0, 0); ++ + /* Enable auto repeat feature of Linux input subsystem */ + if (pdata->rep) + __set_bit(EV_REP, input->evbit); +@@ -1004,7 +1038,7 @@ static int __maybe_unused gpio_keys_susp + return error; + } else { + mutex_lock(&input->mutex); +- if (input_device_enabled(input)) ++ if (input->users) + gpio_keys_close(input); + mutex_unlock(&input->mutex); + } +@@ -1022,7 +1056,7 @@ static int __maybe_unused gpio_keys_resu + gpio_keys_disable_wakeup(ddata); + } else { + mutex_lock(&input->mutex); +- if (input_device_enabled(input)) ++ if (input->users) + error = gpio_keys_open(input); + mutex_unlock(&input->mutex); + } +diff -rupN linux.orig/include/linux/input-polldev.h linux/include/linux/input-polldev.h +--- linux.orig/include/linux/input-polldev.h 1970-01-01 00:00:00.000000000 +0000 ++++ linux/include/linux/input-polldev.h 2024-03-02 18:10:15.311564040 +0000 +@@ -0,0 +1,58 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++#ifndef _INPUT_POLLDEV_H ++#define _INPUT_POLLDEV_H ++ ++/* ++ * Copyright (c) 2007 Dmitry Torokhov ++ */ ++ ++#include ++#include ++ ++/** ++ * struct input_polled_dev - simple polled input device ++ * @private: private driver data. ++ * @open: driver-supplied method that prepares device for polling ++ * (enabled the device and maybe flushes device state). ++ * @close: driver-supplied method that is called when device is no ++ * longer being polled. Used to put device into low power mode. ++ * @poll: driver-supplied method that polls the device and posts ++ * input events (mandatory). ++ * @poll_interval: specifies how often the poll() method should be called. ++ * Defaults to 500 msec unless overridden when registering the device. ++ * @poll_interval_max: specifies upper bound for the poll interval. ++ * Defaults to the initial value of @poll_interval. ++ * @poll_interval_min: specifies lower bound for the poll interval. ++ * Defaults to 0. ++ * @input: input device structure associated with the polled device. ++ * Must be properly initialized by the driver (id, name, phys, bits). ++ * ++ * Polled input device provides a skeleton for supporting simple input ++ * devices that do not raise interrupts but have to be periodically ++ * scanned or polled to detect changes in their state. ++ */ ++struct input_polled_dev { ++ void *private; ++ ++ void (*open)(struct input_polled_dev *dev); ++ void (*close)(struct input_polled_dev *dev); ++ void (*poll)(struct input_polled_dev *dev); ++ unsigned int poll_interval; /* msec */ ++ unsigned int poll_interval_max; /* msec */ ++ unsigned int poll_interval_min; /* msec */ ++ ++ struct input_dev *input; ++ ++/* private: */ ++ struct delayed_work work; ++ ++ bool devres_managed; ++}; ++ ++struct input_polled_dev *input_allocate_polled_device(void); ++struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev); ++void input_free_polled_device(struct input_polled_dev *dev); ++int input_register_polled_device(struct input_polled_dev *dev); ++void input_unregister_polled_device(struct input_polled_dev *dev); ++ ++#endif