क्या USB कीबोर्ड से की-प्रेस को देखने के लिए डेमॉन (यानी बैकग्राउंड) प्रोसेस संभव है?


13

मैं एक एम्बेडेड लिनक्स प्रोजेक्ट पर काम कर रहा हूं, जहां मैं एक प्रोग्राम विकसित कर रहा हूं जो अपने आप बूटअप पर चलेगा और एक चरित्र प्रदर्शन और कुछ प्रकार के बटन सरणी के माध्यम से उपयोगकर्ता के साथ बातचीत करेगा। यदि हम एक साधारण GPIO बटन ऐरे के साथ जाते हैं, तो मैं आसानी से प्रोग्राम लिख सकता हूं जो उन GPIO लाइनों पर keypresses के लिए दिखेगा। हालांकि, हमारा एक विचार उपयोगकर्ता इनपुट के बजाय एक यूएसबी नंबर पैड डिवाइस का उपयोग करना था। मेरी समझ यह है कि वे डिवाइस खुद को एक यूएसबी कीबोर्ड के रूप में ओएस में पेश करेंगे। यदि इस रास्ते से नीचे जाते हैं, तो क्या मेरे प्रोग्राम के लिए लिनक्स के भीतर से इस यूएसबी कीबोर्ड पर इनपुट देखने का कोई तरीका है, यह ध्यान में रखते हुए कि वर्चुअल टर्मिनल या वीजीए डिस्प्ले नहीं है। जब USB कीबोर्ड प्लग-इन किया जाता है, तो क्या '/ dev' में कोई इकाई होती है जो प्रकट होती है कि मैं एक फ़ाइल विवरणक खोल सकता हूं?

जवाबों:


24

उपकरणों को सबसे अधिक संभावना है कि /dev/input/नाम में एक फ़ाइल मिलती है eventNजहां N विभिन्न उपकरण जैसे माउस, कीबोर्ड, जैक, पावर-बटन आदि हैं।

ls -l  /dev/input/by-{path,id}/

आपको संकेत देना चाहिए।

इसे भी देखें:

cat /proc/bus/input/devices

जहां Sysfsमूल्य के तहत रास्ता है /sys

आप उदाहरण के द्वारा परीक्षण कर सकते हैं

cat /dev/input/event2 # if 2 is kbd.

उपयोग ioctl को लागू करने और उपकरणों की जांच + निगरानी करने के लिए।

संपादित करें 2:

ठीक। मैं इस उत्तर के आधार पर विस्तार कर रहा हूं /dev/input/eventNजिसका उपयोग किया जाता है।

एक तरीका हो सकता है:

  1. स्टार्टअप लूप में सभी eventफाइलें मिलीं /dev/input/ioctl()इवेंट बिट्स का अनुरोध करने के लिए उपयोग करें :

    ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
    

    तब जांचें कि क्या EV_KEY-bit सेट है।

  2. IFF सेट तब कुंजियों के लिए जाँच करें:

    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
    

    उदाहरण के लिए यदि संख्या-कुंजी दिलचस्प है, तो जांचें कि क्या बिट्स के लिए KEY_0- KEY9और KEY_KP0टू KEY_KP9

  3. IFF कुंजियाँ मिलीं तो थ्रेड में इवेंट फ़ाइल की निगरानी शुरू करें।

  4. 1 पर वापस।

इस तरह आपको उन सभी उपकरणों की निगरानी करनी चाहिए जो वांछित मानदंडों को पूरा करते हैं। आप केवल जाँच नहीं कर सकते हैं EV_KEYजैसे कि पावर-बटन में यह बिट सेट होगा, लेकिन यह स्पष्ट रूप से KEY_Aसेट आदि नहीं होगा ।

विदेशी कुंजी के लिए झूठी सकारात्मकता देखी है, लेकिन सामान्य कुंजी के लिए यह पर्याप्त होना चाहिए। पावर बटन या जैक के लिए ईवेंट फ़ाइल की निगरानी करने में कोई प्रत्यक्ष नुकसान नहीं है, लेकिन आप उन सवालों (उर्फ खराब) में घटनाओं का उत्सर्जन नहीं करेंगे।

अधिक विस्तार से नीचे।


संपादित करें 1:

के संबंध में "यह बताएं कि अंतिम विवरण ..." । में अधिक जा रहे हैं stackoverflow भूमि यहाँ ... लेकिन:

