Discussion:
[Gambas-user] Gambas class to read a joystick
Rob
2008-03-02 22:36:43 UTC
Permalink
Someone on linuxbasic.net asked for a way to read a joystick in
Gambas. I couldn't find anything in the SDL component for that
purpose, so I wrote a minimal class that reads from the raw device,
parses the data into something useful, and throws events. I wrote a
program to demonstrate it as well.

To make it work, I had to EXEC ["cat", device] instead of just OPEN
device FOR READ WATCH. Gambas told me "System error: Invalid
argument" every time the File_Read event fired and I tried to read
from the file handle, even though the example makes it look like it
works with device nodes. I'm sure there's a better way to do this,
but ultimately gb.sdl should probably have joystick support anyway
(and if I were more familiar with SDL, I would have done that instead
of this.) Nonetheless, this works.

In case the archived version of the list doesn't store attachments,
it's also available at http://www.kudla.org/jstest-0.0.2.tar.gz for
future reference.

Rob
Laurent Carlier
2008-03-02 22:58:03 UTC
Permalink
Post by Rob
Someone on linuxbasic.net asked for a way to read a joystick in
Gambas. I couldn't find anything in the SDL component for that
purpose, so I wrote a minimal class that reads from the raw device,
parses the data into something useful, and throws events. I wrote a
program to demonstrate it as well.
To make it work, I had to EXEC ["cat", device] instead of just OPEN
device FOR READ WATCH. Gambas told me "System error: Invalid
argument" every time the File_Read event fired and I tried to read
from the file handle, even though the example makes it look like it
works with device nodes. I'm sure there's a better way to do this,
but ultimately gb.sdl should probably have joystick support anyway
(and if I were more familiar with SDL, I would have done that instead
of this.) Nonetheless, this works.
In case the archived version of the list doesn't store attachments,
it's also available at http://www.kudla.org/jstest-0.0.2.tar.gz for
future reference.
Rob
An external component (outside of sdl) should be a good idea and not be too
hard to develop.

Some hints (quick search through gg):
http://www.koders.com/c/fid19CB9E605749A439549F8CC9B8433DCAC6AC5A55.aspx
http://www.mjmwired.net/kernel/Documentation/input/joystick.txt

++
Rob
2008-03-03 03:15:58 UTC
Permalink
Post by Laurent Carlier
An external component (outside of sdl) should be a good idea and
not be too hard to develop.
http://www.koders.com/c/fid19CB9E605749A439549F8CC9B8433DCAC6AC5A55
.aspx
http://www.mjmwired.net/kernel/Documentation/input/joystick.txt
My class only supports HID-standard joysticks, which seems to be all
they sell nowadays. (The one I used is USB, but I think Bluetooth
gamepads are HID too.) The links above are for the old
style "gameport" joysticks, and I don't have any way to test those
since I don't own any hardware with a gameport anymore. I think
those disappeared before parallel ports did.

Anyway, my class seems to support most of the features joysticks have
(up to 256 buttons and axes, but no rumble because I don't have a
rumbling controller.) If I do write a proper component I think it'll
be a C version of that class, though hopefully I will no longer have
to spawn /bin/cat.

Rob
Benoit Minisini
2008-03-02 23:00:49 UTC
Permalink
Post by Rob
Someone on linuxbasic.net asked for a way to read a joystick in
Gambas. I couldn't find anything in the SDL component for that
purpose, so I wrote a minimal class that reads from the raw device,
parses the data into something useful, and throws events. I wrote a
program to demonstrate it as well.
To make it work, I had to EXEC ["cat", device] instead of just OPEN
device FOR READ WATCH. Gambas told me "System error: Invalid
argument" every time the File_Read event fired and I tried to read
from the file handle, even though the example makes it look like it
works with device nodes.
Having no joystick, I opened "/dev/input/mouse0" with FOR READ WATCH, the Read
event is fired when I move the mouse, and I don't get such an error. So this
is strange... Where do you get the error exactly?
--
Benoit Minisini
Rob
2008-03-03 03:06:52 UTC
Permalink
Post by Benoit Minisini
Having no joystick, I opened "/dev/input/mouse0" with FOR READ
WATCH, the Read event is fired when I move the mouse, and I don't
get such an error. So this is strange... Where do you get the error
exactly?
On the first "READ #jsdev" line. I've attached a small project to
recreate the error (on my system, with a USB gamepad plugged in)
along with a screenshot so you can see the error.

