Sopho2SIP · Spezifikation der PC-Schnittstelle

ErgoLine D340 Protokoll

Wie ein Programm über die 9-polige PC-Buchse einer Philips ErgoLine D340 an einer Sopho iS3000 Anrufe erkennt, annimmt, wählt und auslöst. Genug, um einen eigenen TAPI- oder SIP-Daemon zu bauen.

Stand 2026-10-01 Gerät ERGOLINE 340-2/LG INT Firmware V4.03.40.01 Leitung 1200 Bd · 8O1 Quelle Mitschnitte + Philips Ergoline.tsp 2.1.2
bestätigtam Gerät gemessen oder mitgeschnitten
Treiberaus dem Philips-Treiber abgeleitet, am Gerät noch nicht gesehen
vermutetDeutung ohne Beleg

01Überblick

Die D340 bleibt als „Leitungsmodem“ an der Anlage. Sie erledigt den gesamten Dialog mit der Sopho (UPN, LAPD, Philips-TMP). Ein PC spricht nur mit der Firmware des Telefons: über eine serielle Leitung mit einem kleinen Binärprotokoll aus Rahmen. Das Telefon meldet Zustände (klingelt, verbunden, ausgelöst …) mit Rufnummern; der PC erteilt Aufträge (anmelden, wählen, annehmen, auflegen), die das Telefon quittiert.

Sopho iS3000Anlage, unverändertErgoLine D340LeitungsmodemGateway-DaemonRaspberry PiSIP-ServerNextcloud-App, SoftphonesUCA222USB-AudioUPNDB9 seriell1200 8O1SIPX_OUT / X_INAudio-BuchseALSADiese Spezifikation
Der Daemon sitzt zwischen der seriellen PC-Schnittstelle der D340 und SIP. Diese Spezifikation beschreibt nur die serielle Strecke (Mitte).

02Voraussetzungen

PunktWertStatus
FreischaltungAm Telefon: Merkmale → Optionen → „TAPI: Sprache über Telefon“ = Ein (oder „… über Zusatzgerät“ für die Audio-Buchse). Sind beide aus, reagiert die Schnittstelle auf nichts. Die Einträge erscheinen nur, wenn die Anlage TAPI für die Nebenstelle erlaubt.bestätigt
SteckerDB9-Buchse hinten am Telefon (Telefon = DCE), 1:1-Kabel. Pin 2 Telefon sendet, Pin 3 Telefon empfängt, Pin 5 Masse. Keine Steuerleitungen.bestätigt
PegelRS-232, Ruhepegel −5 V auf beiden Datenleitungenbestätigt
Rate1200 Baud, fest (Wartungstest 63, Bitmessung 833 µs je Bit)bestätigt
Format8 Datenbits, ungerade Parität, 1 Stoppbit (8O1). Senden und Empfangen damit am Gerät erprobt, ohne Xon/Xoff. Der Treiber schaltet zusätzlich Xon/Xoff (11/13) ein; nötig ist das nicht.bestätigt

03Rahmenformat

Beide Richtungen verwenden dasselbe Format: ein Byte Klasse, ein Byte Länge, dann genau so viele Bytes Nutzdaten. Mehrere Rahmen folgen lückenlos aufeinander. bestätigt Treiber

Klasse1 ByteLänge L1 ByteTypByte 0LeitungByte 1DatenByte 2 … L−1L Bytes NutzdatenBeispiel: Meldung DISCONNECTED, Ursache leer0205320198080002 = Meldung vom Telefon5 Bytes folgenTyp 32 DISCONNECTEDLeitung 01[98] · IE 08 Ursache, Länge 0
Jeder Rahmen beginnt mit Klasse und Länge. Die Länge zählt nur die Nutzdaten; es gibt kein Start- oder Endzeichen und keine Prüfsumme.
KlasseRichtungBedeutungTreibernameStatus
01PC → TelefonAuftrag–bestätigt
02Telefon → PCMeldungL2_REQ_PHONEbestätigt
03Telefon → PCAuftrag abgelehntL2_REJ_PHONETreiber
04Telefon → PCAuftrag quittiert, immer 04 00, nach 100–150 msL2_ACK_PHONEbestätigt
05Telefon → PCFehler / nicht verstanden (05 00)L2_ERR_PHONEbestätigt

Zerlegen: Puffer sammeln; solange mindestens zwei Bytes da sind, Länge L = puffer[1] lesen und warten, bis L + 2 Bytes vorliegen. Der Treiber liest L vorzeichenbehaftet (höchstens 127). Es gibt kein Startzeichen, nach dem man synchronisieren könnte: Nach einem Fehler den Puffer verwerfen und auf die nächste Lücke warten.

def feed(puffer, neu):
    puffer += neu
    while len(puffer) >= 2 and len(puffer) >= puffer[1] + 2:
        klasse, laenge = puffer[0], puffer[1]
        yield klasse, bytes(puffer[2:2 + laenge])
        del puffer[:2 + laenge]

04Meldungen des Telefons

Nutzdaten einer Meldung (Klasse 02): Byte 0 = Typ, Byte 1 = Leitung (bisher immer 01), danach typabhängig. Namen wie im Treiber (L3_STATUS…).

TypNameBedeutung, InhaltStatus
01READYkommt nur 50 ms nach der Quittung auf „Anmelden“, Nutzdaten 01 01 02 00; vermutlich Bereitmeldung (vermutet). Der Treiber wertet sie nicht aus (Parser-Zweig default); ein Daemon kann sie als „angemeldet“ werten oder ignorieren.bestätigt
30RINGINGAnruf kommt an; IE 6c Anrufernummerbestätigt
36DIALTONEWählton; beim Wählen am Telefon erst bei Wahlende gemeldet, ohne Wahl alle 10 s wiederholtbestätigt
19MORE_INFOgewählte Nummer als Block; IE 70 Zielbestätigt
3ePROCEEDINGVerbindungsaufbau läuft, Gegenseite wird gerufenbestätigt
31CONNECTEDverbunden (ein- und abgehend)bestätigt
32DISCONNECTEDGespräch getrennt; IE 08 Ursache (leer = eigene Seite)bestätigt
39RELEASEDLeitung frei, zurück in Ruhebestätigt
3b / 3aFACILITY ein / ausMerkmal an/aus, Kennung in Byte 2 (Tabelle unten)bestätigt
33IDLERuheTreiber
34 / 35HOLD / UNHOLDgehalten / zurückgeholtTreiber
37 / 38BUSY / CAMPONBUSYbesetzt / Anklopfen bei besetztTreiber
3cFACILITYREJECTEDMerkmal abgelehntTreiber
3dERRORFehlerTreiber
3f / 40CALLWAITING act / deactAnklopfen beginnt / endetTreiber
41USERTOUSERUser-to-User-Information (IE 7e)Treiber
44NOHOLDHalten nicht möglichTreiber

Merkmalskennungen bei FACILITY (3b/3a, Byte 2)

KennungMerkmalStatus
0aHörer: ein = abgehoben, aus = aufgelegtbestätigt
30DTMF-Töne möglich (während eines Gesprächs)bestätigt
01UmleitungTreiber
16 / 17wartenden Anruf anzeigen / annehmenTreiber
1aRückruf (ARB)Treiber
1dAufschaltenTreiber
1fKonferenz vorbereitenTreiber
4fX-Eingang statt Mikrofon: Sprache von der Audio-Buchse statt der Mikrofone; nur im Gespräch (sonst 3c 01 4f abgelehnt), endet mit dem Gesprächbestätigt
4b / 4eWechsel Benutzermodus / Special mode des Telefons (je 3a des einen, 3b des anderen)vermutet

Meldung 3c 01 kk (FACILITY_REJECTED): das Telefon hat ein Merkmal abgelehnt, z. B. 4f per Funktionstaste im Ruhezustand. bestätigt

Informationselemente und Rufnummern

Hinter Typ und Leitung folgen Elemente nach dem Muster von ISDN (Q.931): Kennung, Länge, Inhalt. Ein Byte mit gesetztem Bit 8 steht allein (bisher nur 98, Bedeutung offen).

IEInhaltStatus
6cAnrufernummer als ASCII-Ziffernbestätigt
70Zielnummer als ASCII-Ziffern (im Auftrag des PCs mit vorangestelltem Typ-Oktett 81)bestätigt / Treiber
08Ursache; 08 00 = keine, 08 01 8f = Gegenseite hat ausgelöstbestätigt
7eUser-to-User-InformationTreiber

Amtsholung. Externe Nummern stehen mit der Amtsholung der Anlage davor, hier 01. Aus 0101700000000 wird für SIP die Nummer 01700000000; zum Zurückrufen wählt man wieder mit 01. Interne Nebenstellen kommen ohne Vorwahl. Die Amtsholung ist anlagenabhängig und gehört in die Konfiguration des Daemons.

05Aufträge des PCs

Aufträge haben Klasse 01; Byte 0 ist der Typ, Byte 1 ist 00. Alle Rahmen stammen aus dem Philips-Treiber. Anmelden, Keepalive, Annehmen und Auflegen sind am Gerät erprobt (2026-10-01); die übrigen noch nicht.

AuftragRahmenWannStatus
Anmelden01 02 01 00einmal nach dem Öffnen der Schnittstelle; Antwort ACK, dann Meldung Typ 01bestätigt
Keepalive01 02 00 00nach 15 s ohne Empfangbestätigt
Leitung belegen01 02 11 00vor dem Wählen, nur im Ruhezustand; Telefon hebt ab (Freisprechen), meldet Hörer ab, aber keinen Wähltonbestätigt
Wählen01 L 19 00 98 70 n+1 81 Ziffern…nach dem Belegen; Telefon bestätigt mit MORE_INFO (19, Ziel); als Nachwahl/DTMF im Gespräch laut Treiberbestätigt (Nachwahl: Treiber)
Annehmen01 02 14 00während RINGING; das Telefon hebt ab (Freisprechen bei „Sprache über Telefon“)bestätigt
Auflegen01 02 13 00bei genau einem Gespräch; danach DISCONNECTED, RELEASED, Hörer ausbestätigt
Merkmal01 03 26 00 kk16/17 Anklopfen anzeigen/annehmen, c3 Reconnect bei zwei Gesprächen (Treiber); 4f X-Eingang statt Mikrofon im Gespräch → ACK, dann 3b 01 4f (am Gerät, nicht im Treiber)Treiber · 4f bestätigt
weitere15, 18, 1b, 1c, 1d, 21–24, 27, 25Halten, Übergabe, Konferenz, Rückruf, User-to-UserTreiber

Wählen im Detail. Bei n Ziffern ist L = n + 6: Typ 19, Leitung 00, das Einzelbyte 98, dann IE 70 mit Länge n + 1, Typ-Oktett 81 und den Ziffern als ASCII.

Wahl „123“        01 09 19 00 98 70 04 81 31 32 33
Wahl extern „01 0170 0000000“
                  01 13 19 00 98 70 0e 81 30 31 30 31 37 30 30 30 30 30 30 30 30

Im Treiber nicht unterstützt (Rückgabe LINEERR_OPERATIONUNAVAIL): Umleiten eines klingelnden Anrufs, Blind Transfer, Accept.

06Quittung und Zeitverhalten

PC / DaemonErgoLine D340Handlung am Telefonunverständliche Bytesz. B. Text, falsche Rate≈ 1,5 s Stille05 00ERR (bestätigt)15 s ohne Empfang01 02 00 00KEEPALIVE04 00ACK (bestätigt)
Zeitverhalten: Fehlerantwort und Keepalive.

07Abläufe

Links stehen Handlungen am Telefon, Pfeile sind Rahmen. Achtung: Im Freisprechbetrieb beendet die Lautsprecher-Taste am Telefon das Gespräch (Ursache leer). Schwarze Pfeile: Meldungen des Telefons. Farbige Pfeile: Aufträge des PCs. Gestrichelt: erwartet, am Gerät noch nicht gesehen.

Eingehender Anruf, am Telefon angenommen

PC / DaemonErgoLine D340Handlung am TelefonAnruf trifft ein02 12 30 01 98 6c 0d 30 31 …RINGING · Anrufer „01“ + 01700000000Hörer abgenommen02 03 3b 01 0aFACILITY_EIN · HÖRER (off hook)02 02 31 01CONNECTED02 03 3b 01 30FACILITY_EIN · DTMFGespräch, 22 sHörer aufgelegt02 03 3a 01 30FACILITY_AUS · DTMF02 05 32 01 98 08 00DISCONNECTED · Ursache leer02 05 39 01 98 08 00RELEASED02 03 3a 01 0aFACILITY_AUS · HÖRER (on hook)
Eingehender Anruf, am Telefon angenommen und aufgelegt. Mitschnitt serial_20260930_163534.log, alle Rahmen bestätigt.

Eingehender Anruf, nicht angenommen

PC / DaemonErgoLine D340Handlung am TelefonAnruf trifft ein02 12 30 01 98 6c 0d 30 31 …RINGING · Anrufer „01“ + 01700000000klingelt 11 s, niemand nimmt abAnrufer legt auf02 06 39 01 98 08 01 8fRELEASED · Ursache 8f (Gegenseite)
Verpasster Anruf: Legt der Anrufer auf, bevor jemand abnimmt, folgt auf RINGING direkt RELEASED mit Ursache 8f, ohne DISCONNECTED und ohne Hörermeldung. Bestätigt (logs/test_20261001_130201_pi_angenommen_verpasst.log).

Abgehender Anruf, am Telefon gewählt

PC / DaemonErgoLine D340Handlung am Telefonabheben, Nummer tippen02 02 36 01DIALTONE (erst bei Wahlende)02 03 3b 01 0aFACILITY_EIN · HÖRER02 12 19 01 98 70 0d 30 31 …MORE_INFO · Ziel „01“ + Nummer02 02 3e 01PROCEEDING (5,8 s später)Gegenseite nimmt an02 02 31 01CONNECTED02 03 3b 01 30FACILITY_EIN · DTMFGegenseite legt auf02 06 32 01 98 08 01 8fDISCONNECTED · Ursache 8f02 03 3a 01 30FACILITY_AUS · DTMFHörer aufgelegt (8 s)02 05 39 01 98 08 00RELEASED02 03 3a 01 0aFACILITY_AUS · HÖRER
Abgehender Anruf, am Telefon gewählt; die Gegenseite legt auf. Abheben und Einzelziffern werden nicht gemeldet, die Nummer kommt als Block. Bestätigt.

Eingehender Anruf, vom PC angenommen

PC / DaemonErgoLine D340Handlung am Telefon01 02 01 00ANMELDEN04 00ACK nach 100 ms02 04 01 01 02 00READY (Bereitmeldung, vermutet)Anruf trifft ein02 12 30 01 98 6c …RINGING · Anrufer01 02 14 00ANNEHMEN04 00ACK02 03 3b 01 0a · 02 02 31 01HÖRER ein (Freisprechen) · CONNECTEDGespräch, 4 s01 02 13 00AUFLEGEN04 00ACK02 05 32 … · 02 05 39 … · 02 03 3a 01 0aDISCONNECTED · RELEASED · HÖRER aus
Vom PC gesteuert: anmelden, annehmen, auflegen. Am Gerät erprobt (2026-10-01, logs/test_20261001_085744_annehmen_auflegen.log).

Abgehender Anruf, vom PC gewählt

PC / DaemonErgoLine D340Handlung am Telefon01 02 11 00BELEGEN (nur im Ruhezustand)04 00ACK02 03 3b 01 0aFACILITY_EIN · HÖRER (kein DIALTONE!)01 13 19 00 98 70 0e 81 30 31 …WAHL „01“ + 0170000000004 00ACK (nach 360 ms)02 12 19 01 98 70 0d 30 31 …MORE_INFO · Ziel bestätigt02 02 3e 01PROCEEDINGGegenseite nimmt an02 02 31 01CONNECTED02 03 3b 01 30FACILITY_EIN · DTMFGespräch01 02 13 00AUFLEGEN04 00ACK3a…30 · 32 · 39 · 3a…0aDTMF aus · DISCONNECTED · RELEASED · HÖRER aus
Vom PC gesteuert: belegen, wählen, auflegen. Am Gerät erprobt (2026-10-01, logs/test_20261001_150042_waehlen_extern.log). Nach dem Belegen meldet das Telefon nur „Hörer ab“, keinen Wählton; der Anruf entsteht erst mit MORE_INFO.

08Zustandsautomat und SIP

30 RINGING31 CONNECTED36 DIALTONE19 MORE_INFO3e PROCEEDING31 CONNECTED32 DISCONNECTED39 RELEASEDauch direkt aus KLINGELT, WÄHLTON, WAHL, RUFTAuftrag 14 annehmenAuftrag 11 belegenAuftrag 19 wählenAuftrag 13 auflegenRUHEKLINGELTWÄHLTONWAHLRUFTVERBUNDENAUSGELÖST
Zustände eines Anrufs aus Sicht des Daemons. Schwarze Pfeile sind Meldungen des Telefons, farbige Beschriftungen die Aufträge, mit denen der Daemon den Übergang auslöst.

So führt der Originaltreiber die Zustände Treiber

Die Rahmen tragen keine Anrufkennung; das Byte „Leitung“ ist immer 01. Der Philips-Treiber führt deshalb selbst eine Anruftabelle (31 Plätze) und ordnet jede Meldung dem Anruf zu, der gerade in einem passenden Zustand ist. Die Zustände sind die TAPI-Werte LINECALLSTATE_*; im Diagramm oben: RUHE = IDLE, KLINGELT = OFFERING, WÄHLTON = DIALTONE, WAHL = DIALING, RUFT = PROCEEDING/RINGBACK, VERBUNDEN = CONNECTED, AUSGELÖST = DISCONNECTED.

Je Meldung setzt der Parser einen Ereigniscode, eine Übergangstabelle (0x100069eb) bildet „alter Zustand × Code“ auf den neuen Zustand ab, eine zweite Funktion (0x1000b70b) setzt den Modus (Wählton-Art, Besetzt-Art, Auslöseursache als LINEDISCONNECTMODE).

Zustanderlaubte Übergänge (zusätzlich immer: Auslösung → DISCONNECTED)
neuAngebot → OFFERING · Wählton → DIALTONE · weitere Codes setzen den Zustand direkt
OFFERINGAccept → ACCEPTED → CONNECTED (bei Annahme: erst Accept, dann Connect)
DIALTONEWahl → DIALING
DIALINGProceeding → PROCEEDING · besetzt → BUSY
PROCEEDINGRingback → RINGBACK (folgt unmittelbar) · besetzt → BUSY · Konferenz → CONFERENCED
RINGBACK, BUSYConnect → CONNECTED
CONNECTEDHalten → ONHOLD · Halten für Übergabe → ONHOLDPENDTRANSFER · Halten für Konferenz → ONHOLDPENDCONF · Konferenz → CONFERENCED
ONHOLD, ONHOLDPENDTRANSFERConnect → CONNECTED
DISCONNECTEDFreigabe (RELEASED) → IDLE, Platz in der Tabelle wird frei

Wann der Treiber einen Auftrag senden darf Treiber

Für einen Daemon heißt das: eine eigene Anruftabelle führen, jede Meldung über den aktuellen Zustand zuordnen, Aufträge nur bei erfüllter Vorbedingung senden und Modus bzw. Ursache mitführen (für SIP-Statuscodes und Statistik).

EreignisDaemon tutSIP-Seite
30 RINGING mit NummerNummer normalisieren (Amtsholung weg), Anruf anlegenINVITE, From = Anrufernummer
SIP 200 OK vom SoftphoneAuftrag Annehmen 01 02 14 00, Audio durchschaltenACK
INVITE vom SoftphoneBelegen 01 02 11 00, dann Wählen (Amtsholung davor bei extern)100 Trying
3e PROCEEDING–180 Ringing
31 CONNECTEDAudio durchschalten200 OK (abgehend)
BYE vom SoftphoneAuftrag Auflegen 01 02 13 00200 OK
32 DISCONNECTEDAudio trennenBYE, bzw. CANCEL, solange noch nicht verbunden
39 RELEASEDAnruf löschen, zurück in Ruhe–
3b/3a … 0a Hörer ab/aufnur Anzeige (Mensch am Telefon)optional Presence/BLF

09Einen Daemon bauen

Aufbau, der sich im Test bewährt hat (Referenz: gateway/ergoline/ im Repository, Python 3 + pyserial):

from ergoline.link import ErgoLink
from ergoline import protocol as p

with ErgoLink("/dev/serial/by-id/usb-FTDI_…-if00-port0") as link:
    q = link.sende(p.anmelden())                 # erwartet Klasse 04
    while True:
        zeit, r = link.rahmen.get()
        if r.klasse != p.MELDUNG:
            continue
        typ = p.MELDUNGSTYP.get(r.typ)
        if typ == "RINGING":
            ie = dict(p.ies(r.daten[2:]))
            extern, nummer = p.extern(p.rufnummer(ie[0x6C]))
            sip_invite(von=nummer)               # eigener SIP-Stack, z. B. baresip ctrl_tcp
        elif typ == "DISCONNECTED":
            sip_bye()

def sip_angenommen():   link.sende(p.annehmen())
def sip_beendet():      link.sende(p.auflegen())
def sip_waehlen(nr):    link.sende(p.belegen()); link.sende(p.waehlen(nr))

Werkzeug zum Ausprobieren: tools/ergo.py decode|listen|anmelden|keepalive; gesprächsrelevante Aufträge nur mit --freigabe.

10Initialisierung im Originaltreiber

Der Philips-Treiber durchläuft beim Öffnen zusätzlich einen Service-Modus mit 9600 Baud. Für den Betrieb ist das vermutlich nicht nötig vermutet; die Folge ist hier nur zur Vollständigkeit festgehalten. Treiber

  1. Port öffnen (9600), Escape 02 02 0A 00, 500 ms Pause.
  2. 9600 8N1, Probe 05 88 00 89, 2 s auf Quittung; sonst 9600 8O1 und Escape wiederholen.
  3. Versionsabfrage: 05 B0 00 B0 → Quittung („ATS-Mode“, Textzeilen) → RQV:0\r → Quittung → RQQ:1\r → Einzelbyte 02. Die Antwort kommt als Textzeile.
  4. Umschalten auf 1200 8O1 mit Xon/Xoff, dann Anmelden 01 02 01 00 (5 s auf Quittung).

Ein Hayes-AT-Protokoll gibt es an dieser Buchse nicht. Der ältere Octophon-Treiber (AT$CAL …) gehört zu einem anderen Gerät bzw. einer anderen Firmware und ist inkompatibel.

11Sicherheit

Die Anlage ist nicht rücksetzbar, eine gesperrte Nebenstelle ließe sich nicht selbst reparieren. Deshalb: nur dokumentierte Aufträge senden, nichts raten; Wählen nur zu bekannten Testnummern; am Telefon nie das Service-Menü (set TEI, reset data) und nie die Wartungscodes 31–34 benutzen, die den Speicher löschen.

12Offene Fragen

  1. Inhalt der Bereitmeldung 01 (01 02 00): ändert er sich je nach Zustand des Telefons?
  2. Nachwahl im Gespräch: hört die Gegenseite DTMF-Töne?
  3. Stören Xon/Xoff, da 11/13 auch Auftragstypen sind?
  4. Bedeutung von 98 und der Aufträge 15, 18, 1b–24, 27.
  5. Meldet das Telefon Ereignisse auch nach einem Neustart ohne vorherige Eingabe?
  6. Warum wird DIALTONE nach 10 s wiederholt?
  7. Sprachweg über „Sprache über Zusatzgerät“: Pegel und Echo an X_IN/X_OUT.

13Quellen