सी। में एक त्वरित और गंदा नमूना आपको यह जांचने के लिए विभिन्न कोड लागू करने होंगे कि आपको वास्तव में सही उपकरण मिलें, घटना प्रकार, कोड और मूल्य का अनुवाद करें। आमतौर पर की-डाउन, की-अप, की-रिपीट, की-कोड आदि।

बाकी को जोड़ने के लिए समय नहीं है, (और यहाँ बहुत अधिक है)।

मैपिंग कोड के लिए linux/input.hप्रोग्राम dumpkeys, कर्नेल कोड आदि की जाँच करें । उदाहरण के लिएdumpkeys -l

किसी भी तरह:

जैसे भागो:

# ./testprog /dev/input/event2

कोड:

#include <stdio.h>

#include <string.h>     /* strerror() */
#include <errno.h>      /* errno */

#include <fcntl.h>      /* open() */
#include <unistd.h>     /* close() */
#include <sys/ioctl.h>  /* ioctl() */

#include <linux/input.h>    /* EVIOCGVERSION ++ */

#define EV_BUF_SIZE 16

int main(int argc, char *argv[])
{
    int fd, sz;
    unsigned i;

    /* A few examples of information to gather */
    unsigned version;
    unsigned short id[4];                   /* or use struct input_id */
    char name[256] = "N/A";

    struct input_event ev[EV_BUF_SIZE]; /* Read up to N events ata time */

    if (argc < 2) {
        fprintf(stderr,
            "Usage: %s /dev/input/eventN\n"
            "Where X = input device number\n",
            argv[0]
        );
        return EINVAL;
    }

    if ((fd = open(argv[1], O_RDONLY)) < 0) {
        fprintf(stderr,
            "ERR %d:\n"
            "Unable to open `%s'\n"
            "%s\n",
            errno, argv[1], strerror(errno)
        );
    }
    /* Error check here as well. */
    ioctl(fd, EVIOCGVERSION, &version);
    ioctl(fd, EVIOCGID, id); 
    ioctl(fd, EVIOCGNAME(sizeof(name)), name);

    fprintf(stderr,
        "Name      : %s\n"
        "Version   : %d.%d.%d\n"
        "ID        : Bus=%04x Vendor=%04x Product=%04x Version=%04x\n"
        "----------\n"
        ,
        name,

        version >> 16,
        (version >> 8) & 0xff,
        version & 0xff,

        id[ID_BUS],
        id[ID_VENDOR],
        id[ID_PRODUCT],
        id[ID_VERSION]
    );

    /* Loop. Read event file and parse result. */
    for (;;) {
        sz = read(fd, ev, sizeof(struct input_event) * EV_BUF_SIZE);

        if (sz < (int) sizeof(struct input_event)) {
            fprintf(stderr,
                "ERR %d:\n"
                "Reading of `%s' failed\n"
                "%s\n",
                errno, argv[1], strerror(errno)
            );
            goto fine;
        }

        /* Implement code to translate type, code and value */
        for (i = 0; i < sz / sizeof(struct input_event); ++i) {
            fprintf(stderr,
                "%ld.%06ld: "
                "type=%02x "
                "code=%02x "
                "value=%02x\n",
                ev[i].time.tv_sec,
                ev[i].time.tv_usec,
                ev[i].type,
                ev[i].code,
                ev[i].value
            );
        }
    }

fine:
    close(fd);

    return errno;
}

EDIT 2 (जारी):

ध्यान दें कि यदि आप देखते हैं कि /proc/bus/input/devicesआपके पास प्रत्येक पंक्ति के शुरू में एक पत्र है। यहां Bबिट-मैप का मतलब है। यह उदाहरण के लिए है:

B: PROP=0
B: EV=120013
B: KEY=20000 200 20 0 0 0 0 500f 2100002 3803078 f900d401 feffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7

उनमें से प्रत्येक बिट डिवाइस की एक संपत्ति के अनुरूप है। बिट-मैप के माध्यम से, 1 इंगित करता है कि एक संपत्ति मौजूद है, जैसा कि परिभाषित है linux/input.h। :

B: PROP=0    => 0000 0000
B: EV=120013 => 0001 0010 0000 0000 0001 0011 (Event types sup. in this device.)
                   |   |               |   ||
                   |   |               |   |+-- EV_SYN (0x00)
                   |   |               |   +--- EV_KEY (0x01)
                   |   |               +------- EV_MSC (0x04)
                   |   +----------------------- EV_LED (0x11)
                   +--------------------------- EV_REP (0x14)
