Page 1 of 1
ev3 BCC/C: plugged USB keyboard as an input/ stdin device?
Posted: 20 Dec 2013, 14:14
by HaWe
hey,
how can I use a USB keyboard plugged to the ev3 master USB port as a stdin device?
My program is currently not working.
What I'm trying is the following - is there maybe just a mistake by using pointers or is a USB keyboard device driver missing for Lego Linux ?
edit - now completely new from scratch:
Code: Select all
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "lms2012.h"
#include "ev3_button.h"
#include "ev3_lcd.h"
#define msleep(t) usleep(1000*t)
int main()
{
char text[120], tdx;
int key, c[120];
ButtonLedInit();
LcdInit();
LcdClean();
c[0]=32;
tdx=0;
while(1)
{
LcdClean();
while((key=getchar())!=10) { // read input line until [ENTER]
if((key>31)&&(key<128)) { // printable kbd code
c[tdx]=key;
text[tdx]=(char)key; // character to text string
LcdText(1, 0, 10, text) ; // no autom. echo on screen
}
tdx++; // text buffer counter
}
if(ButtonWaitForAnyPress(100) == BUTTON_ID_ESCAPE)
break;
msleep(5);
}
LcdExit();
ButtonLedExit();
return 1;
}
(now the lcd is cleared, but then the ev3 hangs up, no reaction to USB kbd press, batteries have to be removed)
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 21 Dec 2013, 10:21
by mightor
This as much effort as I can put into this. It works on my Ubuntu Linux VM and it should work with an EV3 brick. Experiment with the /dev/input/event<number>. You may need to use 0 or 1 or maybe even 2, I don't know. Play with it.
Taken and adapted from
http://rico-studio.com/linux/read-and-w ... rd-device/
Code: Select all
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#define EV_PRESSED 1
#define EV_RELEASED 0
#define EV_REPEAT 2
void main()
{
int fd = 0;
// Not sure if this has to be event0 or event1 on the EV3
char *device = "/dev/input/event1";
struct input_event event;
unsigned int scan_code = 0;
if( (fd = open(device, O_RDWR)) > 0 )
{
while (1 == 1)
{
int num_bytes = read(fd, &event, sizeof(struct input_event));
if(event.type != EV_KEY)
continue;
if(event.value == EV_RELEASED)
{
// This is the key that is pressed.
// To see which code means which key, take a look here:
// http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/input.h?v=2.6.11.8
// Use an array to map this value to the real character, should be trivial using the info in the link above.
scan_code = event.code;
printf("code: %d\n", scan_code);
}
}
}
else
{
fprintf(stderr, "Could not open keyboard device!\n");
}
}
= Xander
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 21 Dec 2013, 16:43
by HaWe
thank you,
now this one was actually really useful.
As a small contribution from me in return, here's the code to read keys by their ASCII value from a USB keyboard plugged to the EV3 -
Numpad numbers are working , shift and capslock is working, but shift is a little shaky because 2 keys are read shortly behind one another
(different from common PC kbd scancodes - no idea how to poll if 2 keys are pressed simultaneously).
the keys are for German kbd layout (QWERTZ),
for different layouts you'll have to change the characters of the letter QWERTZ[] string accordingly
(maybe copy QWERTZ[] to QWERTY[] and overwrite the entries).
initialize by init_USBkbd()
function call by
int key=getcharUSB();
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 22 Dec 2013, 19:54
by HaWe
there is a bug I cannot fix:
if I print the whole string to which the key is added then there is always a
\
at the 1st position.
e.g., if I enter
1234
it is shown
\1234
2nd problem:
in the line
(event.type != EV_KEY) ...
what is EV_KEY? it's no where been declared AFAIK...?
3rd problem:
at the first call the function appears not to wait for a keypress but runs through,
it just then waits for the 2nd, 3rd, 4th keypress and so on
(what maybe is the reason for the odd output).
what is wrong?
Code: Select all
// read letters from USB keyboard plugged to EV3
// readkeys.c
// ver. 1.02
// read USB kbd keys by: int getcharUSB()
//
// credits to Xander Soldaat
// reference:
// http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/input.h?v=2.6.11.8
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/input.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
//#include "lms2012.h" // still shaky because of re-definitions
#include "ev3_button.h"
#include "ev3_lcd.h"
#define cls() LcdClean() // more C-like
#define mline 118 // line for status msg
//..............................................................................
// USB kbd device
//..............................................................................
#define EV_PRESSED 1
#define EV_RELEASED 0
#define EV_REPEAT 2
// QWERTZ = German kbd layout representation
// uppercase overhead = 128
char QWERTZ[]= " 1234567890-= qwertzuiopü+ asdfghjklöä# <yxcvbnm,.- * 789-456+1230, !'§$%&/()=?` QWERTZUIOPÜ* ASDFGHJKLÖÄ' >YXCVBNM;:_......";
#define KEY_UPPEROVHD 130 // uppercase overhead = 128
#define KEY_LEFTSHIFT 42 // kbd keycode
#define KEY_RIGHTSHIFT 54 // kbd keycode
#define KEY_CAPSLOCK 58 // kbd keycode
int _kbd_fd_; // kbd file dev handle
//..............................................................................
char init_USBkbd() {
char *device = "/dev/input/event0"; // event1: hangs up after cls
_kbd_fd_ = 0;
if ( (_kbd_fd_ = open(device, O_RDWR)) > 0 ) return 1;
else return 0;
}
//..............................................................................
int getcharUSB() {
struct input_event event;
int keycode;
char buf[10];
int retval;
static int UPCASE;
static char LEFTSHIFTTMP;
int num_bytes;
while (event.type != EV_KEY) {
num_bytes = read(_kbd_fd_, &event, sizeof(struct input_event));
}
if(event.value == EV_RELEASED)
{
keycode = event.code;
if(keycode==KEY_CAPSLOCK) {
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0;
return 0;
}
else
{
// SHIFT for uppercase
if ( (keycode==KEY_LEFTSHIFT)||(keycode==KEY_RIGHTSHIFT) ) {
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0; // (still shaky)
LEFTSHIFTTMP=1;
return 0;
}
if(keycode== 1) retval=27; // KEY_ESCAPE
else
if( (keycode==28)||(keycode==96) ) retval=10; // KEY_ENTER
else
if(keycode==14) retval=8; // KEY_BACKSPACE
else
retval= QWERTZ[keycode+UPCASE] ;
if (LEFTSHIFTTMP) { // SHIFT for uppercase
LEFTSHIFTTMP=0;
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0; // (still shaky)
}
// debug:
//sprintf(buf,"keycode:%3d ASCII:%3d", keycode,retval); LcdText(1, 0,20, buf);
}
}
return ( retval );
}
//..............................................................................
// task main()
// how to initialize and how to call
//..............................................................................
int main()
{
int key = 0, i=0;
char buf[120], text[120]; // text string
ButtonLedInit();
LcdInit();
cls();
if (!init_USBkbd()) {
LcdText(1, 0, mline, "keyboard device error! ");
Wait(2000);
goto quit;
}
LcdText(1, 0, mline, "press keys on keyboard! ");
text[0]='\0';
while (1) {
key=getcharUSB(); // read kbd kbdkeycode => ASCII code
// now what to do with the key ?
if (key==27) goto quit; // 27 = ESC => stop program
else
if(key>32) {
// add key to string
text[i+1]='\0';
text[i] =key;
sprintf(buf,"%c ", key);
LcdText(1, 0,10, buf); // display key
LcdText(1, 0,40, text); // display string
i++;
}
Wait(1);
}
quit:
LcdText(1, 0, 10, " ");
LcdText(1, 0, mline, "program terminated ");
Wait(500);
cls();
Wait(10);
LcdExit();
ButtonLedExit();
return 1;
}
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 23 Dec 2013, 05:37
by mightor
I don't have the standard firmware on any of my bricks, nor the BCC C library, but the program seems to function just fine for me. I modified to allow me to compile it on my Ubuntu VM. I ran it in one window and typed in another:
EV_KEY is the type of event that a keyboard generates. Did you look in the link I provided in the source code for input.h? It has to be declared, you would get a compile error if it hadn't.
To make your code a bit saner, avoid using gotos and change your keycode if statements to a switch/case block.
My modified code:
Code: Select all
// read letters from USB keyboard plugged to EV3
// readkeys.c
// ver. 1.02
// read USB kbd keys by: int getcharUSB()
//
// credits to Xander Soldaat
// reference:
// http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/input.h?v=2.6.11.8
// #define EV3
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/input.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#ifdef EV3
//#include "lms2012.h" // still shaky because of re-definitions
#include "ev3_button.h"
#include "ev3_lcd.h"
#define cls() LcdClean() // more C-like
#define mline 118 // line for status msg
#endif
//..............................................................................
// USB kbd device
//..............................................................................
#define EV_PRESSED 1
#define EV_RELEASED 0
#define EV_REPEAT 2
// QWERTZ = German kbd layout representation
// uppercase overhead = 128
char QWERTZ[]= " 1234567890-= qwertzuiopü+ asdfghjklöä# <yxcvbnm,.- * 789-456+1230, !'§$%&/()=?` QWERTZUIOPÜ* ASDFGHJKLÖÄ' >YXCVBNM;:_......";
#define KEY_UPPEROVHD 130 // uppercase overhead = 128
#define KEY_LEFTSHIFT 42 // kbd keycode
#define KEY_RIGHTSHIFT 54 // kbd keycode
#define KEY_CAPSLOCK 58 // kbd keycode
#ifdef EV3
#define KEYBOARD_DEVNAME "/dev/input/event0"
#else
#define KEYBOARD_DEVNAME "/dev/input/event1"
#endif
int _kbd_fd_; // kbd file dev handle
//..............................................................................
char init_USBkbd() {
char *device = KEYBOARD_DEVNAME; // event1: hangs up after cls
_kbd_fd_ = 0;
if ( (_kbd_fd_ = open(device, O_RDWR)) > 0 ) return 1;
else return 0;
}
//..............................................................................
int getcharUSB() {
struct input_event event;
int keycode;
char buf[10];
int retval;
static int UPCASE;
static char LEFTSHIFTTMP;
int num_bytes;
while (event.type != EV_KEY) {
num_bytes = read(_kbd_fd_, &event, sizeof(struct input_event));
}
if(event.value == EV_RELEASED)
{
keycode = event.code;
if(keycode==KEY_CAPSLOCK) {
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0;
return 0;
}
else
{
// SHIFT for uppercase
if ( (keycode==KEY_LEFTSHIFT)||(keycode==KEY_RIGHTSHIFT) ) {
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0; // (still shaky)
LEFTSHIFTTMP=1;
return 0;
}
if(keycode== 1) retval=27; // KEY_ESCAPE
else
if( (keycode==28)||(keycode==96) ) retval=10; // KEY_ENTER
else
else
if(keycode==14) retval=8; // KEY_BACKSPACE
else
retval= QWERTZ[keycode+UPCASE] ;
if (LEFTSHIFTTMP) { // SHIFT for uppercase
LEFTSHIFTTMP=0;
UPCASE=(UPCASE==0)?KEY_UPPEROVHD:0; // (still shaky)
}
#ifdef EV3
// debug:
//sprintf(buf,"keycode:%3d ASCII:%3d", keycode,retval); LcdText(1, 0,20, buf);
#else
fprintf(stderr, "keycode:%3d ASCII:%3d\n", keycode,retval);
#endif
}
}
return ( retval );
}
//..............................................................................
// task main()
// how to initialize and how to call
//..............................................................................
int main()
{
int key = 0, i=0;
char buf[120], text[120]; // text string
#ifdef EV3
ButtonLedInit();
LcdInit();
cls();
#endif
if (!init_USBkbd()) {
#ifdef EV3
LcdText(1, 0, mline, "keyboard device error! ");
Wait(2000);
#else
fprintf(stderr, "keyboard device error!\n");
#endif
goto quit;
}
#ifdef EV3
LcdText(1, 0, mline, "press keys on keyboard! ");
#else
printf("Press keys on keyboard!\n");
#endif
text[0]='\0';
while (1) {
key=getcharUSB(); // read kbd kbdkeycode => ASCII code
// now what to do with the key ?
if (key==27) goto quit; // 27 = ESC => stop program
else
if(key>32) {
// add key to string
text[i+1]='\0';
text[i] =key;
sprintf(buf,"%c ", key);
#ifdef EV3
LcdText(1, 0,10, buf); // display key
LcdText(1, 0,40, text); // display string
#else
printf("buf: %s, text: %s\n", buf, text);
#endif
i++;
}
#ifdef EV3
Wait(1);
#else
sleep(1);
#endif
}
// Using a goto is a big nono if you can solve the issue
// with a simple function call. This is nasty.
quit:
#ifdef EV3
LcdText(1, 0, 10, " ");
LcdText(1, 0, mline, "program terminated ");
Wait(500);
cls();
Wait(10);
LcdExit();
ButtonLedExit();
#else
fprintf(stderr, "Program terminated\n");
#endif
return 1;
}
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 23 Dec 2013, 08:39
by HaWe
thank you for your efforts!
but strangly the problem remains:
on the ev3 screen the text string is always displayed with a leading "\".
There must be issues about the string handling or the string out function - but I have no idea what's faulty.
edit:
indeed lcdline seems not to be able to display the string correctly:
LcdText(1, 0,40, text); // display string // always a leading \
sprintf(buf, text); LcdText(1, 0,40, buf); // display string // no output at all
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 23 Dec 2013, 18:11
by HaWe
update:
Now it just displays the key but doesn't display the combined string any longer at all.
But as it works with Xander's konsole version as expected, there must be severe bugs in John's lcd header, epecially to display strings on the lcd
(but also LcdClean is bugged).
Code: Select all
// read letters from USB keyboard plugged to EV3
// kbdUSB.c
// ver. 1.04
// read USB kbd keys by: int getcharUSB()
//
// credits to Xander Soldaat
// reference:
// http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/input.h?v=2.6.11.8
// define EV3
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/input.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "ev3_button.h"
#include "ev3_lcd.h"
#define cls() LcdClean() // more C-like
#define mline 118 // line for status msg
//..............................................................................
// USB kbd device
//..............................................................................
#define EV_PRESSED 1
#define EV_RELEASED 0
#define EV_REPEAT 2
// QWERTZ = German kbd layout representation
// diphthongs/umlaut diacritics äÄ,öÖ,üÜ,ß, and accents ´` not displayable; patch for ß=\ ü=| ö=[ ä=] Ü=~ Ö={ Ä=} `=@
char QWERTZ[]= " 1234567890\\@ qwertzuiop|+ asdfghjkl[] #yxcvbnm,.- * 789-456+1230, < !'§$%&/()=?@ QWERTZUIOP~* ASDFGHJKL{} 'YXCVBNM;:_ > ";
#define CAPSSTROVHD 130 // uppercase overhead in QWERTZ string
#define KEY_LEFTSHIFT 42 // kbd keycode
#define KEY_RIGHTSHIFT 54 // kbd keycode
#define KEY_CAPSLOCK 58 // kbd keycode
#define KEYBOARD_DEVNAME "/dev/input/event0"
int _kbd_fd_; // kbd file dev handle
//..............................................................................
char init_USBkbd() {
char *device = KEYBOARD_DEVNAME; // event1: hangs up after cls
_kbd_fd_ = 0;
if ( (_kbd_fd_ = open(device, O_RDWR)) > 0 ) return 1;
else return 0;
}
//..............................................................................
int getcharUSB() {
struct input_event event;
int keycode;
char buf[10];
int retval;
static int UPCASE;
static char SHIFTTMP;
int num_bytes;
while (event.type != EV_KEY) {
num_bytes = read(_kbd_fd_, &event, sizeof(struct input_event));
}
if(event.value == EV_RELEASED)
{
keycode = event.code;
if(keycode==KEY_CAPSLOCK) {
UPCASE=(UPCASE==0)?CAPSSTROVHD:0;
return 0;
}
else
{
// SHIFT for uppercase
if ( (keycode==KEY_LEFTSHIFT)||(keycode==KEY_RIGHTSHIFT) )
{
UPCASE=(UPCASE==0)?CAPSSTROVHD:0; // (still shaky)
SHIFTTMP=1;
return 0;
}
if(keycode== 1) retval=27; // KEY_ESCAPE
else
if( (keycode==28)||(keycode==96) ) retval=10; // KEY_ENTER left/right
else
if(keycode==14) retval=8; // KEY_BACKSPACE
else
retval= QWERTZ[keycode+UPCASE] ;
if (SHIFTTMP) { // SHIFT for uppercase
SHIFTTMP=0;
UPCASE=(UPCASE==0)?CAPSSTROVHD:0; // (still shaky)
}
// debug:
sprintf(buf,"keycode:%3d ASCII:%3d", keycode,retval); LcdText(1, 0,20, buf);
}
}
return ( retval );
}
//..............................................................................
// task main()
// how to initialize and how to call
//..............................................................................
int main()
{
int key = 0, ci=0;
char buf[20], text[120]; // text string
ButtonLedInit();
LcdInit();
cls();
if (!init_USBkbd()) {
sprintf(buf,"keyboard device error! "); LcdText(1, 0, mline, buf);
Wait(2000);
goto quit;
}
sprintf(buf,"press kbd keys! "); LcdText(1, 0, mline, buf);
text[0]='\0';
while (1) {
// wait for key-press on keyboard
key=getcharUSB(); // read kbd kbdkeycode => ASCII code
// wait for key-up
// now what to do with the key ?
if (key==27) goto quit; // 27 = ESC => stop program
else
if(key>31) { // printable key
text[ci] =key; // add key to string (char array)
text[ci+1]='\0'; // null-terminated string
sprintf(buf,"%c ", key); // display key numbers as letters
LcdText(1, 0,10, buf);
// display string
LcdText(1, 0,40, text); // <<<<<<<<<<< BUG !!! Not executed!
ci++;
}
Wait(1);
}
quit:
cls();
LcdText(1, 0, mline, "program terminated ");
Wait(500);
cls(); // <<<<<<<<<<< BUG !!! Not executed!
Wait(10);
LcdExit();
ButtonLedExit();
return 1;
}
Re: ev3 BCC/C: plugged USB keyboard as a stdin device?
Posted: 26 Dec 2013, 13:18
by HaWe
I tried to make it run, but no chance -
although the keys are read correctly from keyboard I can't make BCC/C add them to a string and display the string on the screen.
If we only could use the C-functions like getchar, gets (with screen-echo) and also printf like by stdio.h in a console !
I guess I must give up.