Forum: Mikrocontroller und Digitale Elektronik Mega 32 als Xb*x gamepad + obdevs avr usb


von Grobi (Gast)


Lesenswert?

Hi Leute,
Ich versuche aus einem Mega32 (16MHz) ein Xb*x gamepad zu machen.
Ich verwende dafür obdevs avr usb firmware.
Aber wie so oft läuft es nicht auf anhieb :-(
Es liegt wohl momentan daran das mein Mega32 einfach keinen Device 
Descriptor zurücksenden und so die enumeration fehlschlägt.

Habe mir die aktuellste XBCD version (Xb*x gamepad am PC betreiben) 
geholt und mal geschaut was mein normales Xb*x gamepad überhaupt so für 
Daten rausschmeißt. Das prog USBLyzer war da sehr hilfreich.

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

soweit so gut, also hab ich mich erstmal drangesetzt das mein Gerät 
einfach das Xb*x gamepad simuliert.

dafür habe ich die "usbconfig.h" angepaßt :
1
#ifndef __usbconfig_h_included__
2
#define __usbconfig_h_included__
3
/* ---------------------------- Hardware Config ---------------------------- */
4
#define USB_CFG_IOPORTNAME      D
5
#define USB_CFG_DMINUS_BIT      5
6
#define USB_CFG_DPLUS_BIT       2
7
#define USB_CFG_CLOCK_KHZ       (F_CPU/1000)
8
/* --------------------------- Functional Range ---------------------------- */
9
#define USB_CFG_HAVE_INTRIN_ENDPOINT    1
10
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   1
11
#define USB_CFG_EP3_NUMBER              3
12
#define USB_CFG_IMPLEMENT_HALT          0
13
#define USB_CFG_SUPPRESS_INTR_CODE      0
14
#define USB_CFG_INTR_POLL_INTERVAL      4
15
#define USB_CFG_IS_SELF_POWERED         0
16
#define USB_CFG_MAX_BUS_POWER           200
17
#define USB_CFG_IMPLEMENT_FN_WRITE      0
18
#define USB_CFG_IMPLEMENT_FN_READ       0
19
#define USB_CFG_IMPLEMENT_FN_WRITEOUT   0
20
#define USB_CFG_HAVE_FLOWCONTROL        0
21
#define USB_CFG_LONG_TRANSFERS          0
22
#define USB_COUNT_SOF                   0
23
#define USB_CFG_CHECK_DATA_TOGGLING     0
24
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0
25
/* -------------------------- Device Description --------------------------- */
26
#define  USB_CFG_VENDOR_ID       0x0C, 0x12
27
#define  USB_CFG_DEVICE_ID       0x88, 0x02
28
#define USB_CFG_DEVICE_VERSION  0x01, 0x10
29
#define USB_CFG_VENDOR_NAME     'G', 'r', 'o', 'b', 'i'
30
#define USB_CFG_VENDOR_NAME_LEN 5
31
#define USB_CFG_DEVICE_NAME     'P', 'S', '2', 't', 'o', 'X', 'b', 'o', 'X'
32
#define USB_CFG_DEVICE_NAME_LEN 9
33
#define USB_CFG_DEVICE_CLASS        0
34
#define USB_CFG_DEVICE_SUBCLASS     0
35
#define USB_CFG_INTERFACE_CLASS     0x58
36
#define USB_CFG_INTERFACE_SUBCLASS  0x42
37
#define USB_CFG_INTERFACE_PROTOCOL  0
38
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    0
39
40
#define USB_CFG_DESCR_PROPS_DEVICE                  0
41
#define USB_CFG_DESCR_PROPS_CONFIGURATION           0
42
#define USB_CFG_DESCR_PROPS_STRINGS                 0
43
#define USB_CFG_DESCR_PROPS_STRING_0                0
44
#define USB_CFG_DESCR_PROPS_STRING_VENDOR           0
45
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0
46
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0
47
#define USB_CFG_DESCR_PROPS_HID                     0
48
#define USB_CFG_DESCR_PROPS_HID_REPORT              0
49
#define USB_CFG_DESCR_PROPS_UNKNOWN                 0
50
51
#endif /* __usbconfig_h_included__ */

und auch die "usbdrv.c" :
1
/* --------------------------- Device Descriptor --------------------------- */
2
#if USB_CFG_DESCR_PROPS_DEVICE == 0
3
#undef USB_CFG_DESCR_PROPS_DEVICE
4
#define USB_CFG_DESCR_PROPS_DEVICE  sizeof(usbDescriptorDevice)
5
PROGMEM char usbDescriptorDevice[] = {    /* USB device descriptor */
6
    18,         /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
7
    USBDESCR_DEVICE,        /* descriptor type */
8
    0x10, 0x01,             /* USB version supported */
9
    USB_CFG_DEVICE_CLASS,
10
    USB_CFG_DEVICE_SUBCLASS,
11
    0,                      /* protocol */
12
    8,                      /* max packet size */
13
    /* the following two casts affect the first byte of the constant only, but
14
     * that's sufficient to avoid a warning with the default values.
15
     */
16
    (char)USB_CFG_VENDOR_ID,/* 2 bytes */
17
    (char)USB_CFG_DEVICE_ID,/* 2 bytes */
18
    USB_CFG_DEVICE_VERSION, /* 2 bytes */
19
    USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0,         /* manufacturer string index */
20
    USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0,        /* product string index */
21
    USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0,  /* serial number string index */
22
    1,          /* number of configurations */
23
};
24
#endif
25
26
/* ----------------------- Configuration Descriptor ------------------------ */
27
28
#if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0
29
#undef USB_CFG_DESCR_PROPS_HID
30
#define USB_CFG_DESCR_PROPS_HID     9   /* length of HID descriptor in config descriptor below */
31
#endif
32
33
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
34
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
35
#define USB_CFG_DESCR_PROPS_CONFIGURATION   sizeof(usbDescriptorConfiguration)
36
PROGMEM char usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
37
    9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
38
    USBDESCR_CONFIG,    /* descriptor type */
39
    0,
40
   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) */
41
    1,          /* number of interfaces in this configuration */
42
    1,          /* index of this configuration */
43
    0,          /* configuration name string index */
44
#if USB_CFG_IS_SELF_POWERED
45
    USBATTR_SELFPOWER,      /* attributes */
46
#else
47
    (char)USBATTR_BUSPOWER, /* attributes */
48
#endif
49
    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
50
/* interface descriptor follows inline: */
51
    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
52
    USBDESCR_INTERFACE, /* descriptor type */
53
    0,          /* index of this interface */
54
    0,          /* alternate setting for this interface */
55
    USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
56
    USB_CFG_INTERFACE_CLASS,
57
    USB_CFG_INTERFACE_SUBCLASS,
58
    USB_CFG_INTERFACE_PROTOCOL,
59
    0,          /* string index for interface */
60
#if (USB_CFG_DESCR_PROPS_HID & 0xff)    /* HID descriptor */
61
    9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
62
    USBDESCR_HID,   /* descriptor type: HID */
63
    0x01, 0x01, /* BCD representation of HID version */
64
    0x00,       /* target country code */
65
    0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
66
    0x22,       /* descriptor type: report */
67
    USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0,  /* total length of report descriptor */
68
#endif
69
#if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
70
    7,          /* sizeof(usbDescrEndpoint) */
71
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
72
    (char)0x82, /* IN endpoint number 1 */
73
    0x03,       /* attrib: Interrupt endpoint */
74
    0, 0x20,       /* maximum packet size */
75
    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
76
#endif
77
#if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */
78
    7,          /* sizeof(usbDescrEndpoint) */
79
    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
80
    (char)0x02, /* IN endpoint number 1 */
81
    0x03,       /* attrib: Interrupt endpoint */
82
    0, 0x20,       /* maximum packet size */
83
    USB_CFG_INTR_POLL_INTERVAL, /* in ms */
84
#endif
85
};
86
#endif