B: KEY=20... => OK, I'm not writing out this one as  it is a bit huge.

B: MSC=10    => 0001 0000
                   |
                   +------- MSC_SCAN
B: LED=7     => 0000 0111 , indicates what LED's are present
                      |||
                      ||+-- LED_NUML
                      |+--- LED_CAPSL
                      +---- LED_SCROLL

/drivers/input/input.{h,c}कर्नेल स्रोत के पेड़ पर एक नज़र डालें । वहाँ बहुत सारे अच्छे कोड। (जैसे कि उपकरण गुण इस फ़ंक्शन द्वारा निर्मित होते हैं ।)

इनमें से प्रत्येक संपत्ति मानचित्र द्वारा प्राप्त की जा सकती है ioctl। उदाहरण के लिए, यदि आप जांचना चाहते हैं कि एलईडी गुण क्या कहते हैं:

ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), &ledbit);

की परिभाषा को देखो struct input_devमें input.hकैसे के लिए ledbitपरिभाषित कर रहे हैं।

एलईडी के कहने के लिए स्थिति की जांच करने के लिए:

ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);

यदि बिट 1 इन ledbit1 हैं तो अंक-लॉक जलाया जाता है। यदि बिट 2 1 है तो कैप्स लॉक जलाया जाता है आदि।

input.h विभिन्न परिभाषित किया है।


नोट्स जब इवेंट मॉनिटरिंग की बात आती है:

निगरानी के लिए छद्म कोड कुछ इस दिशा में हो सकता है:

WHILE TRUE
    READ input_event
    IF event->type == EV_SYN THEN
        IF event->code == SYN_DROPPED THEN
            Discard all events including next EV_SYN
        ELSE
            This marks EOF current event.
        FI
    ELSE IF event->type == EV_KEY THEN
        SWITCH ev->value
            CASE 0: Key Release    (act accordingly)
            CASE 1: Key Press      (act accordingly)
            CASE 2: Key Autorepeat (act accordingly)
        END SWITCH
    FI
END WHILE

कुछ संबंधित दस्तावेज:

  1. Documentation/input/input.txt, esp। नोट खंड 5।
  2. Documentation/input/event-codes.txt, विभिन्न घटनाओं का वर्णन आदि के EV_SYNबारे में उदाहरण के लिए क्या उल्लेख किया है पर ध्यान देंSYN_DROPPED
  3. Documentation/input ... यदि आप चाहते हैं तो बाकी पर पढ़ें।

2

आप इसे आसानी से संदर्भित करके कर सकते हैं /dev/input/by-id/usb-manufacturername_*serialnumber*। ये प्रतीकात्मक लिंक के रूप में दिखाई देते हैं जिसे आप readlink -eसंबंधित ब्लॉक डिवाइस को निर्धारित करने के लिए उपयोग कर सकते हैं । इन लिंक को हालांकि बनाया गया है udevजो आपके एम्बेडेड वातावरण में मौजूद नहीं हो सकता है।

या .. dmesgUSB डिवाइस को जोड़ने के बाद देखें। यह आपको /devनोड देना चाहिए ।


1
प्रविष्टियों में /dev/disk/by-id/imho द्वारा बनाई गई हैं udev- सवाल यह है कि क्या यह इस आंशिक मामले (एम्बेडेड प्लेटफॉर्म) में उपलब्ध है।
पेट्रफ

@ वेटरेफ़: आप सही हैं। अगर udv का उपयोग नहीं कर रहा है पहला सुझाव काम नहीं करेगा।
21

@ गिल्स: मुझे लगता है कि आपने उत्तर को संपादित किया है और डिस्क के बजाय इनपुट के लिए रास्ता बदल दिया है। उस स्थिति में मेरा मानना ​​है कि यह इनपुट / बाय-पथ होगा न कि डिस्क / बाय-आईडी। मुझे संदेह है कि या तो काम करेगा।
Jeight

1
नहीं, by-idसही है। उदाहरण के लिए अपनी USB कुंजीपटल के रूप में उपलब्ध है /dev/input/by-id/usb-_USB_Keyboard-event-kbdऔर /dev/input/by-path/pci-0000:00:1d.2-usb-0:2:1.0-event-kbd
गिल्स एसओ- बुराई को रोकना '

@Jeight: एक बार जब मुझे सही डिवाइस नोड मिल जाता है, तो क्या आप जानते हैं कि मैं मुख्य प्रेस तक कैसे पहुंच सकता हूं?
केलीएल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.