Joystick USB con PIC18F2550 1 analógico + 8 botones

Bueno acá les dejo un proyecto que hice en colaboración con otros usuarios del foro , se trata de un joistick USB basado en el PIC18F2550. El proyecto funciona correctamente en windows XP y vista (probado). El que tenga alguna duda pregunte.

PD: Hay otros post sobre joistick pero este es para poner el desarrollo definitivo de mi proyecto , el que tenga armado algo parecido que lo postee.

Un especial agradecimiento a LIAMNESSON ! que me ayudo con los descriptores USB y la teoría de funcionamiento.

Moyano! no puedo escribir mensajes privados por ser nuevo en el foro! si me envias un privado con tu mail te respondo, sino vamos a desvirtuar este thread ;)
 
Hola quiero modificar el programa para poder utilizar 2 ejes más.
sucede que voy a hacer mi propio volante estido Logitech G25 y quiero poder implementar 4 ejes:
eje 1: timon
eje 2: acelerador
eje 3: freno
eje 4: clutch
los botones lo usaria para la palanca de cambios y otras fonciones.
tambien quisiera hacer que cuando el voltaje de el eje 1 (timon) sea 0.01V me active un pin para bloquear el giro del timon y que cuando sea 4.99 tambien lo haga.(es para no dañar el potenciometro, ya que pienso utilizar uno de presicion de 10 vueltas y no quiero romperlo ya que son muy caros y el que tengo lo consegui casi en $1 us algo que no volvere a conseguir nunca).
agradesco su ayuda y consejos. tengo poca experiencia con pic's, manejo muy por encima el 16f877, pero en la comunicacion con pc si se me hace muy dificil.
 
Como hago para agregar mas ejes en el codigo? .. necesito al menos 3 ejes mas.

Desde ya muchas gracias.

PD: Probé este y funciona de maravilla en w7 64bits.
 
Hola Moyano,

muy bueno tu joystick, podrías indicarme como hacer para tener 4 direcciones digitales, en vez
de los analógicos?

muchas gracias desde ya.
 
Cualquier duda que tengas comentame y vemos como la resolvemos !

Hola Jonathan,

ya entendí los descriptores, pero al compilarlo con la version de css que comentaste me da este error:


>>> Warning 203 "C:\PICC\drivers\pic18_usb.h" Line 436(1,1): Condition always TRUE
>>> Warning 216 "GAMEPAD.c" Line 96(0,1): Interrupts disabled during call to prevent re-entrancy: (usb_token_reset)
>>> Warning 216 "GAMEPAD.c" Line 96(0,1): Interrupts disabled during call to prevent re-entrancy: (usb_flush_in)
Memory usage: ROM=12% RAM=21% - 23%
0 Errors, 3 Warnings.


puede ser porque me falte alguna librería?
por ahí vi un manual creo que era tuyo para configurar mplab ide con css para compilar,
pero tuve que formatear y no lo encuentro, lo tienes por ahí porfa?


Gracias por tu tiempo.
 
Hola que tal, he probado el circuito y tengo un problema, resulta que a veces el PC si reconoce el joystick, a veces dice que tiene problemas y otras tantas (la mayoría) ni aparece en el PC, es como si estuviera muerto por completo, ya revise la tensión que debería caer en cada parte y esta bien, también he programado varias veces el PIC y nada.

El joystick lo tengo que en protoboard, ya probe varias protoboards y solde algunos cables para garantizar el contacto, y aún así, no consigo que funcione....

Que podrá ser ??
 
Hola a todos,

No he visto si tienen esto en el foro pero espero que sea mi aportación.

La conexión en MAC es mas facil realizarla con HID porque si no se hace así la programación se complica, y si que se complica, existe en la pagina http://www.signal11.us/oss/hidapi/hidapi/doxygen/html/index.html una librería que facilita la conexión.

Este es el programa que yo hice de ejemplo, es solo un contador y una entrada analógica y para la salida son digitales por el puerto B, el programa esta echo en xcode. Espero que les sirva de algo.
 
