HID compliant USB driver

Actually, two Dualshock 3 are working for me!

Thanks for confirming that 2 DS3 Controllers works together… this was not working for Spielvan not sure why.

I will check your code and let you know if you need to change something to make it work… until then.

Isto é musica para os meus ouvidos, uma das principais barreiras do retroarch wii é sem duvida usar outro controle usb sem ser o de playstation 3 e a outra usar mais de um controle usb, quem sabe quando rompermos a barreira dos dois controles no futuro não suporte um Hub usb para 4 controles o que seria muito útil para jogos como Simpsons e tartarugas ninjas Arcade da Konami.

This is music to my ears, one of the main barriers retroarch Wii is no doubt use another USB control without the playstation 3 and the other to use more than one USB control, who knows when we break the barrier of two controls in the future not supports a uSB Hub for 4 controls which would be very useful for games like Simpsons and Konami Arcade ninja turtles.

[QUOTE=Spielvan;38397]Isto é musica para os meus ouvidos, uma das principais barreiras do retroarch wii é sem duvida usar outro controle usb sem ser o de playstation 3 e a outra usar mais de um controle usb, quem sabe quando rompermos a barreira dos dois controles no futuro não suporte um Hub usb para 4 controles o que seria muito útil para jogos como Simpsons e tartarugas ninjas Arcade da Konami.

This is music to my ears, one of the main barriers retroarch Wii is no doubt use another USB control without the playstation 3 and the other to use more than one USB control, who knows when we break the barrier of two controls in the future not supports a uSB Hub for 4 controls which would be very useful for games like Simpsons and Konami Arcade ninja turtles.[/QUOTE]

You can do it using the traditional Wiimotes and GC Controls right now.

[QUOTE=SuperSpongo;38340]My gamepad sends 8 Bytes of data

80 80 00 00 00 00 00 00

The first Byte is the X-Axis, the second one the Y-Axis. The third byte are all buttons. Bit one to eight are (A, B, X, Y, L, R, Select, Start). It also has two buttons on the third byte, 0x10 and 0x20 (CLEAR Button, I want to use this one as MENU).

PID is: 8288 dec VID is: 1411 dec

I modified the “connect_snesusb.c” so that I don’t have to the griffin.c yet. ]

hi SuperSpongo,

If everything you mentioned about your controller is correct you need to change the files as the ones I attached. You got the general idea correctly. You just need to tweak a bit what you did as follows.

Basically, even when you set the correct bytes order, you should use the byte you found plus 1. This because the framework adds 1 (Don’t as me why as the original developer did it that way for some reason so I followed that pattern). So if the button’s byte is 2 i your data you need to look for it in Data[3]… ok?

