Motorola Milestone / Droid and 802.11n Access Points

At UX Camp Europe 2010, my Motorola Milestone could not connect to the barcamp wifi, a WPA2/PSK WLAN running on a mesh of Enterasys APs. The phone would not even manage to associate to the AP, the debug log (adb logcat) showing the following:

E/wpa_supplicant( 3892): ERROR - \
    wpa_driver_tista_private_send - error sending \
    Wext private IOCTL to STA driver \
    (ioctl_cmd = 8021501,  res = -1, errno = 95)
E/wpa_supplicant( 3892): ERROR - Failed to do tista scan!
W/wpa_supplicant( 3892): Failed to initiate AP scan.

So there was never a visible attempt at connecting in the UI.

After a lot of searching, reading source, asking around and debugging, I managed to solve my problem by modifying the configuration of the WLAN driver module (tiwlan.ini) as follows (requires the Android SDK / adb and root access on your phone, or a adb-root recovery partition):

No warranty if you brick your phone, if you don’t feel confident doing this, have someone with Android expertise do it for you or wait for a fix from Motorola. Or try disabling 802.11n (draft-n) in your AP if you can control it.

  1. Connect your phone via USB, make sure you enable USB debugging in Settings > Applications > Development.
  2. Get the configuration file from your phone:

    adb pull /system/etc/wifi/tiwlan.ini tiwlan.ini

  3. Change HT_Enable=1 to HT_Enable=0 in the file.

    sed -i -e s/HT_Enable=1/HT_Enable=0/ tiwlan.ini

  4. Push the changed file back onto your phone (you can’t directly overwrite the file in /system/etc/wifi/ because adb is not running as root on the phone):

    adb push tiwlan.ini /tmp/tiwlan.ini

  5. Start an adb shell on your phone, get root, make /system writable and move the file to the right location:

    adb shell
    su
    mount -o remount,rw -t yaffs2 /dev/block/mtdblock6 /system
    cp -f /tmp/tiwlan.ini /system/etc/wifi/

  6. Reboot your phone

    reboot

Your phone should now be able to associate with the AP.

People have reported similar problems with APs by other manufacturers (Enterasys, D-Link, some old Linksys WRT), so this might work for you.

Rewriting Favcharts – Part 1

Um in Form zu bleiben, widme ich möglichst jeden Tag 30-90 Minuten Nebenprojekten.

Diese Woche baue ich die favcharts neu. Die momentante Implementation der favcharts ist ein Haufen von “Hacks upon hacks”, weil die Charts aus einem Satz hastig programmierter Scripte und viel Zeitdruck entstanden sind. Es funktioniert irgendwie, aber so richtig super ist es nicht. Ein Rewrite ist schon seit einiger Zeit überfällig, jetzt ist es soweit.

Kurz zu den aktuellen favcharts: Der Code ist in PHP geschrieben, die Daten liegen in MySQL, klassischer LAMP-Stack also. Ein Crawler durchforstet regelmäßig die Favorites aller bekannten Nutzer und packt diese Daten in die Datenbank. Das Webfrontend liest aus der DB, macht Auswertungen, und speichert die Resultate dann zwischen, je nach Ansicht (täglich, monatlich, User-spezifisch, etc.) für ein paar Stunden bis mehrere Monate. Beim nächsten Zugriff wird dann nur der Cache gelesen, die Datenbank muss also nicht nochmal ran.

Soweit die Theorie. In der Praxis treten jedoch gehäuft Probleme auf: Viele Requests treffen den Cache gar nicht, weil z.B. jeder seine eigenen Charts abruft, und der User Cache dann irgendwann voll läuft und verdrängt wird. Oder es kommen Suchmaschinencrawler und fragen uralte Charts ab. Außerdem bieten die favcharts relativ viele Ansichten (verschiedene Zeiträume, verschiedene Gewichtungen, etc.), so dass die Anzahl der Cache-Einträge schnell hoch wird. Die Requests, die nicht vom Cache abgehandelt werden können, tun dann richtig weh: Je nach Scoring-Methode muss über riesige Datenmengen berechnet werden. Das kostet Zeit und I/O. Für die gewichtete Bewertung muss sogar das ganze Resultset zweimal durchlaufen werden. Dank mod_php wird dann für geraume Zeit ein Apache-Prozess blockiert und schluckt mehr und mehr Speicher und CPU, und der Rest der Apaches wird dadurch auch nicht schneller. In Stoßzeiten brauchen Requests so manchmal über zehn Sekunden. Der Crawlingprozess funktioniert dafür hervorragend – neue Favs sind oft schon nach wenigen Minuten erfasst. Das Datenbankzugriffsmuster ist allerdings eher ungesund: Gleichzeitig finden viele Writes (von den Crawlern) und viele lange Reads (vom Webfrontend) statt. Das führt zu Congestion, schlechten Indexen, und generell sehr unpraktischen Zugriffsmustern.

All das soll mit dem Rewrite besser werden. In den folgenden Posts beschreibe ich den Prozess des Rewrites, und mit welchen Ansätzen diese Probleme gelöst und in Zukunft verhindert werden sollen.

Und weil ich schon lange nichts mehr mit Ruby gemacht habe, und Rails nach wie vor “in” ist, wird die neue Version auf Ruby on Rails gebaut. Yee-haw.