Última edición:
Que tal gente, ando buscando un poco de ayuda, resulta que quiero armar una interface para dos joysticks. Usando un solo pic18f2550, quiero que windows lo reconozca como dos joysticks independientes, como no soy programador, busque algo ya hecho y no consegui nada que funcione, asi que me puse a leer y modificar algunos codigos fuentes que hay en este mismo foro, por ejemplo los de Jonathan Moyano y los de Leamneesom, pero no logro que funcione, apenas windows reconoce el dispositivo pero no lo puede iniciar. Les dejo el codigo a ver i alguno encuentra el error de por que no puede iniciar siquiera uno de los dos joysticks,

Codigo del descriptor:
CSS:
// Descriptores para GAMEPAD USB.

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>


   const char USB_CLASS_SPECIFIC_DESC[] = {

      0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
      0x09, 0x05, // usage Device is a gamepad
      0xA1, 0x01, // collection (application) This collection encompasses the report format
      0x09, 0x01, // usage (pointer) Choose the key code usage page
      0xA1, 0x00, // collection (physical) Physical collection
      0x85, 0x01, // REPORT ID 1
      0x09, 0x30, // usage (X) X direction of pointer
      0x09, 0x31, // usage (Y) Y direction of pointer
      0x15, 0x00, // logical minimum (0)
      0x26, 0xFF, 0x00, // logical maximum (255)
      0x35, 0x00, // PHYSICAL minimum (0)
      0x46, 0xFF, 0x00, // PHYSICAL maximum (255)
      0x75, 0x08, // report size (8)
      0x95, 0x02, // report count (2) Two reports, eight bit each
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x09, // usage page (buttons) Choose the “button” usage page
      0x19, 0x01, // usage minimum (1) There are three buttons
      0x29, 0x08, // usage maximum (8)
      0x15, 0x00, // logical minimum (0) Each button is represented by one bit
      0x25, 0x01, // logical maximum (1)
      0x95, 0x08, // report count (8) Three reports, one bit each
      0x75, 0x01, // report size (1)
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x01, // usage page (generic desktop Choose the usage page "mouse" is on
      0x09, 0x05, // usage Device is a gamepad
      0xA1, 0x01, // collection (application) This collection encompasses the report format
      0x85, 0x02, // REPORT ID 2
      0x09, 0x01, // usage (pointer) Choose the key code usage page
      0xA1, 0x00, // collection (physical) Physical collection
      0x09, 0x30, // usage (X) X direction of pointer
      0x09, 0x31, // usage (Y) Y direction of pointer
      0x15, 0x00, // logical minimum (0)
      0x26, 0xFF, 0x00, // logical maximum (255)
      0x35, 0x00, // PHYSICAL minimum (0)
      0x46, 0xFF, 0x00, // PHYSICAL maximum (255)
      0x75, 0x08, // report size (8)
      0x95, 0x02, // report count (2) Two reports, eight bit each
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

      0x05, 0x09, // usage page (buttons) Choose the "button" usage page
      0x19, 0x01, // usage minimum (1) There are three buttons
      0x29, 0x08, // usage maximum (8)
      0x15, 0x00, // logical minimum (0) Each button is represented by one bit
      0x25, 0x01, // logical maximum (1)
      0x95, 0x08, // report count (8) Three reports, one bit each
      0x75, 0x01, // report size (1)
      0x81, 0x02, // input (data, variable, absolute)
      0xC0,       // end collection

   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines where to look for it in the const
   // USB_CLASS_SPECIFIC_DESC[] array.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
         0,     
      //interface 1
         50
   };

   //if a class has an extra descriptor not part of the config descriptor,
   // this lookup table defines the size of that descriptor.
   //first element is the config number (if your device has more than one config)
   //second element is which interface number
   //set element to 0xFFFF if this config/interface combo doesn't exist
   const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][2] =
   {
   //config 1
      //interface 0
       49,  //sizeof(USB_CLASS_SPECIFIC_DESC)
      //interface 1
       49
};



