Mega32 as Xb*X gamepad

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Grobi

Mega32 as Xb*X gamepad

Post by Grobi » Sat Jan 24, 2009 2:03 pm

Hi folks,
I am trying to implement an Xb*x gamepad with this firmware, but having some problems with that.
For testing I connect it to a PC with latest XBCD drivers but the device failes enumeration 'cos of not sending a Device Descriptor, thats what the prog USBLyzer told me.
I tried an original Xb*x gamepad which works on my PC and USBLyzer gives me these information about the device :
    XBCD XBox Gamepad
    Connection Status Device connected
    Current Configuration 1
    Speed Full
    Device Address 3
    Number Of Open Pipes 2

    Device Descriptor Zeroplus
    Field Value Description
    bLength 12h
    bDescriptorType 01h Device
    bcdUSB 0110h USB Spec 1.1
    bDeviceClass 00h Class info in Ifc Descriptors
    bDeviceSubClass 00h
    bDeviceProtocol 00h
    bMaxPacketSize0 08h 8 bytes
    idVendor 0C12h Zeroplus
    idProduct 8802h
    bcdDevice 0001h 0.01
    iManufacturer 00h
    iProduct 01h "Zeroplus"
    iSerialNumber 00h
    bNumConfigurations 01h

    Configuration Descriptor 1 Bus Powered, 100 mA
    Field Value Description
    bLength 09h
    bDescriptorType 02h Configuration
    wTotalLength 0020h
    bNumInterfaces 01h
    bConfigurationValue 01h
    iConfiguration 00h
    bmAttributes 80h Bus Powered
    bMaxPower 32h 100 mA

    Interface Descriptor 0/0 2 Endpoints
    Field Value Description
    bLength 09h
    bDescriptorType 04h Interface
    bInterfaceNumber 00h
    bAlternateSetting 00h
    bNumEndpoints 02h
    bInterfaceClass 58h
    bInterfaceSubClass 42h
    bInterfaceProtocol 00h
    iInterface 00h

    Endpoint Descriptor 82 2 In, Interrupt, 4 ms
    Field Value Description
    bLength 07h
    bDescriptorType 05h Endpoint
    bEndpointAddress 82h 2 In
    bmAttributes 03h Interrupt
    wMaxPacketSize 0020h 32 bytes
    bInterval 04h 4 ms

    Endpoint Descriptor 02 2 Out, Interrupt, 4 ms
    Field Value Description
    bLength 07h
    bDescriptorType 05h Endpoint
    bEndpointAddress 02h 2 Out
    bmAttributes 03h Interrupt
    wMaxPacketSize 0020h 32 bytes
    bInterval 04h 4 ms


i want my device to mimic the Xb*x gamepad i have and modified "usbconfig.h" :

Code: Select all

#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__
/* ---------------------------- Hardware Config ---------------------------- */
#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      5
#define USB_CFG_DPLUS_BIT       2
#define USB_CFG_CLOCK_KHZ       (F_CPU/1000)
/* --------------------------- Functional Range ---------------------------- */
#define USB_CFG_HAVE_INTRIN_ENDPOINT    1
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   1
#define USB_CFG_EP3_NUMBER              3
#define USB_CFG_IMPLEMENT_HALT          0
#define USB_CFG_SUPPRESS_INTR_CODE      0
#define USB_CFG_INTR_POLL_INTERVAL      4
#define USB_CFG_IS_SELF_POWERED         0
#define USB_CFG_MAX_BUS_POWER           200
#define USB_CFG_IMPLEMENT_FN_WRITE      0
#define USB_CFG_IMPLEMENT_FN_READ       0
#define USB_CFG_IMPLEMENT_FN_WRITEOUT   0
#define USB_CFG_HAVE_FLOWCONTROL        0
#define USB_CFG_LONG_TRANSFERS          0
#define USB_COUNT_SOF                   0
#define USB_CFG_CHECK_DATA_TOGGLING     0
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0
/* -------------------------- Device Description --------------------------- */
#define  USB_CFG_VENDOR_ID       0x0C, 0x12
#define  USB_CFG_DEVICE_ID       0x88, 0x02
#define USB_CFG_DEVICE_VERSION  0x01, 0x10
#define USB_CFG_VENDOR_NAME     'G', 'r', 'o', 'b', 'i'
#define USB_CFG_VENDOR_NAME_LEN 5
#define USB_CFG_DEVICE_NAME     'P', 'S', '2', 't', 'o', 'X', 'b', 'o', 'X'
#define USB_CFG_DEVICE_NAME_LEN 9
#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_DEVICE_SUBCLASS     0
#define USB_CFG_INTERFACE_CLASS     0x58
#define USB_CFG_INTERFACE_SUBCLASS  0x42
#define USB_CFG_INTERFACE_PROTOCOL  0
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    0

