勇闖新世界︰ 《 Kernel 4.X 》之整裝蓄勢‧設備管理及應用‧二下

同樣當我們想應用 python-evdev uinput 程式庫寫作程式,在閱讀 『技術文件 』時,請務須仔細而且確實,千萬不要隨意放過不清楚的『術語』。底下列出相關文檔,方便讀者參考︰

uinput

class evdev.uinput.UInput(events=None, name=’py-evdev-uinput’, vendor=1, product=1, version=1, bustype=3, devnode=’/dev/uinput’)

A userland input device and that can inject input events into the linux input subsystem.

__init__(events=None, name=’py-evdev-uinput’, vendor=1, product=1, version=1, bustype=3, devnode=’/dev/uinput’)

Parameters:
  • events (dictionary of event types mapping to lists of event codes.) – the event types and codes that the uinput device will be able to inject – defaults to all key codes.
  • name – the name of the input device.
  • vendor – vendor identifier.
  • product – product identifier.
  • version – version identifier.
  • bustype – bustype identifier.

Note

If you do not specify any events, the uinput device will be able to inject only KEY_* and BTN_* event codes.

name
Uinput device name.
vendor
Device vendor identifier.
product
Device product identifier.
version
Device version identifier.
bustype
Device bustype – eg. BUS_USB.
devnode
Uinput device node – eg. /dev/uinput/.
fd
Write-only, non-blocking file descriptor to the uinput device node.
device
An InputDevice instance for the fake input device. None if the device cannot be opened for reading and writing.
write_event(event)

Inject an input event into the input subsystem. Events are queued until a synchronization event is received.

Parameters: event – InputEvent instance or an object with an event attribute (KeyEvent, RelEvent etc).

Example:

ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1)
ui.write_event(ev)
write(etype, code, value)

Inject an input event into the input subsystem. Events are queued until a synchronization event is received.

Parameters:
  • etype – event type (eg. EV_KEY).
  • code – event code (eg. KEY_A).
  • value – event value (eg. 0 1 2 – depends on event type).

Example:

ui.write(e.EV_KEY, e.KEY_A, 1) # key A - down
ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up
syn()

Inject a SYN_REPORT event into the input subsystem. Events queued by write() will be fired. If possible, events will be merged into an ‘atomic’ event.
capabilities(verbose=False, absinfo=True)

See capabilities.

 

【Linux uinput 設備資料結構】

Linux/include/linux/uinput.h

uinput_request

 45 struct uinput_request {
 46         unsigned int            id;
 47         unsigned int            code;   /* UI_FF_UPLOAD, UI_FF_ERASE */
 48 
 49         int                     retval;
 50         struct completion       done;
 51 
 52         union {
 53                 unsigned int    effect_id;
 54                 struct {
 55                         struct ff_effect *effect;
 56                         struct ff_effect *old;
 57                 } upload;
 58         } u;
 59 };

 

uinput_device

 61 struct uinput_device {
 62         struct input_dev        *dev;
 63         struct mutex            mutex;
 64         enum uinput_state       state;
 65         wait_queue_head_t       waitq;
 66         unsigned char           ready;
 67         unsigned char           head;
 68         unsigned char           tail;
 69         struct input_event      buff[UINPUT_BUFFER_SIZE];
 70         unsigned int            ff_effects_max;
 71 
 72         struct uinput_request   *requests[UINPUT_NUM_REQUESTS];
 73         wait_queue_head_t       requests_waitq;
 74         spinlock_t              requests_lock;
 75 };

 

【Linux 輸入設備資料結構】

Linux/include/linux/input.h

