mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-06 00:45:22 +08:00
[dm][input] support input #11031
This commit is contained in:
@@ -22,6 +22,7 @@ rsource "graphic/Kconfig"
|
||||
rsource "hwcrypto/Kconfig"
|
||||
rsource "wlan/Kconfig"
|
||||
rsource "led/Kconfig"
|
||||
rsource "input/Kconfig"
|
||||
rsource "mailbox/Kconfig"
|
||||
rsource "phye/Kconfig"
|
||||
rsource "ata/Kconfig"
|
||||
|
||||
360
components/drivers/include/dt-bindings/input/event-codes.h
Normal file
360
components/drivers/include/dt-bindings/input/event-codes.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_INPUT_EVENT_CODES_H__
|
||||
#define __DT_BINDINGS_INPUT_EVENT_CODES_H__
|
||||
|
||||
/*
|
||||
* Event types
|
||||
*/
|
||||
|
||||
#define EV_SYN 0
|
||||
#define EV_KEY 1
|
||||
#define EV_REL 2
|
||||
#define EV_ABS 3
|
||||
#define EV_MSC 4
|
||||
#define EV_SW 5
|
||||
#define EV_LED 17
|
||||
#define EV_SND 18
|
||||
#define EV_REP 20
|
||||
#define EV_FF 21
|
||||
#define EV_PWR 22
|
||||
#define EV_FF_STATUS 23
|
||||
#define EV_MAX 31
|
||||
#define EV_CNT (EV_MAX + 1)
|
||||
|
||||
/*
|
||||
* Synchronization events.
|
||||
*/
|
||||
|
||||
#define SYN_REPORT 0
|
||||
#define SYN_CONFIG 1
|
||||
#define SYN_MT_REPORT 2
|
||||
#define SYN_DROPPED 3
|
||||
#define SYN_MAX 15
|
||||
#define SYN_CNT (SYN_MAX + 1)
|
||||
|
||||
/*
|
||||
* Keys and buttons
|
||||
*/
|
||||
|
||||
#define KEY_RESERVED 0 /* Reserved, do not use */
|
||||
#define KEY_ESC 1 /* Escape Key */
|
||||
#define KEY_1 2 /* 1 Key */
|
||||
#define KEY_2 3 /* 2 Key */
|
||||
#define KEY_3 4 /* 3 Key */
|
||||
#define KEY_4 5 /* 4 Key */
|
||||
#define KEY_5 6 /* 5 Key */
|
||||
#define KEY_6 7 /* 6 Key */
|
||||
#define KEY_7 8 /* 7 Key */
|
||||
#define KEY_8 9 /* 8 Key */
|
||||
#define KEY_9 10 /* 9 Key */
|
||||
#define KEY_0 11 /* 0 Key */
|
||||
#define KEY_MINUS 12 /* Minus Key */
|
||||
#define KEY_EQUAL 13 /* Equal Key */
|
||||
#define KEY_BACKSPACE 14 /* Backspace Key */
|
||||
#define KEY_TAB 15 /* Tab Key*/
|
||||
#define KEY_Q 16 /* Q Key */
|
||||
#define KEY_W 17 /* W Key */
|
||||
#define KEY_E 18 /* E Key */
|
||||
#define KEY_R 19 /* R Key */
|
||||
#define KEY_T 20 /* T Key */
|
||||
#define KEY_Y 21 /* Y Key */
|
||||
#define KEY_U 22 /* U Key */
|
||||
#define KEY_I 23 /* I Key */
|
||||
#define KEY_O 24 /* O Key */
|
||||
#define KEY_P 25 /* P Key */
|
||||
#define KEY_LEFTBRACE 26 /* Left Brace Key */
|
||||
#define KEY_RIGHTBRACE 27 /* Right Brace Key */
|
||||
#define KEY_ENTER 28 /* Enter Key */
|
||||
#define KEY_LEFTCTRL 29 /* Left Ctrl Key */
|
||||
#define KEY_A 30 /* A Key */
|
||||
#define KEY_S 31 /* S Key */
|
||||
#define KEY_D 32 /* D Key */
|
||||
#define KEY_F 33 /* F Key */
|
||||
#define KEY_G 34 /* G Key */
|
||||
#define KEY_H 35 /* H Key */
|
||||
#define KEY_J 36 /* J Key */
|
||||
#define KEY_K 37 /* K Key */
|
||||
#define KEY_L 38 /* L Key */
|
||||
#define KEY_SEMICOLON 39 /* Semicolon Key */
|
||||
#define KEY_APOSTROPHE 40 /* Apostrophe Key */
|
||||
#define KEY_GRAVE 41 /* Grave (backtick) Key */
|
||||
#define KEY_LEFTSHIFT 42 /* Left Shift Key */
|
||||
#define KEY_BACKSLASH 43 /* Backslash Key */
|
||||
#define KEY_Z 44 /* Z Key */
|
||||
#define KEY_X 45 /* X Key */
|
||||
#define KEY_C 46 /* C Key */
|
||||
#define KEY_V 47 /* V Key */
|
||||
#define KEY_B 48 /* B Key */
|
||||
#define KEY_N 49 /* N Key */
|
||||
#define KEY_M 50 /* M Key */
|
||||
#define KEY_COMMA 51 /* Comma Key */
|
||||
#define KEY_DOT 52 /* Dot Key */
|
||||
#define KEY_SLASH 53 /* Slash Key */
|
||||
#define KEY_RIGHTSHIFT 54 /* Right Shift Key */
|
||||
#define KEY_KPASTERISK 55 /* Keypad Asterisk Key */
|
||||
#define KEY_LEFTALT 56 /* Left Alt Key */
|
||||
#define KEY_SPACE 57 /* Space Key */
|
||||
#define KEY_CAPSLOCK 58 /* Caps Lock Key */
|
||||
#define KEY_F1 59 /* F1 Key */
|
||||
#define KEY_F2 60 /* F2 Key */
|
||||
#define KEY_F3 61 /* F3 Key */
|
||||
#define KEY_F4 62 /* F4 Key */
|
||||
#define KEY_F5 63 /* F5 Key */
|
||||
#define KEY_F6 64 /* F6 Key */
|
||||
#define KEY_F7 65 /* F7 Key */
|
||||
#define KEY_F8 66 /* F8 Key */
|
||||
#define KEY_F9 67 /* F9 Key */
|
||||
#define KEY_F10 68 /* F10 Key */
|
||||
#define KEY_NUMLOCK 69 /* Num Lock Key */
|
||||
#define KEY_SCROLLLOCK 70 /* Scroll Lock Key */
|
||||
#define KEY_KP7 71 /* Keypad 7 Key */
|
||||
#define KEY_KP8 72 /* Keypad 8 Key */
|
||||
#define KEY_KP9 73 /* Keypad 9 Key */
|
||||
#define KEY_KPMINUS 74 /* Keypad Minus Key */
|
||||
#define KEY_KP4 75 /* Keypad 4 Key */
|
||||
#define KEY_KP5 76 /* Keypad 5 Key */
|
||||
#define KEY_KP6 77 /* Keypad 6 Key */
|
||||
#define KEY_KPPLUS 78 /* Keypad Plus Key */
|
||||
#define KEY_KP1 79 /* Keypad 1 Key */
|
||||
#define KEY_KP2 80 /* Keypad 2 Key */
|
||||
#define KEY_KP3 81 /* Keypad 3 Key */
|
||||
#define KEY_KP0 82 /* Keypad 0 Key */
|
||||
#define KEY_KPDOT 83 /* Keypad Dot Key */
|
||||
#define KEY_F11 87 /* F11 Key */
|
||||
#define KEY_F12 88 /* F12 Key */
|
||||
#define KEY_KPENTER 96 /* Keypad Enter Key */
|
||||
#define KEY_RIGHTCTRL 97 /* Right Ctrl Key */
|
||||
#define KEY_KPSLASH 98 /* Keypad Slash Key */
|
||||
#define KEY_SYSRQ 99 /* SysReq Key */
|
||||
#define KEY_RIGHTALT 100 /* Right Alt Key */
|
||||
#define KEY_HOME 102 /* Home Key */
|
||||
#define KEY_UP 103 /* Up Key */
|
||||
#define KEY_PAGEUP 104 /* Page UpKey */
|
||||
#define KEY_LEFT 105 /* Left Key */
|
||||
#define KEY_RIGHT 106 /* Right Key */
|
||||
#define KEY_END 107 /* End Key */
|
||||
#define KEY_DOWN 108 /* Down Key */
|
||||
#define KEY_PAGEDOWN 109 /* Page Down Key */
|
||||
#define KEY_INSERT 110 /* Insert Key */
|
||||
#define KEY_DELETE 111 /* Delete Key */
|
||||
#define KEY_MUTE 113 /* Mute Key */
|
||||
#define KEY_VOLUMEDOWN 114 /* Volume Down Key */
|
||||
#define KEY_VOLUMEUP 115 /* Volume Up Key */
|
||||
#define KEY_POWER 116 /* Power Key */
|
||||
#define KEY_KPEQUAL 117 /* Keypad Equal Key */
|
||||
#define KEY_KPPLUSMINUS 118 /* Keypad Plus Key */
|
||||
#define KEY_PAUSE 119 /* Pause Key */
|
||||
#define KEY_SCALE 120 /* Scale Key */
|
||||
#define KEY_KPCOMMA 121 /* Keypad Comma Key */
|
||||
#define KEY_LEFTMETA 125 /* Left Meta Key */
|
||||
#define KEY_RIGHTMETA 126 /* Right Meta Key */
|
||||
#define KEY_COMPOSE 127 /* Compose Key */
|
||||
#define KEY_STOP 128 /* AC Stop */
|
||||
#define KEY_MENU 139 /* Menu Key */
|
||||
#define KEY_SETUP 141
|
||||
#define KEY_SLEEP 142 /* System Sleep Key */
|
||||
#define KEY_WAKEUP 143 /* System Wake Up Key */
|
||||
#define KEY_COFFEE 152 /* Screen Saver Key */
|
||||
#define KEY_BACK 158 /* Back Key */
|
||||
#define KEY_FORWARD 159 /* Forward Key */
|
||||
#define KEY_PLAYPAUSE 164
|
||||
#define KEY_RECORD 167
|
||||
#define KEY_REWIND 168
|
||||
#define KEY_EXIT 174 /* AC Exit */
|
||||
#define KEY_F13 183 /* F13 Key */
|
||||
#define KEY_F14 184 /* F14 Key */
|
||||
#define KEY_F15 185 /* F15 Key */
|
||||
#define KEY_F16 186 /* F16 Key */
|
||||
#define KEY_F17 187 /* F17 Key */
|
||||
#define KEY_F18 188 /* F18 Key */
|
||||
#define KEY_F19 189 /* F19 Key */
|
||||
#define KEY_F20 190 /* F20 Key */
|
||||
#define KEY_F21 191 /* F21 Key */
|
||||
#define KEY_F22 192 /* F22 Key */
|
||||
#define KEY_F23 193 /* F23 Key */
|
||||
#define KEY_F24 194 /* F24 Key */
|
||||
#define KEY_PLAY 207 /* Play Key */
|
||||
#define KEY_FASTFORWARD 208 /* Fast Forward Key */
|
||||
#define KEY_PRINT 210 /* Print Key */
|
||||
#define KEY_CONNECT 218 /* Connect Key */
|
||||
#define KEY_CANCEL 223 /* AC Cancel */
|
||||
#define KEY_BRIGHTNESSDOWN 224 /* Brightness Down Key */
|
||||
#define KEY_BRIGHTNESSUP 225 /* Brightneess Up Key */
|
||||
#define KEY_MEDIA 226 /* Media toggle */
|
||||
#define KEY_BLUETOOTH 237 /* Bluetooth Key */
|
||||
#define KEY_WLAN 238 /* Wireless LAN Key */
|
||||
#define KEY_UWB 239 /* Ultra-Wideband Key */
|
||||
#define KEY_SELECT 353
|
||||
#define KEY_CLEAR 355
|
||||
#define KEY_INFO 358 /* AL OEM Features/Tips/Tutorial */
|
||||
#define KEY_PROGRAM 362 /* Media Select Program Guide */
|
||||
#define KEY_CALENDAR 397
|
||||
#define KEY_RED 398
|
||||
#define KEY_GREEN 399
|
||||
#define KEY_YELLOW 400
|
||||
#define KEY_BLUE 401
|
||||
#define KEY_CHANNELUP 402 /* Channel Increment */
|
||||
#define KEY_CHANNELDOWN 403 /* Channel Decrement */
|
||||
#define KEY_RESTART 408 /* Restart Key */
|
||||
|
||||
#define BTN_MISC 256
|
||||
#define BTN_0 256
|
||||
#define BTN_1 257
|
||||
#define BTN_2 258
|
||||
#define BTN_3 259
|
||||
#define BTN_4 260
|
||||
#define BTN_5 261
|
||||
#define BTN_6 262
|
||||
#define BTN_7 263
|
||||
#define BTN_8 264
|
||||
#define BTN_9 265
|
||||
|
||||
#define BTN_MOUSE 272
|
||||
#define BTN_LEFT 272
|
||||
#define BTN_RIGHT 273
|
||||
#define BTN_MIDDLE 274
|
||||
#define BTN_SIDE 275
|
||||
#define BTN_EXTRA 276
|
||||
#define BTN_FORWARD 277
|
||||
#define BTN_BACK 278
|
||||
#define BTN_TASK 279
|
||||
|
||||
#define BTN_JOYSTICK 288
|
||||
#define BTN_TRIGGER 288
|
||||
#define BTN_THUMB 289
|
||||
#define BTN_THUMB2 290
|
||||
#define BTN_TOP 291
|
||||
#define BTN_TOP2 292
|
||||
#define BTN_PINKIE 293
|
||||
#define BTN_BASE 294
|
||||
#define BTN_BASE2 295
|
||||
#define BTN_BASE3 296
|
||||
#define BTN_BASE4 297
|
||||
#define BTN_BASE5 298
|
||||
#define BTN_BASE6 299
|
||||
#define BTN_DEAD 303
|
||||
|
||||
#define BTN_GAMEPAD 304
|
||||
#define BTN_SOUTH 304
|
||||
#define BTN_A BTN_SOUTH
|
||||
#define BTN_EAST 305
|
||||
#define BTN_B BTN_EAST
|
||||
#define BTN_C 306
|
||||
#define BTN_NORTH 307
|
||||
#define BTN_X BTN_NORTH
|
||||
#define BTN_WEST 308
|
||||
#define BTN_Y BTN_WEST
|
||||
#define BTN_Z 309
|
||||
#define BTN_TL 310
|
||||
#define BTN_TR 311
|
||||
#define BTN_TL2 312
|
||||
#define BTN_TR2 313
|
||||
#define BTN_SELECT 314
|
||||
#define BTN_START 315
|
||||
#define BTN_MODE 316
|
||||
#define BTN_THUMBL 317
|
||||
#define BTN_THUMBR 318
|
||||
|
||||
#define BTN_DIGI 320
|
||||
#define BTN_TOOL_PEN 320
|
||||
#define BTN_TOOL_RUBBER 321
|
||||
#define BTN_TOOL_BRUSH 322
|
||||
#define BTN_TOOL_PENCIL 323
|
||||
#define BTN_TOOL_AIRBRUSH 324
|
||||
#define BTN_TOOL_FINGER 325
|
||||
#define BTN_TOOL_MOUSE 326
|
||||
#define BTN_TOOL_LENS 327
|
||||
#define BTN_TOOL_QUINTTAP 328 /* Five fingers on trackpad */
|
||||
#define BTN_STYLUS3 329
|
||||
#define BTN_TOUCH 330
|
||||
#define BTN_STYLUS 331
|
||||
#define BTN_STYLUS2 332
|
||||
#define BTN_TOOL_DOUBLETAP 333
|
||||
#define BTN_TOOL_TRIPLETAP 334
|
||||
#define BTN_TOOL_QUADTAP 335 /* Four fingers on trackpad */
|
||||
|
||||
#define KEY_MAX 767
|
||||
#define KEY_CNT (KEY_MAX + 1)
|
||||
|
||||
#define BTN_TOUCH 330
|
||||
|
||||
/*
|
||||
* Relative axes
|
||||
*/
|
||||
|
||||
#define REL_X 0
|
||||
#define REL_Y 1
|
||||
#define REL_Z 2
|
||||
#define REL_RX 3
|
||||
#define REL_RY 4
|
||||
#define REL_RZ 5
|
||||
#define REL_HWHEEL 6
|
||||
#define REL_DIAL 7
|
||||
#define REL_WHEEL 8
|
||||
#define REL_MISC 9
|
||||
#define REL_RESERVED 10
|
||||
#define REL_WHEEL_HI_RES 11
|
||||
#define REL_HWHEEL_HI_RES 12
|
||||
#define REL_MAX 15
|
||||
#define REL_CNT (REL_MAX + 1)
|
||||
|
||||
/*
|
||||
* Absolute axes
|
||||
*/
|
||||
|
||||
#define ABS_X 0
|
||||
#define ABS_Y 1
|
||||
#define ABS_Z 2
|
||||
#define ABS_RX 3
|
||||
#define ABS_RY 4
|
||||
#define ABS_RZ 5
|
||||
#define ABS_THROTTLE 6
|
||||
#define ABS_RUDDER 7
|
||||
#define ABS_WHEEL 8
|
||||
#define ABS_GAS 9
|
||||
#define ABS_BRAKE 10
|
||||
#define ABS_HAT0X 16
|
||||
#define ABS_HAT0Y 17
|
||||
#define ABS_HAT1X 18
|
||||
#define ABS_HAT1Y 19
|
||||
#define ABS_HAT2X 20
|
||||
#define ABS_HAT2Y 21
|
||||
#define ABS_HAT3X 22
|
||||
#define ABS_HAT3Y 23
|
||||
#define ABS_PRESSURE 24
|
||||
#define ABS_DISTANCE 25
|
||||
#define ABS_TILT_X 26
|
||||
#define ABS_TILT_Y 27
|
||||
#define ABS_TOOL_WIDTH 28
|
||||
|
||||
#define ABS_VOLUME 32
|
||||
#define ABS_PROFILE 33
|
||||
|
||||
#define ABS_MISC 40
|
||||
#define ABS_RESERVED 46
|
||||
|
||||
#define ABS_MT_SLOT 47 /* MT slot being modified */
|
||||
#define ABS_MT_TOUCH_MAJOR 48 /* Major axis of touching ellipse */
|
||||
#define ABS_MT_TOUCH_MINOR 49 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_WIDTH_MAJOR 50 /* Major axis of approaching ellipse */
|
||||
#define ABS_MT_WIDTH_MINOR 51 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_ORIENTATION 52 /* Ellipse orientation */
|
||||
#define ABS_MT_POSITION_X 53 /* Center X touch position */
|
||||
#define ABS_MT_POSITION_Y 54 /* Center Y touch position */
|
||||
#define ABS_MT_TOOL_TYPE 55 /* Type of touching device */
|
||||
#define ABS_MT_BLOB_ID 56 /* Group a set of packets as a blob */
|
||||
#define ABS_MT_TRACKING_ID 57 /* Unique ID of initiated contact */
|
||||
#define ABS_MT_PRESSURE 58 /* Pressure on contact area */
|
||||
#define ABS_MT_DISTANCE 59 /* Contact hover distance */
|
||||
#define ABS_MT_TOOL_X 60 /* Center X tool position */
|
||||
#define ABS_MT_TOOL_Y 61 /* Center Y tool position */
|
||||
|
||||
#define ABS_MAX 63
|
||||
#define ABS_CNT (ABS_MAX + 1)
|
||||
|
||||
#endif /* __DT_BINDINGS_INPUT_EVENT_CODES_H__ */
|
||||
@@ -53,7 +53,14 @@ extern "C" {
|
||||
|
||||
#ifdef RT_USING_LED
|
||||
#include "drivers/led.h"
|
||||
#endif /* RT_USING_LED */
|
||||
|
||||
#ifdef RT_USING_INPUT
|
||||
#include "drivers/input.h"
|
||||
#ifdef RT_INPUT_UAPI
|
||||
#include "drivers/input_uapi.h"
|
||||
#endif
|
||||
#endif /* RT_USING_INPUT */
|
||||
|
||||
#ifdef RT_USING_MBOX
|
||||
#include "drivers/mailbox.h"
|
||||
|
||||
36
components/drivers/input/Kconfig
Normal file
36
components/drivers/input/Kconfig
Normal file
@@ -0,0 +1,36 @@
|
||||
menuconfig RT_USING_INPUT
|
||||
bool "Using Input device drivers"
|
||||
depends on RT_USING_DM
|
||||
select RT_USING_ADT
|
||||
select RT_USING_ADT_BITMAP
|
||||
default n
|
||||
|
||||
config RT_INPUT_POWER
|
||||
bool "Input event power"
|
||||
depends on RT_USING_INPUT
|
||||
default y
|
||||
|
||||
config RT_INPUT_UAPI
|
||||
bool "Input event Unix API"
|
||||
depends on RT_USING_INPUT
|
||||
depends on RT_USING_KTIME
|
||||
depends on RT_USING_POSIX_DEVIO
|
||||
default n
|
||||
default y if RT_USING_SMART
|
||||
|
||||
config RT_INPUT_UAPI_EVENT_MAX
|
||||
int "Events storage max"
|
||||
depends on RT_INPUT_UAPI
|
||||
default 128
|
||||
|
||||
config RT_UAPI_FAKE_BLOCK
|
||||
bool "Events fake when block"
|
||||
depends on RT_INPUT_UAPI
|
||||
default y
|
||||
|
||||
if RT_USING_INPUT
|
||||
rsource "joystick/Kconfig"
|
||||
rsource "keyboard/Kconfig"
|
||||
rsource "misc/Kconfig"
|
||||
rsource "touchscreen/Kconfig"
|
||||
endif
|
||||
32
components/drivers/input/SConscript
Normal file
32
components/drivers/input/SConscript
Normal file
@@ -0,0 +1,32 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
objs = []
|
||||
|
||||
if not GetDepend(['RT_USING_INPUT']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
list = os.listdir(cwd)
|
||||
CPPPATH = [cwd + '/../include']
|
||||
|
||||
src = ['input.c']
|
||||
|
||||
if GetDepend(['RT_INPUT_POWER']):
|
||||
src += ['input_power.c']
|
||||
|
||||
if GetDepend(['RT_INPUT_TOUCHSCREEN']):
|
||||
src += ['input_touch.c']
|
||||
|
||||
if GetDepend(['RT_INPUT_UAPI']):
|
||||
src += ['input_uapi.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
objs = objs + group
|
||||
|
||||
Return('objs')
|
||||
405
components/drivers/input/input.c
Normal file
405
components/drivers/input/input.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "rtdm.input"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
static RT_DEFINE_SPINLOCK(input_device_lock);
|
||||
static rt_list_t input_device_nodes = RT_LIST_OBJECT_INIT(input_device_nodes);
|
||||
|
||||
static struct rt_dm_ida input_ida = RT_DM_IDA_INIT(INPUT);
|
||||
|
||||
#ifdef RT_INPUT_TOUCHSCREEN
|
||||
extern void input_touch_register(struct rt_input_device *idev);
|
||||
extern void input_touch_unregister(struct rt_input_device *idev);
|
||||
#endif
|
||||
|
||||
#ifdef RT_INPUT_UAPI
|
||||
extern void input_uapi_init(struct rt_input_device *idev);
|
||||
extern void input_uapi_finit(struct rt_input_device *idev);
|
||||
extern void input_uapi_event(struct rt_input_device *idev, struct rt_input_event *event);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops _input_ops =
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_input_device_register(struct rt_input_device *idev)
|
||||
{
|
||||
rt_err_t err;
|
||||
int device_id;
|
||||
const char *dev_name;
|
||||
|
||||
if (!idev)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
if ((device_id = rt_dm_ida_alloc(&input_ida)) < 0)
|
||||
{
|
||||
err = -RT_EFULL;
|
||||
goto _remove_config;
|
||||
}
|
||||
|
||||
rt_dm_dev_set_name(&idev->parent, "input%u", device_id);
|
||||
dev_name = rt_dm_dev_get_name(&idev->parent);
|
||||
|
||||
rt_list_init(&idev->list);
|
||||
rt_list_init(&idev->handler_nodes);
|
||||
rt_spin_lock_init(&idev->lock);
|
||||
|
||||
/* Just make a search interface */
|
||||
idev->parent.type = RT_Device_Class_Char;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
idev->parent.ops = idev->parent.ops ? : &_input_ops;
|
||||
#endif
|
||||
idev->parent.master_id = input_ida.master_id;
|
||||
idev->parent.device_id = device_id;
|
||||
|
||||
if ((err = rt_device_register(&idev->parent, dev_name, RT_DEVICE_FLAG_DEACTIVATE)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
#ifdef RT_INPUT_UAPI
|
||||
input_uapi_init(idev);
|
||||
#endif
|
||||
|
||||
rt_spin_lock(&input_device_lock);
|
||||
rt_list_insert_before(&input_device_nodes, &idev->list);
|
||||
rt_spin_unlock(&input_device_lock);
|
||||
|
||||
#ifdef RT_INPUT_TOUCHSCREEN
|
||||
/* MUST be registered after the list is inserted */
|
||||
input_touch_register(idev);
|
||||
#endif
|
||||
|
||||
if (idev->poller)
|
||||
{
|
||||
rt_timer_start(&idev->poller->timer);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail:
|
||||
rt_dm_ida_free(&input_ida, device_id);
|
||||
|
||||
_remove_config:
|
||||
rt_input_remove_config(idev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t rt_input_device_unregister(struct rt_input_device *idev)
|
||||
{
|
||||
const char *dev_name;
|
||||
|
||||
if (!idev)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
dev_name = rt_dm_dev_get_name(&idev->parent);
|
||||
|
||||
if (idev->parent.ref_count)
|
||||
{
|
||||
LOG_E("%s: there is %u user", dev_name, idev->parent.ref_count);
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
#ifdef RT_INPUT_UAPI
|
||||
input_uapi_finit(idev);
|
||||
#endif
|
||||
#ifdef RT_INPUT_TOUCHSCREEN
|
||||
input_touch_unregister(idev);
|
||||
#endif
|
||||
rt_input_remove_config(idev);
|
||||
|
||||
rt_dm_ida_free(&input_ida, idev->parent.device_id);
|
||||
|
||||
rt_device_unregister(&idev->parent);
|
||||
|
||||
rt_spin_lock(&input_device_lock);
|
||||
rt_list_remove(&idev->list);
|
||||
rt_spin_unlock(&input_device_lock);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_input_set_capability(struct rt_input_device *idev,
|
||||
rt_uint16_t type, rt_uint16_t code)
|
||||
{
|
||||
if (!idev)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EV_KEY:
|
||||
rt_bitmap_set_bit(idev->key_map, code);
|
||||
break;
|
||||
|
||||
case EV_REL:
|
||||
rt_bitmap_set_bit(idev->rel_map, code);
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
if (!idev->absinfo)
|
||||
{
|
||||
idev->absinfo = rt_calloc(ABS_CNT, sizeof(*idev->absinfo));
|
||||
|
||||
if (!idev->absinfo)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
}
|
||||
rt_bitmap_set_bit(idev->abs_map, code);
|
||||
break;
|
||||
|
||||
case EV_MSC:
|
||||
case EV_SW:
|
||||
case EV_LED:
|
||||
case EV_SND:
|
||||
case EV_REP:
|
||||
case EV_FF:
|
||||
case EV_PWR:
|
||||
case EV_FF_STATUS:
|
||||
return -RT_ENOSYS;
|
||||
|
||||
default:
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
rt_bitmap_set_bit(idev->cap, type);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_input_set_absinfo(struct rt_input_device *idev, rt_uint32_t axis,
|
||||
rt_int32_t min, rt_int32_t max, rt_int32_t fuzz, rt_int32_t flat)
|
||||
{
|
||||
struct rt_input_absinfo *absinfo;
|
||||
|
||||
if (!idev || !idev->absinfo)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
rt_bitmap_set_bit(idev->abs_map, axis);
|
||||
|
||||
absinfo = &idev->absinfo[axis];
|
||||
absinfo->minimum = min;
|
||||
absinfo->maximum = max;
|
||||
absinfo->fuzz = fuzz;
|
||||
absinfo->flat = flat;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void input_poll(void *param)
|
||||
{
|
||||
struct rt_input_device *idev = param;
|
||||
|
||||
idev->poller->poll(idev);
|
||||
}
|
||||
|
||||
rt_err_t rt_input_setup_polling(struct rt_input_device *idev,
|
||||
void (*poll)(struct rt_input_device *idev))
|
||||
{
|
||||
const char *dev_name;
|
||||
|
||||
if (!idev || !poll)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
dev_name = rt_dm_dev_get_name(&idev->parent);
|
||||
|
||||
idev->poller = rt_malloc(sizeof(*idev->poller));
|
||||
|
||||
if (!idev->poller)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
idev->poller->poll = poll;
|
||||
|
||||
rt_timer_init(&idev->poller->timer, dev_name, input_poll, idev,
|
||||
rt_tick_from_millisecond(RT_INPUT_POLL_INTERVAL_DEFAULT),
|
||||
RT_TIMER_FLAG_PERIODIC);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void rt_input_remove_config(struct rt_input_device *idev)
|
||||
{
|
||||
if (!idev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (idev->poller)
|
||||
{
|
||||
rt_timer_stop(&idev->poller->timer);
|
||||
rt_timer_detach(&idev->poller->timer);
|
||||
|
||||
rt_free(idev->poller);
|
||||
idev->poller = RT_NULL;
|
||||
}
|
||||
|
||||
if (idev->absinfo)
|
||||
{
|
||||
rt_free(idev->absinfo);
|
||||
idev->absinfo = RT_NULL;
|
||||
}
|
||||
|
||||
#ifdef RT_INPUT_TOUCHSCREEN
|
||||
if (idev->touch)
|
||||
{
|
||||
rt_free(idev->touch);
|
||||
idev->touch = RT_NULL;
|
||||
}
|
||||
#endif /* RT_INPUT_TOUCHSCREEN */
|
||||
}
|
||||
|
||||
rt_err_t rt_input_set_poll_interval(struct rt_input_device *idev,
|
||||
rt_uint32_t interval_ms)
|
||||
{
|
||||
rt_tick_t tick;
|
||||
|
||||
if (!idev || !idev->poller)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
tick = rt_tick_from_millisecond(interval_ms);
|
||||
|
||||
return rt_timer_control(&idev->poller->timer, RT_TIMER_CTRL_SET_TIME, &tick);
|
||||
}
|
||||
|
||||
rt_err_t rt_input_trigger(struct rt_input_device *idev,
|
||||
rt_uint16_t type, rt_uint16_t code, rt_int32_t value)
|
||||
{
|
||||
RT_ASSERT(idev != RT_NULL);
|
||||
|
||||
if (idev->trigger)
|
||||
{
|
||||
return idev->trigger(idev, type, code, value);
|
||||
}
|
||||
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
void rt_input_event(struct rt_input_device *idev,
|
||||
rt_uint16_t type, rt_uint16_t code, rt_int32_t value)
|
||||
{
|
||||
struct rt_input_event event;
|
||||
struct rt_input_handler *handler, *handler_next;
|
||||
|
||||
RT_ASSERT(idev != RT_NULL);
|
||||
RT_ASSERT(type < EV_MAX);
|
||||
|
||||
event.tick = rt_tick_get();
|
||||
event.type = type;
|
||||
event.code = code;
|
||||
event.value = value;
|
||||
|
||||
rt_spin_lock(&idev->lock);
|
||||
|
||||
#ifdef RT_INPUT_UAPI
|
||||
input_uapi_event(idev, &event);
|
||||
#endif
|
||||
|
||||
rt_list_for_each_entry_safe(handler, handler_next, &idev->handler_nodes, list)
|
||||
{
|
||||
if (handler->callback(handler, &event))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rt_spin_unlock(&idev->lock);
|
||||
}
|
||||
|
||||
rt_err_t rt_input_add_handler(struct rt_input_handler *handler)
|
||||
{
|
||||
struct rt_input_device *idev = RT_NULL, *idev_tmp;
|
||||
|
||||
if (!handler || !handler->callback)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
if (!handler->idev && !handler->identify)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
rt_spin_lock(&input_device_lock);
|
||||
|
||||
rt_list_for_each_entry(idev_tmp, &input_device_nodes, list)
|
||||
{
|
||||
if (handler->idev)
|
||||
{
|
||||
if (handler->idev == idev_tmp)
|
||||
{
|
||||
idev = idev_tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (handler->identify(handler, idev_tmp))
|
||||
{
|
||||
idev = idev_tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rt_spin_unlock(&input_device_lock);
|
||||
|
||||
if (!idev)
|
||||
{
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
handler->idev = idev;
|
||||
rt_list_init(&handler->list);
|
||||
|
||||
rt_spin_lock(&idev->lock);
|
||||
rt_list_insert_before(&idev->handler_nodes, &handler->list);
|
||||
rt_spin_unlock(&idev->lock);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_input_del_handler(struct rt_input_handler *handler)
|
||||
{
|
||||
struct rt_input_device *idev;
|
||||
|
||||
if (!handler)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
idev = handler->idev;
|
||||
|
||||
rt_spin_lock(&idev->lock);
|
||||
rt_list_remove(&handler->list);
|
||||
rt_spin_unlock(&idev->lock);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
130
components/drivers/input/input_power.c
Normal file
130
components/drivers/input/input_power.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "input.power"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
struct input_event_cap
|
||||
{
|
||||
rt_uint16_t code;
|
||||
rt_int32_t value;
|
||||
rt_int32_t current;
|
||||
};
|
||||
|
||||
static rt_bool_t power_input_identify(struct rt_input_handler *handler,
|
||||
struct rt_input_device *idev)
|
||||
{
|
||||
struct input_event_cap *cap = handler->priv;
|
||||
|
||||
if (rt_bitmap_test_bit(idev->key_map, cap->code))
|
||||
{
|
||||
if (cap->value == cap->current)
|
||||
{
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
++cap->current;
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
static rt_bool_t power_input_callback(struct rt_input_handler *handler,
|
||||
struct rt_input_event *ev)
|
||||
{
|
||||
if (ev->code == KEY_POWER)
|
||||
{
|
||||
if (ev->value == 0)
|
||||
{
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
return RT_TRUE;
|
||||
}
|
||||
else if (ev->code == KEY_RESTART)
|
||||
{
|
||||
if (ev->value == 0)
|
||||
{
|
||||
rt_hw_cpu_reset();
|
||||
}
|
||||
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
static rt_bool_t power_test_cap(struct rt_input_handler *handler,
|
||||
struct rt_input_device *idev)
|
||||
{
|
||||
struct input_event_cap *cap = handler->priv;
|
||||
|
||||
if (rt_bitmap_test_bit(idev->key_map, cap->code))
|
||||
{
|
||||
++cap->value;
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
static void power_handler_install(rt_uint16_t code)
|
||||
{
|
||||
rt_uint32_t idev_count;
|
||||
struct input_event_cap cap;
|
||||
struct rt_input_handler tmp_handler, *handlers;
|
||||
|
||||
cap.code = code;
|
||||
cap.value = 0;
|
||||
tmp_handler.idev = RT_NULL;
|
||||
tmp_handler.identify = &power_test_cap;
|
||||
tmp_handler.callback = &power_input_callback;
|
||||
tmp_handler.priv = ∩
|
||||
rt_input_add_handler(&tmp_handler); /* Just test */
|
||||
|
||||
if (!(idev_count = cap.value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handlers = rt_calloc(idev_count, sizeof(*handlers));
|
||||
|
||||
if (!handlers)
|
||||
{
|
||||
LOG_E("No memory to install power handler");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < idev_count; ++i, ++handlers)
|
||||
{
|
||||
cap.value = i;
|
||||
cap.current = 0;
|
||||
|
||||
handlers->identify = &power_input_identify;
|
||||
handlers->callback = &power_input_callback;
|
||||
handlers->priv = ∩
|
||||
|
||||
rt_input_add_handler(handlers);
|
||||
handlers->priv = RT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int input_event_power_init(void)
|
||||
{
|
||||
power_handler_install(KEY_POWER);
|
||||
power_handler_install(KEY_RESTART);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_ENV_EXPORT(input_event_power_init);
|
||||
453
components/drivers/input/input_touch.c
Normal file
453
components/drivers/input/input_touch.c
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "input.touch"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
struct input_touch_device
|
||||
{
|
||||
struct rt_touch_device parent;
|
||||
struct rt_input_handler handler;
|
||||
|
||||
rt_bool_t enabled;
|
||||
rt_uint16_t slot;
|
||||
rt_uint16_t down;
|
||||
struct rt_touch_data points[];
|
||||
};
|
||||
|
||||
struct input_touch_properties
|
||||
{
|
||||
rt_uint32_t max_x;
|
||||
rt_uint32_t max_y;
|
||||
rt_bool_t invert_x;
|
||||
rt_bool_t invert_y;
|
||||
rt_bool_t swap_x_y;
|
||||
|
||||
rt_uint16_t track_id;
|
||||
rt_uint32_t num_slots;
|
||||
struct input_touch_device *touch_dev;
|
||||
};
|
||||
|
||||
static rt_size_t input_touch_readpoint(struct rt_touch_device *touch,
|
||||
void *buf, rt_size_t touch_num)
|
||||
{
|
||||
struct input_touch_device *touch_dev;
|
||||
|
||||
touch_dev = rt_container_of(touch, struct input_touch_device, parent);
|
||||
|
||||
rt_memcpy(buf, &touch_dev->points[touch_dev->slot], sizeof(struct rt_touch_data));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static rt_err_t input_touch_control(struct rt_touch_device *touch, int cmd, void *arg)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
struct input_touch_device *touch_dev;
|
||||
|
||||
if (!arg)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
touch_dev = rt_container_of(touch, struct input_touch_device, parent);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_TOUCH_CTRL_GET_ID:
|
||||
*(int *)arg = 0;
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_GET_INFO:
|
||||
rt_memcpy(arg, &touch_dev->parent.info, sizeof(touch_dev->parent.info));
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_SET_X_RANGE:
|
||||
touch_dev->parent.info.range_x = *(rt_uint16_t *)arg;
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_SET_Y_RANGE:
|
||||
touch_dev->parent.info.range_y = *(rt_uint16_t *)arg;
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_SET_X_TO_Y:
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_DISABLE_INT:
|
||||
case RT_TOUCH_CTRL_POWER_OFF:
|
||||
touch_dev->enabled = RT_FALSE;
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_ENABLE_INT:
|
||||
case RT_TOUCH_CTRL_POWER_ON:
|
||||
touch_dev->enabled = RT_TRUE;
|
||||
break;
|
||||
|
||||
case RT_TOUCH_CTRL_GET_STATUS:
|
||||
*(int *)arg = touch_dev->enabled;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -RT_ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const static struct rt_touch_ops input_touch_ops =
|
||||
{
|
||||
.touch_readpoint = input_touch_readpoint,
|
||||
.touch_control = input_touch_control,
|
||||
};
|
||||
|
||||
static rt_bool_t input_touch_cb(struct rt_input_handler *handler,
|
||||
struct rt_input_event *ev)
|
||||
{
|
||||
struct input_touch_device *touch_dev;
|
||||
|
||||
touch_dev = rt_container_of(handler, struct input_touch_device, handler);
|
||||
|
||||
if (touch_dev->enabled)
|
||||
{
|
||||
struct rt_touch_data *point = &touch_dev->points[touch_dev->slot];
|
||||
|
||||
if (ev->type == EV_ABS)
|
||||
{
|
||||
struct rt_input_device *idev = handler->idev;
|
||||
struct rt_input_absinfo *absinfo = &idev->absinfo[touch_dev->slot];
|
||||
|
||||
switch (ev->code)
|
||||
{
|
||||
case ABS_MT_SLOT:
|
||||
touch_dev->slot = ev->value;
|
||||
break;
|
||||
|
||||
case ABS_MT_TRACKING_ID:
|
||||
point->timestamp = ev->tick;
|
||||
|
||||
if (ev->value == (typeof(ev->code))-1)
|
||||
{
|
||||
point->event = RT_TOUCH_EVENT_UP;
|
||||
|
||||
touch_dev->down = 0;
|
||||
rt_hw_touch_isr(&touch_dev->parent);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
point->track_id = ev->value;
|
||||
point->event = touch_dev->down ? RT_TOUCH_EVENT_MOVE : RT_TOUCH_EVENT_DOWN;
|
||||
|
||||
++touch_dev->down;
|
||||
break;
|
||||
|
||||
case ABS_MT_POSITION_X:
|
||||
case ABS_X:
|
||||
point->x_coordinate = (ev->value * touch_dev->parent.info.range_x) /
|
||||
(absinfo->maximum - absinfo->minimum);
|
||||
break;
|
||||
|
||||
case ABS_MT_POSITION_Y:
|
||||
case ABS_Y:
|
||||
point->y_coordinate = (ev->value * touch_dev->parent.info.range_y) /
|
||||
(absinfo->maximum - absinfo->minimum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ev->type == EV_SYN && ev->code == SYN_REPORT && ev->value == 0)
|
||||
{
|
||||
rt_hw_touch_isr(&touch_dev->parent);
|
||||
}
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
void input_touch_register(struct rt_input_device *idev)
|
||||
{
|
||||
const char *dev_name;
|
||||
struct rt_touch_device *tdev;
|
||||
struct input_touch_device *touch_dev;
|
||||
struct input_touch_properties *prop = idev->touch;
|
||||
|
||||
/* Only register rt_touch_device */
|
||||
if (!prop || !prop->touch_dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
touch_dev = prop->touch_dev;
|
||||
tdev = &touch_dev->parent;
|
||||
|
||||
tdev->ops = &input_touch_ops;
|
||||
|
||||
rt_dm_dev_set_name_auto(&tdev->parent, "touch");
|
||||
dev_name = rt_dm_dev_get_name(&tdev->parent);
|
||||
|
||||
rt_hw_touch_register(tdev, dev_name, RT_DEVICE_FLAG_INT_RX, prop);
|
||||
|
||||
touch_dev->enabled = RT_TRUE;
|
||||
touch_dev->handler.idev = idev;
|
||||
touch_dev->handler.callback = &input_touch_cb;
|
||||
rt_input_add_handler(&touch_dev->handler);
|
||||
}
|
||||
|
||||
void input_touch_unregister(struct rt_input_device *idev)
|
||||
{
|
||||
struct rt_touch_device *tdev;
|
||||
struct input_touch_device *touch_dev;
|
||||
struct input_touch_properties *prop = idev->touch;
|
||||
|
||||
if (!prop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop->touch_dev)
|
||||
{
|
||||
goto _end;
|
||||
}
|
||||
|
||||
touch_dev = prop->touch_dev;
|
||||
tdev = &touch_dev->parent;
|
||||
|
||||
rt_input_del_handler(&touch_dev->handler);
|
||||
rt_device_unregister(&tdev->parent);
|
||||
|
||||
_end:
|
||||
rt_free(idev->touch);
|
||||
idev->touch = RT_NULL;
|
||||
}
|
||||
|
||||
static void input_touch_parse(struct rt_input_device *idev,
|
||||
rt_bool_t multitouch, struct input_touch_properties *prop)
|
||||
{
|
||||
rt_bool_t present = RT_TRUE;
|
||||
rt_uint32_t axis, axis_x, axis_y;
|
||||
rt_uint32_t minimum, maximum, fuzz;
|
||||
struct rt_device *dev = &idev->parent;
|
||||
struct rt_input_absinfo *absinfo = idev->absinfo;
|
||||
|
||||
axis_x = multitouch ? ABS_MT_POSITION_X : ABS_X;
|
||||
axis_y = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
|
||||
|
||||
if ((present = rt_dm_dev_prop_read_u32(dev, "touchscreen-min-x", &minimum)))
|
||||
{
|
||||
minimum = absinfo[axis_x].minimum;
|
||||
}
|
||||
|
||||
if ((present |= rt_dm_dev_prop_read_u32(dev, "touchscreen-size-x", &maximum)))
|
||||
{
|
||||
maximum = absinfo[axis_x].maximum + 1;
|
||||
}
|
||||
|
||||
if ((present |= rt_dm_dev_prop_read_u32(dev, "touchscreen-fuzz-x", &fuzz)))
|
||||
{
|
||||
fuzz = absinfo[axis_x].fuzz;
|
||||
}
|
||||
|
||||
if (present)
|
||||
{
|
||||
rt_input_set_absinfo(idev, axis_x, minimum, maximum - 1, fuzz, 0);
|
||||
}
|
||||
|
||||
if ((present = rt_dm_dev_prop_read_u32(dev, "touchscreen-min-y", &minimum)))
|
||||
{
|
||||
minimum = absinfo[axis_y].minimum;
|
||||
}
|
||||
|
||||
if ((present |= rt_dm_dev_prop_read_u32(dev, "touchscreen-size-y", &maximum)))
|
||||
{
|
||||
maximum = absinfo[axis_y].maximum + 1;
|
||||
}
|
||||
|
||||
if ((present |= rt_dm_dev_prop_read_u32(dev, "touchscreen-fuzz-y", &fuzz)))
|
||||
{
|
||||
fuzz = absinfo[axis_y].fuzz;
|
||||
}
|
||||
|
||||
if (present)
|
||||
{
|
||||
rt_input_set_absinfo(idev, axis_y, minimum, maximum - 1, fuzz, 0);
|
||||
}
|
||||
|
||||
axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
|
||||
|
||||
if ((present = rt_dm_dev_prop_read_u32(dev, "touchscreen-max-pressure", &maximum)))
|
||||
{
|
||||
maximum = absinfo[axis].maximum;
|
||||
}
|
||||
|
||||
if ((present |= rt_dm_dev_prop_read_u32(dev, "touchscreen-fuzz-pressure", &fuzz)))
|
||||
{
|
||||
fuzz = absinfo[axis].fuzz;
|
||||
}
|
||||
|
||||
if (present)
|
||||
{
|
||||
rt_input_set_absinfo(idev, axis, 0, maximum, fuzz, 0);
|
||||
}
|
||||
|
||||
prop->max_x = absinfo[axis_x].maximum;
|
||||
prop->max_y = absinfo[axis_y].maximum;
|
||||
|
||||
prop->invert_x = rt_dm_dev_prop_read_bool(dev, "touchscreen-inverted-x");
|
||||
|
||||
if (prop->invert_x)
|
||||
{
|
||||
absinfo[axis_x].maximum -= absinfo[axis_x].minimum;
|
||||
absinfo[axis_x].minimum = 0;
|
||||
}
|
||||
|
||||
prop->invert_y = rt_dm_dev_prop_read_bool(dev, "touchscreen-inverted-y");
|
||||
|
||||
if (prop->invert_y)
|
||||
{
|
||||
absinfo[axis_y].maximum -= absinfo[axis_y].minimum;
|
||||
absinfo[axis_y].minimum = 0;
|
||||
}
|
||||
|
||||
prop->swap_x_y = rt_dm_dev_prop_read_bool(dev, "touchscreen-swapped-x-y");
|
||||
|
||||
if (prop->swap_x_y)
|
||||
{
|
||||
struct rt_input_absinfo swap_absinfo;
|
||||
|
||||
rt_memcpy(&swap_absinfo, &idev->absinfo[axis_x], sizeof(swap_absinfo));
|
||||
rt_memcpy(&idev->absinfo[axis_x], &idev->absinfo[axis_y], sizeof(swap_absinfo));
|
||||
rt_memcpy(&idev->absinfo[axis_y], &swap_absinfo, sizeof(swap_absinfo));
|
||||
}
|
||||
}
|
||||
|
||||
rt_err_t rt_input_setup_touch(struct rt_input_device *idev,
|
||||
rt_uint32_t num_slots, struct rt_touch_info *info)
|
||||
{
|
||||
rt_size_t alloc_size;
|
||||
rt_bool_t multitouch;
|
||||
struct input_touch_device *touch_dev;
|
||||
struct input_touch_properties *prop;
|
||||
|
||||
if (!idev || idev->touch)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
multitouch = !!num_slots;
|
||||
alloc_size = sizeof(*prop);
|
||||
|
||||
if (info)
|
||||
{
|
||||
alloc_size += sizeof(*touch_dev);
|
||||
alloc_size += sizeof(*touch_dev->points) * rt_max_t(rt_uint32_t, num_slots, 1);
|
||||
}
|
||||
|
||||
if (!(prop = rt_calloc(1, alloc_size)))
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
idev->touch = prop;
|
||||
|
||||
if ((prop->num_slots = num_slots))
|
||||
{
|
||||
rt_input_set_absinfo(idev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
|
||||
rt_input_set_absinfo(idev, ABS_MT_TRACKING_ID, 0, RT_UINT16_MAX, 0, 0);
|
||||
}
|
||||
|
||||
input_touch_parse(idev, multitouch, prop);
|
||||
|
||||
if (info)
|
||||
{
|
||||
rt_size_t points_nr = rt_max_t(rt_uint32_t, num_slots, 1);
|
||||
|
||||
touch_dev = (void *)prop + sizeof(*prop);
|
||||
prop->touch_dev = touch_dev;
|
||||
|
||||
for (int i = 0; i < points_nr; ++i)
|
||||
{
|
||||
touch_dev->points[i].width = 1;
|
||||
}
|
||||
|
||||
rt_memcpy(&touch_dev->parent.info, info, sizeof(*info));
|
||||
|
||||
info = &touch_dev->parent.info;
|
||||
info->point_num = info->point_num ? : prop->num_slots;
|
||||
info->range_x = info->range_x ? : prop->max_x;
|
||||
info->range_y = info->range_y ? : prop->max_y;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_input_parse_touch_position(struct rt_input_device *idev,
|
||||
rt_uint32_t *out_x, rt_uint32_t *out_y)
|
||||
{
|
||||
struct input_touch_properties *prop;
|
||||
|
||||
RT_ASSERT(idev != RT_NULL);
|
||||
RT_ASSERT(out_x != RT_NULL);
|
||||
RT_ASSERT(out_y != RT_NULL);
|
||||
|
||||
prop = idev->touch;
|
||||
|
||||
if (prop->invert_x)
|
||||
{
|
||||
*out_x = prop->max_x - *out_x;
|
||||
}
|
||||
|
||||
if (prop->invert_y)
|
||||
{
|
||||
*out_y = prop->max_y - *out_y;
|
||||
}
|
||||
|
||||
if (prop->swap_x_y)
|
||||
{
|
||||
*out_x ^= *out_y;
|
||||
*out_y ^= *out_x;
|
||||
*out_x ^= *out_y;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_bool_t rt_input_report_touch_inactive(struct rt_input_device *idev,
|
||||
rt_bool_t active)
|
||||
{
|
||||
struct input_touch_properties *prop;
|
||||
|
||||
RT_ASSERT(idev != RT_NULL);
|
||||
|
||||
prop = idev->touch;
|
||||
|
||||
if (!active)
|
||||
{
|
||||
rt_input_event(idev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
rt_input_event(idev, EV_ABS, ABS_MT_TRACKING_ID, prop->track_id++);
|
||||
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
void rt_input_report_touch_position(struct rt_input_device *idev,
|
||||
rt_uint32_t x, rt_uint32_t y, rt_bool_t multitouch)
|
||||
{
|
||||
RT_ASSERT(idev != RT_NULL);
|
||||
|
||||
rt_input_parse_touch_position(idev, &x, &y);
|
||||
rt_input_report_abs(idev, multitouch ? ABS_MT_POSITION_X : ABS_X, x);
|
||||
rt_input_report_abs(idev, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
|
||||
}
|
||||
399
components/drivers/input/input_uapi.c
Normal file
399
components/drivers/input/input_uapi.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <ktime.h>
|
||||
#include <dfs_file.h>
|
||||
|
||||
#define DBG_TAG "input.uapi"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define _IOC_NRBITS 8
|
||||
#define _IOC_TYPEBITS 8
|
||||
#ifndef _IOC_SIZEBITS
|
||||
#define _IOC_SIZEBITS 14
|
||||
#endif
|
||||
#ifndef _IOC_DIRBITS
|
||||
#define _IOC_DIRBITS 2
|
||||
#endif
|
||||
|
||||
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS) - 1)
|
||||
|
||||
#define _IOC_NRSHIFT 0
|
||||
#define _IOC_TYPESHIFT (_IOC_NRSHIFT + _IOC_NRBITS)
|
||||
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT + _IOC_TYPEBITS)
|
||||
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT + _IOC_SIZEBITS)
|
||||
|
||||
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & 0xFF)
|
||||
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & 0xFF)
|
||||
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & 0x3FFF)
|
||||
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & 0x3)
|
||||
|
||||
#ifndef _IOC_READ
|
||||
#define _IOC_READ 2U
|
||||
#endif
|
||||
#ifndef _IOC
|
||||
#define _IOC(dir, type, nr, size) \
|
||||
( \
|
||||
((dir) << _IOC_DIRSHIFT) | \
|
||||
((type) << _IOC_TYPESHIFT) | \
|
||||
((nr) << _IOC_NRSHIFT) | \
|
||||
((size) << _IOC_SIZESHIFT) \
|
||||
)
|
||||
#endif
|
||||
|
||||
struct input_uapi
|
||||
{
|
||||
struct dfs_file *grabbed_file;
|
||||
|
||||
rt_atomic_t write_idx;
|
||||
rt_atomic_t read_idx;
|
||||
rt_atomic_t sync_count;
|
||||
struct input_event events[RT_INPUT_UAPI_EVENT_MAX];
|
||||
};
|
||||
|
||||
static int input_uapi_fops_open(struct dfs_file *file)
|
||||
{
|
||||
struct rt_input_device *idev = file->vnode->data;
|
||||
|
||||
rt_device_open(&idev->parent, RT_DEVICE_OFLAG_RDWR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int input_uapi_fops_close(struct dfs_file *file)
|
||||
{
|
||||
struct rt_input_device *idev = file->vnode->data;
|
||||
struct input_uapi *uapi = idev->uapi;
|
||||
|
||||
rt_device_close(&idev->parent);
|
||||
|
||||
if (uapi->grabbed_file == file)
|
||||
{
|
||||
rt_spin_lock(&idev->lock);
|
||||
uapi->grabbed_file = RT_NULL;
|
||||
rt_spin_unlock(&idev->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int input_uapi_fops_ioctl(struct dfs_file *file, int cmd, void *args)
|
||||
{
|
||||
unsigned int size;
|
||||
struct rt_input_device *idev = file->vnode->data;
|
||||
struct input_uapi *uapi = idev->uapi;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case EVIOCGVERSION:
|
||||
{
|
||||
int version = EV_VERSION;
|
||||
|
||||
rt_memcpy(args, &version, sizeof(int));
|
||||
return 0;
|
||||
}
|
||||
|
||||
case EVIOCGID:
|
||||
{
|
||||
static struct input_id virtual_id =
|
||||
{
|
||||
.bustype = 0x06, /* BUS_VIRTUAL */
|
||||
.vendor = 0x5354, /* "RT" */
|
||||
.product = 0x4556, /* "EV" */
|
||||
.version = RT_VER_NUM >> 16,
|
||||
};
|
||||
|
||||
rt_memcpy(args, &virtual_id, sizeof(virtual_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
case EVIOCGRAB:
|
||||
rt_spin_lock(&idev->lock);
|
||||
|
||||
if (uapi->grabbed_file && uapi->grabbed_file != file)
|
||||
{
|
||||
rt_spin_unlock(&idev->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
uapi->grabbed_file = args ? file : RT_NULL;
|
||||
rt_spin_unlock(&idev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = _IOC_SIZE(cmd);
|
||||
|
||||
switch (((cmd) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)))
|
||||
{
|
||||
case EVIOCGNAME(0):
|
||||
rt_strncpy(args, idev->parent.parent.name, rt_min_t(unsigned int, size, RT_NAME_MAX));
|
||||
return 0;
|
||||
|
||||
case EVIOCGPROP(0):
|
||||
{
|
||||
rt_bitmap_t *bitmap = args;
|
||||
const int input_prop_direct = 0x1;
|
||||
|
||||
rt_memset(bitmap, 0, size);
|
||||
|
||||
if (size >= sizeof(rt_bitmap_t))
|
||||
{
|
||||
bitmap[RT_BIT_WORD(input_prop_direct)] |= RT_BIT_MASK(input_prop_direct);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_IOC_TYPE(cmd) != 'E')
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (_IOC_DIR(cmd) == _IOC_READ)
|
||||
{
|
||||
if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
|
||||
{
|
||||
rt_size_t bit_len;
|
||||
rt_bitmap_t *bitmap;
|
||||
|
||||
switch (_IOC_NR(cmd) & EV_MAX)
|
||||
{
|
||||
case 0: bitmap = idev->cap; bit_len = EV_MAX; break;
|
||||
case EV_KEY: bitmap = idev->key_map; bit_len = KEY_MAX; break;
|
||||
case EV_REL: bitmap = idev->rel_map; bit_len = REL_MAX; break;
|
||||
case EV_ABS: bitmap = idev->abs_map; bit_len = ABS_MAX; break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = rt_min_t(rt_size_t, size, ((bit_len + 8) / 8));
|
||||
rt_memcpy(args, bitmap, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
|
||||
{
|
||||
rt_size_t max;
|
||||
|
||||
if (!idev->absinfo)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max = _IOC_NR(cmd) & ABS_MAX;
|
||||
|
||||
rt_memcpy(args, &idev->absinfo[max], rt_min_t(rt_size_t, size, sizeof(struct input_absinfo)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t input_uapi_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
int err;
|
||||
size_t read = 0;
|
||||
struct input_event *event = buf;
|
||||
struct rt_input_device *idev = file->vnode->data;
|
||||
struct input_uapi *uapi = idev->uapi;
|
||||
|
||||
rt_spin_lock(&idev->lock);
|
||||
|
||||
if (uapi->grabbed_file && uapi->grabbed_file != file)
|
||||
{
|
||||
rt_spin_unlock(&idev->lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
rt_spin_unlock(&idev->lock);
|
||||
|
||||
if (count != 0 && count < sizeof(struct input_event))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!rt_atomic_load(&uapi->sync_count) && (file->flags & O_NONBLOCK))
|
||||
{
|
||||
#ifdef RT_UAPI_FAKE_BLOCK
|
||||
static struct input_event fake_event =
|
||||
{
|
||||
.type = EV_SYN,
|
||||
.code = SYN_REPORT,
|
||||
};
|
||||
|
||||
rt_memcpy(event, &fake_event, sizeof(struct input_event));
|
||||
read += sizeof(struct input_event);
|
||||
|
||||
return read;
|
||||
#else
|
||||
return -EAGAIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* No IO is done but we check for error conditions */
|
||||
if (count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
while (read + sizeof(struct input_event) <= count && rt_atomic_load(&uapi->sync_count))
|
||||
{
|
||||
rt_ubase_t r_idx = rt_atomic_load(&uapi->read_idx);
|
||||
|
||||
rt_memcpy(event, &uapi->events[r_idx], sizeof(struct input_event));
|
||||
|
||||
rt_atomic_store(&uapi->read_idx, (r_idx + 1) % RT_ARRAY_SIZE(uapi->events));
|
||||
|
||||
if (event->type == EV_SYN && event->code == SYN_REPORT)
|
||||
{
|
||||
rt_atomic_sub(&uapi->sync_count, 1);
|
||||
}
|
||||
|
||||
++event;
|
||||
read += sizeof(struct input_event);
|
||||
}
|
||||
|
||||
if (read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(file->flags & O_NONBLOCK))
|
||||
{
|
||||
err = rt_wqueue_wait_interruptible(&idev->parent.wait_queue, 0, RT_WAITING_FOREVER);
|
||||
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
static ssize_t input_uapi_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int input_uapi_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
/* Only support POLLIN */
|
||||
int mask = 0, flags = file->flags & O_ACCMODE;
|
||||
struct rt_input_device *idev = file->vnode->data;
|
||||
struct input_uapi *uapi = idev->uapi;
|
||||
|
||||
if (flags == O_RDONLY || flags == O_RDWR)
|
||||
{
|
||||
rt_poll_add(&idev->parent.wait_queue, req);
|
||||
|
||||
if (rt_atomic_load(&uapi->sync_count))
|
||||
{
|
||||
mask |= POLLIN;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static const struct dfs_file_ops input_uapi_fops =
|
||||
{
|
||||
.open = input_uapi_fops_open,
|
||||
.close = input_uapi_fops_close,
|
||||
.ioctl = input_uapi_fops_ioctl,
|
||||
.read = input_uapi_fops_read,
|
||||
.write = input_uapi_fops_write,
|
||||
.lseek = generic_dfs_lseek,
|
||||
.poll = input_uapi_fops_poll,
|
||||
};
|
||||
|
||||
void input_uapi_init(struct rt_input_device *idev)
|
||||
{
|
||||
struct input_uapi *uapi = rt_calloc(1, sizeof(struct input_uapi));
|
||||
|
||||
if (!uapi)
|
||||
{
|
||||
LOG_W("%s: No memory to create UAPI", rt_dm_dev_get_name(&idev->parent));
|
||||
return;
|
||||
}
|
||||
|
||||
idev->uapi = uapi;
|
||||
idev->parent.fops = &input_uapi_fops;
|
||||
|
||||
RT_ASSERT(sizeof(struct input_absinfo) == sizeof(struct rt_input_absinfo));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, value) == rt_offsetof(struct rt_input_absinfo, value));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, minimum) == rt_offsetof(struct rt_input_absinfo, minimum));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, maximum) == rt_offsetof(struct rt_input_absinfo, maximum));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, fuzz) == rt_offsetof(struct rt_input_absinfo, fuzz));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, flat) == rt_offsetof(struct rt_input_absinfo, flat));
|
||||
RT_ASSERT(rt_offsetof(struct input_absinfo, resolution) == rt_offsetof(struct rt_input_absinfo, resolution));
|
||||
}
|
||||
|
||||
void input_uapi_finit(struct rt_input_device *idev)
|
||||
{
|
||||
if (idev->uapi)
|
||||
{
|
||||
rt_free(idev->uapi);
|
||||
idev->uapi = RT_NULL;
|
||||
idev->parent.fops = RT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void input_uapi_event(struct rt_input_device *idev, struct rt_input_event *event)
|
||||
{
|
||||
rt_ubase_t w_idx, next;
|
||||
struct input_event *uapi_event;
|
||||
struct input_uapi *uapi = idev->uapi;
|
||||
|
||||
if (!idev->parent.ref_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
w_idx = rt_atomic_load(&uapi->write_idx);
|
||||
next = (w_idx + 1) % RT_ARRAY_SIZE(uapi->events);
|
||||
|
||||
if (next == rt_atomic_load(&uapi->read_idx))
|
||||
{
|
||||
LOG_W("%s: Event (type: %d code: %d value: %d) dropped",
|
||||
rt_dm_dev_get_name(&idev->parent),
|
||||
event->type, event->code, event->value);
|
||||
return;
|
||||
}
|
||||
|
||||
uapi_event = &uapi->events[w_idx];
|
||||
|
||||
rt_ktime_boottime_get_us(&uapi_event->time);
|
||||
uapi_event->type = event->type;
|
||||
uapi_event->code = event->code;
|
||||
uapi_event->value = event->value;
|
||||
|
||||
rt_atomic_store(&uapi->write_idx, next);
|
||||
|
||||
if (event->type == EV_SYN && event->code == SYN_REPORT)
|
||||
{
|
||||
rt_atomic_add(&uapi->sync_count, 1);
|
||||
rt_wqueue_wakeup(&idev->parent.wait_queue, (void *)(rt_ubase_t)POLLIN);
|
||||
}
|
||||
}
|
||||
7
components/drivers/input/joystick/Kconfig
Normal file
7
components/drivers/input/joystick/Kconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
menuconfig RT_INPUT_JOYSTICK
|
||||
bool "Joystick"
|
||||
default n
|
||||
|
||||
if RT_INPUT_JOYSTICK
|
||||
osource "$(SOC_DM_INPUT_JOYSTICK_DIR)/Kconfig"
|
||||
endif
|
||||
15
components/drivers/input/joystick/SConscript
Normal file
15
components/drivers/input/joystick/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_INPUT_JOYSTICK']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = []
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
13
components/drivers/input/keyboard/Kconfig
Normal file
13
components/drivers/input/keyboard/Kconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
menuconfig RT_INPUT_KEYBOARD
|
||||
bool "Keyboards"
|
||||
default n
|
||||
|
||||
config RT_INPUT_KEYBOARD_GPIO
|
||||
bool "GPIO"
|
||||
depends on RT_INPUT_KEYBOARD
|
||||
depends on RT_USING_OFW
|
||||
default n
|
||||
|
||||
if RT_INPUT_KEYBOARD
|
||||
osource "$(SOC_DM_INPUT_KEYBOARD_DIR)/Kconfig"
|
||||
endif
|
||||
18
components/drivers/input/keyboard/SConscript
Normal file
18
components/drivers/input/keyboard/SConscript
Normal file
@@ -0,0 +1,18 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_INPUT_KEYBOARD']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = []
|
||||
|
||||
if GetDepend(['RT_INPUT_KEYBOARD_GPIO']):
|
||||
src += ['keys-gpio.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
163
components/drivers/input/keyboard/keys-gpio.c
Normal file
163
components/drivers/input/keyboard/keys-gpio.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "input.keyboard.gpio"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
struct gpio_key
|
||||
{
|
||||
struct rt_input_device parent;
|
||||
|
||||
rt_base_t pin;
|
||||
rt_uint8_t mode;
|
||||
rt_uint32_t code;
|
||||
};
|
||||
|
||||
static void gpio_key_event(void *data)
|
||||
{
|
||||
struct gpio_key *gkey = data;
|
||||
|
||||
rt_input_report_key(&gkey->parent, gkey->code, 1);
|
||||
rt_input_sync(&gkey->parent);
|
||||
|
||||
rt_input_report_key(&gkey->parent, gkey->code, 0);
|
||||
rt_input_sync(&gkey->parent);
|
||||
}
|
||||
|
||||
static rt_err_t ofw_append_gpio_key(struct rt_ofw_node *np)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
rt_uint32_t debounce;
|
||||
const char *propname;
|
||||
struct gpio_key *gkey = rt_calloc(1, sizeof(*gkey));
|
||||
|
||||
if (!gkey)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
gkey->pin = rt_ofw_get_named_pin(np, RT_NULL, 0, &gkey->mode, RT_NULL);
|
||||
|
||||
if (gkey->pin < 0)
|
||||
{
|
||||
err = gkey->pin;
|
||||
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if ((propname = rt_ofw_get_prop_fuzzy_name(np, ",code$")) &&
|
||||
!rt_ofw_prop_read_u32(np, propname, &gkey->code))
|
||||
{
|
||||
rt_input_set_capability(&gkey->parent, EV_KEY, gkey->code);
|
||||
|
||||
if (!(err = rt_input_device_register(&gkey->parent)))
|
||||
{
|
||||
err = rt_pin_attach_irq(gkey->pin, gkey->mode, gpio_key_event, gkey);
|
||||
|
||||
if (err)
|
||||
{
|
||||
rt_input_device_unregister(&gkey->parent);
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
rt_pin_irq_enable(gkey->pin, RT_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if (!rt_ofw_prop_read_u32(np, "debounce-interval", &debounce))
|
||||
{
|
||||
rt_pin_debounce(gkey->pin, debounce);
|
||||
}
|
||||
|
||||
rt_ofw_data(np) = gkey;
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail:
|
||||
rt_free(gkey);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t gpio_key_probe(struct rt_platform_device *pdev)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
struct rt_ofw_node *key_np, *np = pdev->parent.ofw_node;
|
||||
|
||||
rt_ofw_foreach_available_child_node(np, key_np)
|
||||
{
|
||||
err = ofw_append_gpio_key(key_np);
|
||||
|
||||
if (err == -RT_ENOMEM)
|
||||
{
|
||||
rt_ofw_node_put(key_np);
|
||||
|
||||
return err;
|
||||
}
|
||||
else if (err)
|
||||
{
|
||||
LOG_E("%s: create KEY fail", rt_ofw_node_full_name(key_np));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t gpio_key_remove(struct rt_platform_device *pdev)
|
||||
{
|
||||
struct rt_ofw_node *key_np, *np = pdev->parent.ofw_node;
|
||||
|
||||
rt_ofw_foreach_available_child_node(np, key_np)
|
||||
{
|
||||
struct gpio_key *gkey = rt_ofw_data(key_np);
|
||||
|
||||
if (!gkey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rt_ofw_data(key_np) = RT_NULL;
|
||||
|
||||
rt_pin_irq_enable(gkey->pin, RT_FALSE);
|
||||
rt_pin_detach_irq(gkey->pin);
|
||||
|
||||
rt_input_device_unregister(&gkey->parent);
|
||||
|
||||
rt_free(gkey);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_ofw_node_id gpio_key_ofw_ids[] =
|
||||
{
|
||||
{ .compatible = "gpio-keys" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_platform_driver gpio_key_driver =
|
||||
{
|
||||
.name = "gpio-keys",
|
||||
.ids = gpio_key_ofw_ids,
|
||||
|
||||
.probe = gpio_key_probe,
|
||||
.remove = gpio_key_remove,
|
||||
};
|
||||
RT_PLATFORM_DRIVER_EXPORT(gpio_key_driver);
|
||||
12
components/drivers/input/misc/Kconfig
Normal file
12
components/drivers/input/misc/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
menuconfig RT_INPUT_MISC
|
||||
bool "Misc"
|
||||
default n
|
||||
|
||||
config RT_INPUT_MISC_BUTTON_E3X0
|
||||
bool "NI Ettus Research USRP E3xx Button support"
|
||||
depends on RT_INPUT_MISC
|
||||
default n
|
||||
|
||||
if RT_INPUT_MISC
|
||||
osource "$(SOC_DM_INPUT_MISC_DIR)/Kconfig"
|
||||
endif
|
||||
18
components/drivers/input/misc/SConscript
Normal file
18
components/drivers/input/misc/SConscript
Normal file
@@ -0,0 +1,18 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_INPUT_MISC']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = []
|
||||
|
||||
if GetDepend(['RT_INPUT_MISC_BUTTON_E3X0']):
|
||||
src += ['button-e3x0.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
115
components/drivers/input/misc/button-e3x0.c
Normal file
115
components/drivers/input/misc/button-e3x0.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
struct e3x0_button
|
||||
{
|
||||
struct rt_input_device parent;
|
||||
|
||||
int press_irq, release_irq;
|
||||
};
|
||||
|
||||
static void e3x0_button_press_isr(int irqno, void *param)
|
||||
{
|
||||
struct e3x0_button *btn = param;
|
||||
|
||||
rt_input_report_key(&btn->parent, KEY_POWER, 1);
|
||||
rt_input_sync(&btn->parent);
|
||||
}
|
||||
|
||||
static void e3x0_button_release_isr(int irqno, void *param)
|
||||
{
|
||||
struct e3x0_button *btn = param;
|
||||
|
||||
rt_input_report_key(&btn->parent, KEY_POWER, 0);
|
||||
rt_input_sync(&btn->parent);
|
||||
}
|
||||
|
||||
static rt_err_t e3x0_button_probe(struct rt_platform_device *pdev)
|
||||
{
|
||||
rt_err_t err;
|
||||
struct rt_device *dev = &pdev->parent;
|
||||
struct e3x0_button *btn = rt_calloc(1, sizeof(*btn));
|
||||
|
||||
if (!btn)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
if ((btn->press_irq = rt_dm_dev_get_irq_by_name(dev, "press")) < 0)
|
||||
{
|
||||
err = btn->press_irq;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if ((btn->release_irq = rt_dm_dev_get_irq_by_name(dev, "release")) < 0)
|
||||
{
|
||||
err = btn->release_irq;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
rt_input_set_capability(&btn->parent, EV_KEY, KEY_POWER);
|
||||
|
||||
if ((err = rt_input_device_register(&btn->parent)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
dev->user_data = btn;
|
||||
|
||||
rt_hw_interrupt_install(btn->press_irq, e3x0_button_press_isr, btn, "button-e3x0-press");
|
||||
rt_hw_interrupt_umask(btn->press_irq);
|
||||
|
||||
rt_hw_interrupt_install(btn->release_irq, e3x0_button_release_isr, btn, "button-e3x0-release");
|
||||
rt_hw_interrupt_umask(btn->release_irq);
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail:
|
||||
rt_free(btn);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t e3x0_button_remove(struct rt_platform_device *pdev)
|
||||
{
|
||||
struct e3x0_button *btn = pdev->parent.user_data;
|
||||
|
||||
rt_hw_interrupt_mask(btn->press_irq);
|
||||
rt_pic_detach_irq(btn->press_irq, btn);
|
||||
|
||||
rt_hw_interrupt_mask(btn->release_irq);
|
||||
rt_pic_detach_irq(btn->release_irq, btn);
|
||||
|
||||
rt_input_device_unregister(&btn->parent);
|
||||
|
||||
rt_free(btn);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_ofw_node_id e3x0_button_ofw_ids[] =
|
||||
{
|
||||
{ .compatible = "ettus,e3x0-button" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_platform_driver e3x0_button_driver =
|
||||
{
|
||||
.name = "e3x0-button",
|
||||
.ids = e3x0_button_ofw_ids,
|
||||
|
||||
.probe = e3x0_button_probe,
|
||||
.remove = e3x0_button_remove,
|
||||
};
|
||||
RT_PLATFORM_DRIVER_EXPORT(e3x0_button_driver);
|
||||
8
components/drivers/input/touchscreen/Kconfig
Normal file
8
components/drivers/input/touchscreen/Kconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
menuconfig RT_INPUT_TOUCHSCREEN
|
||||
bool "Touchscreens"
|
||||
select RT_USING_TOUCH
|
||||
default n
|
||||
|
||||
if RT_INPUT_TOUCHSCREEN
|
||||
osource "$(SOC_DM_INPUT_TOUCHSCREEN_DIR)/Kconfig"
|
||||
endif
|
||||
15
components/drivers/input/touchscreen/SConscript
Normal file
15
components/drivers/input/touchscreen/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_INPUT_TOUCHSCREEN']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = []
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
Reference in New Issue
Block a user