Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Exposed Joystick Name, Product ID and Manufacturer ID  (Read 34161 times)

0 Members and 4 Guests are viewing this topic.

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #15 on: January 21, 2014, 10:25:28 pm »
So I tried that with no joy. Do we know that SDL's implementation works?

From my reading using struct before the declaration is related to C syntax (getting this from StackOverflow). The chosen answer for the question states that using the struct keyword in this way restricts the identifier lookup to user defined classes. This seems odd as we want to use the input_id defined in the standard Linux headers. Maybe I'm understanding that wrong? That SO post points to some further reading here.

I'm a little under the weather right now so I'm planning on giving this a fresh look later this week. I think the next thing I'll do is compile SDL on Linux and see what their implementation gives me. My reference article is over tens years old, things may have changed.

Agreed on the renaming stuff to match SFML conventions.

Antidote

  • Newbie
  • *
  • Posts: 35
    • View Profile
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #16 on: January 22, 2014, 08:10:53 am »
@NoobsArePeople2
I've gotten it to work intermittently, it seems to depend on the device, some report, some don't.
When it fails just set them to 0 and don't worry about it.

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #17 on: January 22, 2014, 07:23:15 pm »
@Antidote

Good to know. Perhaps it's driver related then. Can you post a list of the devices that do and don't work? Are you running in a VM?

Antidote

  • Newbie
  • *
  • Posts: 35
    • View Profile
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #18 on: January 22, 2014, 08:47:50 pm »
About the VM, nope 100% hardware for my quadboot.
About the controller, my old SideWinder was the only one I have that returned anything.

Those are the only ones I had to test.
Ones that don't are:
DS3
Nyko Airflo (Shows up as Honeybee)
And the Xbox 360 controller.
« Last Edit: January 22, 2014, 08:49:33 pm by Antidote »

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #19 on: January 22, 2014, 10:08:19 pm »
Awesome! Thanks for the details.

Antidote

  • Newbie
  • *
  • Posts: 35
    • View Profile
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #20 on: January 23, 2014, 12:47:08 am »
No problem, glad to help.

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #21 on: January 24, 2014, 08:13:14 am »
I've created a simple SDL app to read joystick names and GUIDs. SDL doesn't have an API for something like getJoystickVendorID(), instead you read the GUID. For Linux you can see the GUID implementation here.

My test app is on Github here.

Using my wired 360 controller on Ubuntu (running in a VM) I get the following output from my SDL test app:

Name: Microsofy X-Box 360 pad
GUID: 030000005e0400008e02000014010000

If I'm reading the SDL source code correctly this means SDL sees the vendor ID as "5e04" and the product ID as "8e02". SDL forces bytes into a little endian representation so these might typically be written as "0x045e" and "0x028e" which match what lsusb -v outputs for me:

...a bunch of stuff...
idVendor: 0x045e
idProduct: 0x028e
...a bunch more stuff stuff...

So SDL looks to be getting the correct values. With my latest commit (see here) my vendor/product ID reading is essentially identical to SDL's yet I'm still seeing EINVAL when attempting to read the EVIOCGID ioctl.

I think we should be able to get the correct values (at least with the 360 pad anyway). Going to keep digging on this.



NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #22 on: January 26, 2014, 03:19:27 am »
Short version: By using udev I'm able to get the manufacturer and product IDs! See commit. People of Linux, please test and let me know how this works for you.

Long version:

I spent some time digging through the SDL joystick implementation and reading up on iotcl and this is what I've found. SDL looks for joysticks in /dev/input/event while SFML looks in /dev/input/js. This means SDL must use the "EV" iotcls like EVIOCGNAME while SFML must use the "JS" ioctls like JSIOCGNAME. When attempting to mix and match I get EINVAL errors (EVIOCGNAME fails with an EINVAL error in SFML but it's JS counterpart JSIOCGNAME works great).

Unfortunately there is not a JS version of EVIOCGID, the ioctl used for retrieve an input_id struct, and hence the vendor and product IDs. SFML could switch to use /dev/input/event rather than /dev/input/js but it's my understanding that "js" is the more modern way of handling joysticks (also, my install of Ubuntu would get a "permission denied" error when attempting to read "event" which is odd since SDL worked...).

Enter libudev. I had seen mention of udev before in the tracker (here) in which Laurent posted a tutorial for udev. Using it is pretty straightforward and it looks to be the standard way for working with hardware devices on Linux systems. It also provides a really easy way to read vendor and product IDs. The downside is that we've introduced another dependency for the Linux implementation of SFML.

The commit with the udev update uses udev to retrieve the vendor (manufacturer) and product IDs and the JSIOCGNAME ioctl to get the joystick name. It also updates Cmake to link udev when compiling SFML on Linux.

While the Cmake update works I'm not really sure it's the best way to do it. A cursory google yields a FindUDev.cmake file. Honestly, I don't know enough about Cmake to know the best way so I guess reading up on that is next ;)

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #23 on: February 02, 2014, 05:01:03 am »
Today I put my Linux joystick updates to the test in several Linux distros:

  • Ubuntu 13.10 x64
  • Mint 16 Cinnamon x64
  • Manjaro x64
  • Fedora 20 x64