Now, the mapping array don’t always need to cover all 17 buttons… in this case as all the button data is in 2 bytes we can do it with an array of 14 (because the first nibble of the second byte is not used as you explalined that the CLEAR button is 0x20, right?

Now, for the autoconfig file… if you change the mapping array correctly you don’t really need to change much here… all buttons follow the RA orders so you just need to change the Name and the VID, PID values and maybe the buttons labels…

All other changes you did are correct!

I’m providing all the files changed. You just need to replace them and compile them… Please remember these to make it work once you run RA…

  1. Set the autonconfig path within RetroArch to the folfer you put your autonconfig files (not the “hid” folder but the autoconfig one)
  2. Make sure the autodetect is enabled for the pads
  3. also be sure the pad has the option to automatically map the left analog to digital set to “Left Analog” (as the pad reports the direction pad as analogs)
  4. Obviously change the pad driver to HID and restart.

I think with this the iBuffalo will work :slight_smile: Good luck

Thank you very much for your support netux79. That’s really weird, that the array has to be addressed “plus 1”. Something you have to know, I guess… If I remember correctly, I did not encounter this discrepancy when comparing the Dualshock3 data, though? Another thing that worries me ist that the controller was not recognized by RetroArch when being plugged in during gameplay. When I plug in a Dualshock, a small message appears on the bottom of the screen. I was assuming that this at least should have worked because I modified the PID and VID.

I will have a look at your files this evening and report back if they worked.

Again, thanks for your support!

I’m going to have to give up until an easier solution pops up. :frowning:

Thanks for all your patience and help.

Will a separate little config app ever be a thing?

[QUOTE=barnard;38582]I’m going to have to give up until an easier solution pops up. :frowning:

Thanks for all your patience and help.

Will a separate little config app ever be a thing?[/QUOTE]

I honestly don’t even think that it’s all that difficult, but there’s a lack of information or proper “noob-friendly” tutorials. Most people will not want to setup a toolchain to compile the software, but with a tutorial, it should boil down to a couple of fairly easy steps.

That being said, I still haven’t been able to get it to work just yet, but if I do, I might write something up.

IT WORKED!!! Basically, I still had an error in my understanding. I did not recompile the cores, I only executed make -f Makefile.wii.salamander clean pkg and make -f Makefile.griffin platform=wii with the same old SNES core thinking that would work. Goes to show that I do not really have an idea what I’m doing.

After that I plugged the controller in and was initially disappointed because moving the cursor still didn’t work. HOWEVER, buttons now finally worked, so all I had to do now was map the left analog to digital set to “Left Analog” , as netux79 suggested.

Now the iBuffalo pads are working, and two of them at that! I also modified the PIDs and VIDs in the “joypad_connection.c”. I don’t really know if it is necessary, but at this point I am just happy it works and I won’t test if it works with the default file. I also will not test anymore, if my previous code was working or not, as netux79 provided a working version.

As I still lack the understanding of how exactly everything works, I am not really comfortable to write a tutorial after all. But I’ll be sure to upload my compiled version and my config files with the iBuffalo support built in.

Thank you for your help, netux79! I wouldn’t have been able to figure it out.

Could not attach it here in the forums, maybe because I dont have permissions yet? If someone could host the file here, that would be great.

[QUOTE=barnard;38582]I’m going to have to give up until an easier solution pops up. :frowning:

Thanks for all your patience and help.

Will a separate little config app ever be a thing?[/QUOTE] y As some part of the functionality need to be compiled, we cannot have a tool to help with the setup. This because the original HID framework for RetroArch works this way. Maybe some day a bunch of controllers will be able to work so you just need to plug them in. At least maybe the most common ones.

[QUOTE=SuperSpongo;38606]IT WORKED!!! Basically, I still had an error in my understanding. I did not recompile the cores, I only executed make -f Makefile.wii.salamander clean pkg and make -f Makefile.griffin platform=wii with the same old SNES core thinking that would work. Goes to show that I do not really have an idea what I’m doing.

After that I plugged the controller in and was initially disappointed because moving the cursor still didn’t work. HOWEVER, buttons now finally worked, so all I had to do now was map the left analog to digital set to “Left Analog” , as netux79 suggested.

Now the iBuffalo pads are working, and two of them at that! I also modified the PIDs and VIDs in the “joypad_connection.c”. I don’t really know if it is necessary, but at this point I am just happy it works and I won’t test if it works with the default file. I also will not test anymore, if my previous code was working or not, as netux79 provided a working version.

As I still lack the understanding of how exactly everything works, I am not really comfortable to write a tutorial after all. But I’ll be sure to upload my compiled version and my config files with the iBuffalo support built in.

Thank you for your help, netux79! I wouldn’t have been able to figure it out.

Could not attach it here in the forums, maybe because I dont have permissions yet? If someone could host the file here, that would be great. http://www93.zippyshare.com/v/rWgArnyz/file.html[/QUOTE]

Good to know it worked for you. Really happy as I was not sure if it will work as I don’t own an iBuffalo snes controller. I will push the changes to github to everyone can have the support with this controller from now own :slight_smile:

That would be great! Although for that to work, we would have to tidy up a bit, right? As of now, the code replaces the existing snesusb controller driver. Also, I don’t know if the PID VID changes in the joypad_connection.c were necessary…

I’m trying to write a driver for my Qanba Q4RAF arcade stick. I was able to get the left stick axis working without much trouble, but no matter what I do I can’t get the buttons or d-pad to work (The Q4RAF has a switch that swaps the single physical joystick between controlling the left stick and the d-pad FYI).

Here’s the info from HIDTest:


80 7F 80 7F 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Left Stick Horizontal (Byte 00):
Range = 00 - FF
Left = 00
Centre = 80
Right = FF

Left Stick Vertical (Byte 01):
Range = 00 - FF
Up = 00
Centre = 7F
Down = FF

Right Stick Horizontal (Byte 02):
Physically inaccessible

Right Stick Vertical (Byte 03):
Physically inaccessible

Hat (Byte 04):
Neutral = 0F
Up = 00
UpRight = 01
Right = 02
RightDown = 03
Down = 04
DownLeft = 05
Left = 06
LeftUp = 07

Face Buttons (Byte 05):
None = 00
A = 01
B = 02
X = 04
Y = 08
RB = 10
LB = 20
RT = 40
LT = 80

Other Buttons (Byte 06):
None = 00
Select = 01
Start = 02
Home = 10

Here’s what I have so far:


/*  RetroArch - A frontend for libretro.
 *  Copyright (C) 2013-2014 - Jason Fetters
 *  Copyright (C) 2011-2016 - Daniel De Matteis
 *
 *  RetroArch is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with RetroArch.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#include <boolean.h>
#include "joypad_connection.h"

#include "../input_defines.h"

struct hidpad_qanbaq4raf_data
{
   struct pad_connection* connection;
   uint8_t data[64];
   uint32_t slot;
   uint64_t buttons;
};

static void* hidpad_qanbaq4raf_init(void *data, uint32_t slot, send_control_t ptr)
{
   struct pad_connection* connection = (struct pad_connection*)data;
   struct hidpad_qanbaq4raf_data* device    = (struct hidpad_qanbaq4raf_data*)
      calloc(1, sizeof(struct hidpad_qanbaq4raf_data));

   if (!device)
      return NULL;

   if (!connection)
   {
      free(device);
      return NULL;
   }

   device->connection   = connection;
   device->slot         = slot;

   return device;
}

static void hidpad_qanbaq4raf_deinit(void *data)
{
   struct hidpad_qanbaq4raf_data *device = (struct hidpad_qanbaq4raf_data*)data;

   if (device)
      free(device);
}

static uint64_t hidpad_qanbaq4raf_get_buttons(void *data)
{
   struct hidpad_qanbaq4raf_data *device = (struct hidpad_qanbaq4raf_data*)data;
   if (!device)
      return 0;
   return device->buttons;
}

static int16_t hidpad_qanbaq4raf_get_axis(void *data, unsigned axis)
{
   int val;
   struct hidpad_qanbaq4raf_data *device = (struct hidpad_qanbaq4raf_data*)data;

   if (!device || axis >= 2)
      return 0;
  
   val = device->data[1 + axis];
   val = (val << 8) - 0x8000;

   return (abs(val) > 0x1000) ? val : 0;
}

#define Q4_H_GET(a) (a & 0x0F) /*HAT MASK = 0x0F */
#define Q4_H_LEFT(a) (a == 0x05) || (a == 0x06) || (a == 0x07)
#define Q4_H_RIGHT(a) (a == 0x01) || (a == 0x02) || (a == 0x03)
#define Q4_H_UP(a) (a == 0x07) || (a == 0x00) || (a == 0x01)
#define Q4_H_DOWN(a) (a == 0x03) || (a == 0x04) || (a == 0x05)

static void hidpad_qanbaq4raf_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
   uint32_t i, pressed_keys;
   //int16_t hat_value;
   static const uint32_t button_mapping[13] =
   {
      RETRO_DEVICE_ID_JOYPAD_A,
      RETRO_DEVICE_ID_JOYPAD_B,
      RETRO_DEVICE_ID_JOYPAD_X,
      RETRO_DEVICE_ID_JOYPAD_Y,
      RETRO_DEVICE_ID_JOYPAD_R,
      RETRO_DEVICE_ID_JOYPAD_L,
      RETRO_DEVICE_ID_JOYPAD_R2,
      RETRO_DEVICE_ID_JOYPAD_L2,
      RETRO_DEVICE_ID_JOYPAD_SELECT,
      RETRO_DEVICE_ID_JOYPAD_START,
      NO_BTN,
      NO_BTN,
      16,
   };
   struct hidpad_qanbaq4raf_data *device = (struct hidpad_qanbaq4raf_data*)data;
   
   if (!device)
      return;
   
   memcpy(device->data, packet, size);
   
   device->buttons = 0;
   
   pressed_keys = device->data[6] | (device->data[7] << 8);
   
   for (i = 0; i < 13; i ++)
      if (button_mapping[i] != NO_BTN)
         device->buttons |= (pressed_keys & (1 << i)) ? (UINT64_C(1) << button_mapping[i]) : 0;
     
   /* Now process the hat values as if they were pad buttons */
   //hat_value = Q4_H_GET(device->data[5]);
   //device->buttons |= Q4_H_LEFT(hat_value) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
   //device->buttons |= Q4_H_RIGHT(hat_value) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
   //device->buttons |= Q4_H_UP(hat_value) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
   //device->buttons |= Q4_H_DOWN(hat_value) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
}

