1

I've been attempting to hook up my BBC Micro to my Raspberry Pi and use it as a Keyboard over Serial TTY. I've found some great code on Github to forward Serial Keypresses to X11, but I can't seem to get it to work as I'd have hoped. I'm not great at C and had a go but sadly haven't got anywhere.

The below works in that it sends keypresses to X11 only when you press 'Return'. The trouble is, if you type 'ABCDE(RETURN)', it'll send 'ABCDE' to the X11 session and also hit the Return Key, you can't see what you've typed until you hit return. What i want it to do is send 'A' when i've pressed 'A', 'B' when i've hit B etc.

I think it seems to be holding everything in some kind of buffer (readbuf?) somehow controlled by the XFlush(dpy); at 112 flushing character input to X11, so moved that to 104 (didn't work), tried it at 53 and 155 in the hope that'd do the trick.

Any help at all would be greatly appreciated!

static int serialPort;
static Display *dpy;

static void xtest_key_press(unsigned char letter) {
  unsigned int shiftcode = XKeysymToKeycode(dpy, XStringToKeysym("Shift_L"));
  int upper = 0;
  int skip_lookup = 0;
  char s[2];
  s[0] = letter;
  s[1] = 0;
  KeySym sym = XStringToKeysym(s);
  KeyCode keycode;



  if (sym == 0) {
    sym = letter;
  }


  if (sym == '\n') {
    sym = XK_Return;
    skip_lookup = 1;

  } else if (sym == '\t') {
    sym = XK_Tab;
    skip_lookup = 1;
  }

  keycode = XKeysymToKeycode(dpy, sym);
  if (keycode == 0) {
    sym = 0xff00 | letter;
    keycode = XKeysymToKeycode(dpy, sym);

  }

  if (!skip_lookup) {
    // Here we try to determine if a keysym
    // needs a modifier key (shift), such as a
    // shifted letter or symbol.
    // The second keysym should be the shifted char
    KeySym *syms;
    int keysyms_per_keycode;
    syms = XGetKeyboardMapping(dpy, keycode, 1, &keysyms_per_keycode);
    int i = 0;
    for (i = 0; i <= keysyms_per_keycode; i++) {
      if (syms[i] == 0)
        break;

      if (i == 0 && syms[i] != letter)
        upper = 1;


    }
  }

  if (upper)
    XTestFakeKeyEvent(dpy, shiftcode, True, 0); 


  XTestFakeKeyEvent(dpy, keycode, True, 0); 
  XTestFakeKeyEvent(dpy, keycode, False, 0);

  if (upper)
    XTestFakeKeyEvent(dpy, shiftcode, False, 0);  



}

static void press_keys(char* string) {
  int len = strlen(string);
  int i = 0;
  for (i = 0; i < len; i++) {
    xtest_key_press(string[i]);
  }
  XFlush(dpy);
}


int sw_open_serial(const char *port) {
  serialPort = open(port, O_RDONLY);
  if (serialPort < 0) {
    fprintf(stderr, "Can't open serial port: %s\n", port);
    exit(-1);
  }

  return 0;
}

void sw_init() {

  int xtest_major_version = 0;
  int xtest_minor_version = 0;
  int dummy;


  /*
   * Open the display using the $DISPLAY environment variable to locate
   * the X server.  See Section 2.1.
   */
  if ((dpy = XOpenDisplay(NULL)) == NULL) {
    fprintf(stderr, "%s: can't open %s\en", "softwedge", XDisplayName(NULL));
    exit(1);
  }

  Bool success = XTestQueryExtension(dpy, &dummy, &dummy,
                     &xtest_major_version, &xtest_minor_version);
  if(success == False || xtest_major_version < 2 ||
     (xtest_major_version <= 2 && xtest_minor_version < 2))
  {
    fprintf(stderr,"XTEST extension not supported. Can't continue\n");
    exit(1);
  }

}


void sw_read_loop() {

  char readbuf[2];
  readbuf[1] = 0;

  while(read(serialPort, readbuf, 1) > 0) {
    if (readbuf[0] == 0x02 || readbuf[0] == 0x03) 
      continue;
    press_keys(readbuf);
  }
  // We're done now
  close(serialPort);
}
dvyio
  • 339
  • 1
  • 7
  • 20
  • 1
    Welcome to Stack Overflow! Please read the (short! friendly!) introductory [tour] some time. Rather than referring to an off-site resource, try to write up a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) and [edit] that into your post. – Jongware Nov 06 '15 at 23:39
  • Sorry! I'd have liked to have pasted the code in directly here though in all honesty am struggling to know which part is relevant to my issue, and didn't want to create a 100 line post! – David James Nov 06 '15 at 23:47
  • 1
    A good strategy is to remove everything that is *clearly* not related to the issue, followed by iteratively removing functions and lines until the program no longer displays your error (possibly because it got reduced to `void main (){}`). The step right before that should be the one that reproduces your problem. Do note that it is not uncommon that you happen to find a solution while doing this. – Jongware Nov 06 '15 at 23:51
  • You want to configure your serial port for *raw mode*. See e.g. [here](https://www.cmrr.umn.edu/~strupp/serial.html). Note that you need to do a lot more to get a semi-functional X11 keyboard. Right now you have no arrows, no functional keys, no Ctrl or Alt... – n. m. could be an AI Nov 07 '15 at 12:51

0 Answers0