#define USB_CFG_DESCR_PROPS_DEVICE                  0
#define USB_CFG_DESCR_PROPS_CONFIGURATION           0
#define USB_CFG_DESCR_PROPS_STRINGS                 0
#define USB_CFG_DESCR_PROPS_STRING_0                0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR           0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0
#define USB_CFG_DESCR_PROPS_HID                     0
#define USB_CFG_DESCR_PROPS_HID_REPORT              0
#define USB_CFG_DESCR_PROPS_UNKNOWN                 0

#endif /* __usbconfig_h_included__ */


"usbdrv.c" :

Code: Select all

/* --------------------------- Device Descriptor --------------------------- */
#if USB_CFG_DESCR_PROPS_DEVICE == 0
#undef USB_CFG_DESCR_PROPS_DEVICE
#define USB_CFG_DESCR_PROPS_DEVICE  sizeof(usbDescriptorDevice)
PROGMEM char usbDescriptorDevice[] = {    /* USB device descriptor */
    18,         /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
    USBDESCR_DEVICE,        /* descriptor type */
    0x10, 0x01,             /* USB version supported */
    USB_CFG_DEVICE_CLASS,
    USB_CFG_DEVICE_SUBCLASS,
    0,                      /* protocol */
    8,                      /* max packet size */
    /* the following two casts affect the first byte of the constant only, but
     * that's sufficient to avoid a warning with the default values.
     */
    (char)USB_CFG_VENDOR_ID,/* 2 bytes */
    (char)USB_CFG_DEVICE_ID,/* 2 bytes */
    USB_CFG_DEVICE_VERSION, /* 2 bytes */
    USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0,         /* manufacturer string index */
    USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0,        /* product string index */
    USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0,  /* serial number string index */
    1,          /* number of configurations */
};
#endif

/* ----------------------- Configuration Descriptor ------------------------ */

#if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0
#undef USB_CFG_DESCR_PROPS_HID
#define USB_CFG_DESCR_PROPS_HID     9   /* length of HID descriptor in config descriptor below */
#endif

#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
#define USB_CFG_DESCR_PROPS_CONFIGURATION   sizeof(usbDescriptorConfiguration)
PROGMEM char usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
    9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
    USBDESCR_CONFIG,    /* descriptor type */
    0,
   18 + (7 * USB_CFG_HAVE_INTRIN_ENDPOINT) + (7 * USB_CFG_HAVE_INTRIN_ENDPOINT3) + (USB_CFG_DESCR_PROPS_HID & 0xff), /* total length of data returned (including inlined descriptors) */
    1,          /* number of interfaces in this configuration */
    1,          /* index of this configuration */
    0,          /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
    USBATTR_SELFPOWER,      /* attributes */
#else
    (char)USBATTR_BUSPOWER, /* attributes */
#endif
    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
/* interface descriptor follows inline: */
    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
    USBDESCR_INTERFACE, /* descriptor type */
    0,          /* index of this interface */
    0,          /* alternate setting for this interface */
    USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
    USB_CFG_INTERFACE_CLASS,
    USB_CFG_INTERFACE_SUBCLASS,
    USB_CFG_INTERFACE_PROTOCOL,
    0,          /* string index for interface */
#if (USB_CFG_DESCR_PROPS_HID & 0xff)    /* HID descriptor */
    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
    USBDESCR_HID,   /* descriptor type: HID */
    0x01, 0x01, /* BCD representation of HID version */
    0x00,       /* target country code */
    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
    0x22,       /* descriptor type: report */
    USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0,  /* total length of report descriptor */
#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
    7,          /* sizeof(usbDescrEndpoint) */
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
    (char)0x82, /* IN endpoint number 1 */
    0x03,       /* attrib: Interrupt endpoint */
    0, 0x20,       /* maximum packet size */
    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */
    7,          /* sizeof(usbDescrEndpoint) */
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
    (char)0x02, /* IN endpoint number 1 */
    0x03,       /* attrib: Interrupt endpoint */
    0, 0x20,       /* maximum packet size */
    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
#endif
};
#endif


my code on the avr looks like :

Code: Select all