Rob
Benoit Minisini
2008-03-03 13:29:57 UTC
Permalink
This post might be inappropriate. Click to display it.
Rob
2008-03-03 14:56:26 UTC
Permalink
Thanks, I might as well write the joystick component in Gambas then.
How do you think it should be named?

Rob
Benoit Minisini
2008-03-03 15:53:59 UTC
Permalink
Post by Rob
Thanks, I might as well write the joystick component in Gambas then.
How do you think it should be named?
Rob
Mmm, good question...

Maybe you should first read the documentation on /dev/input in the
Documentation directory of the linux kernel sources. Not to implement all its
features, but to see what the specific joystick part has in common with
other /dev/input devices, so that your component could easily be extended to
support other devices.

Then this component is linux specific. At the moment, the interpreter does not
tell anything about the underlying OS. Maybe it should? With an
implementation of #ifdef / #endif in the gambas compiler? For the 3.0 version
then...

So I suggest something like "gb.linux.joystick", to tell that is really linux
specific.

Regards,
--
Benoit Minisini
Audiossis
2008-03-04 09:25:42 UTC
Permalink
Post by Benoit Minisini
------------------------------
Message: 3
Date: Mon, 3 Mar 2008 09:56:26 -0500
Subject: Re: [Gambas-user] Gambas class to read a joystick
Content-Type: text/plain; charset="iso-8859-1"
Thanks, I might as well write the joystick component in Gambas then.
How do you think it should be named?
Rob
Rob,
Sorry, it took me a little time to post to your request. I am
another Gambas user (not a developer), but I have written a Gambas class
file to make use of a C library called libusb. It would seem to me that
you may benefit from this class file with your joystick issue if your
joystick is not detected in a way that Gambas can otherwise use.

This library will let you write a user mode driver or program that
will access almost any type of usb device, although it does have its
limits (isochronous tranfers are not supported yet). However, that being
said, if you know enough C to program a Gambas module, then you may be
able to add isochronous support to this library for your own uses......?
You could then build on my class file and get the joystick support you
are looking for. Using libusb would allow you to bypass the HID driver
altogether.

Perhaps you could even base a Gambas module on the libusb library....?

Just a suggestion.

Ben

(PS. Sorry for the double post Benoit, I keep forgetting to change the
subject line......)
Benoit Minisini
2008-03-04 15:57:18 UTC
Permalink
Post by Audiossis
Post by Benoit Minisini
------------------------------
Message: 3
Date: Mon, 3 Mar 2008 09:56:26 -0500
Subject: Re: [Gambas-user] Gambas class to read a joystick
Content-Type: text/plain; charset="iso-8859-1"
Thanks, I might as well write the joystick component in Gambas then.
How do you think it should be named?
Rob
Rob,
Sorry, it took me a little time to post to your request. I am
another Gambas user (not a developer), but I have written a Gambas class
file to make use of a C library called libusb. It would seem to me that
you may benefit from this class file with your joystick issue if your
joystick is not detected in a way that Gambas can otherwise use.
This library will let you write a user mode driver or program that
will access almost any type of usb device, although it does have its
limits (isochronous tranfers are not supported yet). However, that being
said, if you know enough C to program a Gambas module, then you may be
able to add isochronous support to this library for your own uses......?
You could then build on my class file and get the joystick support you
are looking for. Using libusb would allow you to bypass the HID driver
altogether.
Perhaps you could even base a Gambas module on the libusb library....?
Just a suggestion.
Ben
(PS. Sorry for the double post Benoit, I keep forgetting to change the
subject line......)
I think you shouldn't read usb directly, because the Linux kernel has
implemented an abstraction layer with devices located in /dev/input.
Apparently you have /dev/input/event? devices that send input events, and
specific devices for mice, joystick, and other things I don't know. If the
joystick/keyboard/mouse is USB or serial is managed by these drivers.