static void hidpad_qanbaq4raf_set_rumble(void *data,
      enum retro_rumble_effect effect, uint16_t strength)
{
    (void)data;
    (void)effect;
   (void)strength;
}

const char * hidpad_qanbaq4raf_get_name(void *data)
{
    (void)data;
    /* For now we return a single static name */
    return "QanBa Joystick Plus";
}

pad_connection_interface_t pad_connection_qanbaq4raf = {
   hidpad_qanbaq4raf_init,
   hidpad_qanbaq4raf_deinit,
   hidpad_qanbaq4raf_packet_handler,
   hidpad_qanbaq4raf_set_rumble,
   hidpad_qanbaq4raf_get_buttons,
   hidpad_qanbaq4raf_get_axis,
   hidpad_qanbaq4raf_get_name,
};

I’ve done as netux79 suggested and added 1 to the actual index of each byte I want to read. No button inputs are detected and if I uncomment the hat processing code, I get a constant up press in the Retroarch menu, meaning device->data[5] is 0x00 when I’d expect it to be 0x0F. I’ve also tried every value from 0 - 8 as indexes for the hat switch and none have worked.

Any help is appreciated.

Have you also implemented an autoconf file for your stick?

One thing I noticed when I compared netux79’s implementation to mine using diff was that he included driver.h instead of input_defines.h