#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>   /* required by usbdrv.h */
#include <usbdrv.h>
// USB
static uint8_t reportBuffer[20];
static uchar    idleRate;   /* repeat rate for keyboards, never used for mice */

void InitControllerVars()
{
   reportBuffer[0] = 0x00;
   reportBuffer[1] = 0x10; // size
   reportBuffer[2] = 0x00; // D buttons
   reportBuffer[3] = 0x00; // reserved
   reportBuffer[4] = 0x00; // A
   reportBuffer[5] = 0x00; // B
   reportBuffer[6] = 0x00; // X
   reportBuffer[7] = 0x00; // Y
   reportBuffer[8] = 0x00; // Black
   reportBuffer[9] = 0x00; // White
   reportBuffer[10] = 0x00; // L trigger
   reportBuffer[11] = 0x00; // R trigger
   reportBuffer[12] = 0x00; // L stick X
   reportBuffer[13] = 0x00; // L stick X
   reportBuffer[14] = 0x00; // L stick Y
   reportBuffer[15] = 0x00; // L stick Y
   reportBuffer[16] = 0x00; // R stick X
   reportBuffer[17] = 0x00; // R stick X
   reportBuffer[18] = 0x00; // R stick Y
   reportBuffer[19] = 0x00; // R stick Y
}

void BuildControllerReport()
{
   reportBuffer[0] = 0x00;
   reportBuffer[1] = 0x10; // size
   reportBuffer[2] = 0x00; // D buttons
   reportBuffer[3] = 0x00; // reserved
   reportBuffer[4] = 0x00; // A
   reportBuffer[5] = 0x00; // B
   reportBuffer[6] = 0x00; // X
   reportBuffer[7] = 0x00; // Y
   reportBuffer[8] = 0x00; // Black
   reportBuffer[9] = 0x00; // White
   reportBuffer[10] = 0x00; // L trigger
   reportBuffer[11] = 0x00; // R trigger
   reportBuffer[12] = 0x00; // L stick X
   reportBuffer[13] = 0x00; // L stick X
   reportBuffer[14] = 0x00; // L stick Y
   reportBuffer[15] = 0x00; // L stick Y
   reportBuffer[16] = 0x00; // R stick X
   reportBuffer[17] = 0x00; // R stick X
   reportBuffer[18] = 0x00; // R stick Y
   reportBuffer[19] = 0x00; // R stick Y
}

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
   usbRequest_t    *rq = (void *)data;
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
   {
        if(rq->bRequest == USBRQ_HID_GET_REPORT)
      {   reportBuffer[0] = 0x00;
         reportBuffer[1] = 0x10; // size
         reportBuffer[2] = 0x00; // D buttons
         reportBuffer[3] = 0x00; // reserved
         reportBuffer[4] = 0x00; // A
         reportBuffer[5] = 0x00; // B
         reportBuffer[6] = 0x00; // X
         reportBuffer[7] = 0x00; // Y
         reportBuffer[8] = 0x00; // Black
         reportBuffer[9] = 0x00; // White
         reportBuffer[10] = 0x00; // L trigger
         reportBuffer[11] = 0x00; // R trigger
         reportBuffer[12] = 0x00; // L stick X
         reportBuffer[13] = 0x00; // L stick X
         reportBuffer[14] = 0x00; // L stick Y
         reportBuffer[15] = 0x00; // L stick Y
         reportBuffer[16] = 0x00; // R stick X
         reportBuffer[17] = 0x00; // R stick X
         reportBuffer[18] = 0x00; // R stick Y
         reportBuffer[19] = 0x00; // R stick Y
         usbMsgPtr = (void *)&reportBuffer;
            return sizeof(reportBuffer);
        }
      else if(rq->bRequest == USBRQ_HID_GET_IDLE)
      {
            usbMsgPtr = &idleRate;
            return 1;
        }
      else if(rq->bRequest == USBRQ_HID_SET_IDLE)
      {
            idleRate = rq->wValue.bytes[1];
        }
    }
   else
   {
        /* no vendor specific requests implemented */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}



int main()
{
   InitControllerVars();
   // USB init etc.....
   wdt_disable();
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    uint8_t i = 0;
    while(--i){             /* fake USB disconnect for > 250 ms */
        _delay_ms(1);
    }
    usbDeviceConnect();
    sei();
    for(;;)
   {
      usbPoll();
        if(usbInterruptIsReady())
      {
         BuildControllerReport();
            usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
        }
    }
   return 1;
}