My 2 cents...
--
Benoit Minisini
Rob
2008-03-04 16:14:11 UTC
Permalink
Post by Benoit Minisini
I think you shouldn't read usb directly, because the Linux kernel
has implemented an abstraction layer with devices located in
/dev/input. Apparently you have /dev/input/event? devices that send
Yeah, I agree. It may be useful to have a generalized Gambas USB
library available, but where there are abstraction layers I think we
should use them. That's why I might end up making an SDL input
component rather than a raw joystick component, assuming SDL input is
usable by applications that don't use an SDL event loop, like Qt and
Gtk ones. If it works, all Gambas apps on SDL-supported platforms
would get joystick support, not just Linux.

I wish I could just throw something together to try it, but my time
for coding is pretty much just the weekends right now.

Rob
Laurent Carlier
2008-03-04 16:32:29 UTC
Permalink
Post by Rob
Post by Benoit Minisini
I think you shouldn't read usb directly, because the Linux kernel
has implemented an abstraction layer with devices located in
/dev/input. Apparently you have /dev/input/event? devices that send
Yeah, I agree. It may be useful to have a generalized Gambas USB
library available, but where there are abstraction layers I think we
should use them. That's why I might end up making an SDL input
component rather than a raw joystick component, assuming SDL input is
usable by applications that don't use an SDL event loop, like Qt and
Gtk ones. If it works, all Gambas apps on SDL-supported platforms
would get joystick support, not just Linux.
I wish I could just throw something together to try it, but my time
for coding is pretty much just the weekends right now.
Rob
I've just add a quick and small piece of code for a joystick devices
component. Currently only "autodetect" is done.

svn co
https://gambas.svn.sourceforge.net/svnroot/gambas/gambas/branches/2.0-lordhExpComp/gb.joydev

++
a***@netspace.net.au
2008-03-04 22:35:15 UTC
Permalink
This post might be inappropriate. Click to display it.
kevinfishburne
2010-09-07 03:19:44 UTC
Permalink
Post by Rob
Someone on linuxbasic.net asked for a way to read a joystick in
Gambas. I couldn't find anything in the SDL component for that
purpose, so I wrote a minimal class that reads from the raw device,
parses the data into something useful, and throws events. I wrote a
program to demonstrate it as well.
Referenced from:

http://old.nabble.com/Gambas-class-to-read-a-joystick-td15794466.html#a15797006

Hi Rob. Thanks for the awesome code. It was the only method I could find for
reading a gamepad in GAMBAS. I've since integrated it into my own program
and thought I'd list it here for folks who need to monitor asynchronous
button presses along with stick input.

I've integrated a time stamp comparison for each button so "taps" and
"holds" may be differentiated. I left debug prints where programmers may
insert their own code (myself included). The values are reported from a PS2
"dual shock"-style USB controller, a Logitech "DUAL ACTION" $30 piece of
history. Here it is, for better or worse:

' Gambas module file
' Player input module

PUBLIC pad_device AS Process ' Device to accept gamepad input.
PUBLIC pad_time AS Integer ' Current time input occurred.
PUBLIC pad_data AS Short ' Current input data (stick data, 0=press,
1=release).
PUBLIC pad_type AS Byte ' Current input type (1 = button, 2 =
stick).
' Current button or axis number.
' (0 - 11 = buttons, 0 = left horizontal, 1 = left verticle, 2 = right
horizontal, 3 = right verticle, 4 = d-pad horizontal, 5 = d-pad verticle).
PUBLIC pad_number AS Byte
PUBLIC button AS Integer[12, 2] ' Button number, old button status (true =
pressed, false = released) and time stamp.
PUBLIC taptime AS Integer = 375 ' Number of milliseconds to elapse after
holding a button for it to become a hold command.

