netzstaub

beatz & funkz

Friday, March 25, 2005

Sturm

Nach dem RFSID-Posting ging’s hier ein bisschen rund. Aber der beste Trackback ist wohl der von diesem entweder verwirrten oder verarschenden Menschen: Hacker verbreiten Musik über RFID-Sicherheitslücke

posted by manuel at 5:25 pm  

Friday, March 25, 2005

iPod-surgery

I was a pretty early user of the ipod, and have used a first-generation ipod for quite a long while. As I am pretty rough when it comes to hardware, I had to change my first model eight times (!), each time getting a refurbished one which would die a few weeks later. Finally, I switched to a touch-wheel iPod, but pretty soon it fell down on the ground. During the fall, a few sectors of the hard-disk went bad, which would not be really troublesome normally. However, the sectors were destroyed in such a way that even only trying to read them would lock the ipod up. As it seems, it would lock it up at a very low-level, as even the BIOS hard-disk check locked up. Using the iPod in firewire Harddisk mode yielded no better results. However, I came up with a very dirty and low-level hack to make it work again…

(more…)

posted by manuel at 5:20 pm  

Sunday, March 20, 2005

RFSID – play C64 SIDs with an RFID reader

Dividuum, my flat-mate, has built a very cool RFID application. He stores SID-files (SID is the music format for the C64) on RFID tags. When you put such a tag near to the reader, the music is played on the stereo. He got a RFID reader (ID ISC.PR100) which you can connect to your PC through USB, and has written a library in C to control it. The C library has a very simple interface: it searches for the USB device using libusb, and the application using the library can then send vendor requests to the device (vendor requests are “USB ioctls on speed”). The whole functionality of the device can be called using these vendor requests. The C library is used by a Ruby wrapper which has methods for all the commands of the reader. You can read and write the configuration data of the reader, control the LED, write its EEPROM, and, of course, read and write RFID tags, all of this using the OO system of Ruby.

(more…)

posted by manuel at 9:22 pm  

Sunday, March 20, 2005

Process Watch

Dividuum war diese Woche ganz schön fleissig, und ich werde hier mal kurz über die Software bloggen die er geschrieben hat. Wir wollten demnächst die Welt mit unser Streaming-Software übernehmen. Doch dazu braucht man auch Software, die den Zustand der ganzen Tools, die für erfolgreiches Streaming notwendig sind, überwacht. Wie überwacht man am besten Encoder, HTTP-Server, Mitschneide-Prozesse, Umkodiersoftware, usw…? Am Besten mit eigener Process-Watch Software, den anderen Lösungen ist ja nicht zu trauen. Klar, es gibt schon init-Skripte. Doch wer will sowas hässliches schreiben wie start-stop-daemon zu verwenden? Und wie prüft man nachher nach, das die Software auch läuft? Integrieren von Pipe-basierten Shellskripten ist da auch nicht wirklich einfach. Genauso ist es mit supervise von djb z.B. Da ist die User-Schnittstelle ganz schön anstrengend, selbst die Logs kann man nicht als Mensch parsen.

Die Software von Dividuum heisst “Process-Watch”, abgekürzt “pw.rb”, und ist natürlich in Ruby geschrieben. Sie liest ein Config-File in YAML ein, und verwendet den Webserver Webrick zur Darstellung des Prozess-status. Die Software ist in unserem Subversion Repository unter svn://bl0rg.net/pw/ zu finden. Zuerst eine kleine Übersicht von YAML.

YAML

YAML heisst YAML Ain’t Markup Language, und ist so eine Art Sprache, die man benutzen kann, um Daten zu serialisieren. Im Gegensatz zu XML, mit der YAML oft verglichen wird, ist das explizite Ziel von YAML auch noch von Menschen lesbar und editierbar zu sein. Dazu verwendet YAML eine Mischung von speziellen Zeichen und Indentierung. Weiterhin kann man YAML auch in einem Stream-Context verwenden. Wenn man also nur eine Kommunikationspipe hat, kann man darüber mit YAML getrennte Dokumente übermitteln. In dem Fall von Process-Watch werden nur die “einfachen” Features von YAML unterstützt. Eine Beispielskonfigurationsdatei sieht so aus:

Sleeper:
    command: sleep 5

Test:
    command: sleep 10
    graceTime: 2
    
Top:
    command: top 1>&2
    graceTime: 3
    activateOnStartup: false

Diese Konfigurationsdatei lässt sich ungefähr so lesen: Es gibt 3 Knoten in der Datei. Die Knoten heissen “Sleeper”, “Test” und “Top”, und sind Kommandos, die Process-Watch überwachen soll. Jeder Knoten ist ein Mapping, d.h. z.B. eine Hashtabelle. Der Key “command” ist jeweils das Kommando, das ausgeführt werden muss. Der Parameter “graceTime” ist dazu da, einem Prozess bevor er gekillt wird ein bisschen Zeit zu geben. Ein Prozess wird gekillt, wenn in der Steueroberfläche ein Stop-Kommando abgesetzt wird, oder Process-Watch allgemein gestoppt wird. Der Parameter “activateOnStartup” ist dazu da, um ein Prozess nicht gleich beim Starten von Process-Watch zu starten. Wie man sehen kann, sind die “command”-Parameter vollwertige Shellkommandos, mit Pipes, usw… Daher kann man z.B. Programme wie unseren FEC-Streamclient gleich mit mpg123 über Process-Watch starten:

poc:
    command: ~/progs/poc/pob-fec | mpg123 -
    maxLogItems: 30
    graceTime: 5

Hier sieht man auch gleich an dem “maxLogItems”-Parameter, dass Process-Watch nicht nur Programme ausführen kann, sondern auch ihre Ausgaben mitloggen kann, und über die Kontrollschnittstelle anzeigen kann.

Process-Watch im Einsatz

Ganz “user”-friendly ist Process-Watch noch nicht, und im Moment ist der Name der Konfigurationsdatei (“config.yaml”) noch fest verdrahtet. Wenn man jetzt Process-Watch mit der obigen Datei startet, bekommt man folgende Konfigurationsoberfläche auf dem Port 8080:

Pw1-1

Mit “start” und “stop” kann man hier die Programme starten und stoppen, mit “log” kann man den Output des Programms einsehen. Unten kann man auch noch die Konfiguration neuladen (wenn man z.B. neue Programme eingefügt hat). Process-Watch geht dabei recht klever vor, indem es nicht nur die Konfiguration dumm neulädt, sondern erkennt, welche Programme dazu gekommen sind, und welche gekillt werden müssen, und bei welchen sich die Parameter geändert haben.

Process-Watch Internals

Intern ist Process-Watch recht klar aufgebaut. Es gibt ein Master-Objekt, dass die laufenden Prozesse kontrolliert, und auch Anfragen von dem Webserver abarbeitet. Für die einzeln gestartete Prozess sind “WatchProcess”-Objekte zuständig. Das Hauptprogramm (die “main”-Routine, sozusagen) instanziiert ein “Master”-Objekt, einen HTTP Server, und biegt das “INT” Signal um, um Process-Watch sauber zu stoppen. Nachdem der Webserver instanziiert wurde, wird für die Url “/” ein Handler angegeben, der die Anfrage an das Master-Objekt weiterleitet, indem es bei ihm die Methode “statusRequest” aufruft. Anschliessend wird der Webserver-thread gestartet, und alle 0.5 Sekunden wird dann der Master gepollt. Bei diesem Schritt überprüft er dass jeder Prozess richtig läuft, usw… Hier dieses Hauptprogramm:

done = false

trap("INT") do 
    done = true
end

master = Master.new("config.yaml")
http   = WEBrick::HTTPServer.new(:Port => 8080)

http.mount_proc("/") do |req, res|
    master.statusRequest(req, res)
end

httpThread = Thread.new do 
    http.start
end

until done do
    master.iteration
    sleep 0.5
end

http.shutdown 
httpThread.join
master.activateNewConfig({})