so, I am stuck, I have no idea on how to solve this and make it work.
Maybe somebody could have a look at this and could give me some advice on how to fix this.
I don't think that the speed difference ,original pad fullspeed, my device low speed, prevents it from working.

Xb*x gamepad information : http://euc.jp/periphs/xbox-controller.ja.html

Mega32 running on 16 MHz

thx Grobi

Grobi

Post by Grobi » Mon Jan 26, 2009 3:45 pm

nobody?

Grobi

Post by Grobi » Mon Jan 26, 2009 7:25 pm

ok is anybody able to have a look at the usbconfig.h and usbdrc.c so that the configuration is similar to the Xb*x gamepad data I posted, because I am not sure if all data is set correctly (high and low byte order of values).

Thx Grobi

Grobi

Post by Grobi » Mon Feb 16, 2009 4:38 pm

damnn this is lame, 294 views and no answer :-(

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Sun Oct 11, 2009 4:52 am

Hi , I know its been a bit here, but any luck with this. I just started the same venture to day. Plan on doing the same thing as you..


Ok, I got it to work. Look like you no longer are a member? but took a few hours to get it work so if you return one day look me up.

bencao74
Posts: 4
Joined: Tue Jul 07, 2009 11:58 am

Re: Mega32 as Xb*X gamepad

Post by bencao74 » Sun Oct 25, 2009 11:10 pm

Hi,

I'm interested in your work. Could you contact me about your solution?


Bencao

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Mon Oct 26, 2009 1:50 am

as soon as I find the pm.

OK for getthat I found you on the net, log in to you tube;)

Alan Chatham
Rank 1
Rank 1
Posts: 28
Joined: Wed Sep 30, 2009 3:36 am
Location: Osaka, Japan
Contact:

Re: Mega32 as Xb*X gamepad

Post by Alan Chatham » Sat Nov 07, 2009 10:00 am

Dear Ulao -

Are you emulating an Xbox controller? Is it an Xbox or an Xbox 360 controller? I've been looking around for people trying to emulate a 360 controller, but I haven't found anything. Would you be willing to share your code with me and my project? You can find it at http://www.OpenChord.org ...

Thanks,
Alan Chatham

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Sat Nov 07, 2009 7:47 pm

Alan Chatham wrote:Dear Ulao -

Are you emulating an Xbox controller? Is it an Xbox or an Xbox 360 controller? I've been looking around for people trying to emulate a 360 controller, but I haven't found anything. Would you be willing to share your code with me and my project? You can find it at http://www.OpenChord.org ...

Thanks,
Alan Chatham
-I'm able to act as an xbox, not read it. In other words the xbox thinks I'm ( avr controller ) a official xbox controller. The 360 has a security dongle of sorts in it. So no I can not emulate it and so far nor can anyone else. m$ has got us all stumped on this. As far as sharing code, its just a mangled descriptor. All you have to do is change a few things and make the xbox think you are an Xbox controller.

this is how I set it up.


Code: Select all

const char usbXboxDescrDevice[] PROGMEM = {  
    0x12, //size of this descriptor in bytes
   USBDESCR_DEVICE, //descriptor type = XBOXUSB_Device_Descriptor
   0x10, 0x01,    //USB Spec 2.0
   0x00,        //class code
   0x00,        //subclass code
   0x00,        //protocol code
   8,//  0x40,        //EPO buffer size
   0x5E, 0x04,    //vendor ID 04D8
   0x02, 0x02, //product ID
   0x00, 0x01, //device release number

   1,          /* manufacturer string index */
   2,          /* product string index */
   3,          /* serial number string index */
   1,          /* number of configurations */
 };

After doing this my device was seen as a xbox controller. You may have to play with the usbHidReportDescriptor a but to get it right.

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Tue Jan 26, 2010 7:03 pm

Hey Ulao, I am glad to hear that sombody has got that thing working, I am very interested in your solution.
My project laid on ice since yesterday, found it in the basement, and I am willing to continue it, maybe you could give me some advice or some examples, I knew that it is possible and there has to be a way on how to solve this but over the weeks I forgot about the whole thing.

Grobi

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Wed Jan 27, 2010 3:37 am

...do i really need an hid report descriptor? i've read almost everywhere that the gamepads lack those descriptor.
I tried to use your device descriptor but the device isn't recognized, not in dashboard, not in xbmc and not even on a wind*ws system.
Do you use one endpoint or two?

Code: Select all

