]> Matthias Wimmer (溫雅石)

GSM-Modem SIM900 und GsmMuxd

Tagged as DE · gsm

Written on

Diese Woche habe ich an einer spannenden Aufgabenstellung gearbeitet: ich musste die Firmware für ein Gerät zur Datenerfassung und zum Monitoring an ein neues zukünftig darin verbautes GSM-Modem anpassen.

Bisher wurde darin hauptsächlich das Modem SIM300 von SIMcom eingesetzt, mit der Anpassung soll auch das Nachfolgemodell SIM900 unterstützt werden, da das Vorgängermodell nicht mehr produziert wird.

Hardwaretechnisch war die Umstellung kein Problem. Das neue Modem konnte einfach anstatt des bisherigen eingebaut werden. Jedoch konnte die bestehende Firmware dem neuen Modem nicht viel entlocken. In unserem eigenen Logfile konnte ich nur einige Einträge finden, dass das Modem nicht reagieren würde.

Die Arbeit der Anpassung begannt mit dem Studium der Hinweise des Herstellers was sich im neuen Modem inkompatibel geändert habe. Hier wurde ich auch in bei ein paar AT-Kommandos fündig, die Anpassungen haben wollten. Mit den neuen Init-Skripten für das Modem meldete die Firmware nun immerhin schon, dass ein Modem gefunden wurde. – Ein schönes Zeichen, immerhin war damit schon mal bestätigt, dass hardwaretechnisch das Modem tatsächlich als Replacement dienen konnte. Der Rest, der nicht tat war Software und die lässt sich leichter anpassen.

Ich machte mich nun an die Arbeit die Kommunikation der Firmware mit dem Modem näher zu analysieren und stellte fest, dass die Probleme in der Implementierung des Protokolles 3GPP TS 07.10 liegen. Dieses Protokoll ist dafür zuständig mehrere virtuelle serielle Verbindungen über eine physikalische Verbindung zu übertragen. Dies ermöglicht es, dass das GSM-Modem nur über einen Seriellport angeschlossen wird, aber gleichzeitig per PPP auf einer virtuellen Verbindung ein Zugang zum Internet hergestellt wird während auf einer anderen virtuellen Verbindung noch immer beispielsweise AT-Kommandos zum Versand von SMS oder zur Abfrage der GSM-Signalstärke gemacht werden können. Für dieses Protokoll benutzen wir eine angepasste Version des Open-Source-Programmes GsmMuxd.

Etwas nach SIM900 und GsmMuxd gegooglt zeigte auch, dass es schon ein paar andere Entwickler gab, die anscheinend vor dem gleichen Problem standen. Allerdings hatte auf keiner der Seiten jemand davon berichtet, dass er das Problem lösen konnte, geschweige denn wie er das getan habe. Ich war also mal wieder auf meine eigenen Analysefähigkeiten angewiesen.

Ich habe mir ein paar Frames mitprotokolliert und anhand der Protokollspezifikation nachvollzogen. Sah soweit alles gut aus, die Frames waren gültig. Trotzdem verwarf GsmMuxd alle empfangenen Frames als ungültig:

if ((*data & 1) == 0) {
    /* Current spec (version 7.1.0) states these kind of frames to be invalid
     * Long lost of sync might be caused if we would expect a long
     * frame because of an error in length field.
    INC_BUF_POINTER(buf,data);
    frame->data_length += (*data*128);
    fcs = r_crctable[fcs^*data];
    length_needed++;
    */
    free(frame);
    buf->readp = data;
    buf->flag_found = 0;
    return gsm0710_buffer_get_frame(buf);
}

In diesem Stück Code in der Methode gsm0710_buffer_get_frame() in buffer.c wird das niederwertigste Bit in der Längenfeld des Frames geprüft. Dieses Feld kann ein oder zwei Byte lang sein und dieses Bit steuert eben genau die Länge des Feldes. Der bestehende Code von GsmMuxd erlaubt dabei nur eine Längenangabe mit einem Byte was einer maximalen Framelänge von 127 Bytes entspricht.
Im Gegensatz zum bisherigen SIM300-Modem überträgt das SIM900-Modem die Framelänge jedoch immer in 2 Bytes, auch wenn sie in einem Byte hätte dargestellt werden können.

Interessant in diesem Zusammenhang ist, dass im GsmMuxd der Code für die Dekodierung des zweiten Bytes bereits enthalten aber auskommentiert ist. Im Kommentar steht dazu, dass laut Version 7.1.0 der Spezifikation eine solche Längenangabe ungültig sei. Ich habe sowohl diese Version der Spezifikation wie auch die aktuelle eingehend danach untersucht, aber nichts gefunden was meiner Ansicht nach diese Annahme stützt. Vielmehr ist festgelegt, dass ein Frame nicht länger als „N1“ sein darf. Dies ist ein Wert, der optional von der Software beim Umschalten in den Multiplexmodus an das Modem übergeben wird. Wird dieser Wert nicht explizit übergeben, so gilt ein Defaultwert von 64. Da GsmMuxd nie einen expliziten Wert für „N1“ an das Modem übergibt, gilt also hier dieser Defaultwert. In der Tat ließe sich also die Framelänge immer in einem Byte übertragen. Aber es gibt keine Notwendigkeit dies auch zu tun. Ich denke, es ist deswegen sinnvoller erst auch ein zweites Byte der Längenangabe zu akzeptieren und danach die ermittelte Framelänge zu überprüfen:

if ((*data & 1) == 0) {
    /* Current spec (version 7.1.0) states these kind of frames to be invalid
     * Long lost of sync might be caused if we would expect a long
     * frame because of an error in length field.
     *
     * => I can't find this in the spec (either 7.1.0 or 7.2.0)
     * but we may check the length against N1. As we do not pass
     * N1 in the AT+CMUX command, we have the default which is 64.
     * (Matthias Wimmer, 20130207)
     */
    INC_BUF_POINTER(buf,data);
    frame->data_length += (*data*128);
    fcs = r_crctable[fcs^*data];
    length_needed++;
}
if (frame->data_length > 64) {
    free(frame);
    buf->readp = data;
    buf->flag_found = 0;
    return gsm0710_buffer_get_frame(buf);
}

Mit dieser Änderung war dann die Kompatibilität zum neuen Modem erreicht und ich um einen GSM/UMTS/…-Standard reicher, den ich gelesen habe.

Nachtrag 30. April 2013 15:12

Die letzten Tage habe ich ein Problem mit der Interneteinwahl und dem Modem festgestellt. Konkret konnte ich per PPP eine Verbindung zum Internet herstellen und darüber IP-Pakete verschicken. Ich habe jedoch nie ankommende IP-Pakete erhalten.

Beim Debugging bin ich auf das Problem gestoßen, dass das SIM900-Modem (und zwei andere getestete Modemes auch) entgegen dem Standard Frames mit einer Länge größer N1 geschickt hat. Diese werden durch den obigen Code (weiterhin) gedropped.

Es scheint mir, dass das SIM900 beim Senden der Frames N1 überhaupt nicht berücksichtigt. Bei einer üblichen MTU von 1500 Byte und einem PPP-Overhead von 6 Byte heißt das, dass Frames bis zu einer Länge von 1506 Bytes (anstatt der oben stehenden 64 Byte) akzeptiert werden sollten.


Unless otherwise credited all material Creative Commons License by Matthias Wimmer