Wie man sieht, wird hier die “eigentliche” Arbeit in der Methode “iteration” von dem Masterobjekt gemacht. Diese Routine sieht wie folgt aus:

    def iteration
        @masterMutex.synchronize do 
            fdlist = {}
            @processes.values.each do |process|
                fdlist[process.stderr] = process if process.stderr
            end
            readable, _, _ = *IO.select(fdlist.keys, nil, nil, 0)
            if readable
                readable.each do |fd| 
                    fdlist[fd].onStderrReadable
                end
            end
            
            collectDeadChilds
            checkProcessConfig
        end
    end

Process-Watch benutzt 2 Threads (der Master-thread, und der Webserver-thread), und deswegen wird zur Synchronisation hier in “iteration” das Mastermutex reserviert. Innerhalb des Mutex geht dann der Masterprozesse alle gestarteten Prozesse durch (die in dem Array “@processes” gespeichert sind), und checkt, ob bei einem Prozess was von Stderr gelesen werden kann. Ist dies der Fall, dann stehen Daten für das Log bereit, und die Methode “onStderrReadable” wird bei dem “WatchProcess” Objekt aufgerufen. Nachdem die Logfiles aller gestarteten Prozesse aufgefrischt wurden, wird in der Method “collectDeadChilds” nachgeguckt, welche Subprozesse gestorben sind, und sammelt ihre Leichen auf. Schliesslich wird verifiziert, ob die Konfiguration neugeladen werden muss, was durch die “checkProcessConfig” Methode erledigt wird. Bei dem ersten Ausführen von “iteration” ist noch gar keine Konfiguration geladen worden, so dass diese Methode auf jedem Fall aufgerufen wird.

“checkProcessConfig” tut nichts anderes, als die YAML Konfigurationsdatei zu laden, und nachher “activateNewConfig” aufzurufen, die sich darum kümmert, die neuen Prozesse zu erkennen, die nicht-mehr existierenden zu identifizieren, und die modifizierten Parameter der gleich-bleibenden Prozesse zu übernehmen. Der YAML-Reader benutzt die YAML-Library für Ruby, und ist verheerend einfach 🙂

def readYaml(file)
    begin 
        cfgfile = File.open(file)
        config  = YAML::load(cfgfile.read)
    rescue SystemCallError => e
        puts "error while reading configuration file #{file}: #{e}"
    rescue ArgumentError => e
        puts "error while parsing configuration file #{file}: #{e}"
    ensure
        cfgfile.close
    end
    config
end

def checkProcessConfig(reload = @mustReload)
    return unless reload
    @mustReload = false

    config = readYaml(@config)
    unless config
        log "could not read configuration"
        return false
    end
    activateNewConfig(config)
end

Die neuen und alten Prozesse werden über ihren Namen identifiziert, also die Keys vom ersten Mapping in der YAML-Datei. Für jeden neuen Prozess wird ein neues “WatchProcess” Objekt instanziiert, was sich dann auch darum kümmert, zu Forken und den neuen Prozess auszuführen (und auch Stderr umzuleiten, damit die Nachrichten, die darüber kommen mitloggen zu können). Das ganze Unix-Handling ist ziemlich ekelhaft, und ich werde hier nicht näher drauf eingehen. Vermerken, dass Unix wirklich stinkt, muss ich allerdings schon.

posted by manuel at 6:19 pm  

Sunday, March 20, 2005

Usb Host-Entwicklung

Ich durfte in den letzten Tagen eine USB-Host-Applikation entwickeln. Dazu wurde ein EZ-OTG Kontroller von Cypress eingesetzt. Fürs erste keinen Code, weil der nicht mir gehört.

Der EZ-OTG Kontroller