PUBLIC SUB Initialize()

' Perform player input initialization.

' Set up the gamepad.
pad_device = EXEC ["cat", "/dev/input/js0"] FOR READ AS "Gamepad"
WAIT 1

END

PUBLIC SUB Gamepad_READ()

' General declarations.
DIM counter AS Byte

' Read new gamepad data.
READ #pad_device, pad_time, 4
READ #pad_device, pad_data, 2
READ #pad_device, pad_type, 1
READ #pad_device, pad_number, 1

' Deal with button mashing.
IF pad_type = 1 THEN
' Button mashing has occurred.
IF pad_data = 1 THEN
' Button was pressed.
button[pad_number, 0] = TRUE
button[pad_number, 1] = pad_time
ELSE
' Button was released.
FOR counter = 0 TO 11
' Determine if button was tapped or held.
IF pad_number = counter THEN
IF Abs(pad_time - button[counter, 1]) < taptime THEN
PRINT "tapped", Abs(pad_time - button[counter, 1])
ELSE
PRINT "held", Abs(pad_time - button[counter, 1])
ENDIF
ENDIF
NEXT
' Preserve command history.
button[pad_number, 0] = FALSE
button[pad_number, 1] = pad_time
ENDIF
ENDIF
' Deal with stick flailing.
IF pad_type = 2 THEN
' Stick flailing has occurred.
SELECT CASE pad_number
CASE 0
' Left analog, horizontal.
IF pad_data < 0 THEN PRINT "Left analog: Move left"
IF pad_data > 0 THEN PRINT "Left analog: Move right"
CASE 1
' Left analog, vertical.
IF pad_data < 0 THEN PRINT "Left analog: Move up"
IF pad_data > 0 THEN PRINT "Left analog: Move down"
CASE 2
' Right analog, horizontal.
IF pad_data < 0 THEN PRINT "Right analog: Move left"
IF pad_data > 0 THEN PRINT "Right analog: Move right"
CASE 3
' Right analog, vertical.
IF pad_data < 0 THEN PRINT "Right analog: Move up"
IF pad_data > 0 THEN PRINT "Right analog: Move down"
CASE 4
' D-pad, horizontal.
IF pad_data < 0 THEN PRINT "D-pad: Move left"
IF pad_data > 0 THEN PRINT "D-pad: Move right"
CASE 5
' D-pad, vertical.
IF pad_data < 0 THEN PRINT "D-pad: Move up"
IF pad_data > 0 THEN PRINT "D-pad: Move down"
END SELECT
ENDIF

' Debug info.
PRINT "pad_time: " & Str$(pad_time), "pad_data: " & Str$(pad_data),
"pad_type: " & Str$(pad_type), "pad_number: " & Str$(pad_number)

END


-----
Kevin Fishburne, Eight Virtues
www: http://sales.eightvirtues.com http://sales.eightvirtues.com
e-mail: mailto:***@eightvirtues.com ***@eightvirtues.com
phone: (770) 853-6271
--
View this message in context: http://old.nabble.com/Gambas-class-to-read-a-joystick-tp15794466p29639131.html
Sent from the gambas-user mailing list archive at Nabble.com.
Benoît Minisini
2010-09-08 12:00:58 UTC
Permalink
Post by kevinfishburne
Post by Rob
Someone on linuxbasic.net asked for a way to read a joystick in
Gambas. I couldn't find anything in the SDL component for that
purpose, so I wrote a minimal class that reads from the raw device,
parses the data into something useful, and throws events. I wrote a
program to demonstrate it as well.
http://old.nabble.com/Gambas-class-to-read-a-joystick-td15794466.html#a1579
7006
Hi Rob. Thanks for the awesome code. It was the only method I could find
for reading a gamepad in GAMBAS. I've since integrated it into my own
program and thought I'd list it here for folks who need to monitor
asynchronous button presses along with stick input.
...
You should put that on the wiki, that may interest some people.
--
Benoît Minisini
Loading...