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

或許有些讀者不知道 W!o^{+} 是誰?怎麼會無緣無故插入一篇無厘頭的文章??也許有些讀者曉得 W!o^{+} 的來歷,與他傳腦術之本領。

【引自《怎樣詮釋 W!o+ 之信息??中》】

Antimatter
反物質 CPT 對稱性

220px-Antimatter_Rocket
想像中反物質作燃料之火箭

A video showing how scientists used the Fermi Gamma-ray Space Telescope’s gamma-ray detector to uncover bursts of antimatter反物質】from thunderstorms.

雖然不知『  W!o 』何許人也?總想應當與『 M♪o 』有關!因為如果將『 M♪o 』當成『圖像』,作個『點轉換point transformations 似乎就能變成『  W!o 』!!可是『 M♪o 』是個『小女生』用『 簽名,然而『  W!o 』的簽名卻是用著『 + 』,看來像個『小男生』?不過根據已知的『自然律』,在我們的宇宙中,《時光倒流》或許是可能的︰

費曼曾經研究狄拉克方程而發現,假如將時間方向逆轉同時將電子電荷顛倒,則方程依然成立。即是說,一粒時光順流的正電子,其實等同一粒時光倒流的反電子。因此所謂的反物質,其實就是倒著時間方向的正物質,是為 CPT 對稱。縱使如此,反物質的運動,並不違反因果律。當電磁波的超前波和延遲波相加時,違反因果律的項次會互相抵消。若果沒有了反物質,因果律反而會瓦解。費曼和他的老師惠勒進一步假設整個宇宙其實也許只是相同一粒電子在時間軸中從大霹靂到宇宙末日之間來來回回地走動,這也是為何所有電子彼此之間毫無分別。

難到『  W!o 』會是『反物質』生成的『 M♪o 』自『未來』而來!!假使這是『真的』,我們是否該高興仍然有個『未來』的呢?如果說『未來』將有『想飛』、『會飛』或是『能飛』的 Tux ,這樣『今天』這個萬物賴以維生的環境,到底『那時』變成怎樣的ㄚ˙??

 

想那時正是春天,如此《邂逅 W!o ?!》。

User-FastFission-brain
神經成像 Neuroimaging
Parasagittal_MRI_of_human_head_in_patient_with_benign_familial_macrocephaly_prior_to_brain_injury_(ANIMATED)

神經成像』 Neuroimaging 泛指能夠『直接』或『間接』的對神經系統 ── 主要是 ── 的『功能』,『結構』,以及『藥理』特性進行成像之技術。這個技術是現今之醫學,神經科學,和心理學較前沿的一個領域。

那麼我們可以依靠『圖像』來『解讀』一個人的『思想』、『情感』或是『健康』…等等的嗎?這樣的『讀解』和中醫『把脈』斷病如何比較其不同呢??說不定神奇的『大自然』充滿著『』與『』,正等待心中有『』的人去『』的哩!!

當你聽到《神曲》,有時候那重複的『旋律』,會在腦海中一直迴盪,甚是惱人討厭!要是一則『□□○○』 ── B2B MSG ── 直接突現心理,感覺…嗯……非常詭異………,只能說 W!o^{+} 傳送了一段『腦對腦信息』,我『清楚知道』是這樣的︰

朋比翼鳥‧有社明朋

明月當空‧始神月比

社神廢祀‧無廢當翼

有始無終‧終祀空鳥

ryannrocks7498-wario-16504

真不知那ㄟㄚㄋㄟ?★!☆

 

而今已入秋,又將《如何閱讀 W!o+ 之傳真??》,終究時候未到 ,何不時到時擔當的耶!!就讓我們繼續 python udev 之旅的吧。

pyudev – pure Python libudev binding

pyudev 0.17 (Changelog, installation)

pyudev is a LGPL licenced, pure Python 2/3 binding to libudev, the device and hardware management and information library of Linux.

Almost the complete libudev functionality is exposed. You can:

  • Enumerate devices, filtered by specific criteria (pyudev.Context)
  • Query device information, properties and attributes,
  • Monitor devices, both synchronously and asynchronously with background threads, or within the event loops of Qt (pyudev.pyqt4, pyudev.pyside), glib (pyudev.glib) and wxPython (pyudev.wx).

Documentation