//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      59 //config+interface+class+endpoint

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size          ==1
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==2
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config      ==3,4
         2, //number of interfaces this device supports       ==5
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==6
         0x00, //index of string descriptor for this configuration      ==7
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==8
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)

   //interface descriptor 1
         USB_DESC_INTERFACE_LEN, //length of descriptor      =10
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =11
         0x00, //number defining this interface (IF we had more than one interface)    ==12
         0x00, //alternate setting     ==13
         1, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==14
         0x03, //class code, 03 = HID     ==15
         0x00, //subclass code //boot     ==16
         0x00, //protocol code      ==17
         0x02, //index of string descriptor for interface      ==18

   //class descriptor 1  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==19
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==20
         0x01,0x01, //hid class release number (1.0) (try 1.10)      ==21,22
         0x00, //localized country code (0 = none)       ==23
         0x00, //number of hid class descrptors that follow (1)      ==24
         0x22, //report descriptor type (0x22 == HID)                ==25
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor            ==26,27

   //endpoint descriptor 1
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==28
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==29
         0x81, //endpoint number and direction (0x81 = EP1 IN)       ==30
         0x03, //USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==31
         USB_EP1_TX_SIZE,0x00, //maximum packet size supported                  ==32,33
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==34
 
   //interface descriptor 2
         USB_DESC_INTERFACE_LEN, //length of descriptor      =35
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =36
         0x01, //number defining this interface (IF we had more than one interface)    ==37
         0x00, //alternate setting     ==38
         1, //number of endpoins, except 0 (pic167xx has 3, but we dont have to use all).       ==39
         0x03, //class code, 03 = HID     ==40
         0x00, //subclass code //boot     ==41
         0x00, //protocol code      ==42
         0x03, //index of string descriptor for interface      ==43

   //class descriptor 2  (HID)
         USB_DESC_CLASS_LEN, //length of descriptor    ==44
         USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID)      ==45
         0x01,0x01, //hid class release number (1.0) (try 1.10)      ==46,47
         0x00, //localized country code (0 = none)       ==48
         0x00, //number of hid class descrptors that follow (0)      ==49
         0x22, //report descriptor type (0x22 == HID)                ==50
         USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][1], 0x00, //length of report descriptor            ==51,52

   //endpoint descriptor 2
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==53
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==54
         0x82, //endpoint number and direction (0x82 = EP2 IN)       ==55
         0x03, //USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt)         ==56
         USB_EP2_TX_SIZE,0x00, //maximum packet size supported                  ==57,58
         10  //polling interval, in ms.  (cant be smaller than 10 for slow speed devices)     ==59
      
   };


   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
   //      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
   #define USB_NUM_HID_INTERFACES   2

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //define where to find class descriptors
   //first dimension is the config number
   //second dimension specifies which interface
   //last dimension specifies which class in this interface to get, but most will only have 1 class per interface
   //if a class descriptor is not valid, set the value to 0xFFFF
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][2][1]=
   {
   //config 1
      //interface 0
         //class 1
         18,
   //config 1
      //interface 1
         //class 1
         43
   };


   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   Descriptores del dispositivo
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
         USB_DESC_DEVICE_LEN, // Longitud del reporte.
         0x01, // Constante del dispositivo = 1
         0x00,0x02, // Versión del USB 1.10.
         0x00, // Código de clase.
         0x00, // Código de subclase.
         0x00, // Código de protocolo.
         USB_MAX_EP0_PACKET_LENGTH, // Tamaño máximo del paquete de datos del endpoint 0 = 8 para HID.
         0x81,0x17, // Vendor  id =  decimal(6017), hexadecimal(1781) // Identificadores de easyHID.
         0xD0,0x07, // Product id =  decimal(2000), hexadecimal(7D0)
         0x00,0x01, // Número del dispositivo.
         0x01,
         0x02,
         0x00,
         USB_NUM_CONFIGURATIONS  // Número de posibles configuraciones.
   };

   #if (sizeof(USB_DEVICE_DESC) != USB_DESC_DEVICE_LEN)
      #error USB_DESC_DEVICE_LEN not defined correctly
   #endif

