www.mikrocontroller.net

Forum: Compiler & IDEs USB HID Descriptor (V-USB)


Autor: Andreas S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen wunderschönen guten Abend! :)
Ich experimentiere zur Zeit ein wenig am V-USB Beispielprojekt 
"HID-Keys" (http://www.obdev.at/products/vusb/hidkeys.html) herum. Ziel 
ist, die Mediatasten moderner USB-Tastaturen (Play, Pause, ...) 
hinzukriegen.
Mein Descriptor, von dem ich mir erhoffe, dass er einfach auf den 
angestrebten Zweck umzuschreiben ist, sieht jetzt wie folgt aus (und 
kann für die üblichen Lettern/Ziffern benutzt werden, Shift ist für mich 
irrelevant)
char usbHidReportDescriptor[35] = {
    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)

    0x09, 0x00,                    //   USAGE (Unassigned)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x00,                    //   REPORT_COUNT (0)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};
Was mir einiges an Rumgewurschtle bereitet hat, ist der zweite Teil, der 
ja eigentlich 0 mal ein Bit unbelegten Inhaltes ankündigt, aus mir 
unbekanntem Grunde jedoch unerlässlich ist.
Auf dieser (funktionierenden) Basis dann Versuch zwei mit 
Mediafunktionen:
char usbHidReportDescriptor[43] = {
    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x0c,                    //   USAGE_PAGE (Consumer Devices)
    0x09, 0xb0,                    //   USAGE (Play)
    0x09, 0xb1,                    //   USAGE (Pause)
    0x09, 0xb5,                    //   USAGE (Scan Next Track)
    0x09, 0xb6,                    //   USAGE (Scan Previous Track)
    0x09, 0xb7,                    //   USAGE (Stop)
    0x09, 0xe2,                    //   USAGE (Mute)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0x00,                    //   USAGE (Unassigned)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x02,                    //   REPORT_COUNT (2)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};
XP gibt mir dafür ein "Gerät konnte nicht gestartet werden", ich kann 
aber nicht nachvollziehen, was das Problem sein könnte.

Ich hoffe auf Anregungen und danke euch vielmals fürs Lesen und Helfen!
Andreas

Autor: enwo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaub nicht daß der HID Descriptor noch korrekt ist mit den 
zusätzlichen USAGE einträgen. Wenn du Media Keys übertragen willst, 
passiert das innerhalb eines Reports den du abschickst ( der mit 
modifier keys an 1. stelle und dann folgend den pressed keys. 8byte groß 
wie in deinem ersten beispiel angegeben) Die Hex-Werte für die 
speziellen keys müßten auf der usb.org seite gelistet sein.

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinst du so?
char usbHidReportDescriptor[36] = {
    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x0c,                    //   USAGE_PAGE (Consumer Devices)
    0x19, 0x00,                    //   USAGE_MINIMUM (Unassigned)
    0x29, 0xb7,                    //   USAGE_MAXIMUM (Stop)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xb7, 0x00,              //   LOGICAL_MAXIMUM (183)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0x09, 0x00,                    //   USAGE (Unassigned)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x00,                    //   REPORT_COUNT (0)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};
Klappt leider auch nicht :(

Autor: Potter S. (potter68)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andreas S.,

versuchs mal hiermit:
//Class specific descriptor - HID Keyboard
char usbHidReportDescriptor[63] = {
    0x05, 0x01,    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,     // USAGE (Keyboard)
    0xa1, 0x01,     // COLLECTION (Application)
    0x05, 0x07,     //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,     //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,     //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,     //   LOGICAL_MINIMUM (0)
    0x25, 0x01,     //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,     //   REPORT_SIZE (1)
    0x95, 0x08,     //   REPORT_COUNT (8)
    0x81, 0x02,     //   INPUT (Data,Var,Abs)
    0x95, 0x01,     //   REPORT_COUNT (1)
    0x75, 0x08,     //   REPORT_SIZE (8)
    0x81, 0x03,     //   INPUT (Cnst,Var,Abs)
    0x95, 0x05,     //   REPORT_COUNT (5)
    0x75, 0x01,     //   REPORT_SIZE (1)
    0x05, 0x08,     //   USAGE_PAGE (LEDs)
    0x19, 0x01,     //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,     //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,     //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,     //   REPORT_COUNT (1)
    0x75, 0x03,     //   REPORT_SIZE (3)
    0x91, 0x03,     //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,     //   REPORT_COUNT (6)
    0x75, 0x08,     //   REPORT_SIZE (8)
    0x15, 0x00,     //   LOGICAL_MINIMUM (0)
    0x25, 0x65,     //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,     //   USAGE_PAGE (Keyboard)
    0x19, 0x00,     //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,     //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,     //   INPUT (Data,Ary,Abs)
    0xc0            // End Collection
};

Die zugehörigen Usage ID's findest Du in 'Hut1_11.pdf' (S. 53 ff) bei 
usb.org.

Gruß Ralf

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,
Der Descriptor funktioniert zwar für ein Keyboard, jedoch nicht für die 
gewünschten Sondertasten :(
"LOGICAL_MAXIMUM" und "USAGE_MAXIMUM" habe ich auf 0x7f (Usage ID für 
"Mute" aus der genannten Tabelle, danke!) angehoben. Stelle ich nun 
"0x7f" zum Abholen bereit tut sich leider nichts.

Könnte das u.U. damit zusammenhängen, dass in der Tabelle rechts bei den 
Usages für Play, Pause, Mute usw. nur bei "UNIX" ein Haken ist, nicht 
aber bei "PC-AT" ? USBLyzer zeigt mir beim entsprechenden Tastendruck 
nämlich auch an, dass 0x7f ("Mute") bzw. einer der anderen tabellierten 
Werte abgeholt wurde. Mag sich vielleicht jemand die Trial runterladen 
und mir das Protokoll nach Druck der Mediatasten zur Verfügung stellen?

Autor: Info (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du schon weitergekommen?

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das Projekt habe ich bisher zurückgestellt. Wenn immer die 
Möglichkeit bestand, mal bei einem bekannten den USBLyzer laufen zu 
lassen, habe ich's anscheinend vergessen :-/

Bedarf an Logs oder Vorschlägen besteht aber immer noch!

Andreas

Autor: Remote One (remote1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst dir doch einfach nur deinen keyReport anpassen. Bei mir sieht 
das z.B. so aus:
#define MOD_CONTROL_LEFT    (1<<0)
#define MOD_SHIFT_LEFT      (1<<1)
#define MOD_ALT_LEFT        (1<<2)
#define MOD_GUI_LEFT        (1<<3)
#define MOD_CONTROL_RIGHT   (1<<4)
#define MOD_SHIFT_RIGHT     (1<<5)
#define MOD_ALT_RIGHT       (1<<6)
#define MOD_GUI_RIGHT       (1<<7)

#define KEY_A       4
#define KEY_B       5

....

#define KEY_X       27
#define KEY_Y       28
#define KEY_Z       29
#define KEY_1       30

...

#define KEY_9       38
#define KEY_0       39

#define KEY_ENTER   40
#define KEY_SPACE   44
#define KEY_RARROW  79
#define KEY_LARROW  80
#define KEY_DOWN  81
#define KEY_UP    82


static const uchar  keyReport[NUM_KEYS + 1][2] PROGMEM = {
/* none */  {0, 0},                     /* no key pressed */
/*  1 */    {MOD_CONTROL_RIGHT, KEY_RARROW},//hoch
/*  2 */    {MOD_CONTROL_RIGHT, KEY_LARROW},//runter
/*  3 */    {MOD_SHIFT_RIGHT, KEY_LARROW},  //links
/*  4 */    {MOD_SHIFT_RIGHT, KEY_RARROW},  //rechts
/*  5 */    {0, KEY_ENTER},          //OK
/*  6 */    {0, KEY_N},            //CH+
/*  7 */    {0, KEY_P},            //CH-
/*  8 */    {MOD_CONTROL_LEFT, KEY_UP},    //Vol+
/*  9 */    {MOD_CONTROL_LEFT, KEY_DOWN},  //Vol-
/* 10 */    {0, KEY_P},            //rewind
/* 11 */    {0, KEY_SPACE},          //play
/* 12 */    {0, KEY_N},            //forward
/* 13 */    {0, KEY_S},            //stop
/* 14 */    {0, KEY_SPACE},          //pause
/* 15 */    {MOD_ALT_RIGHT, KEY_D},      //videotext, DualView
/* 16 */    {MOD_ALT_LEFT, KEY_F4},      //ausschalten

};

Soll heißen, deinem play etc ist ein Hexwert zugeordnet den du senden 
musst. Schau dazu mal in dem angehängten PDF ab Seite 53 nach dem 
entsprechenden Wert (ist ja alles  standardisiert).
Stop, Mute etc. stehen da alle drin.

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke dir :-)
Dass der keyReport ebenfalls angepasst werden muss ist mir klar, Problem 
ist wie gesagt, dass eben die übermittelten "Play", "Pause" und wie sie 
alle heißen mögen keinen Effekt haben. Dein keyReport ist leider nur die 
eine für mich provisorische Lösung, die ich auch schon gefunden habe. 
Problem daran ist, dass sich bspw. mit CTRL-Up nur bestimmte Software 
steuern lässt. (Ich hoffe, ich liege nicht grottenfalsch und selbiges 
gilt nicht etwa auch für die Mediatasten einer USB-Tastatur)

Autor: Info (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast den Anhang vergessen, es würde mich interessieren!

Autor: Remote One (remote1)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch mal der Anhang.
Schau mal da vorbei: http://www.usb.org/developers/hidpage/
interessant sollte das Tool "HID Descriptor Tool" bzw. "HIDView" sein

USB View zeigt die evtl. auch den Descriptor deiner Tastatur:
http://www.ftdichip.com/Support/Utilities.htm

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich mache gerade etwas ähnliches. ich möchte ein kleines Keypad 
zusammenstellen das mir Klammern und andere Operatoren leichter 
zugänglich macht. Ich verstehe soweit eigentlich den Code des VUSB 
Projektes nur die Funktion keyreport ist mir ein Rätsel. Was passiert 
mit der Usage-ID wenn ich einen MOD_KEY voranstelle. Im HID Usage Table 
sind ja für jeden erdenklichen Key die werte aufgelistet. ich könnte 
also immer
{0, KEY_XY}
in der keyreport Funktion schreiben?
Also direkt ohne MOD KEYS? Wie gesagt verstehe lediglich diese Funktion 
nicht so ganz, wäre toll wenn mich jemand erleuchten könnte.

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tag,
Die "Mod Keys" sind Tasten à la Shift, Ctrl etc.
Wenn du die "Mod Keys" grundsätzlich nicht brauchst, stellst du entweder 
jeweils eine 0 vor (siehe dein Post) oder reduzierst die Zellen des 
keyReport auf jeweils ein Byte (KEY_XY). Der Descriptor muss dann 
entsprechend angepasst werden.

Autor: Nicholas Feix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist bewusst, dass der Thread schon lange unbeobachtet blieb, doch da 
ich mich selbst auf der Suche nach den Media Funktionen befand und eine 
lösung dazu zusammenstellen konnte.
Der Descriptor hat bei mir in diesem Falle folgende Struktur:
PROGMEM char usbHidReportDescriptor[65] = { // USB report descriptor
    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x01,                    //   REPORT_ID (1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x0a,                    //   REPORT_COUNT (10)
    0x09, 0x00,                    //   USAGE (Undefined)
    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
    0xc0,                          // END_COLLECTION

    0x05, 0x0c,                    // USAGE_PAGE (Consumer)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x09, 0xe9,                    //   USAGE (Volume Increment)
    0x09, 0xea,                    //   USAGE (Volume Decrement)
    0x75, 0x01,                    //   REPORT_SIZE  (1)
    0x95, 0x02,                    //   REPORT_COUNT (2)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0xe2,                    //   USAGE (Mute)
    0x09, 0xb5,                    //   USAGE (Scan Next Track)
    0x09, 0xb6,                    //   USAGE (Scan Previous Track)
    0x09, 0xb7,                    //   USAGE (Stop)
    0x09, 0xcd,                    //   USAGE (Play/Pause)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x81, 0x06,                    //   INPUT (Data,Var,Rel)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x01,                    //   INPUT (Constant)
    0xc0                           // END_COLLECTION
};
Die Feature ID ist hier mal nicht von Bedeutung, ich nutze sie als Setup 
Schnittstelle. Von Interesse ist die Consumer Page.
Dem Host muss man demnach einen Datenblock von 2 Bytes senden. Das erste 
Byte enthält die Report ID und das zweite dann bitweise die Keys...
[{2, 0b00100000} würde die Mute Funktion toggeln]
Wie der Report zu übermitteln ist, sollte jedem aus den Comunity 
Projekten auf www.obdev.at bekannt sein. Dennoch führe ich das zu 
Sicherheit nochmal auf:
uchar  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)
        {
            usbMsgPtr = BUFFER;
            return 2;
        }

...

}
Als Reaktion, falls der Report explizit gefordert wird. Dies kommt kaum 
bis überhaupt nicht vor, doch schaden kanns nicht.

Im main loop muss man nun nur noch die Reports selbst senden, wenn man 
die Änderung eines Keys vermelden möchte.
int  main (void)
{

...

    while(42)
    {

...

        usbPoll();

...

        if(KEY_CHANGED && usbInterruptIsReady())
        {
            usbSetInterrupt(BUFFER, 2);
        }
    }
    return 0;
}
Ich hoffe das dies irgendwem helfen kann, denn ich persönlich war 
zwischenzeitlich von der Suche durchaus frustriert.


Viel Spass weiterhin beim Werkeln...

Nicki

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin begeistert! Danke Nicholas, das sind tolle Neuigkeiten! :-) Ich 
habe allzu häufig mit Wehmut das verwaiste Eclipse-Projekt entdeckt... 
womit nun auch der arbeitsfreie Teil der Semesterferien seine Erfüllung 
finden wird.

Wirklich, vielen herzlichen Dank!

Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön, dass ich helfen konnte.
Meine Bastelei (kapazitieves volume wheel mit 5 Keys vektoriell 
integriert) arbeitet damit wunderbar.
Lass hören wie dein Eclipse-Projekt fortschreitet :)

Nicki

Autor: Kurt Bohnen (kurt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Nicholas,
könntest du das vieleicht genauer erklären?

Nicholas Feix schrieb:
> Dem Host muss man demnach einen Datenblock von 2 Bytes senden. Das erste
> Byte enthält die Report ID und das zweite dann bitweise die Keys...
> [{2, 0b00100000} würde die Mute Funktion toggeln]

Anders gefragt, was muss in HID-Keys noch geändert werden?

Mfg,
Kurt

Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kurt,
wie du vermutlich bemerkt hast, hab ich strukturelle Einzelheiten aus 
HID-Keys übernommen.
In diesem jenen Projekt wird folgende Funktion zum bilden des Reports 
aufgerufen:
static uchar    reportBuffer[2];    /* buffer for HID reports */

...

static void buildReport(uchar key)
{
/* This (not so elegant) cast saves us 10 bytes of program memory */
    *(int *)reportBuffer = pgm_read_word(keyReport[key]);
}

Hier wird ja nur für den Inhalt des Buffers auf einen 
Programmspeicherbereich bestehend aus einem Word verwiesen. An diesem 
Punkt musst du dann Eingreifen und den Inhalt, wie es der HID Treiber 
wünscht, beschreiben. Das erste Byte muss also der Report ID 
entsprechen, die in dem obigen Descriptor vorliegt (bzw. welche auch 
immer du definierst), und das zweite Byte enthält dann den aktuellen 
status der Keys.
Im Descriptor werden hintereinander die Funktionen, welche du 
beeinflussen möchtest, aufgelistet. Diese Reihenfolge muss bei der 
Statusübertragung eingehalten werden, die mit dem niedrigsten Bit 
beginnt.

Ich geb dir im folgenden mal eine Beispiel, bei der die Mute Funktion 
gesendet wird. Bedenke, dass dies nur symbolisch ist, letzten Endes 
musst du das an deine Hardware und deine genaue Funktionsvorstellung 
anpassen.
...
static uchar    reportBuffer[2];    /* buffer for HID reports */

#define     KEY_VOLUME_INC      0x01
#define     KEY_VOLUME_DEC      0x02
#define     KEY_MUTE            0x04

...

PROGMEM char usbHidReportDescriptor[65] = { // USB report descriptor
    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x01,                    //   REPORT_ID (1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x0a,                    //   REPORT_COUNT (10)
    0x09, 0x00,                    //   USAGE (Undefined)
    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
    0xc0,                          // END_COLLECTION

    0x05, 0x0c,                    // USAGE_PAGE (Consumer)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x09, 0xe9,                    //   USAGE (Volume Increment)
    0x09, 0xea,                    //   USAGE (Volume Decrement)
    0x75, 0x01,                    //   REPORT_SIZE  (1)
    0x95, 0x02,                    //   REPORT_COUNT (2)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0xe2,                    //   USAGE (Mute)
    0x09, 0xb5,                    //   USAGE (Scan Next Track)
    0x09, 0xb6,                    //   USAGE (Scan Previous Track)
    0x09, 0xb7,                    //   USAGE (Stop)
    0x09, 0xcd,                    //   USAGE (Play/Pause)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x81, 0x06,                    //   INPUT (Data,Var,Rel)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x01,                    //   INPUT (Constant)
    0xc0                           // END_COLLECTION
};

...

static void buildReport()    // Das Argument aus dem Beispielproject brauchen wir nicht,
{                            // da wir den Inhalt kennen.
    reportBuffer[0] = 0x02;  // Inhalt gehört zur Report ID 2 (Consumer Page)
    if (PIND & (1 << PIN0))  // Mute Taste abfragen (Debounce soll hierbei nicht interessieren)
        reportBuffer[1] |= (1 << KEY_MUTE);  // Mute wird als aktiv beschrieben
    else
        reportBuffer[1] &= ~(1 << KEY_MUTE); // Mute wird als inaktiv beschrieben
}

...

Im Projekt HID-Keys wird im mainloop im Zuge der IdleRate zyklisch der 
Report gebildet und geschickt, somit könnte dies theoretisch so 
eingebunden werden. Allerdings wird der Fall, dass der Report zur ID 1 
gewünscht ist gänzlich ignoriert, da wir das Highbyte permament auf 2 
setzen...

Desweiteren muss man sich zu den Benutzungstypen der einzelnen Tasten 
genau erkundigen. Mute als Beispiel wird vom UsageType als OOC (On/Off 
Control) angegeben, was bedeutet, dass man den absoluten Wert sendet. 
Bei OSC (One Shot Control) andererseits würde ein Wechsel vom Wert 0 zu 
1 triggern, also sowohl aktivieren als auch deaktivieren.

Mehr dazu im Abschnitt "15 Consumer Page (0x0C)" (Seite 75 ff) der "USB 
HID Usage Tables".
http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
Die Funktionstypen findest du in der gleichen pdf im Abschnitt "3.4.1 
Usage Types (Controls)" (Seite 18).

Ich hoffe das ist dir eine Hilfe und stellt sich nicht als verwirrend 
dar.

Für Fragen steh ich selbstverständlich auch weiter zur Verfügung ;)


Greez, Nicki

Autor: Kurt Bohnen (kurt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, ich werde das mal in Ruhe durcharbeiten.

Mfg,
Kurt

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da ich mich gerade mit dem gleichen beschäftige, wollt ich hier noch 
meine Lösung posten. Ich brauchte die Mute-Taste für ein vusb projekt. 
Die Lösung hat jedoch einen Nachteil: Sie funktioniert bei mir nur unter 
Linux. Windows erkennt zwar das HID-Gerät und "normale" Tasten 
funktionieren, jedoch die Mute Taste nicht.

Ich nutze folgenden Report:
const char usbHidReportDescriptor[36] PROGMEM = { /* USB report descriptor */
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x26, 0xe7, 0x00,              //   LOGICAL_MAXIMUM (231)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0                           // END_COLLECTION
    };
Ich habe dazu einfach den Report Descriptor aus dem HID Beispiel in das 
HID Descriptor Tool abgetippt und dann im zweiten Block die Felder 
Logical Maximum und Usage Maximum auf einen höheren Wert gesetzt.

Wenn ich nun {0x00,0x7f} als report sende, funktioniert der Mute.

MfG
  Micha

Autor: Nico Hood (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier gibt es massiv funktionierende USB Descriptors und die 
dazugehörigen reporte:
https://github.com/NicoHood/HID

Guckst du HID.cpp und HID_Reports.h ;)

Mehr konnte ich aus usb HID nicht rausholen. Das einzige was fehlt ist 
rumble für controller, das ist aber komplizierter.

Beitrag #3949666 wurde von einem Moderator gelöscht.
Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, jemand heraus, mit diesem?

haben einen bereit Quellcode des Projekts?

wenn nicht schwer zu legen, =)

Autor: ;o) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Please write again without Google Translator.
This automated translations are hard to understand.

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hello, the project is ready? I wanted to see the source code, since I 
did not get (((do on Atmega328

Autor: Andreas S. (drohgebaerde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F. posted one example over two years ago - works just fine! - 
and there are several more solutions under Nico Hood's link. :-)

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas S, You are using Atmega8?

Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ KazakOFF

It works on almost every AVR MCU with at least 4k of flash memory ;)

: Bearbeitet durch User
Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F, Atmega328 not work (((

Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Well, that is strange.
I got it all working on the ATmega48/88, which are both basically the 
same MCU as yours, only with less memory.
There must be something wrong with your hardware setup (chosen pins, 
pullup res, ...) or the USB firmware configuration (more likely).
I suggest you have a look into that because it should work, of that I am 
certain.

Good luck ;)

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F. ,This example works!! 
http://www.obdev.at/products/vusb/hidkeys.html

But this example does not work(((

...
static uchar    reportBuffer[2];    /* buffer for HID reports */

#define     KEY_VOLUME_INC      0x01
#define     KEY_VOLUME_DEC      0x02
#define     KEY_MUTE            0x04

...

PROGMEM char usbHidReportDescriptor[65] = { // USB report descriptor
    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x01,                    //   REPORT_ID (1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x0a,                    //   REPORT_COUNT (10)
    0x09, 0x00,                    //   USAGE (Undefined)
    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
    0xc0,                          // END_COLLECTION

    0x05, 0x0c,                    // USAGE_PAGE (Consumer)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x09, 0xe9,                    //   USAGE (Volume Increment)
    0x09, 0xea,                    //   USAGE (Volume Decrement)
    0x75, 0x01,                    //   REPORT_SIZE  (1)
    0x95, 0x02,                    //   REPORT_COUNT (2)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0xe2,                    //   USAGE (Mute)
    0x09, 0xb5,                    //   USAGE (Scan Next Track)
    0x09, 0xb6,                    //   USAGE (Scan Previous Track)
    0x09, 0xb7,                    //   USAGE (Stop)
    0x09, 0xcd,                    //   USAGE (Play/Pause)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x81, 0x06,                    //   INPUT (Data,Var,Rel)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x01,                    //   INPUT (Constant)
    0xc0                           // END_COLLECTION
};

...

static void buildReport()    // Das Argument aus dem Beispielproject brauchen wir nicht,
{                            // da wir den Inhalt kennen.
    reportBuffer[0] = 0x02;  // Inhalt gehört zur Report ID 2 (Consumer Page)
    if (PIND & (1 << PIN0))  // Mute Taste abfragen (Debounce soll hierbei nicht interessieren)
        reportBuffer[1] |= (1 << KEY_MUTE);  // Mute wird als aktiv beschrieben
    else
        reportBuffer[1] &= ~(1 << KEY_MUTE); // Mute wird als inaktiv beschrieben
}

...

 


whether to make changes to makefile's ?

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F. , Can upload your file main.c

Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Well, my code was based on "hidkeys" but does not have a lot in common 
with it anymore and is way too packed with other stuff to be a good 
reference.

But you wrote that "hidkeys" worked on your controller and I assume that 
you know your MCU and all the code beside V-USB (regarding IO, change of 
key state, ...).

So if "not work" means the device can't be recognized by the USB driver, 
my wild guess would be, that the HID descriptor length in "usbconfig.h" 
was not adjusted...
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    65

If that is not your the problem, (maybe) I could put a sample file 
together.
But I would not be able to test it on any hardware.

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F, Upload sample you please.

Autor: Nicholas F. (snip3rnick)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Sorry for the delay...

Here is the example, but as I said, it could not be tested!
Though it should be easy to rule out remaining errors with the hardware 
to run it ;)

I hope it works for you

Autor: KazakOFF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicholas F,

avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c 
main.c -o main.o
main.c:33:14: error: conflicting types for ‘usbDescriptorHidReport’
usbdrv/usbdrv.h:477:6: note: previous declaration of 
‘usbDescriptorHidReport’ was here
main.c: In function ‘buildReport’:
main.c:72:5: error: ‘USB_BUF_TX’ undeclared (first use in this function)
main.c:72:5: note: each undeclared identifier is reported only once for 
each function it appears in
main.c:73:21: error: ‘KEY_VALUES’ undeclared (first use in this 
function)
main.c:74:5: warning: ‘return’ with a value, in function returning void
main.c: In function ‘usbFunctionSetup’:
main.c:81:17: error: ‘USB_BUF_TX’ undeclared (first use in this 
function)
main.c:87:13: error: void value not ignored as it ought to be
main.c: In function ‘main’:
main.c:117:5: warning: implicit declaration of function ‘hardwareInit’
main.c:132:11: error: ‘KEY_VALUES’ undeclared (first use in this 
function)
main.c:136:5: warning: implicit declaration of function ‘_delay_ms’
main.c:151:29: error: ‘USB_BUF_TX’ undeclared (first use in this 
function)
main.c:151:13: warning: implicit declaration of function 
‘usbBuildReport’
main.c:114:10: warning: unused variable ‘idleCounter’

Autor: Nicholas F. (snip3rnick)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Well, that was a bummer...
Clearly I should have put more time into that, sorry.

I had the chance to set my AVR environment up, so this one actually 
compiled ;)

Though the usbDescriptorHidReport type conflict is on your side, that is 
a false configured 'usbconfig.h'.

: Bearbeitet durch User
Autor: Nicholas F. (snip3rnick)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
The first file sends the wrong reportID!
I had two reportIDs but removed the first, so it must be 1 instead of 2

sorry again ;)

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.