Der EZ-OTG ist ein kleiner, netter USB-OTG Kontroller. OTG heisst “On-The-Go”, und bezeichnet die Fähigkeit, sowohl USB-Host als auch USB-Device zu sein. Der EZ-OTG kann also im Betrieb seine Funktion wechseln. Der Chip verfügt über 2 sogenannte SIE (Serial Interface Engine), die beide Host oder Device sein können. Nur die erste SIE kann allerdings OTG. Der EZ-OTG ist allerdings nicht nur ein “stumpfer” Kontroller, sondern hat eine eigene 16-Bit CPU, für die man auch Programmcode nachladen kann. Man kann den EZ-OTG also in zwei verschiedenen Modi fahren: in dem einen “Slave”-Modus wird der EZ-OTG praktisch als Kontroller eingesetzt, in dem “Standalone”-Modus ist er CPU und Kontroller zugleich. In beiden Fällen kann man den “BIOS” des EZ-OTG verwenden. Der BIOS besteht aus 8 kB Assembler Code, der sich über Interrupts ansprechen lässt (ganz wie der alte PC-Bios). Er übernimmt schon die meiste Hardware-Funktionalität (z.B. UART Handling), man kann aber jederzeit die Interrupt-Einträge des BIOS überschreibe, um seinen eigenen Code da reinzufrimeln.

In dem Standalone Modus kann der Kontroller Code aus einem EEPROM laden, oder z.B. über USB laden (wie die anderen USB-Device Kontroller von Cypress, dem EZ-FX und EZ-FX2). In dem Slave Modus bietet der Cypress verschiedene Schnittstellen an, über die die eigentliche CPU mit dem LCP Protokoll Kommandos an den Cypress absetzen kann (z.B. BIOS Funktionen aufrufen, oder im RAM rumschreiben). In dem Fall meiner Applikation habe ich den Standalone-Modus verwendet.

Die Entwicklungsumgebung

Das Entwicklungsboard von Cypress zu dem EZ-OTG hat einen EZ-OTG, 4 EEPROMS, eine ganze Reihe an Pins zum Anschliessen von Hardware an den Kontroller, ein paar Taster, ein LED-Display, und 2 SIE-Schnittstellen. An jeder SIE Schnittstelle kann man 2 USB-Devices anschliessen, oder einen USB-Host. Die erste SIE wird standardmässig zum Debuggen verwendet, der BIOS lässt da normalerweise Code laufen, mit dem der GDB dann die CPU steuern kann (so eine Art JTAG für Arme). Die zweite SIE kann man dann frei verwenden.

Software-mässig liefert Cypress eine Cygwin-Umgebung mit Crosscompiler Toolchain für die 16-Bit CPU auf dem EZ-OTG (mal sehen, ob ich irgendwo den Source dazu finde, unter Linux entwickeln wär schick0r). Zum Debuggen kommt ein GDB mit einer anstrengenden Tk-Oberfläche (namens Insight), die über TCP mit einer Zwischensoftware kommuniziert, die dann USB-Kommandos an den Cypress absetzt. Bei dem Entwicklungsboard liegt auch ein Buch bei, das “Developing Multi-Role USB Applications” heisst, von John Hyde, der auch ein Buch über USB-Entwicklung geschrieben hat. Dieses Buch beschreibt, wie man mit dem EZ-Host (der grosse Bruder des EZ-OTGs) und dem EZ-OTG Applikationen baut. Das in einer ziemlich angenehmen Hands-On Art. Ich steh ja normalerweise nicht wirklich auf Bücher, die an eine spezielle Technologie gebunden sind, aber in dem Fall war es recht angenehm. In einem Kapitel stellt er kurz vor, wie man die LEDs blinken lässt (also eher ein Tutorial, wie man überhaupt den GCC und den GDB und so verwendet), wie man ein kleines HID-Device baut, dass die Tastendrücke als Tastatur weiterleitet. Dann kommt ein Kapitel über Host-Entwicklung, in der gerade diese HID-Device jetzt als Host kontrolliert wird. Zu den ganzen Applikationen haben Hyde und seine Kumpanen einen riesigen Framework gebaut, der sage und schreibe 20000 Zeilen Code umfasst. Die Host-Applikation ist dadurch, trotz extensiver Unterstützung durch den BIOS immerhin 16 kB gross (!).