Maybe you can try that.


#include "../../driver.h"

Also, have you tried that your Makros work? (a == 0x05) || (a == 0x06) || (a == 0x07)

Results in device->buttons |= (a == 0x05) || (a == 0x06) || (a == 0x07) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; Maybe this is not possible, maybe you need an additional bracket around your boolean logic like so:

device->buttons |= ( (a == 0x05) || (a == 0x06) || (a == 0x07) ) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;

[QUOTE=SuperSpongo;38657]Have you also implemented an autoconf file for your stick?

One thing I noticed when I compared netux79’s implementation to mine using diff was that he included driver.h instead of input_defines.h

Maybe you can try that.


#include "../../driver.h"

[/QUOTE]

Thanks for the suggestion, but no dice. Although interestingly the hat switch is now stuck pressing down instead of up with the #include changed.

Here’s my cfg:


input_device = "QanBa Joystick Plus"
input_driver = "hid"
input_vendor_id = 3888
input_product_id = 4114
input_b_btn = "0"
input_y_btn = "1"
input_select_btn = "2"
input_start_btn = "3"
input_up_btn = "4"
input_down_btn = "5"
input_left_btn = "6"
input_right_btn = "7"
input_a_btn = "8"
input_x_btn = "9"
input_l_btn = "10"
input_r_btn = "11"
input_l2_btn = "12"
input_r2_btn = "13"
input_l_x_plus_axis = "+0"
input_l_x_minus_axis = "-0"
input_l_y_plus_axis = "+1"
input_l_y_minus_axis = "-1"
input_menu_toggle_btn = "16"


input_b_btn_label = "Cross"
input_y_btn_label = "Square"
input_select_btn_label = "Select"
input_start_btn_label = "Start"
input_up_btn_label = "D-Pad Up"
input_down_btn_label = "D-Pad Down"
input_left_btn_label = "D-Pad Left"
input_right_btn_label = "D-Pad Right"
input_a_btn_label = "Circle"
input_x_btn_label = "Triangle"
input_l_btn_label = "L1"
input_r_btn_label = "R1"
input_l2_btn_label = "L2"
input_r2_btn_label = "R2"
input_l_x_plus_axis_label = "Left Analog X+"
input_l_x_minus_axis_label = "Left Analog X-"
input_l_y_plus_axis_label = "Left Analog Y+"
input_l_y_minus_axis_label = "Left Analog Y-"
input_menu_toggle_btn_label = "Home"