main.c:
#define USBATTR_BUSPOWER 0x80
static uint8_t reportBuffer[20];
static const char usbXboxDeviceDescriptor[] PROGMEM =

       0x12, //size of this descriptor in bytes
       USBDESCR_DEVICE, //descriptor type = XBOXUSB_Device_Descriptor
       0x10, 0x01,    //USB Spec 2.0
       0x00,        //class code
       0x00,        //subclass code
       0x00,        //protocol code
       0x08,//  0x40,        //EPO buffer size
       USB_CFG_VENDOR_ID,    //vendor ID 04D8
       USB_CFG_DEVICE_ID, //product ID
       USB_CFG_DEVICE_VERSION, //device release number
       1,          /* manufacturer string index */
       2,          /* product string index */
       3,          /* serial number string index */
       1,          /* number of configurations */
};

static const char usbXboxConfigDescriptor[] PROGMEM =
{   /* USB configuration descriptor */
   9,         /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
   USBDESCR_CONFIG,   /* descriptor type */
   0x20, 0x00,
   /* total length of data returned (including inlined descriptors) */
   1,         /* number of interfaces in this configuration */
   1,         /* index of this configuration */
   0,         /* configuration name string index */
   USBATTR_BUSPOWER,   /* attributes */
   USB_CFG_MAX_BUS_POWER / 2,   /* max USB current in 2mA units */
/* --- interface 0 --- */
   9,         /* sizeof(usbDescrInterface): length of descriptor in bytes */
   USBDESCR_INTERFACE,   /* descriptor type */
   0,         /* index of this interface */
   0,         /* alternate setting for this interface */
   2,         /* endpoints excl 0: number of endpoint descriptors to follow */
   USB_CFG_INTERFACE_CLASS,         /* 3=HID class */
   USB_CFG_INTERFACE_SUBCLASS,         /* subclass: 0=none, 1=boot */
   0,         /* protocol: 0=none, 1=keyboard, 2=mouse */
   0,         /* string index for interface */
/* endpoint descriptor for endpoint 0 */
   7,         /* sizeof(usbDescrEndpoint) */
   USBDESCR_ENDPOINT,   /* descriptor type = endpoint */
   0x82,         /* IN endpoint number 1 */
   3,         /* attrib: Interrupt endpoint */
   0x20, 0x00,         /* maximum packet size */
   USB_CFG_INTR_POLL_INTERVAL,   /* in ms */
/* endpoint descriptor for endpoint 2 */
   7,         /* sizeof(usbDescrEndpoint) */
   USBDESCR_ENDPOINT,   /* descriptor type = endpoint */
   0x02,         /* OUT endpoint number 2 */
   3,         /* attrib: Interrupt endpoint */
   0x20, 0x00,         /* maximum packet size */
   USB_CFG_INTR_POLL_INTERVAL,   /* in ms */
};

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
    usbRequest_t    *rq = (void *)data;

    /* The following requests are never used. But since they are required by
     * the specification, we implement them in this example.
     */
    if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
    {   /* class request type */
   if (rq->bRequest == USBRQ_HID_GET_REPORT)
   { 
/* wValue: ReportType (highbyte), ReportID (lowbyte) */
/* we only have one report type, so don't look at wValue */
       reportBuffer[0] = 0x00;
      reportBuffer[1] = 0x10; // size
...
      reportBuffer[19] = 0x00; // R stick Y
      usbMsgPtr = (void *)&reportBuffer;
      return sizeof(reportBuffer);
       }
       else if(rq->bRequest == USBRQ_HID_GET_IDLE)
       {
            usbMsgPtr = &idleRate;
            return 1;
       }
      else if(rq->bRequest == USBRQ_HID_SET_IDLE)
      {
            idleRate = rq->wValue.bytes[1];
       }
    }
   else
   {
/* no vendor specific requests implemented */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}

usbMsgLen_t usbFunctionDescriptor(usbRequest_t * rq)
{
   uchar *p = 0, len = 0;

#if 0   /* default descriptor from driver */
    if (rq->wValue.bytes[1] == USBDESCR_DEVICE) {
          p = (uchar *) usbXboxDeviceDescriptor;
       len = sizeof(usbXboxDeviceDescriptor);
   } else
#endif
   if (rq->wValue.bytes[1] == USBDESCR_CONFIG) {
      p = (uchar *) usbXboxConfigDescriptor;
      len = sizeof(usbXboxConfigDescriptor);
   }
   usbMsgPtr = p;
   return len;
}

