Quart: OpenELEC branch commit breakdown
I've been putting off dealing with the documentation of all the snags I've run into thus far and decided to just take a look at the commit log and rationalize each one. Some of these are fairly specific to my situation, while others may have broader implications.
Once the gamecon module was added to the build, this was the first and largest hurdle to jump in getting gamepad input in OpenELEC for Raspberry Pi. Here's the situation:
the gamepad device is simply not utilized, or even logged as enabled, though running evtest shows that it's blocked. The first place you might look for a solution, understanding that you're using Linux window events, is LinuxInputDevices.cpp. Scrolling down and seeing the Linux input device type enumeration confirms the supposition that you are on the right track.
Your supposition, as it turns out, is bad and you should feel bad because the GetInfo method is going to be called to determine what type your little device falls into, and it will do this:
...since the button counting loop stopped at BTN_JOYSTICK (this is the index at witch joystick/gamepad buttons start), num_buttons is 0 and your gamepad is left as LI_DEVICE_NONE. Unfortunately the solution is not just to bump the index limit up on the loop, because there is no codepath in the application loop for CLinuxInputDevice into CButtonTranslator's TranslateJoystickString method.
There are only two paths to TranslateJoystickString in CApplication. One is the event server, the other uses SDL. The latter seemed an easier, cleaner option to me. Theoretically, it would just mean the inclusion of libSDL in the build.
This is from the graphic configuration script in the OpenELEC build system.
We start to see how a problem like this could happen, because right now it's relegated to users running XBMC in Linux without X, who require joystick support sans event server. One could make an argument of course that you can use SDL input without the rest, which is what I did.
The solution was mostly just changing a few variables. I commented out the lines above and changed some defines in system.h. The only real functional issue was that after XBMC's CLinuxInputDevice assigns LI_DEVICE_NONE to the gamepad devices it continues to hold onto block file descriptors, so when SDL uses evdev to grab the device, it's blocked as well. This is addressed in SDL_input_only.patch, after the call to GetInfo.
This was absolutely infuriating, and took a good bit of GDB to figure out. The failure mode is that a button will behave as though it is being held down, often after advancing a menu, so depending on the next focused item on each screen you may be in for a fun guided tour through the UI. The offender this time was the SDL joystick class. As it turns out, evdev drivers can miss an event. I get a sense that it happens when the system is taxed, so the situation is exacerbated on RPi, but certainly not unique to it. When an event is missed evdev transmits a SYN_DROPPED event, at which point it can be polled to correct internal buffers. Unfortunately there is no concept of SYN_DROPPED as of SDL 1.2.15. Fortunately a contributor named Simon has proposed a patch, which was merged in last month, and addresses this issue with regard to axes, but not buttons. I modified it to poll the button states and merged those changes back into the 1.2.15 joystick class with this patch.
Originally I was going to fix these issues by using the js* devices in SDL and applying calibrations with jscal (I added linuxconsole package to my build in order to support it), but I really wanted the D-Pad to be supported properly as a HAT input, which is unique to evdev. As a result, I made some changes to the initialization numbers in gamecon. The problems are these:
1. Analog trigger axes come to rest at the low end of their value range. As a result XBMC thinks that the triggers are always being pulled negative. Creating a unattainable "false bottom" for analog triggers equidistant from the resting and max values prevents this.
2. The theoretical range for all Gamecube axes is 0-255. These values are possible, but only when the controllers are taken out of their frames, because the plastic limits their range of motion. The following is a quote from the Linux Kernel Documentation(italics added for emphasis):
input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
This setting would be appropriate for a joystick X axis, with the minimum of 0, maximum of 255 (which the joystick *must* be able to reach, no problem if it sometimes reports more, but it must be able to always reach the min and max values), with noise in the data up to +- 4, and with a center flat position of size 8.
I tested the four controllers I own and unfortunately, there's a good bit of variance between them. The values I ended up with represent worst case ranges (ensuring all the axes of all four gamepads were well within reach of the mins and maxes) and midpoints that represent axes at rest within precision.
Even if these values do not perfectly suit all Gamecube gamepads, they should be an improvement over the unattainable 0-255.
That more-or-less covers it to where I am today. I'm happy to say that XBMC is fully functional, and I'm using it in my bedroom now with no input device other than a Gamecube controller. There are some things I left out that are very specific to my hardware build. I can cover some of those things (joystick module initialization, keybinding xml, etc.) when I can write a proper Quart how-to. In the meantime, I need to try and get some of these things patched in officially and make this easier to replicate.
Quart: (Re)Enter the Gamecube
In the last post I laid out the motivation for the little network appliance I've dubbed Quart. The reason for the name is that I'm enclosing and operating a Raspberry Pi inside the nearly-quart-sized Nintendo Gamecube, which has been collecting dust in the basement for the last six years or so, since we replaced it with the Wii.
Why Gamecube?
After all, this system lived out a relatively short tenure as a video input in our household and doesn't evoke the same nostalgia as, say, Super Nintendo (or more in my case, Commodore 64). In fact, the short answer to the question above is: We couldn't find the Super Nintendo. But having decided on the Gamecube, I hit on a number of other great qualifications that make RPi and Gamecube a delightful abomination.
Cheap and Available
I hit on this already. What else are you going to do with the bloody thing? If you still own a Gamecube, you likely have a Wii as well. The Wii is, of course, fully backward compatible. So your Gamecube is either on your shelf, or the one at your local game trader; waiting to be sold for a pittance.
Relatively Small
We saw Nintendo and competitors take drastically different paths for the first time in this generation. Sony and newcomer Microsoft came out with their enthusiast-oriented powerhouses, while Nintendo released the smaller, lower-powered, inexpensive Gamecube. Admittedly it's still quite a bit larger than cases made to fit a Pi snugly, but it cleanly exposes the required controller ports, power and reset buttons.
Serviceable
Once you get past the four blasted security screws on the bottom, and start pulling it apart you may start noticing how well the various concerns are isolated and accessible. We end up using precious little of the remaining guts, but the wheat is cleanly separated from the chaff. More details on this later.
Buttons
Remember, one of the major requirements for this system is that all user functions will be available via the gamepad. Gamecube controllers have an ample number of inputs, and even sport some fairly modern concepts, like analog triggers, which make XBMC navigation a far more pleasurable experience.
Features
All four control ports are fed to GPIO and are functional using Markus Hiienkari's work with the original Linux gamecon driver by Vojtech Pavlik, and some modifications.
Runs OpenELEC, forked to support SDL gamepad input and modified gamecon driver.
Integrated power button and LED
Integrated reset button
Integrated classic power and AV cables
Quart: A Raspberry Pi Prototype
Recently I have been spending my nights obsessed with this latest prototype based on everyone's favorite low-cost, low-power, educational computing platform, Raspberry Pi. I have to say, this platform and its community have cleared away any fear that the tech industry would someday yield nothing but and endless supply of lowest-common-denominator targeted "gadgets", leaving no refuge for thought. Nay, this is in fact a golden age for the curious and inventive. So now with my jaded husk removed and my enthusiasm refreshed it's time to document all the things, because I've been having too much fun to stop.
Motivation
The prototype I'm now affectionately referring to as "Quart" started with my dissatisfaction with using my XBox 360 as the media solution for our bedroom. The Windows Media Center Extender has been worthy of its tenure in our home, but every time I wanted to play a game, I'd be missing out on important visual details (truer every year), due to the extremely dated, stereo, standard definition tube in that room. Call me cheap, I just can't justify another LCD for a room where it would be so casually used. I moved the 360 downstairs in time to play Halo 4.
Enter XBMC as the obvious front runner. I really have only one overarching SAF feature requirement for this particular terminal, and that is to watch TV upstairs. TV, in this scenario is primarily qualified as recorded shows. I don't witness a lot of channel surfing and god knows I hate doing it. Nevertheless I seem to get both features with MediaPortal on my server and the latest Frodo release of XBMC. Let me say right now, from the perspective of an MCE stalwart, XBMC's is not a great TV experience right now. It's a brand new feature so I'm sure it will be improving. However this is a decision that reflects where the cable TV sits on my own list of priories, when laid next to other virtues; flexibility, internet streaming options, active support and great new features like mobile DLNA and Airplay streaming.
So what else was the hardware going to be? I had looked at some passively cooled Atom/Ion devices in the past, but this decision did not take long. The RPi runs at a positively green 3.5 Watts under load and is completely silent. Maybe not the most powerful system, but this room needed a light terminal. Now, with an open source 10 foot interface, open source operating system and open hardware platform, I could look at the whole picture with an ideal in mind.
The Ideal
Having used the XBox as an extender, It's easy to see that the gamepad as a 10-foot control peripheral works in this scenario. I simply don't need another remote for this room. Ultimately no remote, however ergonomically designed, works as well in the dark as a gamepad, and a UI built to support it. This may be a polarizing point, and I'm willing to concede that it requires two whole hands, and that in a living room it would never fly. I can't imagine flipping on my TV and expecting a visitor to find the game or start the movie this way, but this is the bedroom. It needs to be easy to use for us, but the muscle memory is an inexpensive one-time cost.
Also, my wife and I are on the cusp of generations X and Y. Are there games in our room? Yes, there are games in our room. Naturally this is not a beefy device, but it's more than capable of being a great platform on which to curate some of my favorites of old and serve them up in a pleasing way for myself, my wife and for posterity. So here then is the short list of targeted features/qualities.
1. Plays recorded cable programming from TV server
2. Plays my old games from dusty platforms
3. All functionality must be gamepad accessible. I'll be able to SSH into it for maintenance, but I don't intend to attach a keyboard or anything else.
4. Sturdy enclosure, well integrated with gamepad/s. Should be pleasing to the eye, though it will be in a cabinet.
5. Fast boots/game loads
Incidentally, similar forays by Steam and OUYA lend credence to the concept of a light-weight Linux-based network appliance as a 10-foot entertainment hub.
Current progress to these ends discussed in the next post.