LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   use SDL to read joystick/gamepad input (https://www.linuxquestions.org/questions/programming-9/use-sdl-to-read-joystick-gamepad-input-490136/)

samel_tvom 10-06-2006 05:47 PM

use SDL to read joystick/gamepad input
 
Hi!

I have written a really ugly program in C that reads input from my gamepad and then generates xevents, or sends keycodes, whatever you wanna call it, using the Xtest library (#include <X11/extensions/XTest.h>). So that for example, when you press the X-button on the gamepad, I make X generate a "press return key event".

I read byte by byte from /dev/input/js0 and I figured that maybe all gamepads and joysticks haven't got the same output, so I wanted to use something generic to read joystick/gamepad input. Something like SDL maybe.

But I can't get SDL to read input when the SDL app window is passive. I rather not use a gui at all since I only want to launch a daemon that listens for gamepad inputs and then makes xevents.

Any idea how to do this? Any other lib to use?

And yes, I have heard of qjoypad. http://qjoypad.sourceforge.net/

Thanks!

tuxdev 10-07-2006 11:17 AM

Where's the code? Can't say why it is doing whatever it is doing without looking at the code. Make sure you wrap them in [code] tags to preserve indentation.

osor 10-07-2006 03:33 PM

Quote:

Originally Posted by samel_tvom
Hi!

I have written a really ugly program in C that reads input from my gamepad and then generates xevents, or sends keycodes, whatever you wanna call it, using the Xtest library (#include <X11/extensions/XTest.h>). So that for example, when you press the X-button on the gamepad, I make X generate a "press return key event".

I read byte by byte from /dev/input/js0 and I figured that maybe all gamepads and joysticks haven't got the same output, so I wanted to use something generic to read joystick/gamepad input. Something like SDL maybe.

But I can't get SDL to read input when the SDL app window is passive. I rather not use a gui at all since I only want to launch a daemon that listens for gamepad inputs and then makes xevents.

If you are going to use linux, the /dev/input/jsX interfaces all generate the same sort of output, regardless of manufacturer (IIRC, joydev is the driver responsible for this). Why are you reading one byte at a time? You should read more bytes (maybe 8?). Whatever the number, it's probably better to use sizeof(whatever_the_js_event_struct_is_called) instead. It's been awhile, but I think upon the opening of the device, joydev spits out some stuff (i.e., fake events with special meaning) that's supposed to tell you about the number of buttons/axes/etc. on this specific joypad. There are also some IOCTL's to figure this out.

You can use the linux joydev API directly instead of trying to find a library with its own joystick API (unless, of course, you want some sort of cross-platform portability). Documentation should be in the linux source tree.

samel_tvom 10-07-2006 05:02 PM

Yeah, I found out later on that using the js_event is probably the way to go. However, I can't seem to compile the program. Maybe you guys could help me.

Code:

#include <stdio.h>
#include <stdlib.h>
#include <linux/joystick.h>

int main() {
        int len;
        js_event msg;
        char* device = "/dev/input/js0";
        FILE *f = fopen(device, "rb+");
       
        while(1) {
                read(f, &msg, sizeof(js_event));
                if (len == (int) sizeof(js_event)) {
                        printf("wii\n");
                }
        }
       
        return 0;

}

I try to compile with "gcc test.c" but I get
‘js_event’ undeclared (first use in this function)
and I can't figure out what lib the #include <linux/joystick.h> whould be in.
What args should I have to gcc?

Thanks!

samel_tvom 10-07-2006 05:09 PM

Hehe, I might add that the program I just posted is just a test program to get the reading from the joystick work =)

Now that I found out that using linux/joystick.h my old program (shitty and all) is useless, but I'll post it anyways.

There's some code from qjoypad, it's GPL'ed

Code:

// gcc gamepad.c -lXtst

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

#include <X11/extensions/XTest.h>
#include <X11/Xlib.h>

// so that we get the definintions of keys in keysymdef.h
#define XK_LATIN1
#define XK_MISCELLANY

#include <X11/keysymdef.h>


typedef struct xevent xevent;

struct xevent {
        int type;
        unsigned int value1;    //button, keycode, or x
        unsigned int value2; //y
};


void sendevent(xevent e, Display *display) {
        if (e.value1 == 0 && e.value2 == 0) return;
        if (e.type == 4) {
                XTestFakeRelativeMotionEvent(display, e.value1, e.value2, 0);
        }
        else {
                if (e.type == 0 || e.type == 1) {
                        XTestFakeKeyEvent(display, e.value1, (e.type == 1), 0);
                }
                else if (e.type == 2 | e.type == 3) {
                        XTestFakeButtonEvent(display, e.value1, (e.type == 3), 0);
                }
        }
        XFlush(display);
}




int main() {
        unsigned char down_down[] = {255, 127, 2, 1};
        unsigned char down_up[] = {0, 0, 2, 1};
        unsigned char up_down[] = {1, 128, 2, 1};
        unsigned char up_up[] = {0, 0, 2, 1};

        unsigned char left_down[] = {1, 128, 2, 0};
        unsigned char left_up[] = {0, 0, 2, 0};
        unsigned char right_down[] = {255, 127, 2, 0};
        unsigned char right_up[] = {0, 0, 2, 0};
       
        unsigned char anybutton_down[] = {1, 0, 1, 1};

        Display *display;
        display = XOpenDisplay(":0.0");       
        xevent e;

        char* device = "/dev/input/js0";
        unsigned char packet[8];
        unsigned char key[4];       

        FILE *f = fopen(device, "wb+");

        // read away stuff at the begining
        void *tmp = malloc(8*12*sizeof(char));
        fread(tmp, sizeof(char)*8*12, 1, f);
        free(tmp);
       
        while(1) {
                fread(&packet, sizeof(char)*8, 1, f);
                key[0] = packet[4];
                key[1] = packet[5];
                key[2] = packet[6];
                key[3] = packet[7];
               
                if(strncasecmp(key, up_down, 4) == 0) {
                        e.type = 1;
                        e.value1 = XKeysymToKeycode(display, XK_Up);
                        sendevent(e, display);
                        e.type = 0;
                        sendevent(e, display);
                       
                }
                       
                if(strncasecmp(key, down_down, 4) == 0) {
                        e.type = 1;
                        e.value1 = XKeysymToKeycode(display, XK_Down);
                        sendevent(e, display);
                        e.type = 0;
                        sendevent(e, display);
                }
                if(strncasecmp(key, left_down, 4) == 0) {
                        e.type = 1;
                        e.value1 = XKeysymToKeycode(display, XK_Left);
                        sendevent(e, display);
                        e.type = 0;
                        sendevent(e, display);

                }
                if(strncasecmp(key, right_down, 4) == 0) {
                        e.type = 1;
                        e.value1 = XKeysymToKeycode(display, XK_Right);
                        sendevent(e, display);
                        e.type = 0;
                        sendevent(e, display);
                }
                if(strncasecmp(key, anybutton_down, 4) == 0) {
                        e.type = 1;
                        e.value1 = XKeysymToKeycode(display, XK_Return);
                        sendevent(e, display);
                        e.type = 0;
                        sendevent(e, display);
                }
                       
                usleep(1000);
        }
       
        return 0;

}


samel_tvom 10-07-2006 05:16 PM

Hmm, I should think before I post, anyways. Since qjoypad is written in c++ maybe I should use
Code:

struct js_event msg;
However, adding the "struct" did no difference.

osor 10-07-2006 10:02 PM

Quote:

Originally Posted by samel_tvom
Hmm, I should think before I post, anyways. Since qjoypad is written in c++ maybe I should use
Code:

struct js_event msg;
However, adding the "struct" did no difference.

The struct is not typedef'd, so you need to add struct everytime you use it (i.e., wherever it says js_event, change it to struct js_event).

Also, currently, you don't do anything to len, rendering your program useless.

You could change
Code:

read(f, &msg, sizeof(struct js_event));
        if (len == (int) sizeof(struct js_event)) {

to
Code:

len = read(f, &msg, sizeof(struct js_event));
        if (len == (int) sizeof(struct js_event)) {

or even
Code:

if ( (len = read(f, &msg, sizeof(struct js_event))) == (int) sizeof struct js_event) {
Someone needs to brush up on their C.

samel_tvom 10-09-2006 03:11 PM

Yepp, that's totally true =)

Thanks for the info, really appreciate it!


All times are GMT -5. The time now is 09:25 AM.