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