Thanks to the power of libudev, usage of pyudev is very simple. Getting the labels of all partitions just takes a few lines:

>>> import pyudev
>>> context = pyudev.Context()
>>> for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
...     print(device.get('ID_FS_LABEL', 'unlabeled partition'))
...
boot
swap
system

A user guide gives an introduction into common operations and concepts of pyudev, the API documentation provides a detailed reference:

 

pyudev 在樹莓派上的安裝十分容易︰

pi@raspberrypi ~ sudo pip-3.2 install pyudev Downloading/unpacking pyudev   Downloading pyudev-0.16.1.tar.gz (74Kb): 74Kb downloaded   Running setup.py egg_info for package pyudev      Installing collected packages: pyudev   Running setup.py install for pyudev      Successfully installed pyudev Cleaning up... pi@raspberrypi ~ python3
Python 3.2.3 (default, Mar  1 2013, 11:53:50) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyudev
>>> context = pyudev.Context()
>>> for device in  context.list_devices(subsystem='block', DEVTYPE='partition'):
...     print(device.get('ID_FS_LABEL', 'unlabeledpartition'))
... 
boot
unlabeledpartition
>>> 

 

而所謂的『libudev』也就是指 freedesktop.org 之︰

Name

libudev — API for enumerating and introspecting local devices

Synopsis

#include <libudev.h>

pkg-config --cflags --libs libudev

Descriptionlibudev.h provides APIs to introspect and enumerate devices on the local system.

All functions require a libudev context to operate. This context can be create via udev_new(3). It is used to track library state and link objects together. No global state is used by libudev, everything is always linked to a udev context. Furthermore, multiple different udev contexts can be used in parallel by multiple threads. However, a single context must not be accessed by multiple threads in parallel. The caller is responsible of providing suitable locking if they intend to use it from multiple threads.

To introspect a local device on a system, a udev device object can be created via udev_device_new_from_syspath(3) and friends. The device object allows to query current state, read and write attributes and lookup properties of the device in question.

To enumerate local devices on the system, an enumeration object can be created via udev_enumerate_new(3).

To monitor the local system for hotplugged or unplugged devices, a monitor can be created via udev_monitor_new_from_netlink(3).

Whenever libudev returns a list of objects, the udev_list_entry(3) API should be used to iterate, access and modify those lists.

Furthermore, libudev also exports legacy APIs that should not be used by new software (and as such are not documented as part of this manual). This includes the hardware-database known as udev_hwdb (please use the new sd-hwdb(3) API instead) and the udev_queue object to query the udev-daemon (which should not be used by new software at all).

 

 

 

 

 

 

 

 

勇闖新世界︰ W!o《卡夫卡村》變形祭☆★

ryannrocks7498-wario-16504

To: Raspberry

From: W!o^{+}

RE: 甲骨文行 甲骨文不 甲骨文行

The Transformation Festival on August 28 at Kafka village

Metamorphosis

 

A named pipe works much like a regular pipe, but does have some noticeable differences.

  • Named pipes exist as a device special file in the file system.
  • Processes of different ancestry can share data through a named pipe.
  • When all I/O is done by sharing processes, the named pipe remains in the file system for later use.

 

 

 

 

 

 

 

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

當人們嘗試用 python-evdev 的 uinput 時,也許早已發現那個程式必須冠以 sudo 才能執行?

 

