কোনও ডিমন (অর্থাত্ পটভূমি) প্রক্রিয়াটির জন্য কোনও ইউএসবি কীবোর্ড থেকে কী-প্রেসগুলি সন্ধান করা সম্ভব?


13

আমি একটি এমবেডেড লিনাক্স প্রকল্পে কাজ করছি যেখানে আমি এমন একটি প্রোগ্রাম বিকাশ করব যা বুটআপে স্বয়ংক্রিয়ভাবে চালিত হবে এবং একটি চরিত্র প্রদর্শন এবং কিছু ধরণের বোতাম অ্যারের মাধ্যমে ব্যবহারকারীর সাথে ইন্টারঅ্যাক্ট করবে। যদি আমরা একটি সাধারণ জিপিআইও বোতাম অ্যারে নিয়ে যাই তবে আমি সহজেই এমন প্রোগ্রাম লিখতে পারি যা জিপিআইও লাইনগুলিতে কী-চাপগুলি সন্ধান করবে। তবে আমাদের চিন্তার মধ্যে একটি ছিল ইউজার ইনপুটটির পরিবর্তে একটি ইউএসবি নম্বর প্যাড ডিভাইস ব্যবহার করা। আমার বোধগম্যতা হল যে এই ডিভাইসগুলি ইউএসবি কীবোর্ড হিসাবে ওএসের কাছে নিজেকে উপস্থাপন করবে। যদি এই পথে চলে যান তবে ভার্চুয়াল টার্মিনাল বা ভিজিএ প্রদর্শন নেই তা মনে রেখে লিনাক্সের মধ্যে থেকে এই ইউএসবি কীবোর্ডের ইনপুট সন্ধান করার জন্য কি আমার প্রোগ্রামের জন্য কোনও উপায় আছে? যখন কোনও ইউএসবি কীবোর্ড প্লাগ ইন করা থাকে, তখন কি '/ dev' তে এমন কোনও সত্ত্বা উপস্থিত থাকে যা উপস্থিত হয়ে দেখা যায় যে আমি কোনও ফাইল বর্ণনাকারী খুলতে পারি?

উত্তর:


24

ডিভাইসগুলি সম্ভবত /dev/input/নামযুক্ত একটি ফাইল পায় eventNযেখানে এন বিভিন্ন ডিভাইস যেমন মাউস, কীবোর্ড, জ্যাক, পাওয়ার বোতাম ইত্যাদি etc.

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

আপনাকে ইঙ্গিত দেওয়া উচিত

এছাড়াও দেখুন:

cat /proc/bus/input/devices

যেখানে Sysfsমানটি পাথের নিচে /sys

আপনি উদাহরণ দিয়ে পরীক্ষা করতে পারেন

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

আইওসিটিএল ব্যবহার করতে এবং ডিভাইসগুলি + মনিটর পরীক্ষা করতে।

সম্পাদনা 2:

ঠিক আছে. অনুমানটি /dev/input/eventNব্যবহৃত হয়েছে এর ভিত্তিতে আমি এই উত্তরের প্রসার ঘটিয়েছি on

একটি উপায় হতে পারে:

  1. প্রারম্ভকালে লুপ সমস্ত eventফাইল পাওয়া যায় /dev/input/ioctl()ইভেন্ট বিট অনুরোধ করতে ব্যবহার করুন :

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

    তারপরে EV_KEY-বিট সেট করা আছে কিনা তা পরীক্ষা করে দেখুন ।

  2. আইএফএফ সেট করে তারপরে কীগুলি পরীক্ষা করুন:

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

    উদাহরণস্বরূপ যদি নম্বর-কীগুলি আকর্ষণীয় হয় তবে তার জন্য বিটগুলি KEY_0- KEY9এবং - তে পরীক্ষা KEY_KP0করুন KEY_KP9

  3. আইএফএফ কীগুলি খুঁজে পাওয়া গেলে থ্রেডে ইভেন্ট ফাইলটি পর্যবেক্ষণ শুরু করে।

  4. ফিরে 1।

এইভাবে আপনাকে এমন সমস্ত ডিভাইস পর্যবেক্ষণ করতে হবে যা চাওয়া মানদণ্ডগুলি পূরণ করে। আপনি কেবল পরীক্ষা করতে পারবেন না EV_KEYযেমন পাওয়ার-বোতামটিতে এই বিট সেট থাকবে তবে এটি অবশ্যই KEY_Aসেট করবে না won't

বহিরাগত কীগুলির জন্য মিথ্যা ইতিবাচক চিত্র দেখেছেন, তবে সাধারণ কীগুলির জন্য এটি যথেষ্ট। পাওয়ার বাটন বা জ্যাকের জন্য যেমন ইভেন্ট ফাইলের তদারকি করার ক্ষেত্রে কোনও সরাসরি ক্ষতি নেই তবে আপনি যেগুলি প্রশ্নে ইভেন্টগুলি উদ্বোধন করবেন না (যেমন। খারাপ কোড)।

নীচে আরও বিস্তারিত।


সম্পাদনা 1:

শুভেচ্ছা "যে শেষ কথাটা ব্যাখ্যা কর ..." । এখানে স্ট্যাকওভারফ্লো জমির উপর দিয়ে যাচ্ছে ... তবে:

সি তে একটি দ্রুত এবং নোংরা নমুনা আপনাকে আসলে সঠিক ডিভাইস পেয়েছে কিনা তা যাচাই করতে, ইভেন্টের ধরণ, কোড এবং মান অনুবাদ করতে আপনাকে বিভিন্ন কোড প্রয়োগ করতে হবে। সাধারণত কী-ডাউন, কী-আপ, কী-পুনরাবৃত্তি, কী-কোড ইত্যাদি

বাকি সময় যোগ করার জন্য সময় নেই (এবং এখানে খুব বেশি)।

কোডিং ম্যাপিংয়ের জন্য 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;
}

সম্পাদনা 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, এসএসপি নোট বিভাগ 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যার দ্বারা আপনার এমবেডড পরিবেশে উপস্থিত নাও হতে পারে।

বা .. dmesgইউএসবি ডিভাইস সংযোগ করার পরে দেখুন । এটি আপনাকে /devনোড দেওয়া উচিত ।


1
এন্ট্রিগুলি ইমো /dev/disk/by-id/দ্বারা তৈরি করা হয়েছে udev- প্রশ্নটি হ'ল এটি এই পার্টিকুলার কেসে (এমবেডেড প্ল্যাটফর্ম) পাওয়া যায় কিনা is
পিটার্ফ

@ পিটারফ: আপনি সঠিক বলেছেন। যদি উদেব ব্যবহার না করা হয় তবে প্রথম পরামর্শটি কাজ করবে না।
জিত

@ গিলস: আমি দেখতে পাচ্ছি যে আপনি উত্তরটি সম্পাদনা করেছেন এবং ডিস্কের পরিবর্তে ইনপুটটির পথ পরিবর্তন করেছেন। সেক্ষেত্রে আমি বিশ্বাস করি এটি ইনপুট / বাই-পাথ এবং ডিস্ক / বাই-আইডি নয়। আমি সন্দেহ করি হয় কাজ করবে।
জিত

1
না, by-idসঠিক। উদাহরণস্বরূপ, আমার ইউএসবি কীবোর্ড /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
গিলস 'অশুভ হওয়া বন্ধ করুন'

@ জাইট: আমি একবার সঠিক ডিভাইস নোড পেয়ে গেলে, আপনি কী কী কী প্রেসগুলি অ্যাক্সেস করতে পারবেন তা জানেন?
কাইলএল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.