das Programm in meinem mega32 sieht wie folgt aus :
1
#include <stdlib.h>
2
#include <inttypes.h>
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
#include <avr/wdt.h>
7
#include <avr/pgmspace.h>   /* required by usbdrv.h */
8
#include <usbdrv.h>
9
// USB
10
static uint8_t reportBuffer[20];
11
static uchar    idleRate;   /* repeat rate for keyboards, never used for mice */
12
13
void InitControllerVars()
14
{
15
   reportBuffer[0] = 0x00;
16
   reportBuffer[1] = 0x10; // size
17
   reportBuffer[2] = 0x00; // D buttons
18
   reportBuffer[3] = 0x00; // reserved
19
   reportBuffer[4] = 0x00; // A
20
   reportBuffer[5] = 0x00; // B
21
   reportBuffer[6] = 0x00; // X
22
   reportBuffer[7] = 0x00; // Y
23
   reportBuffer[8] = 0x00; // Black
24
   reportBuffer[9] = 0x00; // White
25
   reportBuffer[10] = 0x00; // L trigger
26
   reportBuffer[11] = 0x00; // R trigger
27
   reportBuffer[12] = 0x00; // L stick X
28
   reportBuffer[13] = 0x00; // L stick X
29
   reportBuffer[14] = 0x00; // L stick Y
30
   reportBuffer[15] = 0x00; // L stick Y
31
   reportBuffer[16] = 0x00; // R stick X
32
   reportBuffer[17] = 0x00; // R stick X
33
   reportBuffer[18] = 0x00; // R stick Y
34
   reportBuffer[19] = 0x00; // R stick Y
35
}
36
37
void BuildControllerReport()
38
{
39
   reportBuffer[0] = 0x00;
40
   reportBuffer[1] = 0x10; // size
41
   reportBuffer[2] = 0x00; // D buttons
42
   reportBuffer[3] = 0x00; // reserved
43
   reportBuffer[4] = 0x00; // A
44
   reportBuffer[5] = 0x00; // B
45
   reportBuffer[6] = 0x00; // X
46
   reportBuffer[7] = 0x00; // Y
47
   reportBuffer[8] = 0x00; // Black
48
   reportBuffer[9] = 0x00; // White
49
   reportBuffer[10] = 0x00; // L trigger
50
   reportBuffer[11] = 0x00; // R trigger
51
   reportBuffer[12] = 0x00; // L stick X
52
   reportBuffer[13] = 0x00; // L stick X
53
   reportBuffer[14] = 0x00; // L stick Y
54
   reportBuffer[15] = 0x00; // L stick Y
55
   reportBuffer[16] = 0x00; // R stick X
56
   reportBuffer[17] = 0x00; // R stick X
57
   reportBuffer[18] = 0x00; // R stick Y
58
   reportBuffer[19] = 0x00; // R stick Y
59
}
60
61
usbMsgLen_t usbFunctionSetup(uchar data[8])
62
{
63
   usbRequest_t    *rq = (void *)data;
64
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
65
   {
66
        if(rq->bRequest == USBRQ_HID_GET_REPORT)
67
      {   reportBuffer[0] = 0x00;
68
         reportBuffer[1] = 0x10; // size
69
         reportBuffer[2] = 0x00; // D buttons
70
         reportBuffer[3] = 0x00; // reserved
71
         reportBuffer[4] = 0x00; // A
72
         reportBuffer[5] = 0x00; // B
73
         reportBuffer[6] = 0x00; // X
74
         reportBuffer[7] = 0x00; // Y
75
         reportBuffer[8] = 0x00; // Black
76
         reportBuffer[9] = 0x00; // White
77
         reportBuffer[10] = 0x00; // L trigger
78
         reportBuffer[11] = 0x00; // R trigger
79
         reportBuffer[12] = 0x00; // L stick X
80
         reportBuffer[13] = 0x00; // L stick X
81
         reportBuffer[14] = 0x00; // L stick Y
82
         reportBuffer[15] = 0x00; // L stick Y
83
         reportBuffer[16] = 0x00; // R stick X
84
         reportBuffer[17] = 0x00; // R stick X
85
         reportBuffer[18] = 0x00; // R stick Y
86
         reportBuffer[19] = 0x00; // R stick Y
87
         usbMsgPtr = (void *)&reportBuffer;
88
            return sizeof(reportBuffer);
89
        }
90
      else if(rq->bRequest == USBRQ_HID_GET_IDLE)
91
      {
92
            usbMsgPtr = &idleRate;
93
            return 1;
94
        }
95
      else if(rq->bRequest == USBRQ_HID_SET_IDLE)
96
      {
97
            idleRate = rq->wValue.bytes[1];
98
        }
99
    }
100
   else
101
   {
102
        /* no vendor specific requests implemented */
103
    }
104
    return 0;   /* default for not implemented requests: return no data back to host */
105
}
106
107
108
109
int main()
110
{
111
   InitControllerVars();
112
   // USB init etc.....
113
   wdt_disable();
114
    usbInit();
115
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
116
    uint8_t i = 0;
117
    while(--i){             /* fake USB disconnect for > 250 ms */
118
        _delay_ms(1);
119
    }
120
    usbDeviceConnect();
121
    sei();
122
    for(;;)
123
   {
124
      usbPoll();
125
        if(usbInterruptIsReady())
126
      {
127
         BuildControllerReport();
128
            usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
129
        }
130
    }
131
   return 1;
132
}

so, nu hängt ich fest. Den super plan wie das ganze mit obdevs firmware 
läuft habe ich leider auch nicht, darum bin ich mir auch garnicht so 
sicher das meine Änderungen an den source files überhaupt soweit korrekt 
sind. Könnte sein das z.B. bei manchen Werten die High-Low byte order 
vertauscht ist...
Leider hat ein Post in obdevs forum überhaupt nix gebracht, 112 views 
und keine einzige Antwort :-( und da ich bisher sehr gute Erfahrungen 
mit diesem Forum gemacht habe, dacht ich mir probier ichs einfach mal 
hier, vielleicht kennt sich ja jemand mit der Materie aus und kann n 
paar tips oder hilfen geben.

P.S. ich denke nicht das es nicht funktioniert weil mein Gerät ein 
lowspeed device ist und das Xb*x gamepad eigentlich ein fullspeed.
Aber wenn mich da jemand eines Besseren belehren möchte, nur zu.
Achja, musste leider feststellen, g**gle.de is nicht sehr hilfreich was 
dieses Thema angeht, ein paar habens wohl schon probiert, aber hat wohl 
auch nich so wirklich bei denen hingehauen.

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

THX Grobi

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.