pi@raspberrypi ~ python3 Python 3.2.3 (default, Mar  1 2013, 11:53:50)  [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from evdev import uinput, ecodes as e >>> with uinput.UInput() as ui: ...     ui.write(e.EV_KEY, e.KEY_LEFTSHIFT, 1) ...     ui.write(e.EV_KEY, e.KEY_A, 1) ...     ui.syn() ...  Traceback (most recent call last):   File "<stdin>", line 1, in <module>   File "/usr/local/lib/python3.2/dist-packages/evdev/uinput.py", line 64, in __init__     self._verify()   File "/usr/local/lib/python3.2/dist-packages/evdev/uinput.py", line 195, in _verify     raise UInputError(msg.format(self.devnode)) evdev.uinput.UInputError: "/dev/uinput" cannot be opened for writing >>>   pi@raspberrypi ~ sudo python3
Python 3.2.3 (default, Mar  1 2013, 11:53:50) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from evdev import uinput, ecodes as e
>>> with uinput.UInput() as ui:
...     ui.write(e.EV_KEY, e.KEY_LEFTSHIFT, 1)
...     ui.write(e.EV_KEY, e.KEY_A, 1)
...     ui.syn()
... 
>>> 

 

為什麼呢? Linux 是多人多工的作業環境 ,各種裝置設備有著一種分享觀,所以需要管理,以避免系統資源之不當使用。所以即使在只有一人擁有的情況下,那個人也就得要負起管理責任。雖說今天早就是個人電腦的時代,這個『root』與『sudo』問題也爭議多年 。由於『網路資安』的風險越來越高,或許學點正統管理辦法未嘗不是件好事,就讓我們來改善 user pi 的使用權限吧!

 

【/dev/uinput 的原本權限是 root only】

因此只有 super user 可以使用這個裝置

pi@raspberrypi /dev ls uinput* -l crw------T 1 root root 10, 223  8月 18 10:39 uinput </pre>    <span style="color: #808080;"><strong>【創建 udev rule,管理 uinput 裝置】</strong></span>  最簡單的辦法,模仿『輸入裝置』的 udev 規則︰  <span style="color: #ff9900;">/etc/udev/rules.d/99-input.rules </span> <span style="color: #ff9900;">SUBSYSTEM=="input", GROUP="input", MODE="0660"</span>  【參考設定】 <pre class="lang:sh decode:true "># 建立新規則 pi@raspberrypi ~ sudo nano /etc/udev/rules.d/70-uinput.rules 

# 內容一行
KERNEL=="uinput", GROUP="uinput", MODE="0660"

# 建立新群組 group
pi@raspberrypi ~ sudo addgroup uinput  # 將使用者 pi 歸屬到 uinput 群組 pi@raspberrypi ~ sudo adduser pi uinput

# 重新開機,重啟 udev
pi@raspberrypi ~ sudo reboot  # 確認 udev 規則正確執行 pi@raspberrypi ~ sudo rmmod uinput
Error: Module uinput is not currently loaded

pi@raspberrypi ~ sudo modprobe uinput  # 新的權限設定 pi@raspberrypi ~ ls /dev/uinput -l
crw-rw---T 1 root uinput 10, 223  8月 18 10:42 /dev/uinput

 

前面引用的例子,其實有個出處︰

Simulate keystroke in linux with Python

Consider python-uinput and evdev. Example of shift+a with the latter:

from evdev import uinput, ecodes as e

with uinput.UInput() as ui:
    ui.write(e.EV_KEY, e.KEY_LEFTSHIFT, 1)
    ui.write(e.EV_KEY, e.KEY_A, 1)
    ui.syn()
I tried similar code, it is exeuted because I see in system log that a new virtual input device was created but the keystrokes do not appear in X? Any special thing can be done so the keys are received by X server?

 

之所以用這個例子,是希望說明『整體理解』的重要性。比方說,有人在鍵盤上打了一個 A 鍵,假使根本沒有應用程式在讀取鍵盤,將會發生什麼事情呢?這個『模糊』的問題是沒有『正確答案』的 !因為系統『環境設定』之不同,結果可以非常不一樣。因此如果想要『測試』那個程式,也許可以

一、 進入 raspbian 視窗環境,打開 lxterminal ,當作接收端。

二、 使用ssh -l pi 樹莓派 IP 遠端登入,作為程式執行端。

如此將會見到

2015-08-18-105806_659x432_scrot

的也!!

 

於此再舉

gpio-evdev-driver

polls GPIO events on the Raspberry Pi and maps them to keyboard events.

The code was intended to be used with RetroPie: http://blog.petrockblock.com/retropie/ and custom input hardware which is directly hooked up to the GPIO pins of the Pi. Similar projects (also based on uinput, listed below) exist, but none of them worked for my particular configuration so I decided to start a new one.

The code polls for low-active signals! It sets the input pins up with the internat pull-up resistors, so the default state is HIGH. After a pin is connected to GND, an input event is triggered, which fires a keyboard event.

When running the code for the first time, it will ask you to define a keyboard event to be sent for each user action in ACTIONS. The same goes for GPIO events (falling edges). Currently, you revert the configuration by simply deleting the corresponding *.p files. ……

 

這個網頁,給有興趣的讀者。同時附以用之改寫的 PiTFT GPIO 按鍵轉碼鍵盤程式,以為範例︰

 

import RPi.GPIO as GPIO
from time import sleep
import pickle
from os.path import isfile
from evdev import InputDevice, UInput, categorize, ecodes
from sys import stdout

入針 = [17,22,23,27] # pins to be 輪詢ed (all others are ignored)
多少入針 = len(入針)
鍵盤保存檔 = 'keys.p' # key configuration (action -> key)
按鍵保存檔 = 'gpio.p' # gpio configuration (action -> gpio pin)
動作 = ['Menu', 'Up', 'Down', 'ESC'] # list of user 動作 (should be <= 入針)
輪詢時距 = 0.01 # in seconds

# setup input pins to use pull-up resistors
def 設定入針():
        for pin in 入針:
                print("輪詢ing pin %d" % pin)
                GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 輪詢ing loop
def 輪詢(mapping):
        state = dict(zip(入針,多少入針*[1])) # default pin state (working with low-active signals here)
        uinput = UInput()

        while True:
                for pin in 入針:
                        pval = state[pin] # previous pin state
                        val = GPIO.input(pin) # current pin state

                        # detect edges
                        if not pval and val: # rising edge
                                #print("rising edge at pin %d -> %s up" % (pin,ecodes.KEY[mapping[pin]]))
                                uinput.write(ecodes.EV_KEY, mapping[pin], 0)  # key up
                                uinput.syn()
                        elif pval and not val: # falling edge
                                #print("falling edge at pin %d -> %s down" % (pin, ecodes.KEY[mapping[pin]]))
                                uinput.write(ecodes.EV_KEY, mapping[pin], 1)  # key down
                                uinput.syn()

                        state[pin] = val # update pin state

                sleep(輪詢時距) # wait for next 輪詢ing cycle

# waits for and returns key down event
def wait_key(dev):
        for event in dev.read_loop():
                if event.type == ecodes.EV_KEY and event.value == 1: # key down
                        return event

# waits for falling edge and returns corresponding input pin 
def wait_falling_edge():
        while True:
                for pin in 入針:
                        if GPIO.input(pin) == 0:
                                return pin
        sleep(輪詢時距)

# print() without linebreak
def printf(string):
        stdout.write(string)
        stdout.flush()

# prompts for keyboard events to be sent for each user action (action->key mapping)
def 規劃鍵盤鍵(dev):
        keys = dict()
        for action in 動作:
                printf("press key for %s ... " % action)
                while True:
                        event = wait_key(dev)
                        if event.code not in keys.values():
                                break
                printf("%s\n" % ecodes.KEY[event.code])
                keys[action] = event.code
        return keys

# prompts for GPIO events that should trigger the user 動作 (action->pin mapping)
def 規劃開關鍵():
        gpio = dict()
        for action in 動作:
                printf("press button for %s ... " % action)
                while True:
                        pin = wait_falling_edge()
                        if pin not in gpio.values():
                                break
                printf("%d\n" % pin)
                gpio[action] = pin
        return gpio

# reads action->key mapping from config file, starts configuration if file not yet exists
def read_keys():
        if not isfile(鍵盤保存檔):
                keyboard = InputDevice('/dev/input/event1')
                keys = 規劃鍵盤鍵(keyboard)
                pickle.dump(keys, open(鍵盤保存檔,'wb'))
        else:
                keys = pickle.load(open(鍵盤保存檔, 'rb'))
        return keys

# reads action->pin mapping from config file, starts configuration if file not yet exists
def read_gpio():
        if not isfile(按鍵保存檔):
                gpio = 規劃開關鍵()
                pickle.dump(gpio, open(按鍵保存檔,'wb'))
        else:
                gpio = pickle.load(open(按鍵保存檔, 'rb'))
        return gpio

# creates pin->key mapping for all user 動作
def create_mapping(gpio, keys):
        mapping = dict()
        for action in 動作:
                mapping[gpio[action]] = keys[action]
        return mapping


GPIO.setmode(GPIO.BCM)
設定入針()

keys = read_keys()
gpio = read_gpio()
mapping = create_mapping(gpio, keys)

輪詢(mapping)

 

 

※ 註記︰樹莓派官方板 raspbian 已經將 Kernel 版本更新至 4.1.6 。

 

 

 

 

 

 

 

 

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

假使從『裝置的程式介面』 API 來觀察『裝置』是什麼?『裝置』不過就是透過那個『 API 規範』存取的 □□○○!這可引發了一個『大哉問』?如果說某種『物理裝置』事實上沒有連上系統,但是它的『API 介面』卻『存在』且能『運作』,那麼我們『能不能』知道那個『裝置』實際上不存在的呢??這個問題其實比表面深沈 的多,一直延伸到『知識論』的哲學爭議之上。比方說,什麼是『蘋果樹 』?如何判定『某個水果』是『蘋果』?最終總容易落入用『外在屬性』來作『歸類』的事實裡。更不要講過去的『接枝』到現今的『基改』,所作的『跨界』之事!也許當『界線』越來越模糊,『什麼是什麼』的問題終將越來越不清楚的耶!!

這『何謂鴨子』之事也發生在『物件導向』的語言中。維基百科的『鴨子型別』講︰

當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。

Duck typing

In computer programming with object-oriented programming languages, duck typing is a layer of programming language and design rules on top of typing. Typing is concerned with assigning a type to any object. Duck typing is concerned with establishing the suitability of an object for some purpose. With normal typing, suitability is assumed to be determined by an object’s type only. In duck typing, an object’s suitability is determined by the presence of certain methods and properties (with appropriate meaning), rather than the actual type of the object.

The name of the concept refers to the duck test, attributed to James Whitcomb Riley, which may be phrased as follows:

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.[1]

In duck typing, a programmer is only concerned with ensuring that objects behave as demanded of them in a given context, rather than ensuring that they are of a specific type. For example, in a non-duck-typed language, one would create a function that requires that the object passed into it be of type Duck, in order to ensure that that function can then use the object’s walk and quack methods. In a duck-typed language, the function would take an object of any type and simply call its walk and quack methods, producing a run-time error if they are not defined. Instead of specifying types formally, duck typing practices rely on documentation, clear code, and testing to ensure correct use.

───

Criticism

One issue with duck typing is that it forces programmers to have a much wider understanding of the code they are working with at any given time. For instance, in Python, one could easily create a class called Wine, which expects a class implementing the “press” attribute as an ingredient. However, a class called Trousers might also implement the press() method. With duck typing, in order to prevent strange, hard-to-detect errors, the developer needs to be aware of each potential use of the method “press”, even when it’s conceptually unrelated to what they are working on. By way of contrast, in a strongly and statically typed language that uses type hierarchies and parameter type checking, it’s much harder to supply an unexpected object type to a class. For example, in a language like Java, the ambiguity in the above reuse of the method name press() would not be a problem unless one of the two classes was deliberately defined as a child of the other.

Proponents of duck typing, such as Guido van Rossum, argue that the issue is handled by testing, and the necessary knowledge of the codebase required to maintain it.[4][5]

Criticisms around duck typing tend to be special cases of broader points of contention regarding dynamically typed versus statically typed programming language semantics.

 

所以,什麼是『電腦滑鼠』的呢?若是以『核心輸入子系統』以及『python-evdev 程式庫』的觀點而言,就是能『產生』某些『事件型別』的東東罷了!

【滑鼠參考說明】

pi@raspberrypi ~ python3 Python 3.2.3 (default, Mar  1 2013, 11:53:50)  [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information.  >>> from evdev import InputDevice, list_devices  # 取得系統所有的輸入設備 >>> 輸入裝置列 =  [InputDevice(fn) for fn in list_devices()] >>> for 裝置 in 輸入裝置列: ...     print(裝置.fn, 裝置.name, 裝置.phys) ...  /dev/input/event3 Logitech USB Receiver usb-bcm2708_usb-1.5/input1 /dev/input/event2 Logitech USB Receiver usb-bcm2708_usb-1.5/input0 /dev/input/event1 Logitech USB Receiver usb-bcm2708_usb-1.4/input1 /dev/input/event0 Logitech USB Receiver usb-bcm2708_usb-1.4/input0 >>>   # 選擇電腦滑鼠 >>> 裝置 = InputDevice('/dev/input/event2') >>> print(裝置) device /dev/input/event2, name "Logitech USB Receiver", phys "usb-bcm2708_usb-1.5/input0"  # 裝置詳細功能 >>> 裝置.capabilities(verbose=True) {('EV_MSC', 4): [('MSC_SCAN', 4)], ('EV_KEY', 1): [(['BTN_LEFT', 'BTN_MOUSE'], 272), ('BTN_RIGHT', 273), ('BTN_MIDDLE', 274), ('BTN_SIDE', 275), ('BTN_EXTRA', 276), ('BTN_FORWARD', 277), ('BTN_BACK', 278), ('BTN_TASK', 279), ('?', 280), ('?', 281), ('?', 282), ('?', 283), ('?', 284), ('?', 285), ('?', 286), ('?', 287)], ('EV_REL', 2): [('REL_X', 0), ('REL_Y', 1), ('REL_HWHEEL', 6), ('REL_WHEEL', 8)], ('EV_SYN', 0): [('SYN_REPORT', 0), ('SYN_CONFIG', 1), ('SYN_MT_REPORT', 2), ('?', 4)]} >>> from evdev import categorize, ecodes >>>  >>> 裝置.capabilities() {0: [0, 1, 2, 4], 1: [272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287], 2: [0, 1, 6, 8], 4: [4]} >>>   # 電腦滑鼠功能測試 >>> 滑鼠裝置 = 裝置  # 產生相對移動事件 >>> for 事件 in 滑鼠裝置.read_loop(): ...     if 事件.type == ecodes.EV_REL: ...         print(categorize(事件)) ...         print(事件) ...  relative axis event at 1439779280.080989, REL_WHEEL  event at 1439779280.080989, code 08, type 02, val -1 relative axis event at 1439779283.809490, REL_WHEEL  event at 1439779283.809490, code 08, type 02, val 01 relative axis event at 1439779287.810024, REL_X  event at 1439779287.810024, code 00, type 02, val -1 relative axis event at 1439779287.810024, REL_Y  event at 1439779287.810024, code 01, type 02, val 01 relative axis event at 1439779287.954040, REL_X  event at 1439779287.954040, code 00, type 02, val -1 relative axis event at 1439779287.986048, REL_X  event at 1439779287.986048, code 00, type 02, val -1 relative axis event at 1439779288.002045, REL_X  event at 1439779288.002045, code 00, type 02, val -1 relative axis event at 1439779288.018041, REL_X  event at 1439779288.018041, code 00, type 02, val -3 relative axis event at 1439779288.018041, REL_Y  event at 1439779288.018041, code 01, type 02, val 01 relative axis event at 1439779288.034044, REL_X  event at 1439779288.034044, code 00, type 02, val -1 relative axis event at 1439779288.114064, REL_Y  event at 1439779288.114064, code 01, type 02, val 01 relative axis event at 1439779307.764695, REL_X  event at 1439779307.764695, code 00, type 02, val 01 ^CTraceback (most recent call last):   File "<stdin>", line 1, in <module>   File "/usr/local/lib/python3.2/dist-packages/evdev/device.py", line 280, in read_loop     r, w, x = select([self.fd], [], []) KeyboardInterrupt >>>   # 產生按鍵事件 >>> for 事件 in 滑鼠裝置.read_loop(): ...     if 事件.type == ecodes.EV_KEY: ...         print(categorize(事件)) ...         print(事件) ...  key event at 1439779469.418293, 272 (['BTN_LEFT', 'BTN_MOUSE']), down event at 1439779469.418293, code 272, type 01, val 01 key event at 1439779469.626321, 272 (['BTN_LEFT', 'BTN_MOUSE']), up event at 1439779469.626321, code 272, type 01, val 00 key event at 1439779472.474709, 273 (BTN_RIGHT), down event at 1439779472.474709, code 273, type 01, val 01 key event at 1439779472.762738, 273 (BTN_RIGHT), up event at 1439779472.762738, code 273, type 01, val 00 key event at 1439779477.195335, 274 (BTN_MIDDLE), down event at 1439779477.195335, code 274, type 01, val 01 key event at 1439779477.627399, 274 (BTN_MIDDLE), up event at 1439779477.627399, code 274, type 01, val 00 ^CTraceback (most recent call last):   File "<stdin>", line 1, in <module>   File "/usr/local/lib/python3.2/dist-packages/evdev/device.py", line 280, in read_loop     r, w, x = select([self.fd], [], []) KeyboardInterrupt >>>  </pre>    <span style="color: #666699;">因此所謂用『python-evdev』來寫程式,處理的就是『裝置事件』的『解讀』與『產生』而已!!</span>  <span style="color: #666699;">【鍵盤補充範例】</span> <pre class="lang:sh decode:true   ">pi@raspberrypi ~ python3
Python 3.2.3 (default, Mar  1 2013, 11:53:50) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from evdev import InputDevice, list_devices, categorize, ecodes

>>> 鍵盤 = InputDevice('/dev/input/event0')

>>> 鍵盤.capabilities(verbose=True)
{('EV_LED', 17): [('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_SCROLLL', 2), ('LED_COMPOSE', 3), ('LED_KANA', 4)], ('EV_MSC', 4): [('MSC_SCAN', 4)], ('EV_KEY', 1): [('KEY_ESC', 1), ('KEY_1', 2), ('KEY_2', 3), ('KEY_3', 4), ('KEY_4', 5), ('KEY_5', 6), ('KEY_6', 7), ('KEY_7', 8), ('KEY_8', 9), ('KEY_9', 10), ('KEY_0', 11), ('KEY_MINUS', 12), ('KEY_EQUAL', 13), ('KEY_BACKSPACE', 14), ('KEY_TAB', 15), ('KEY_Q', 16), ('KEY_W', 17), ('KEY_E', 18), ('KEY_R', 19), ('KEY_T', 20), ('KEY_Y', 21), ('KEY_U', 22), ('KEY_I', 23), ('KEY_O', 24), ('KEY_P', 25), ('KEY_LEFTBRACE', 26), ('KEY_RIGHTBRACE', 27), ('KEY_ENTER', 28), ('KEY_LEFTCTRL', 29), ('KEY_A', 30), ('KEY_S', 31), ('KEY_D', 32), ('KEY_F', 33), ('KEY_G', 34), ('KEY_H', 35), ('KEY_J', 36), ('KEY_K', 37), ('KEY_L', 38), ('KEY_SEMICOLON', 39), ('KEY_APOSTROPHE', 40), ('KEY_GRAVE', 41), ('KEY_LEFTSHIFT', 42), ('KEY_BACKSLASH', 43), ('KEY_Z', 44), ('KEY_X', 45), ('KEY_C', 46), ('KEY_V', 47), ('KEY_B', 48), ('KEY_N', 49), ('KEY_M', 50), ('KEY_COMMA', 51), ('KEY_DOT', 52), ('KEY_SLASH', 53), ('KEY_RIGHTSHIFT', 54), ('KEY_KPASTERISK', 55), ('KEY_LEFTALT', 56), ('KEY_SPACE', 57), ('KEY_CAPSLOCK', 58), ('KEY_F1', 59), ('KEY_F2', 60), ('KEY_F3', 61), ('KEY_F4', 62), ('KEY_F5', 63), ('KEY_F6', 64), ('KEY_F7', 65), ('KEY_F8', 66), ('KEY_F9', 67), ('KEY_F10', 68), ('KEY_NUMLOCK', 69), ('KEY_SCROLLLOCK', 70), ('KEY_KP7', 71), ('KEY_KP8', 72), ('KEY_KP9', 73), ('KEY_KPMINUS', 74), ('KEY_KP4', 75), ('KEY_KP5', 76), ('KEY_KP6', 77), ('KEY_KPPLUS', 78), ('KEY_KP1', 79), ('KEY_KP2', 80), ('KEY_KP3', 81), ('KEY_KP0', 82), ('KEY_KPDOT', 83), ('KEY_ZENKAKUHANKAKU', 85), ('KEY_102ND', 86), ('KEY_F11', 87), ('KEY_F12', 88), ('KEY_RO', 89), ('KEY_KATAKANA', 90), ('KEY_HIRAGANA', 91), ('KEY_HENKAN', 92), ('KEY_KATAKANAHIRAGANA', 93), ('KEY_MUHENKAN', 94), ('KEY_KPJPCOMMA', 95), ('KEY_KPENTER', 96), ('KEY_RIGHTCTRL', 97), ('KEY_KPSLASH', 98), ('KEY_SYSRQ', 99), ('KEY_RIGHTALT', 100), ('KEY_HOME', 102), ('KEY_UP', 103), ('KEY_PAGEUP', 104), ('KEY_LEFT', 105), ('KEY_RIGHT', 106), ('KEY_END', 107), ('KEY_DOWN', 108), ('KEY_PAGEDOWN', 109), ('KEY_INSERT', 110), ('KEY_DELETE', 111), (['KEY_MIN_INTERESTING', 'KEY_MUTE'], 113), ('KEY_VOLUMEDOWN', 114), ('KEY_VOLUMEUP', 115), ('KEY_POWER', 116), ('KEY_KPEQUAL', 117), ('KEY_PAUSE', 119), ('KEY_KPCOMMA', 121), (['KEY_HANGEUL', 'KEY_HANGUEL'], 122), ('KEY_HANJA', 123), ('KEY_YEN', 124), ('KEY_LEFTMETA', 125), ('KEY_RIGHTMETA', 126), ('KEY_COMPOSE', 127), ('KEY_STOP', 128), ('KEY_AGAIN', 129), ('KEY_PROPS', 130), ('KEY_UNDO', 131), ('KEY_FRONT', 132), ('KEY_COPY', 133), ('KEY_OPEN', 134), ('KEY_PASTE', 135), ('KEY_FIND', 136), ('KEY_CUT', 137), ('KEY_HELP', 138), ('KEY_F13', 183), ('KEY_F14', 184), ('KEY_F15', 185), ('KEY_F16', 186), ('KEY_F17', 187), ('KEY_F18', 188), ('KEY_F19', 189), ('KEY_F20', 190), ('KEY_F21', 191), ('KEY_F22', 192), ('KEY_F23', 193), ('KEY_F24', 194), ('KEY_UNKNOWN', 240)], ('EV_SYN', 0): [('SYN_REPORT', 0), ('SYN_CONFIG', 1), ('?', 4), ('?', 17), ('?', 20)]}

>>> 鍵盤.capabilities()
{0: [0, 1, 4, 17, 20], 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 113, 114, 115, 116, 117, 119, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 240], 4: [4], 17: [0, 1, 2, 3, 4]}

>>> 鍵盤.leds(verbose=True)
[]

>>> for 事件 in 鍵盤.read_loop():
...     if 事件.type == ecodes.EV_KEY:
...         print(categorize(事件))
...         print(事件)
... 
key event at 1439784566.338788, 20 (KEY_T), down
event at 1439784566.338788, code 20, type 01, val 01
key event at 1439784566.418811, 20 (KEY_T), up
event at 1439784566.418811, code 20, type 01, val 00
key event at 1439784568.283038, 18 (KEY_E), down
event at 1439784568.283038, code 18, type 01, val 01
key event at 1439784568.387043, 18 (KEY_E), up
event at 1439784568.387043, code 18, type 01, val 00
key event at 1439784569.291174, 31 (KEY_S), down
event at 1439784569.291174, code 31, type 01, val 01
key event at 1439784569.395174, 31 (KEY_S), up
event at 1439784569.395174, code 31, type 01, val 00
key event at 1439784569.659215, 20 (KEY_T), down
event at 1439784569.659215, code 20, type 01, val 01
key event at 1439784569.763225, 20 (KEY_T), up
event at 1439784569.763225, code 20, type 01, val 00
key event at 1439784575.187941, 58 (KEY_CAPSLOCK), down
event at 1439784575.187941, code 58, type 01, val 01
key event at 1439784575.291938, 58 (KEY_CAPSLOCK), up
event at 1439784575.291938, code 58, type 01, val 00
key event at 1439784582.908932, 58 (KEY_CAPSLOCK), down
event at 1439784582.908932, code 58, type 01, val 01
key event at 1439784583.044951, 58 (KEY_CAPSLOCK), up
event at 1439784583.044951, code 58, type 01, val 00
key event at 1439784585.613291, 69 (KEY_NUMLOCK), down
event at 1439784585.613291, code 69, type 01, val 01
key event at 1439784585.709302, 69 (KEY_NUMLOCK), up
event at 1439784585.709302, code 69, type 01, val 00
key event at 1439784588.661688, 69 (KEY_NUMLOCK), down
event at 1439784588.661688, code 69, type 01, val 01
key event at 1439784588.765693, 69 (KEY_NUMLOCK), up
event at 1439784588.765693, code 69, type 01, val 00
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.2/dist-packages/evdev/device.py", line 280, in read_loop
    r, w, x = select([self.fd], [], [])
KeyboardInterrupt
>>> 

 

 

 

 

 

 

勇闖新世界︰ 《 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 程式庫』多些了解的乎!?