That is strange. Let’s go back for a second: You said, that the left analog stick works (I have a Madcatz stick, which is also able to switch between DPAD and Stick)… Have you configured Retroarch in a way that the Analog Axis works as directions when you tested it? Maybe you did not revert that change and the Qanba sends garbage when you switch from Analog to digital? You could test this with HIDTest…

Damn, I was planning on writing a driver for my 2 TE Sticks aswell :smiley:

[QUOTE=SuperSpongo;38663]That is strange. Let’s go back for a second: You said, that the left analog stick works (I have a Madcatz stick, which is also able to switch between DPAD and Stick)… Have you configured Retroarch in a way that the Analog Axis works as directions when you tested it? Maybe you did not revert that change and the Qanba sends garbage when you switch from Analog to digital? You could test this with HIDTest…

Damn, I was planning on writing a driver for my 2 TE Sticks aswell :D[/QUOTE]

I had changed the “Player 1 Analog To Digital Type” setting to “Left Analog” but reverting it doesn’t fix anything. HIDTest doesn’t show any changes when switching the stick mode, apart from the relevant bytes being affected by stick presses.

I have it working fine with Nintendont if that’s of any use.

[QUOTE=SuperSpongo;38657] Also, have you tried that your Makros work? (a == 0x05) || (a == 0x06) || (a == 0x07)

Results in device->buttons |= (a == 0x05) || (a == 0x06) || (a == 0x07) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; Maybe this is not possible, maybe you need an additional bracket around your boolean logic like so:

device->buttons |= ( (a == 0x05) || (a == 0x06) || (a == 0x07) ) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;[/QUOTE]

Didn’t help I’m afraid. I took the macros from connect_ps2adapter.c because it follows the same mapping and I assume they work properly there.

Okay, so at least the analog values were used correctly… since these are being read in another function and your buttons don’t work either, I would assume, that hidpad_qanbaq4raf_get_buttons(void *data) does not work at all?

You could test this by assigning one of the analog values that are working to a button or digital direction. So something along the lines of

if( data[1] == 0x00 —> Set RETRO_DEVICE_ID_JOYPAD_LEFT if( data[1] == 0xFF —> Set RETRO_DEVICE_ID_JOYPAD_RIGHT

[QUOTE=SuperSpongo;38670]Okay, so at least the analog values were used correctly… since these are being read in another function and your buttons don’t work either, I would assume, that hidpad_qanbaq4raf_get_buttons(void *data) does not work at all?

You could test this by assigning one of the analog values that are working to a button or digital direction. So something along the lines of

if( data[1] == 0x00 —> Set RETRO_DEVICE_ID_JOYPAD_LEFT if( data[1] == 0xFF —> Set RETRO_DEVICE_ID_JOYPAD_RIGHT[/QUOTE]

Adding the following to hidpad_qanbaq4raf_get_buttons or hidpad_qanbaq4raf_packet_handler:


   if(device->data[2] == 0xFF)
       device->buttons |= (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN);

allows me to get a DOWN press when I hit down in Left Stick mode. So the functions are definitely being called.

But if I follow what HIDTest told me about where the hat switch is and replace it with:


   if(device->data[5] == 0x04)
       device->buttons |= (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN);

and hit down in d-pad mode, I get nothing.

It’s almost as if the data past the Left Stick axis bytes isn’t making it to any of these functions intact. Very strange.

Indeed! Maybe the memcpy works with a size that is too small! That would explain the data truncation.

EDIT: You could check if size in your packet handler is <= 2 and send RETRO_DEVICE_ID_JOYPAD_DOWN when true.

[QUOTE=SuperSpongo;38681]Indeed! Maybe the memcpy works with a size that is too small! That would explain the data truncation.

EDIT: You could check if size in your packet handler is <= 2 and send RETRO_DEVICE_ID_JOYPAD_DOWN when true.[/QUOTE]

Good idea,

I tried a few different comparisons and narrowed it down. size == 8 so that can’t be the problem :frowning: