USB-Deskriptoren programmieren
Die Boards der ersten Serie meldeten sich am Mac mit unlesbarem Namen und liessen sich nicht als Tonausgabe wählen, weil der Audiochip seine USB-Kennung aus einem Speicherbaustein liest, der noch leer war. Ein Board ist inzwischen beschrieben und spielt Musik. Dabei kam ein zweiter Befund heraus, der die nächste Revision bestimmt: Solange der Audiochip Strom hat, blockiert er den Bus zu diesem Speicher vollständig.
Inhalt
- Messumgebung
- Was die Boards meldeten
- Woher das kam
- Der Audiochip blockiert den Bus
- Was in den Speicher gehört
- Der Ablauf am Raspberry Pi
- Das Programmiermodul
- Die Mac-App
- Revision 1.1
- Was daraus nicht folgt
- Quellennachweis
Anhang
1. Messumgebung
Alle Zahlen in diesem Dokument stammen von einem Exemplar der ersten Fertigungsserie der Revision 1.0, bestückt bei JLCPCB, am 25. September 2026. Der Speicherbaustein U4 war zu Beginn unbeschrieben, also im Auslieferungszustand des Herstellers.
Gemessen wurde am Mac über die Geräteregistrierung des Betriebssystems und über die Audioübersicht des Systemberichts. Die Spannungen an den Testpunkten und an den Anschlüssen von U4 wurden mit einem Multimeter aufgenommen. Der I²C-Bus wurde von einem Raspberry Pi 5 aus untersucht, angeschlossen an J1, mit dem Bus an GPIO2 und GPIO3 bei 100 kHz.
2. Was die Boards meldeten
Der Mac erkannte das Board und lud seinen Audiotreiber. Die drei USB-Schnittstellen waren vorhanden und richtig eingeordnet, nämlich die Steuerschnittstelle für Audio, die Datenschnittstelle für den Tonstrom und die Schnittstelle für die Tasten. Der Chip arbeitete also.
Was er über sich selbst sagte, stimmte dagegen nicht.
| Angabe | Vorher | Jetzt |
|---|---|---|
| Hersteller-Kennung | 0xFFFF | 0x08BB |
| Produkt-Kennung | 0xFFFF | 0x2704 |
| Produktname | 16 Füllzeichen | NeXT Sound Box |
| Herstellername | 32 Füllzeichen | LAYERED.work |
| Ausgangskanäle | keine gemeldet | 2 |
| Anschlussart | unbekannt | USB |
Die letzten beiden Zeilen waren der Grund, warum sich das Board nicht als Tonausgabe wählen liess. Ein Ausgabegerät ohne Ausgänge bietet das System nicht an. Nach dem Beschreiben erscheint es im Menü, lässt sich wählen und spielt.
3. Woher das kam
Der PCM2704C hat seine USB-Kennung nicht fest eingebaut. Er liest sie nach jedem Einschalten über den I²C-Bus aus einem externen Speicherbaustein und überschreibt damit seine eigenen Vorgaben. Auf dem Board ist das U4, ein Speicher vom Typ M24C02.1
Ein fabrikneuer Speicherbaustein enthält in jeder Zelle den Wert 0xFF. Genau das las der Chip und meldete es weiter. Die sechzehn Füllzeichen im Produktnamen waren die sechzehn Bytes, die für dieses Feld vorgesehen sind.
Aus demselben Speicher kommen auch die beiden Angaben zur Stromversorgung. Bei 0xFF meldete das Board, es versorge sich selbst und benötige 510 mA. Beides war falsch, denn das Board zieht seinen Strom aus dem USB-Anschluss, und 510 mA liegt über dem, was USB zulässt. Der Hersteller des Chips weist darauf hin, dass diese beiden Angaben zur tatsächlichen Beschaltung passen müssen, weil das Gerät sonst unerwartet arbeitet.1 Dass genau daran die fehlenden Ausgangskanäle hingen, hat sich bestätigt: Mit den richtigen Werten meldet das Board seine zwei Kanäle.
4. Der Audiochip blockiert den Bus
Der Speicher lässt sich nicht beschreiben, während der Audiochip Strom hat. Das ist der zweite Befund dieser Sitzung und der wichtigere für die nächste Revision.
Der Pin CK des Audiochips ist im Datenblatt als Taktausgang geführt, also als treibender Ausgang und nicht als offener Kollektor.1 Er gibt den Bus nach seinem eigenen Lesevorgang nicht frei. Ein zweiter Teilnehmer am selben Bus verliert deshalb jedes Mal die Arbitrierung, sobald er eine Leitung loslassen will.
| Zustand | Datenleitung heruntergezogen | Ergebnis eines Bus-Scans |
|---|---|---|
| Board am USB | die Taktleitung geht mit | 56 Adressen melden Arbitrierungsverlust |
| Board stromlos | die Taktleitung bleibt oben | 112 Adressen melden ein normales NACK |
| Nur der Speicher versorgt | die Taktleitung bleibt oben | der Speicher antwortet auf 0x50 |
Die 56 Adressen des ersten Falls sind genau die, deren erstes Bit eine Eins ist. Der Master lässt die Leitung dafür los, liest aber eine Null zurück und bricht ab. Die andere Hälfte, deren erstes Bit eine Null ist, läuft durch, weil der Master die Leitung dabei selbst herunterzieht und gar nicht in den Konflikt kommt.
Der Speicher, seine Anschlüsse und die Leiterbahnen sind dabei in Ordnung. Sie wurden einzeln gemessen, und sobald der Audiochip stromlos ist, antwortet der Speicher sofort.
Der Speicher braucht eine eigene Versorgung
Das Netz mit den 3,3 V versorgt nur U4, seine beiden Pullup-Widerstände und zwei Kondensatoren. Der Audiochip hängt nicht daran, er hat einen eigenen Regler eingebaut. Diese Trennung ist es, die das Programmieren überhaupt möglich macht: Wird diese Schiene allein gespeist und das USB-Kabel weggelassen, läuft der Speicher und der Audiochip nicht.
J1 führt in Revision 1.0 aber nur Daten, Masse und Takt. Die Versorgung muss deshalb an den Testpunkten abgegriffen werden, und genau das ändert sich in der nächsten Revision.
5. Was in den Speicher gehört
Ab der ersten Speicherstelle stehen 57 Bytes, lückenlos hintereinander und ohne Längenangaben davor. Jedes Feld muss deshalb genau seine vorgesehene Grösse einnehmen, sonst verschiebt sich alles dahinter.
| Feld | Bytes | Wert |
|---|---|---|
| Hersteller-Kennung | 2 | 0x08BB |
| Produkt-Kennung | 2 | 0x2704 |
| Produktname | 16 | NeXT Sound Box, mit Leerzeichen aufgefüllt |
| Herstellername | 32 | LAYERED.work, mit Leerzeichen aufgefüllt |
| Stromart | 1 | 0x80, versorgt sich aus dem USB-Anschluss |
| Stromaufnahme | 1 | 0xFA, entspricht 500 mA |
| Tastenkennung | 3 | 0x0A 0x93 0x01 |
Die beiden Kennungen bleiben die des Chipherstellers. Eine eigene Herstellerkennung muss beim USB-Konsortium gekauft werden, und diese Werte sind ohnehin die, die der Chip ohne Speicher melden würde.
Die Namen werden mit Leerzeichen auf ihre Länge gebracht und nicht mit einem Abschlusszeichen beendet, weil der Chip das Feld immer vollständig liest und ein Abschlusszeichen als sichtbares Zeichen beim Rechner ankäme. Der Produktname fasst sechzehn Zeichen, der vollständige Produktname ist neunzehn Zeichen lang und passt deshalb nicht hinein.
Die Stromaufnahme von 500 mA muss so dort stehen, weil der Pin HOST des Chips auf der Platine fest an die USB-Versorgung gelegt ist und damit dieselbe Klasse wählt.
Jedes Byte steht spiegelverkehrt im Speicher
Der Chip liest die Bits eines Bytes in umgekehrter Reihenfolge, als ein üblicher Speicherbaustein sie ausgibt. Jedes Byte muss deshalb bitweise gespiegelt abgelegt werden. Aus der Herstellerkennung 0x08BB werden im Speicher die beiden Bytes 0xDD und 0x10, aus dem Buchstaben N wird 0x72.
Das Datenblatt verlangt diese Spiegelung an zwei Stellen, zeigt in seinem Beispiel daneben aber lesbaren Klartext.1 Das Beispiel ist die Darstellung für den Leser. Ein Mitarbeiter des Chipherstellers bestätigt die Spiegelung im Supportforum2, zwei Anwender belegen sie an laufenden Geräten34, und das beschriebene Board bestätigt sie ein weiteres Mal.
6. Der Ablauf am Raspberry Pi
So wurde das erste Board beschrieben, und so lassen sich die übrigen der Serie ebenfalls beschreiben, solange Revision 1.0 gilt.
| Pi | Board | Anmerkung |
|---|---|---|
| Pin 3, GPIO2 | J1, äusserer Pin | Daten |
| Pin 5, GPIO3 | J1, anderer äusserer Pin | Takt |
| Pin 9 | J1, mittlerer Pin | Masse des Busses |
| Pin 1, 3,3 V | TP7 | versorgt allein den Speicher |
| Pin 6 | TP8 | Masse der Versorgung |
Das USB-Kabel bleibt dabei abgezogen. Nur dann ist der Audiochip stromlos und gibt den Bus frei. Die beiden Versorgungsleitungen müssen nicht gelötet sein, weil Scannen und Schreiben zusammen wenige Sekunden dauern.
Auf dem Pi wird I²C eingeschaltet, was ohne Neustart geht, und anschliessend gescannt und geschrieben:
sudo dtparam i2c_arm=on
sudo modprobe i2c-dev
./i2c_diag.py scan
./write_usb_descriptor.py
Der Scan muss den Speicher unter 0x50 zeigen. Das Schreibwerkzeug legt die 57 Bytes seitenweise ab, liest sie zurück und vergleicht. Danach wird das Board vom Pi getrennt und an den Rechner gesteckt.
7. Das Programmiermodul
Für den dauerhaften Gebrauch tritt an die Stelle des Raspberry Pi der isolierte USB-auf-I²C-Adapter von Pololu, Artikelnummer 5397.5 Er meldet sich am Rechner als serielle Schnittstelle und braucht deshalb keinen Treiber. Seine Befehle sind wenige Bytes lang, eine App kann sie also ohne Fremdbibliothek selbst schicken.
Entscheidend ist seine zweite Eigenschaft: Er stellt auf der I²C-Seite eine eigene, galvanisch getrennte Versorgung bereit, wahlweise 3,3 V oder 5 V bei bis zu 200 mA. Damit übernimmt er genau die Rolle, die beim Raspberry Pi zwei zusätzliche Leitungen an die Testpunkte hatten.
Der Schiebeschalter steht auf 3,3 V
Die Pins CK und DT des Audiochips vertragen laut Datenblatt höchstens die Betriebsspannung plus 0,3 V, was rund 3,6 V ergibt.1 Bei 5 V am Bus liegt der Chip darüber.
Der Adapter liest die Stellung des Schalters beim Einschalten ein, ein Umlegen im Betrieb bleibt folgenlos. Welche Spannung eingestellt ist, lässt sich per Software nicht abfragen, sondern nur an zwei Leuchtdioden am Modul ablesen, wobei grün für 3,3 V steht.
8. Die Mac-App
Die App findet den Adapter selbst, weil er sich mit einer eindeutigen Kennung meldet, und zeigt die sieben Felder aus Tabelle 3 als Eingabemaske. Sie zählt die Zeichen der beiden Namen mit, weist auf Zeichen hin, die sich nicht übertragen lassen, und füllt selbst mit Leerzeichen auf. Die Spiegelung der Bits nimmt sie dem Benutzer ab.
Nach dem Schreiben liest sie den Speicher zurück und zeigt ihn an. Schlägt etwas fehl, meldet der Adapter einen von dreizehn Fehlerwerten zurück, die die App im Klartext anzeigt.
Ein Punkt gehört fest in die App: Wird die serielle Verbindung mit einer Übertragungsrate von 600 geöffnet und wieder geschlossen, startet der Adapter in seinen Firmware-Updater. Die App verwendet diese Rate deshalb nie.
9. Revision 1.1
Zwei Änderungen am Schaltplan, beide klein und beide auf der Platine gut unterzubringen.
| Bauteil | Änderung | Grund |
|---|---|---|
| J1 | Vierpoliger JST-SH-Steckverbinder mit 1 mm Raster, belegt mit Masse, 3,3 V, Daten, Takt | Ohne eigene Versorgung am Anschluss ist der Speicher nicht erreichbar, solange der Audiochip läuft. Mit ihr genügt ein Kabel von der Stange, ohne Löten und ohne Klemmen an Testpunkten. |
| LED1 | Ein kleiner Schalttransistor vom Typ 2N7002 zwischen SSPND und der Leuchtdiode, die ihren Strom aus der USB-Versorgung bekommt | Der Ausgang SSPND liefert zu wenig Spannung für diese Leuchtdiode. Mit dem Transistor hängt die Helligkeit nicht mehr an ihm, und die Farbe ist wieder frei wählbar. |
Die Belegung des neuen Anschlusses folgt dem verbreiteten Vierpol-Standard, den sowohl Pololu als auch andere Hersteller solcher Module verwenden. Damit passt jedes davon.
Der Schaltplan trägt diese Änderungen bereits. Was sich dadurch an der Bestückung ändert:
| Bauteil | Wert | Bestellnummer | Kategorie |
|---|---|---|---|
| Q1 | 2N7002, SOT-23, neu | C8545 | Basic Part |
| R15 | 10 kΩ, 0402, neu | C25744 | Basic Part |
| R1 | 2,2 kΩ statt 220 Ω, 0603 | C4190 | Basic Part |
| J1 | JST SH, vierpolig, liegend | C160404 | Extended Part |
Drei der vier sind Basic Parts und kosten keine Rüstgebühr. Für den Steckverbinder führt JLCPCB keinen Basic Part, dort fallen einmalig gut drei Dollar an. J1 muss diesmal bestückt werden, denn ein Steckverbinder im Millimeterraster lässt sich nicht von Hand nachrüsten, und die bisherige Stiftleiste war nur deshalb unbestückt geblieben, weil man an sie Draht anlöten konnte.
Die Leuchtdiode bleibt die verbaute grüne. Sie ist bei JLCPCB ebenfalls ein Basic Part und bei kleinem Strom die lichtstärkste der dort ohne Aufpreis erhältlichen Farben.
Zur Leuchtdiode gehört die Zahl dazu: Die bestückte Diode braucht zwischen 2,6 und 3,1 V6, der Ausgang des Chips ist dagegen nur mit mindestens 2,4 V zugesichert.1 An TP9 liegen im Betrieb saubere 3,3 V measured, der Ausgang schaltet also richtig. Es fehlt allein die Spannung, um diese Diode zu zünden.
10. Was daraus nicht folgt
Das beschriebene Board spielt Musik und behält seinen Namen auch nach einer längeren Trennung vom Strom. Damit sind der Wandler, die Endstufe und der Lautsprecheranschluss belegt, und ebenso, dass der Audiochip den Speicher beim gewöhnlichen Einschalten rechtzeitig liest.
Nicht belegt ist alles, was an diesem Board noch nie betätigt wurde. Die Tasten für Lautstärke und Stummschaltung sind ungeprüft, der Anschluss für Lautstärkeregler und Schalter ebenso, und über die Tonqualität sagt ein Höreindruck nichts aus.
Die Aussagen dieses Dokuments gelten für ein einzelnes Exemplar. Die übrigen Boards der Serie tragen denselben leeren Speicher und werden sich gleich verhalten, aber gemessen ist das nicht.
Quellennachweis
Sechs Quellen, in der Reihenfolge ihres Auftretens.
- Texas Instruments (2015): PCM2704C, PCM2705C, PCM2706C, PCM2707C. PCM270xC Stereo Audio DAC With USB Interface, Single-Ended Headphone Output and S/PDIF Output. Dokument SBFS036B, überarbeitet August 2015. Abschnitte 9.3.7 und 9.3.8, Pinbelegung auf Seite 4, Grenzwerte auf Seite 7, Ausgangspegel auf Seite 9. Volltext gelesen Quelle↩↩↩↩↩↩
- Texas Instruments E2E Support Forum: PCM2704: Custom EEPROM info. Antwort eines Mitarbeiters des Herstellers auf einen Anwender, der die Beispieldaten des Datenblatts ungespiegelt abgelegt hatte und zerstörte Zeichen im Gerätenamen erhielt. Volltext gelesen Quelle↩
- Texas Instruments E2E Support Forum: PCM2704C: ROM DESCRIPTOR DATA MODIFICATION. Anwender mit Protokollmitschnitt, der die Ablage der Herstellerkennung 0x08BB als die beiden Bytes 0xDD und 0x10 zeigt. Volltext gelesen Quelle↩
- Kakade, N.: PCM2704 USB Audio DAC Device Name Change. Durchgerechnetes Beispiel für einen eigenen Gerätenamen mit Bildbeleg des Ergebnisses. Volltext gelesen Quelle↩
- Pololu Corporation: Isolated USB-to-I²C Adapter with Isolated Power. Artikel 5397, mit dem zugehörigen Benutzerhandbuch 0J89 und der offenen Firmware. Volltext gelesen Quelle↩
- LCSC Electronics: KT-0805G, Hubei KENTO Electronics. Artikel C2297, Durchlassspannung 2,6 bis 3,1 V bei 5 mA. Volltext gelesen Quelle↩
Anhang
Feldbelegungen, Werkzeuge und Fundstellen. Für die Aussagen oben braucht man das hier nicht.
A. Die Felder im Speicher
Die Werte stehen hier in der logischen Form, also so, wie der Chip sie sehen soll. Was tatsächlich im Speicherbaustein landet, ist jedes dieser Bytes bitweise gespiegelt.
| Ab | Länge | Feld | Inhalt für dieses Board |
|---|---|---|---|
| 0 | 2 | idVendor | BB 08 |
| 2 | 2 | idProduct | 04 27 |
| 4 | 16 | Produktname | NeXT Sound Box gefolgt von zwei Leerzeichen |
| 20 | 32 | Herstellername | LAYERED.work gefolgt von zwanzig Leerzeichen |
| 52 | 1 | bmAttributes | 80 |
| 53 | 1 | bMaxPower | FA |
| 54 | 3 | HID Usage | 0A 93 01 |
So sehen diese 57 Bytes im Speicher aus, also gespiegelt:
00 DD 10 20 E4 72 A6 1A 2A 04 CA F6 AE 76 26 04 42
10 F6 1E 04 04 32 82 9A A2 4A A2 22 74 EE F6 4E D6
20 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04
30 04 04 04 04 01 5F 50 C9 80
Der Speicherbaustein liegt auf dem Bus unter der Adresse 0xA0, was der Siebenbit-Adresse 0x50 entspricht. Diese Adresse ist im Audiochip fest verdrahtet und nicht einstellbar. Auf dem Board liegen die drei Adressleitungen des M24C02 an Masse, was genau diese Adresse ergibt. Ein Speicherbaustein mit zweistufiger Adressierung, wie ihn Typen ab 512 Bytes verwenden, würde hier nicht funktionieren.
B. Die Werkzeuge
Beide liegen unter Electronic/Tools und laufen mit der Standardbibliothek von Python, brauchen auf dem Raspberry Pi also keine Installation.
| Werkzeug | Aufruf | Zweck |
|---|---|---|
| i2c_diag.py | scan | jede Adresse abfragen und den genauen Fehler je Adresse melden |
| i2c_diag.py | levels | Funktion und Pegel der beiden Busleitungen zeigen |
| i2c_diag.py | hold | eine Leitung auf Masse halten, um am Chip selbst nachzumessen |
| i2c_diag.py | dump | den Anfang des Speichers lesen und anzeigen |
| write_usb_descriptor.py | ohne Argumente | die 57 Bytes schreiben, zurücklesen und vergleichen |
| write_usb_descriptor.py | --dry-run | nur zeigen, was geschrieben würde |
Die Unterscheidung der Fehlerwerte ist das, was die Fehlersuche entschieden hat. Ein Speicher, der nicht antwortet, meldet etwas anderes als ein Bus, den jemand anderes hält, und nur der zweite Fall weist vom Speicher weg.
C. Geprüfte Belege
| Aussage | Fundstelle |
|---|---|
| Der Chip auf dem Board ist ein PCM2704CDBR | Electronic/Export/fab-2026-09-16-2127/bom-jlcpcb.csv, Zeile für U1 |
| Der Speicherbaustein ist ein M24C02 mit Adressleitungen an Masse | Schaltplan, U4, Pins 1 bis 3 |
| J1 führt Daten, Masse und Takt, keine Versorgung | Schaltplan, J1, Pins 1 bis 3 |
| Vor J1 liegen 220 Ω in Reihe | Schaltplan, R12 und R13 |
| Der Bus wird mit 10 kΩ hochgezogen | Schaltplan, R10 und R11 |
| Das Netz mit 3,3 V versorgt nur U4, R10, R11, C16 und C18 | Schaltplan, Netz +3.3V |
| Die Leuchtdiode hängt über 220 Ω an SSPND | Schaltplan, R1 und LED1 |
| Der Pin HOST liegt an der USB-Versorgung | Schaltplan, U1 Pin 21 |
| Der Pin PSEL liegt an der Betriebsspannung | Schaltplan, U1 Pin 4 |