Hallo. Ich versuche seit einiger Zeit einen kleinen Touchscreen Monitor mit einem atmega32ux dazu zu bewegen, das Android auf ihn reagiert. Leider bin ich mittlerweile so durcheinander gekommen, das ich erstmal keine Codeschnuipsel posten kann. Hatte zwar schon einen 'Touch' bekommen, aber die Koordinaten werden nicht ünertragen. Mein Grundgerüst war die LUFA Mouse Class Demo. Hatte dann den Report geändert. Also die X/Y Koordinaten auf 16 Bit unsigned (uint16_t) sowie den Mouse-Descriptor geändert. Das Gerät wird auch unter Windows (meist) einwandfrei erkannt, aber viel passiert trotzdem nicht. Hat wer vielleicht schon ein ähnliches Problem gehabt und eine Lösung dafür? Ich möchte nur absolute Koordinaten und (mindestens) einen Touch-Event übertragen. Wie wäre egal. Kann auch eine Maus mit absoluten Koordinaten sein. Das funzt zwar unter Windows, aber nicht unter Android. Verwendet wird die Android Version 4.2.2 (FInless 1.5) mit Kernel 3.0.36+ auf einem Tropnsmart MK908 mit 2G/8G. Die Touch Auswertung läuft auch halbwegs (Verbesserungspotential gibts ja immer). Es fehlt nur die Anbindung an den Android-Stick. Zur Kontrolle nehme ich immer das HID Descriptor Tool von USB.org und erstelle auch damit den Descriptor. Recherchen i Internet waren immer recht erfolglos. Ich schau noch, ob ich den Descriptor mit Touch finde (muss von anderer Partition booten) und reiche den nach. Viele Grüsse Jürgen
Hier mal der Descriptor, bei dem es mit der geänderten LUFA CLASS MOUSE DEMO mit dem Touch funktioniert:
1 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) |
2 | 0x09, 0x02, // USAGE (Mouse) |
3 | 0xa1, 0x01, // COLLECTION (Application) |
4 | 0x09, 0x01, // USAGE (Pointer) |
5 | 0xa1, 0x00, // COLLECTION (Physical) |
6 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) |
7 | 0x09, 0x33, // USAGE (Touch) |
8 | 0x19, 0x01, // USAGE_MINIMUM (Digitizer) |
9 | 0x29, 0x01, // USAGE_MAXIMUM (Digitizer) |
10 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
11 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) |
12 | 0x95, 0x01, // REPORT_COUNT (1) |
13 | 0x75, 0x01, // REPORT_SIZE (1) |
14 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
15 | 0x95, 0x01, // REPORT_COUNT (1) |
16 | 0x75, 0x07, // REPORT_SIZE (7) |
17 | 0x81, 0x01, // INPUT (Cnst,Ary,Abs) |
18 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) |
19 | 0x09, 0x30, // USAGE (X) |
20 | 0x09, 0x31, // USAGE (Y) |
21 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
22 | 0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023) |
23 | 0x65, 0x00, // UNIT (None) |
24 | 0x75, 0x10, // REPORT_SIZE (16) |
25 | 0x95, 0x02, // REPORT_COUNT (2) |
26 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
27 | 0xc0, // END_COLLECTION |
28 | 0xc0 // END_COLLECTION |
29 | [/code>] |
30 | |
31 | Datei für das HID Descriptor Tool von USB.org im Anhang. |
32 | |
33 | Weiter habe och in der Mouse.c |
34 | den Teil der Button und Joystick Abfrage geändert, so dass sinnvolle Werte entstehen. |
35 | [code} |
36 | if (JoyStatus_LCL & JOY_UP) |
37 | { |
38 | MouseReport->X = 100; |
39 | MouseReport->Y = 100; |
40 | MouseReport->Button |= (1 << 0); |
41 | } |
42 | |
43 | if (JoyStatus_LCL & JOY_DOWN) |
44 | { |
45 | MouseReport->X = 100; |
46 | MouseReport->Y = 200; |
47 | MouseReport->Button |= (1 << 0); |
48 | } |
49 | |
50 | if (JoyStatus_LCL & JOY_LEFT) |
51 | { |
52 | MouseReport->X = 200; |
53 | MouseReport->Y = 100; |
54 | MouseReport->Button |= (1 << 0); |
55 | } |
56 | |
57 | if (JoyStatus_LCL & JOY_RIGHT) |
58 | { |
59 | MouseReport->X = 200; |
60 | MouseReport->Y = 200; |
61 | MouseReport->Button |= (1 << 0); |
62 | } |
63 | |
64 | if (JoyStatus_LCL & JOY_PRESS) |
65 | MouseReport->Button |= (1 << 0); |
Dann noch den Report angepasst:
1 | typedef struct |
2 | { |
3 | uint8_t Button; // unverändert |
4 | uint16_t X; // von int8_t auf uint16_t geändert |
5 | uint16_t Y; // von int8_t auf uint16_t geändert |
6 | } ATTR_PACKED USB_MouseReport_Data_t; |
Wie gesagt: Touch funktionert. Anm einer freien auf dem Bildschrim kommt bei langem Touch der Dialog für den Hintergrund. Es lasen sich, mit der Maus vorher entsprechend positioniert, auch Apps starten.
Hier mal das gesamte Projekt (nach 'make clean') für AVR Studio 6.1 Das HID Descriptor Tool von USB.org gibt es hier: http://www.usb.org/developers/hidpage/dt2_4.zip
Als Grundlage bin ich hiervon ausgegangen: http://source.android.com/devices/tech/input/touch-devices.html Sorry für die vielen Antworten... Kommt halt kleckerweise...
Arno Nüm schrieb: > uint16_t X; // von int8_t auf uint16_t geändert > uint16_t Y; // von int8_t auf uint16_t geändert Nach meinem Verständnis sind die logical values immer signed. Solange man nur Werte >=0 und <=32767 verwendet ist das aber egal. Ich hab bei mir die Werte min=-32768 und max=32768 verwendet um genauer positionieren zu könnnen (SubPixel Mouse Movement :-), ist aber vielleicht doch etwas übertrieben. > 0x05, 0x0d, // USAGE_PAGE (Digitizers) > 0x09, 0x33, // USAGE (Touch) Ob man die Usage Digitizers:Touch oder Desktop:Mouse verwendet scheint keine große Rolle zu spielen, zumindest unter Windows und Mac OSX. Je nachdem welcher Treiber sich dafür zuständig fühlt kann es sich aber auswirken. Windows hat die Einschränkung, dass man ohne eigenen Treiber auf den ersten Bildschirm beschränkt ist. Bei MacOS gibt es 15% logischen Rand um den eigentliche Desktop (mit dem Standard-Treiber und Standard Settings), d.h. für min=0 und max=1023 bewegt sich der Pointer nur zwischen den Werten 76 und 946, ansonsten klebt er am Rand. Ich hab das letztens für den Arduino Leonardo (ATmega32U4) umgesetzt, d.h. den Core angepasst. Siehe auch Kommentare und Verweis auf den Pull-Request in Git: [https://github.com/arduino/Arduino/issues/1417#ref-commit-7b77d1e] Michael
Hallo und danke für die Antwort. Leider kann ich das mit einem Arduino Leonardo noch nicht tsten, da die grad erst bestellt wurden. Habe sonst nur noch einen MattairTech MT-DB-U4 hier, der aber, trotz gewisser Konpatibilitäten, nicht so will. Mein XP muckt auch nach einiger Zeit... Würde bei dem Porjekt auch gerne bei AVRStudio bleiben, auch, wenn ich schon eine ganze Kiste von Arduino Teilen habe. Di emeisten aber ohne Bootloader, da alles über AVRStudio... Wobei ich mir ja zumindest mal den Descriptor auslesen könnte, wenns funzt. :D
Arno Nüm schrieb: > Leider kann ich das mit einem Arduino Leonardo noch nicht tsten, da die > grad erst bestellt wurden. Das muss kein Arduino Board sein. Ich hab das auch hauptsächlich mit einem Teensy 1.0++ mit AT90USB646 und einem FLIP Bootloader gemacht. Es geht ja nicht um das Board oder den Bootloader, sondern nur um die USB HID Features. > Habe sonst nur noch einen MattairTech MT-DB-U4 hier, der aber, trotz > gewisser Konpatibilitäten, nicht so will. Mein XP muckt auch nach > einiger Zeit... Deine Report-Struktur kommt mir komisch vor:
1 | typedef struct |
2 | { |
3 | uint8_t Button; // unverändert |
4 | uint16_t X; // von int8_t auf uint16_t geändert |
5 | uint16_t Y; // von int8_t auf uint16_t geändert |
6 | } ATTR_PACKED USB_MouseReport_Data_t; |
Der Compiler wird höchstwahrscheinlich zwischen 'Button' und 'X' ein Füllbyte einfügen. Das siehst du am einfachsten, wenn Du die erwartete Strukturgröße (5 Byte) mit der tatsächlichen (ich vermute: 6 Byte) vergleichst. Ich kann das heute zeitlich nicht mehr überprüfen. Außerdem sollte man bei Netzwerk-Protokollen nicht auf die endianess der CPU verlassen (USB benötigt 'little endian') und die Bytes besser direkt dahin schreiben wo sie hin müssen. Probier mal folgendes:
1 | #define LSB(v) ((v >> 8) & 0xff) |
2 | #define MSB(v) (v & 0xff) |
3 | void FillUsbReport(uint8_t reportData[5], uint8_t buttons, int16_t x, int16_t y) |
4 | { |
5 | reportData[0] = buttons; |
6 | reportData[1] = LSB(x); |
7 | reportData[2] = MSB(x); |
8 | reportData[3] = LSB(y); |
9 | reportData[4] = MSB(y); |
10 | } |
Hier mal den Descriptor, den ich verwende:
1 | #if 1 |
2 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) |
3 | 0x09, 0x02, // USAGE (Mouse) |
4 | 0xa1, 0x01, // COLLECTION (Application) |
5 | 0x09, 0x01, // USAGE (Pointer) |
6 | 0xa1, 0x00, // COLLECTION (Physical) |
7 | #else |
8 | 0x05, 0x0D, // USAGE_PAGE (Digitizers) |
9 | 0x09, 0x01, // USAGE (Digitizer) |
10 | 0xa1, 0x01, // COLLECTION (Application) |
11 | 0x09, 0x14, // USAGE (Stylus) |
12 | 0xa1, 0x02, // COLLECTION (Logical) |
13 | #endif |
14 | //0x85, HID_REPORTID_MOUSE_ABS, // REPORT_ID (5) |
15 | 0x05, 0x09, // USAGE_PAGE (Button) |
16 | 0x19, 0x01, // USAGE_MINIMUM (Button 1) |
17 | 0x29, 0x03, // USAGE_MAXIMUM (Button 3) |
18 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
19 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) |
20 | 0x95, 0x03, // REPORT_COUNT (3) |
21 | 0x75, 0x01, // REPORT_SIZE (1) |
22 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
23 | 0x95, 0x01, // REPORT_COUNT (1) |
24 | 0x75, 0x05, // REPORT_SIZE (5) |
25 | 0x81, 0x03, // INPUT (Cnst,Var,Abs) |
26 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) |
27 | 0x09, 0x30, // USAGE (X) |
28 | 0x09, 0x31, // USAGE (Y) |
29 | 0x09, 0x38, // USAGE (Wheel) |
30 | 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) |
31 | 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) |
32 | 0x36, 0x00, 0x80, // Physical minimum = -37678 |
33 | 0x46, 0xFF, 0x7f, // Physical maximum = 32767 |
34 | |
35 | //0x66, 0x00, 0x00 // Unit (None) TODO: is this a good idea and is it correct? |
36 | 0x75, 0x10, // REPORT_SIZE (16) |
37 | 0x95, 0x03, // REPORT_COUNT (3) |
38 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
39 | 0xc0, // END_COLLECTION |
40 | 0xc0, // END_COLLECTION |
Wenn Du aus dem #if 0 ein #if 1 machst, wird anstatt der Maus ein Digitizer emuliert. Die ReportID brauchst du wohl nicht, wenn du nicht unterschiedliche Reports pro Endpoint schicken willst Ich habe 3 Maus-Buttons, eine x-, y- und eine wheel-Achse definiert. Michael
Soooooo... Ansatzweise habe ich es! Descriptor für 800x480:
1 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) |
2 | 0x09, 0x01, // USAGE (Digitizer) |
3 | 0xa1, 0x01, // COLLECTION (Application) |
4 | 0x09, 0x04, // USAGE (Touch Screen) |
5 | 0xa1, 0x00, // COLLECTION (Physical) |
6 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) |
7 | 0x09, 0x33, // USAGE (Touch) |
8 | 0x09, 0x32, // USAGE (In Range) |
9 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
10 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) |
11 | 0x75, 0x01, // REPORT_SIZE (1) |
12 | 0x95, 0x02, // REPORT_COUNT (2) |
13 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
14 | 0x75, 0x01, // REPORT_SIZE (1) |
15 | 0x95, 0x06, // REPORT_COUNT (6) |
16 | 0x81, 0x03, // INPUT (Cnst,Var,Abs) |
17 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) |
18 | 0x09, 0x30, // USAGE (X) |
19 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
20 | 0x26, 0x20, 0x03, // LOGICAL_MAXIMUM (800) |
21 | 0x75, 0x10, // REPORT_SIZE (16) |
22 | 0x95, 0x01, // REPORT_COUNT (1) |
23 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
24 | 0x09, 0x31, // USAGE (Y) |
25 | 0x15, 0x00, // LOGICAL_MINIMUM (0) |
26 | 0x26, 0xe0, 0x01, // LOGICAL_MAXIMUM (480) |
27 | 0x75, 0x10, // REPORT_SIZE (16) |
28 | 0x95, 0x01, // REPORT_COUNT (1) |
29 | 0x81, 0x02, // INPUT (Data,Var,Abs) |
30 | 0xc0, // END_COLLECTION |
31 | 0xc0 // END_COLLECTION |
Touch funzt, Position funzt. Der Rest vom COde (weiter oben) ist unverändert. Naja, die Auswertung der Eingänge hat sich ein wenig geändert und die Auswahl des Wertes für den/die Button(s) habe ich auf ein #define umgelegt, um das ewige Editieren zu umgehen.
@Michael Vielen Dank für Deine Mühe. Werde mir das auf alle Fälle auch mal genauer anschauen. Das mit den Descriptoren habe ich mittlerweile wohl geschnallt. Zumindest den Aufbau. Ob sie funktionieren ist was anderes... Das mit den Füllbits habe ich auch schon gelernt.
1 | 0x75, 0x01, // REPORT_SIZE (1) |
2 | 0x95, 0x06, // REPORT_COUNT (6) |
Damit kommt man dann auf glatte Bytes (oder so - mir felhen manchmal die Fachausdrücke). Das ganze aufzudröselön ist auch keine schlechte Idee. Da merkt man, das Du 'etwas' mehr drauf hast als ich. Werde dann mal anfangen, die Panelauswertung mit dem USB Kram zu verbinden. Der (über)nächste Schritt ist dann, die Daten aus dem Navianschluss meines Alpine Radios auszuwerten und einen H/V -> Composite-Sync Adapter sowie das Signal des HDMI -> VGA Wandlers einzuspeisen. Und schon bin ich der erste mit 'nem Auroradio, Android 4.2 und Quadcore CPU/GPU!
> Damit kommt man dann auf glatte Bytes
Padding ist das Stichwort.
Hallo Auf der Suche nach einem Touch Screen HID device descriptor hat mich Google hierher gebracht und ich habe beide oben geposteten Descriptoren getestet. Mein Vorhaben war einen universalen HID Descriptor zu finden der auf ALLEN Betriebssystemen funktioniert. Die beiden Deskriptoren von Arno und Michael oben taugen dafür beide nicht. Das Probem mit USAGE_PAGE (Digitizers) ist z.B. daß Windows XP diese nicht unterstützt. Der Touchscreen von Michael verwendet DREI buttons! Kein realer Touchscreen hat 3 Finger oder 3 Stifte. Mit solchen selbstgebauten Deskriptoren hat man vielleicht Glück auf seinem Heimcomputer, aber sobald man damit in die weite Welt geht, wird man unweigerlich Betriebssysteme finden die das nicht akzeptieren. Ein Treiber für einen Touchscreen ist nicht für 3 Buttons ausgelegt. Der Linux X11 Server ist voller Bugs und hat schon Probleme mit einer Maus die absolute Koordinaten sendet! Ich bin deshalb auf Nummer Sicher gegangen und habe einen echten Touchscreen von ELO Touchsystems geklont. Wer an einem universellen Touchscreen für alle Betriebssystem interessiert ist, der lese meinen Artikel auf Codeproject: http://www.codeproject.com/Articles/1001891/A-USB-HID-Keyboard-Mouse-Touchscreen-emulator-with
Elmü Meister schrieb: > Der Touchscreen von Michael verwendet DREI buttons! > Kein realer Touchscreen hat 3 Finger oder 3 Stifte. > Mit solchen selbstgebauten Deskriptoren hat man vielleicht Glück auf > seinem Heimcomputer, aber sobald man damit in die weite Welt geht, wird > man unweigerlich Betriebssysteme finden die das nicht akzeptieren. Ein > Treiber für einen Touchscreen ist nicht für 3 Buttons ausgelegt. Die Idee hinter HID ist, dass es keine spezifischen Treiber für Mäuse, Tastaturen, Touchscreens, etc. mehr gibt sondern genau einen HID Treiber der das alles kann. Man definiert und implementiert gegen die HID Spec, welche keine Einschränkungen bei der Anzahl der Buttons macht und nicht gegen die Implementierung irgendeines 3rd Party Treiberherstellers welcher implizite Annahmen in seinem Code macht. Der Stift für den Digitizer meines alten Notebooks Toshiba M200 hatte 3 physikalische Buttons: links, rechts, radierer Auf wie viele HID Buttons diese abgebildet wurden habe ich nicht geprüft. > Mein Vorhaben war einen universalen HID Descriptor zu finden der auf ALLEN Betriebssystemen funktioniert. > Die beiden Deskriptoren von Arno und Michael oben taugen dafür beide nicht. Kannst du das mal etwas genauer ausführen, damit ich meinen Descriptor korrigieren kann? Michael
:
Bearbeitet durch User
Hallo Michael Wie gesagt: Es kann sein dass bei dir dein Descriptor funktioniert. Aber auf Linux ist das alles sehr buggy implementiert und wenn du willst dass dein Descriptor auch auf Linux sicher funktioniert empfehle ich dir auf Nummer sicher zu gehen. > Kannst du das mal etwas genauer ausführen, > damit ich meinen Descriptor korrigieren kann? Offenbar hast du meinen Artikel auf Codeproject nicht gelesen ? Auch Microsoft macht seine Anforderungen an Touchscreens die von deinem nicht erfüllt werden: https://msdn.microsoft.com/en-us/library/windows/hardware/ff553737%28v=vs.85%29.aspx Du mußt einen TipSwitch und InRange definieren. Aber wenn du diesen Descriptor benutzt wird er auf Windows XP nicht funktionieren. Deshalb empfehle ich dir meinen (von ELO kopierten) zu nehmen, den ich bereits auf etlichen Betriebssystemen getestet habe.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.