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