Ich muss jetzt wirklich ein bisschen rumlästern. Den dieses Framework wär ja vielleicht noch ganz nett, wenn es a) gut dokumentiert wäre, und b), noch viel wichtiger, keine groben Bugs beinhalten würde. Scheinbar haben Cypress und Hyde den Code aber nie “wirklich” verwendet, denn es ist z.B. unmöglich, in der Form ein dual-Host Device zu schreiben, oder BULK-Transfers sauber zu machen. In dem ersten Fall hat ein scheinbar dummer Fehler beim Copy/Paste Code die Auswirkung, dass ein zweites Gerät nicht erkannt wird, und dafür den Zustand des ersten kaputt-schreibt. Bei BULK-Transfers resettet ein Lesen immer das Data-Toggle-bit vom Schreiben, so dass die DATA0 und DATA1-Pakete Abwechslung, die bei USB notwendig ist, nicht mehr passiert. Ich finde das wirklich sehr peinlich, und es gingen ein paar Stunden aufgeregtes Debuggen drauf, diese Fehler zu finden. Der GDB, der für jeden Singlestep 5 Sekunden braucht, ist da auch keine wirklich Hilfe. Ich musste ziemlich schnell auf das alt-bewährte Mittel des printf-Debuggings zurückgreifen.

Ich frage mich also, wieso Cypress mit dem EZ-OTG und EZ-Host dieses Framework vertreibt (man kann natürlich ohne programmieren, dafür gibt es aber keine Application Notes). Viel schöner wäre es doch gewesen, kleine Standalone-Applikationen zu bauen, die zwar dann komplizierter zu verstehen sind, weil sie das ganze Host-Handling selber machen. Dafür aber kein 16 kB-grosses Code-Monstrum mit sich schleppen (mit, achtung, dynamischer Speicheralloziierung, verketteten Listen in jede Richtung, einer Treiber-Infrastruktur, und was weiss ich noch alles geile). Nun gut, vielleicht werde ich da noch was schönes schreiben, wenn ich an die passende Hardware komme. In dem Umfeld wäre es auch denke ich ganz schick, Protothreads zu verwenden, anstatt riesige Callback-basierte State-Machines zu verwenden, wie es im Moment der Fall ist.

posted by manuel at 3:44 pm  

Sunday, March 20, 2005

Fanless Gentoo-Router with read-only CF-root-fs

Our Internet-Router for the last 2 months was a mini-Desktop Gentoo-PC with a conventional harddisk. In the process of minimizing our energy costs and reducing the noise in the kitchen, where our router is hidden away in a cupboard, we bought a NEO-LX barebone PC. The NEO-LX barebone has a 1Ghz VIA Eden Nehemiah processor, and is completely fanless. It comes in a solid black metal housing, with a fantastic design. You can add a 2.5″ IDE-Disk if you want, but we chose to put the whole system on a CF-Card. Our setup is quite hackish, but it works.

(more…)

posted by manuel at 3:17 pm  

Thursday, March 17, 2005

USB Kotzen

Den groessten Teil des heutigen Tages mit vergammelter Software der untersten Schicht verbracht. Ich frage mich, was ich ohne USB Analyzer geworden waere. Jedenfalls funktionniert jetzt alles, und in den naechsten Tagen gibt es hier dann ein USB-Host-Entwicklungsspezial mit ganz vielen Details, die nach Aas und Leiche riechen. Jaja.

posted by manuel at 12:16 am  

Tuesday, March 15, 2005

Link

A general purpose macrogenerator by Strachey. Mmmmhhh, string substitution… That’s all for today.

posted by manuel at 11:56 pm  

Tuesday, March 15, 2005

New quickhoney site

Hans has programmed a very nice JavaScript based website for quickhoney. The backend uses BKNR, and runs under FreeBSD with CMUCL 19a, and its complete sourcecode can be found in the BKNR subversion repository. I spent most of the morning browsing through the amazing images there 🙂

posted by manuel at 4:21 pm  

Tuesday, March 15, 2005

Name collision

It seems ParenScript is already used as a project name :/ I’ll have to come up with another thing, then…

posted by manuel at 4:09 pm  
Next Page »

Powered by WordPress