int main(void)
{
...
   cli();
   wdt_disable();
   usbInit();
   usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
   uint8_t i = 0;
   while(--i){             /* fake USB disconnect for > 250 ms */
       _delay_ms(1);
   }
   usbDeviceConnect();
   sei();
   for(;;)
   {
       usbPoll();
       if(usbInterruptIsReady())
       {                       
/* called after every poll of the interrupt endpoint */
          BuildControllerReport();
          usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
        }
    }
}
...
}

//-------------------------------------------------------------------------------------------

usbconfig.h:
#define USB_CFG_HAVE_INTRIN_ENDPOINT    1
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   1
#define USB_CFG_EP3_NUMBER              3
#define USB_CFG_IMPLEMENT_HALT          0
#define USB_CFG_SUPPRESS_INTR_CODE      0
#define USB_CFG_INTR_POLL_INTERVAL      10
#define USB_CFG_IS_SELF_POWERED         1
#define USB_CFG_MAX_BUS_POWER           200
#define USB_CFG_IMPLEMENT_FN_WRITE      0
#define USB_CFG_IMPLEMENT_FN_READ       0
#define USB_CFG_IMPLEMENT_FN_WRITEOUT   0
#define USB_CFG_HAVE_FLOWCONTROL        0
#define USB_CFG_LONG_TRANSFERS          0
#define USB_COUNT_SOF                   0
#define USB_CFG_CHECK_DATA_TOGGLING     0
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0
#define  USB_CFG_VENDOR_ID       0x0C, 0x12
#define  USB_CFG_DEVICE_ID       0x88, 0x02
#define USB_CFG_DEVICE_VERSION  0x01, 0x02
#define USB_CFG_VENDOR_NAME     'G', 'r', 'o', 'b', 'i'
#define USB_CFG_VENDOR_NAME_LEN 5
#define USB_CFG_DEVICE_NAME     'P', 'S', '2', 't', 'o', 'X', 'b', 'o', 'X'
#define USB_CFG_DEVICE_NAME_LEN 9
#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_DEVICE_SUBCLASS     0
#define USB_CFG_INTERFACE_CLASS     0x58
#define USB_CFG_INTERFACE_SUBCLASS  0x42
#define USB_CFG_INTERFACE_PROTOCOL  0
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    0


Grobi

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Wed Jan 27, 2010 7:28 am

Wow, I have also put this aside for a bit.. I know you need the DescrDevice I posted.

as for a report I used this.

Code: Select all

//XBOX
// standard descriptor types
#define   CONFIGURATION   2
#define   INTERFACE      4
#define   ENDPOINT      5
uchar XBOXDescriptorConfiguration[] = {
   0x09,          //size of this desc in bytes
    CONFIGURATION, //type of desc
    0x20,    0x00,      //size of total descriptor
    0x01,          //# of interfaces
    0x01,         //index number of this config
    0x00,         //config string index
    0x80,          //attributes:Default
    0x32,         //power consumption * 2mA
   //Interface portion
    0x09,         //size of this desc in bytes
    INTERFACE,      //type of desc
    0x00,         //interface number (ordinal)
    0x00,         //alternate setting number
    0x02,         //number of endpoints (not including EP0)
    0x58,         //Interface class - HID
    0x42,         //sublass - HID boot device subclass
    0x00,         //protocol code - mouse
    0x00,         //interface string index
    //endpoint portion
    0x07,      //size of desc in bytes
    ENDPOINT,   //type od desc
    0x82,      //endpoint address (EP2 IN)
    0x03,      //transfer style: interrupt
    0x20, 0x00,   //max packet size : 32
    0x04,      //interval: 4ms
    //endpoint portion
    0x07,      //size of desc in bytes
    ENDPOINT,   //type od desc
    0x02,      //endpoint address (EP2 OUT)
    0x03,      //transfer style: interrupt
    0x20, 0x00,   //max packet size : 32
    0x04      //interval: 4ms
};

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Wed Jan 27, 2010 5:38 pm

...man I can't make it work,
I put up a lil test-prog without the whole PS2 mouse and keyboard stuff but it won't work either.
Please, if you could spare some time and have a look at the code and maybe compare it to your solution and tell me what the heck I am doing wrong?
hw setup : self powered, Mega32 16MHz USB D- on PortD.5

main.c :

Code: Select all

#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>   /* required by usbdrv.h */
#include <usbdrv.h>

static uint8_t reportBuffer[20];