//////////////////////////////////////////////////////////////////
/// Descriptores del fabricante
//////////////////////////////////////////////////////////////////


char USB_STRING_DESC_OFFSET[]={0,4,14,46};

char const USB_STRING_DESC[]={
   // Primer descriptor.
         4, // Longitud del descriptor. 1
         USB_DESC_STRING_TYPE, // 2
         0x09,0x04,   // Lenguaje id = Inglés (Definido por microsoft). 3,4
   // Segundo descriptor.
         10, // Longitud del descriptor. 5
         USB_DESC_STRING_TYPE, // Descriptor del compilador utilizado. (STRING) (Puede ser el nombre de la compañía) 6
         'C',0, //7,8
         'C',0, //9,10
         's',0, //11,12
         'P',0, //13,14
        
   // Tercer descriptor.
         32, //length of string index //15
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) //16
         'A',0, //17,18
         'R',0, //19,20
         'C',0, //23,24
         'A',0, //25,26
         'D',0, //27,28
         'E',0, //29,30
         ' ',0, //31,32
         'J',0, //33,34
         'O',0, //35,36
         'Y',0, //37,38
         'S',0, //39,40
         'T',0, //41,42
         'I',0, //43,44
         'C',0, //45,46
         'K',0, //47,46
    
   // Cuarto desciptor
         22, //length of string index //47
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) //50
         'J',0, //51,52
         'O',0, //53,54
         'Y',0, //55,56
         'S',0, //57,58
         'T',0, //59,60
         'I',0, //61,62
         'C',0, //63,64
         'K',0, //65,66
         ' ',0, //67,68
         '2',0, //69,70

};

#ENDIF

Desde ya agradezco alguna orientacion de que me esta faltando o le estoy errando


Codigo del Joystick:
CSS:
// Programa de control para probar un GAMEPAD compuesto por 1 control analógico y 8 botones digitales.
// Utilizaremos un PIC18F2550 con conexión USB.
// Programador: Moyano Jonathan
// Librerías de descriptores: Programada por LIAMNESSON y modificada para uso personal.
// 30/03/09
//*****************************************************************************************************

#include <18F2550.h> // Definición de registros internos del PIC18F2550.
#device ADC=8 // CAD a 8 bits, justificación a a la derecha.
#fuses NOMCLR,HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
// NOMCLR: No vamos ha usar el PIN MCLR, el reset se hará por soft.
// XTPLL: Vamos a usar un cristal de 4.00Mhz.
// NOWDT: No vamos a usar el perro guardian.
// NOPROTECT: Memoria no protejida contra lecturas.
// NODEBUG: No utilizamos código para debugear.
// NOLVP: No utilizamos el modo de programación con bajo voltaje.
// USBDIV: signfica que el clock del usb se tomará del PLL/2 = 96Mhz/2 = 48Mhz.
// PLL1: significa que el PLL prescaler no dividirá la frecuencia del cristal. para XT = 4Mhz.
// CPUDIV1: El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejamos como está.
// VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB.
// NOPBADEN: Deshabilitamos el módulo conversor ADC del puerto B.

#use delay(clock=48000000)


#DEFINE USB_HID_DEVICE TRUE // Vamos a utilizar el protocolo HID.

// Solamente definimos el buffer de salida ya que solamente enviaremos datos a la PC.

#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE 4 // Definición del tamaño del buffer de salida.
#define USB_EP2_TX_ENABLE USB_ENABLE_INTERRUPT
#define USB_EP2_TX_SIZE 4 // Definición del tamaño del buffer de salida.

/*********************************************************************************************************/

// Definición de las librerías utilizadas.
#include <pic18_usb.h>    // Drivers's USB del PIC18F2550.
#include <joystick-2.h> // Descriptores USB para el GAMEPAD.
#include <usb.c> // Funciones del USB.

/*********************************************************************************************************/

// Comienza programa principal.