All of these are virtualized in VirtualBox running in a Windows 8 x64 host. For testing I've used an official wired Microsoft XBox 360 pad. On Windows I'm using the official MS driver for the pad and it's passed through to Linux via VirtualBox's USB support.

In all cases udev was installed by default. This is expected as the udev Wikipedia entry notes that udev was merged into systemd in April 2012. It also notes that some Distros like Debian (upon which Ubuntu and Mint are based) ship is separately. In my test, I did the default install for all distros and udev was present in every case so I think it safe to assume udev will be present and running on most Linux distros.

I did however need to install libudev (the development version) in order to have the udev headers. This means the Linux version of SFML will have a new dependency (to go along with pthread, freetype, etc): udev. I've updated CMake to include udev for Linux.

On Windows there was some concern about some macro magic I was doing with _UNICODE. I did some reading on this and found this StackOverflow question which lead to this blog post. The short version is the UNICODE define affects everything in the Windows headers and _UNICODE affects everything in the C runtime headers. So, in order to fully force the Windows version to Unicode both UNICODE and _UNICODE need to be defined.

I've squashed all my changes into a single commit and submitted a pull request here.

Thanks everyone for all the help!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #24 on: February 13, 2014, 04:30:29 pm »
Since it's a general API question, I'll post it here and not in the pull request:

Instead of three sf::Joystick methods getName(), getManufacturerId() and getProductId(), it would be a good idea to have a dedicated type for this kind of information. This introduces some structure and makes it easier to pass the related information around.

There is already sf::priv::JoystickInfo used internally, can we expose this struct in the API? Maybe we should make it a nested type of the sf::Joystick class, that is:
class Joystick
{
public:
    struct Info
    {
        JoystickInfo();

        unsigned int buttonCount;               ///< Number of buttons supported by the joystick
        bool         axes[Joystick::AxisCount]; ///< Support for each axis
        sf::String   name;                      ///< Name of the joystick
        unsigned int manufacturerId;            ///< Manufacturer identifier
        unsigned int productId;                 ///< Product identifier
    };

    static Info getInfo(unsigned int joystick);
};
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #25 on: February 18, 2014, 12:02:39 am »
What you've described is essentially what's happening with the current get*() methods behind the scenes. This is what getProductId() looks like:

Code: [Select]
unsigned int Joystick::getProductId(unsigned int joystick)
{
    return priv::JoystickManager::getInstance().getInfo(joystick).productId;
}

Making this change would reduce the number of methods in the joystick API by 4, replacing getButtonCount(), hasAxis(), getName(), getProductId(), and getManufacturerId() with getInfo(). Which might be nice but it's not as if there are dozens of methods in the joystick API (or likely to be many more).

On the downside, the convenience of hasAxis() would be lost with this change. Conceptually, I think going with getInfo() breaks from the logic of the current API.

As it stands all of the methods of sf::Joystick ask a specific question about the capabilities or state of a specific joystick: isConnected(), isButtonPressed(), hasAxis(), etc. getInfo() changes that so we instead ask specific questions about joystick state but a non-specific, indirect question about joystick info.

Further, when reading code I think sf::Joystick::getName(index) is easier to read and comprehend than sf::Joystick::getInfo(index).name.

While it would be easier to pass around a JoystickInfo object rather than multiple properties this doesn't strike me as something that will be happening all that much -- probably only when a joystick is first connected and being configured. I prefer the readability of the current API.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #26 on: February 18, 2014, 10:37:34 am »
You're making good points.

hasAxis() and getButtonCount() exist already now, so they won't be removed. Thus, the info structure would only contain 3 members (name, manufacturer ID, product ID)... The question is whether it's worth aggregating these attributes to a common type.

Any other opinions on the topic?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #27 on: February 18, 2014, 11:30:30 am »
Vendor ID and product ID always go together. Then, if we have a structure for them, why not put the name in it as well?

Another argument: sf::Font already does it this way. Even if it defines only one attribute (the font family), it is put in a Font::Info structure that is accessed with the getInfo() function.
Laurent Gomila - SFML developer

NoobsArePeople2

  • Newbie
  • *
  • Posts: 47
    • View Profile
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #28 on: February 18, 2014, 06:08:06 pm »
hasAxis() and getButtonCount() exist already now, so they won't be removed. Thus, the info structure would only contain 3 members (name, manufacturer ID, product ID)... The question is whether it's worth aggregating these attributes to a common type.

So this is a slight change from your previous proposal. Now JoystickInfo would not contain buttonCount or axes. Would axes and buttonCount go back into a JoystickCapabilities struct?

That makes more sense to me. That said, let me play devil's advocate:

It seems odd to me that we'd put name, vendor ID and product ID into an info structure but leave out button count and axes. All those things fall under the category of "info". And they are all contained in the current JoystickInfo struct (from the pull request).

Looking at that from the perspective of a developer using SFML I'd expect a getInfo() method to return all available info to me, not some subset of it.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Exposed Joystick Name, Product ID and Manufacturer ID
« Reply #29 on: February 18, 2014, 06:19:11 pm »
A struct with name and IDs would obviously not be named JoystickInfo, but rather JoystickIdentification or similar. Which solves the problem of not having buttons and axes in it.
Laurent Gomila - SFML developer