static const char usbXboxDeviceDescriptor[] PROGMEM = {  /* USB device descriptor */
    0x12,             // size of this descriptor in bytes
    0x01,            // descriptor type = DEVICE
    0x10, 0x01,          // USB Spec 2.0
    0x00,              // class code
    0x00,              // subclass code
    0x00,              // protocol code
    0x08,//  0x40,        // EPO buffer size
    0x5E, 0x04,        // vendor ID 04D8
    0x02, 0x02,       // product ID
    0x00, 0x01,       // device release number
    0x01,                // manufacturer string index
    0x02,                // product string index
    0x03,                // serial number string index
    0x01,                // number of configurations
};

static const char usbXboxConfigDescriptor[] PROGMEM = {   /* USB configuration descriptor */
   0x09,            /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
   0x02,            /* descriptor type */
   0x20, 0x00,         /* total length of data returned (including inlined descriptors) */
   0x01,            /* number of interfaces in this configuration */
   0x01,            /* index of this configuration */
   0x00,            /* configuration name string index */
   0x80,            /* attributes */
   0x32,            /* max USB current in 2mA units */

/* --- interface 0 --- */
   0x09,            /* sizeof(usbDescrInterface): length of descriptor in bytes */
   0x04,            /* descriptor type */
   0x00,            /* index of this interface */
   0x00,            /* alternate setting for this interface */
   0x02,            /* endpoints excl 0: number of endpoint descriptors to follow */
   0x58,            /* 3=HID class */
   0x42,            /* subclass: 0=none, 1=boot */
   0x00,            /* protocol: 0=none, 1=keyboard, 2=mouse */
   0x00,            /* string index for interface */

   /* endpoint descriptor for endpoint 0 */
   0x07,            /* sizeof(usbDescrEndpoint) */
   0x05,            /* descriptor type = endpoint */
   0x82,            /* IN endpoint number 1 */
   0x03,            /* attrib: Interrupt endpoint */
   0x20, 0x00,         /* maximum packet size */
   0x04,            /* in ms */

   /* endpoint descriptor for endpoint 2 */
   0x07,            /* sizeof(usbDescrEndpoint) */
   0x05,            /* descriptor type = endpoint */
   0x02,            /* OUT endpoint number 2 */
   0x03,            /* attrib: Interrupt endpoint */
   0x20, 0x00,         /* maximum packet size */
   0x04,            /* in ms */
};

static uchar    idleRate;   /* repeat rate for keyboards, never used for mice */

// USB

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
   usbRequest_t    *rq = (void *)data;
    if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
   {   /* class request type */
      if (rq->bRequest == USBRQ_HID_GET_REPORT)
      {  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
         reportBuffer[0] = 0x00;
         reportBuffer[1] = 0x10; // size
         reportBuffer[2] = 0x00; // D buttons
         reportBuffer[3] = 0x00; // reserved
         reportBuffer[4] = 0x00; // A
         reportBuffer[5] = 0x00; // B
         reportBuffer[6] = 0x00; // X
         reportBuffer[7] = 0x00; // Y
         reportBuffer[8] = 0x00; // Black
         reportBuffer[9] = 0x00; // White
         reportBuffer[10] = 0x00; // L trigger
         reportBuffer[11] = 0x00; // R trigger
         reportBuffer[12] = 0x00; // L stick X
         reportBuffer[13] = 0x00; // L stick X
         reportBuffer[14] = 0x00; // L stick Y
         reportBuffer[15] = 0x00; // L stick Y
         reportBuffer[16] = 0x00; // R stick X
         reportBuffer[17] = 0x00; // R stick X
         reportBuffer[18] = 0x00; // R stick Y
         reportBuffer[19] = 0x00; // R stick Y
         usbMsgPtr = reportBuffer;
            return sizeof(reportBuffer);
        }
      else if(rq->bRequest == USBRQ_HID_GET_IDLE)
      {
            usbMsgPtr = &idleRate;
            return 1;
        }
      else if(rq->bRequest == USBRQ_HID_SET_IDLE)
      {
            idleRate = rq->wValue.bytes[1];
        }
    }
   else
   {
        /* no vendor specific requests implemented */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}

usbMsgLen_t usbFunctionDescriptor(usbRequest_t * rq)
{
   uchar *p = 0, len = 0;

#if 0   /* default descriptor from driver */
   if (rq->wValue.bytes[1] == USBDESCR_DEVICE)
   {
      p = (uchar *) usbXboxDeviceDescriptor;
      len = sizeof(usbXboxDeviceDescriptor);
      PORTC &= ~(1<<PC6);
   } else
#endif
   if (rq->wValue.bytes[1] == USBDESCR_CONFIG)
   {
      p = (uchar *) usbXboxConfigDescriptor;
      len = sizeof(usbXboxConfigDescriptor);
      PORTC &= ~(1<<PC5);
   }
   usbMsgPtr = p;
   return len;
}

