www.mikrocontroller.net

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


Autor: Grobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :
#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__ */ 

und auch die "usbdrv.c" :
/* --------------------------- 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 

das Programm in meinem mega32 sieht wie folgt aus :
#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, 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.