void main(void) {

int envia[3]; // Definimos los 3 bytes a enviar al EP1.
#define     eje_x       envia[0]     // Byte del eje X del mando analógico.                         
#define     eje_y       envia[1]     // Byte del eje Y del mando analógico.
#define     botones     envia[2]     // Byte de los 8 botones del PAD.

int envia2[3]; // Definimos los 3 bytes a enviar al EP2.
#define     eje_x2       envia2[0]     // Byte del eje X del mando analógico.                         
#define     eje_y2       envia2[1]     // Byte del eje Y del mando analógico.
#define     botones2     envia2[2]     // Byte de los 8 botones del PAD.

int botonera; // Variable que toma el valor de los botones presionados.
int botonera2; // Variable que toma el valor de los botones presionados.
                                                              
output_b(0x00); // Limpiamos el puerto B.
output_c(0x00); // Limpiamos el puerto C.
// Configuraciones varias:
   disable_interrupts(global);
   disable_interrupts(int_timer1);
   disable_interrupts(int_rda);
   disable_interrupts(int_ext);
   disable_interrupts(int_ext1);
   disable_interrupts(int_ext2);
   setup_spi(FALSE);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   port_b_pullups(FALSE);
   //port_c_pullups(FALSE);

   setup_adc_ports(AN0_TO_AN3 || VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_64);


// Iniciamos el USB.
      usb_init();                           // Inicializamos el USB.
      usb_wait_for_enumeration();           // Esperamos hasta que el dispositivo sea configurado por la PC.
      while(true) {
      usb_task();                                                         // Habilita el periferico usb y las interrupciones.

        if (usb_enumerated()) // Si el puerto es enumerado y configurado por el host..
                  {

                          set_adc_channel(0); // Selecciono el canal de conversión para el eje X.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_x = read_adc(); // Guardamos el valor de la variable.

                          set_adc_channel(1); // Selecciono el canal de conversión para el eje Y.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_y = read_adc(); // Guardamos el valor de la variable.

                          botonera = input_b(); // Tomamos el valor de los botones.
                          botones = botonera;   // Guardamos el valor de la variable.
                          usb_put_packet(1,envia,3,USB_DTS_TOGGLE);   // Enviamos los datos por USB.

                          set_adc_channel(2); // Selecciono el canal de conversión para el eje X.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_x2 = read_adc(); // Guardamos el valor de la variable.

                          set_adc_channel(3); // Selecciono el canal de conversión para el eje Y.
                          delay_us(10); // Espero 10uS, a que termine la conversión.
                          eje_y2 = read_adc(); // Guardamos el valor de la variable.

                          botonera2 = input_c(); // Tomamos el valor de los botones.
                          botones2 = botonera2;   // Guardamos el valor de la variable.
                          usb_put_packet(1,envia2,3,USB_DTS_TOGGLE);   // Enviamos los datos por USB

                      }

                      }
}
 
Que tal gente, ando buscando un poco de ayuda, resulta que quiero armar una interface para dos joysticks. Usando un solo pic18f2550, quiero que windows lo reconozca como dos joysticks independientes, como no soy programador, busque algo ya hecho y no consegui nada que funcione, asi que me puse a leer y modificar algunos codigos fuentes que hay en este mismo foro, por ejemplo los de Jonathan Moyano y los de Leamneesom, pero no logro que funcione, apenas windows reconoce el dispositivo pero no lo puede iniciar. Les dejo el codigo a ver i alguno encuentra el error de por que no puede iniciar siquiera uno de los dos joysticks

Yo hace poco estuve jugando con esto para armarme un conversor gamport a usb (no usé el uC que estás usando). ¿Te aparece en windows el dispositivo?

El descriptor pareciera estar bien, salvo que lo inicias como gampad en vez de joystick:

Código:
0x09, 0x05, // usage Device is a gamepad

En vez de:

Código:
0x09, 0x04, // usage Device is a joystick

No creo que eso sea un problema en si, pero si queremos un joystick, avisémosle al SO lo que realmente es.

Te puedo pasar los descriptores con los que estuve jugando, pero antes te recomendaría que trates de hacer funcionar un joystick a la vez y después implementes el 2do.
 
Atrás
Arriba