121 struct input_dev {
122         const char *name;
123         const char *phys;
124         const char *uniq;
125         struct input_id id;
126 
127         unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
128 
129         unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
130         unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
131         unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
132         unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
133         unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
134         unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
135         unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
136         unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
137         unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
138 
139         unsigned int hint_events_per_packet;
140 
141         unsigned int keycodemax;
142         unsigned int keycodesize;
143         void *keycode;
144 
145         int (*setkeycode)(struct input_dev *dev,
146                           const struct input_keymap_entry *ke,
147                           unsigned int *old_keycode);
148         int (*getkeycode)(struct input_dev *dev,
149                           struct input_keymap_entry *ke);
150 
151         struct ff_device *ff;
152 
153         unsigned int repeat_key;
154         struct timer_list timer;
155 
156         int rep[REP_CNT];
157 
158         struct input_mt *mt;
159 
160         struct input_absinfo *absinfo;
161 
162         unsigned long key[BITS_TO_LONGS(KEY_CNT)];
163         unsigned long led[BITS_TO_LONGS(LED_CNT)];
164         unsigned long snd[BITS_TO_LONGS(SND_CNT)];
165         unsigned long sw[BITS_TO_LONGS(SW_CNT)];
166 
167         int (*open)(struct input_dev *dev);
168         void (*close)(struct input_dev *dev);
169         int (*flush)(struct input_dev *dev, struct file *file);
170         int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
171 
172         struct input_handle __rcu *grab;
173 
174         spinlock_t event_lock;
175         struct mutex mutex;
176 
177         unsigned int users;
178         bool going_away;
179 
180         struct device dev;
181 
182         struct list_head        h_list;
183         struct list_head        node;
184 
185         unsigned int num_vals;
186         unsigned int max_vals;
187         struct input_value *vals;
188 
189         bool devres_managed;
190 };

 

【Linux uinput API】

Linux/include/uapi/linux/uinput.h

input_event

 24 struct input_event {
 25         struct timeval time;
 26         __u16 type;
 27         __u16 code;
 28         __s32 value;
 29 };

 

input_id

 41 struct input_id {
 42         __u16 bustype;
 43         __u16 vendor;
 44         __u16 product;
 45         __u16 version;
 46 };

 

【核心說明文件】

Documentation/input

再經過範例的練習,

【Injecting input events】

>>> from evdev import UInput, ecodes as e

>>> ui = UInput()

>>> # accepts only KEY_* events by default
>>> ui.write(e.EV_KEY, e.KEY_A, 1)  # KEY_A down
>>> ui.write(e.EV_KEY, e.KEY_A, 0)  # KEY_A up
>>> ui.syn()

>>> ui.close()

 

【Injecting events (2)】

>>> ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1)
>>> with UInput() as ui:
...    ui.write_event(ev)
...    ui.syn()

 

【Specifying uinput device options】

>>> from evdev import UInput, AbsInfo, ecodes as e

>>> cap = {
...     e.EV_KEY : [e.KEY_A, e.KEY_B],
...     e.EV_ABS : [
...         (e.ABS_X, AbsInfo(value=0, min=0, max=255,
...                           fuzz=0, flat=0, resolution=0)),
...         (e.ABS_Y, AbsInfo(0, 0, 255, 0, 0, 0)),
...         (e.ABS_MT_POSITION_X, (0, 255, 128, 0)) ]
... }

>>> ui = UInput(cap, name='example-device', version=0x3)
>>> print(ui)
name "example-device", bus "BUS_USB", vendor "0001", product "0001", version "0003"
event types: EV_KEY EV_ABS EV_SYN

>>> print(ui.capabilities())
{0: [0, 1, 3],
 1: [30, 48],
 3: [(0,  AbsInfo(value=0, min=0, max=0,   fuzz=255, flat=0, resolution=0)),
     (1,  AbsInfo(value=0, min=0, max=0,   fuzz=255, flat=0, resolution=0)),
     (53, AbsInfo(value=0, min=0, max=255, fuzz=128, flat=0, resolution=0))]}

>>> # move mouse cursor
>>> ui.write(e.EV_ABS, e.ABS_X, 20)
>>> ui.write(e.EV_ABS, e.ABS_Y, 20)
>>> ui.syn()


 

,或將能對『核心輸入子系統』以及『python-evdev 程式庫』多些了解的乎!?