سؤال

وكتبت برنامج بسيط هو أن يقرأ حرفا من جهاز خارجي (شريط رمز الماسح الضوئي) من المنفذ التسلسلي (/ ديف / ttyS1) ويتغذى عليه إلى الإطار النشط حاليا (باستخدام XSendEvent).

والبرنامج يعمل بشكل جيد على أجهزة الكمبيوتر بشكل أسرع، ولكن على بطء منها يحدث الوضع (في كثير من الأحيان) أن الأحرف لا تحصل تلقى في نفس الترتيب الذي تم إرسالها. على سبيل المثال، الماسح الضوئي يرسل 1234567 إلى المنفذ التسلسلي، يرسل برنامجي أحداث شار 1234567، ولكن البرنامج النشط (إكس تيرم على سبيل المثال) يتلقى 3127456. حاولت يدعو XSync في أماكن مختلفة وإضافة <م> usleep المكالمات، ولكنها لم يساعد.

هل لديها فكرة عن كيفية إجبار "النظام" من الأحرف؟

وأم أن هناك طريقة أخرى لإرسال السلسلة إلى الإطار النشط (أنا لا أمانع حتى باستخدام برنامج خارجي إذا لزم الأمر)؟

وهنا هو رمز، ربما أنا فقط تفعل شيئا خطأ:

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>  // serial port stuff
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <X11/Xlib.h>

/*
    BarCode KeyboardFeeder: BCKF
    Copyright (c) Milan Babuskov
    Licence: GNU General Public Licence

    Compile with: g++ bckf.cpp -lX11 -L /usr/X11R6/lib/ -o bckf
    Keycodes:  /usr/X11R6/include/X11/keysymdef.h
*/
//-----------------------------------------------------------------------------
void SendEvent(XKeyEvent *event, bool press)
{
    if (press)
        XSendEvent(event->display, event->window, True, KeyPressMask, (XEvent *)event);
    else
        XSendEvent(event->display, event->window, True, KeyReleaseMask, (XEvent *)event);
    XSync(event->display, False);
}
//-----------------------------------------------------------------------------
bool sendChar(int c)
{
    if (c >= 0x08 && c <= 0x1b)     // send CR twice
    {
        sendChar(0xff0d);
        c = 0xff0d;
    }

    printf("Sending char : 0x%02x\n", c);
    char disp[] = ":0";
    char *dp = getenv("DISPLAY");
    if (!dp)
        dp = disp;
    else
        printf("Using env.variable $DISPLAY = %s.\n", dp);
    Display *dpy = XOpenDisplay(dp);
    if (dpy == NULL)
    {
        printf("ERROR! Couldn't connect to display %s.\n", dp);
        return false;
    }
    else
    {
        Window cur_focus;   // focused window
        int revert_to;      // focus state
        XGetInputFocus(dpy, &cur_focus, &revert_to);    // get window with focus
        if (cur_focus == None)
        {
            printf("WARNING! No window is focused\n");
            return true;
        }
        else
        {
            XKeyEvent event;
            event.display = dpy;
            event.window = cur_focus;
            event.root = RootWindow(event.display, DefaultScreen(event.display));
            event.subwindow = None;
            event.time = CurrentTime;
            event.x = 1;
            event.y = 1;
            event.x_root = 1;
            event.y_root = 1;
            event.same_screen = True;
            event.type = KeyPress;
            event.state = 0;
            event.keycode = XKeysymToKeycode(dpy, c);
            SendEvent(&event, true);
            event.type = KeyRelease;
            SendEvent(&event, false);
        }
        XCloseDisplay(dpy);
    }

    usleep(20);
    return true;
}
//-----------------------------------------------------------------------------
// Forward declaration
int InitComPort(const char *port);
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
    if (argc != 2)
    {
        printf("Usage: bckf serial_port\n");
        return 1;
    }

    int port = InitComPort(argv[1]);
    if (port == -1)
        return 1;

    while (true)
    {
        char buf[30];
        ssize_t res = read(port, buf, 30);
        if (res > 0)
        {
            for (ssize_t i=0; i<res; ++i)
            {
                int c = buf[i];
                printf("Received char: 0x%02x\n", c);
                if (c >= '0' && c <= '9' || c >= 0x08 && c <= 0x1b)
                    if (!sendChar(c))   // called from console?
                        break;
            }
        }
    }
    return 0;
}
//-----------------------------------------------------------------------------
int InitComPort(const char *port)
{
    int c, res;
    struct termios newtio;
    struct termios oldtio;

    // Open modem device for reading and writing and not as controlling tty
    // because we don't want to get killed if linenoise sends CTRL-C.
    int fdSerial = open(port, O_RDWR | O_NOCTTY );
    if (fdSerial < 0)
    {
        printf(0, "Error opening port: %s\n%s", port, strerror(errno));
        return -1;
    }

    tcgetattr(fdSerial,&oldtio); // save current port settings
    memset(&newtio, 0, sizeof(newtio));
    newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;                  // CREAD   : enable receiving characters
                                                                    // CS8     : character size 8
                                                                    // CLOCAL  : Ignore modem control lines
    newtio.c_iflag = IGNPAR;                                        // IGNPAR  : ignore bytes with parity errors
    newtio.c_oflag = 0;                                             // 0       : raw output (no echo, non-canonical)
    //newtio.c_cc[VTIME]    = timeout;                              // 10=1sec : inter-character timer (deciseconds)
    newtio.c_cc[VMIN]     = 1;                                      // 50      : blocking read until 50 chars received
    tcflush(fdSerial, TCIOFLUSH);                                   // clear the line and...
    tcsetattr(fdSerial,TCSANOW,&newtio);                            // ...activate new settings for the port
    return fdSerial;
}
//-----------------------------------------------------------------------------
هل كانت مفيدة؟

المحلول

والمشكلة في التعليمات البرمجية الخاصة بك التي تقوم فيها بفتح عرض كل مرة مع XOpenDisplay (...). كل دعوة إلى XOpenDisplay يخلق سياق بروتوكول جديد. يجب أن افتح الشاشة مرة واحدة فقط، ودائما استخدام نفس مقبض العرض عند إرسال هذه الأحداث. في سياق مقبض عرض واحد، ويضمن الأحداث أن يبقي أمر.

وتهيئة الشاشة مرة واحدة، على سبيل المثال، في main (...)، قبل البدء في استدعاء sendChar (...)، ودائما استخدام نفس مؤشر العرض. إغلاق العرض فقط عند الانتهاء منها، كما تفعل مع ميناء كوم.

نصائح أخرى

هل محاولة فرض الطابع الزمني إلى زيادة واحد لكل؟ يجب أن أقول خادم X التي تنتشر الأحداث عبر الزمن، ولكنه يعني أيضا أنه اختناقات الماسح الضوئي إلى حوالي 142 بالاشعة / ثانية. هذا يبدو بخير على الرغم من افتراض البشر يشاركون في استخدامه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top