int main()
{
   DDRC &= ~(1<<DDC7);
   DDRC |= (1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2);
   PORTC |= (1<<PC6) | (1<<PC5) | (1<<PC4) | (1<<PC3) | (1<<PC2);
   // USB init etc.....
   cli();
   wdt_disable();
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    uint8_t i = 0;
    while(--i)            /* fake USB disconnect for > 250 ms */
   {             
        _delay_ms(1);
    }
    usbDeviceConnect();
    sei();
   //debug
   PORTC &= ~(1<<PC2);
   
   for(;;)
   {
      usbPoll();
        if(usbInterruptIsReady())
      {
            /* called after every poll of the interrupt endpoint */
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
        }
    }
   return 1;
}


usbconfig.h :

Code: Select all

#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      5
#define USB_CFG_DPLUS_BIT       2
#define USB_CFG_CLOCK_KHZ       (F_CPU/1000)
#define USB_CFG_HAVE_INTRIN_ENDPOINT    1
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   0
#define USB_CFG_EP3_NUMBER              3
#define USB_CFG_IMPLEMENT_HALT          0
#define USB_CFG_SUPPRESS_INTR_CODE      0
#define USB_CFG_INTR_POLL_INTERVAL      4
#define USB_CFG_IS_SELF_POWERED         1
#define USB_CFG_MAX_BUS_POWER           200
#define USB_CFG_IMPLEMENT_FN_WRITE      0
#define USB_CFG_IMPLEMENT_FN_READ       0
#define USB_CFG_IMPLEMENT_FN_WRITEOUT   0
#define USB_CFG_HAVE_FLOWCONTROL        0
#define USB_CFG_LONG_TRANSFERS          0
#define USB_COUNT_SOF                   0
#define USB_CFG_CHECK_DATA_TOGGLING     0
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0
#define  USB_CFG_VENDOR_ID       0x5e, 0x04
#define  USB_CFG_DEVICE_ID       0x02, 0x02 /* obdev's shared PID for HIDs */
#define USB_CFG_DEVICE_VERSION  0x10, 0x01
#define USB_CFG_VENDOR_NAME     'G', 'r', 'o', 'b', 'i'
#define USB_CFG_VENDOR_NAME_LEN 5
#define USB_CFG_DEVICE_NAME     'P', 'S', '2', 't', 'o', 'X', 'b', 'o', 'X'
#define USB_CFG_DEVICE_NAME_LEN 9
#define USB_CFG_DEVICE_CLASS        0
#define USB_CFG_DEVICE_SUBCLASS     0
#define USB_CFG_INTERFACE_CLASS     0x58
#define USB_CFG_INTERFACE_SUBCLASS  0x42
#define USB_CFG_INTERFACE_PROTOCOL  0
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    0
#define USB_CFG_DESCR_PROPS_DEVICE                  0
#define USB_CFG_DESCR_PROPS_CONFIGURATION           0
#define USB_CFG_DESCR_PROPS_STRINGS                 0
#define USB_CFG_DESCR_PROPS_STRING_0                0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR           0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0
#define USB_CFG_DESCR_PROPS_HID                     0
#define USB_CFG_DESCR_PROPS_HID_REPORT              0
#define USB_CFG_DESCR_PROPS_UNKNOWN                 0


on a wind*ws system I get an Device is not recognized error when I plug it in but I think thats normal for an Xb*x gamepad...

Grobi

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: Mega32 as Xb*X gamepad

Post by ulao » Wed Jan 27, 2010 11:53 pm

Do your self to favors. 1) get xbcdhttp://www.redcl0ud.com/xbcd.html 2) get USBlyzer. Once the xbcd is installed it will show up as a xbox when you connect a real xbox or this avr. Tell me what you learn. I will look over your code later, when I have time.

Grobi
Posts: 6
Joined: Tue Jan 26, 2010 6:55 pm

Re: Mega32 as Xb*X gamepad

Post by Grobi » Thu Jan 28, 2010 3:19 pm

Usblyzer :
Enumeration of device failed.
USB get node connection Information, all values of DeviceDescriptor are 0x00 that can't be right.

Grobi

Post Reply