Ricerca tra la vecchia roba

Onda MT505UP

Posted: Giugno 19th, 2008 | Author: | Filed under: Approfondimenti, Hack, Installation party, Life | 1 Comment »

Quello che vado a descrivere è la mia lotta per il corretto funzionamento di uno di quei dispositivi che stanno uscendo ultimamente per il collegamento internet tramite chiavetta USB; questo modello è prodotto dalla onda communication per la TIM e permette il collegamento attraverso la rete GPRS, UTMS con protocollo HSPA a internet. La caratteristica di questi prodotti è di essere del tipo "Zero CD": inseriti normalmente nel computer vengono montati come CD con all’interno i driver (per winzoz of course) da installare così da poter usare il modem internamente; benché molti buttino merda su questa scelta, personalmente penso che sia interessante visto che almeno non mi devo ricordare dove ho messo il cd di installazione.

In questa guida descriverò in maniera sommaria le avventure che ho dovuto affrontare per poter riuscire a collegarsi ad internet tramite abbonamento TIM un computer con una distribuzione Debian/lenny e mi scuso in anticipo per le bestemmie inside (ma neanche troppo). Di seguito tutti i passaggi concernenti un utilizzo pressoché immediato e che per questo interessa tutti gli aspetti che riguardano un desktop environment linux based con un pizzico di reverse engineering.

 Switching

Come detto nell’introduzione questi apparecchi hanno una doppia modalità di esistenza una volta inserite nello slot USB: appena inserite sono individuate come CDROM e in presenza di opportuni comandi si può switchare e mettere in funzione il modem interno; su linux questo può essere messo in funzione tramite usb_modeswitch, una applicazione che fa uso delle libusb e che manda certe sequenze di comandi alla periferica per ottenere l’effetto desiderato. Per la periferica in questione esistono dei codici trovati da Alex Scortegagnache però per sua stessa ammissione non funzionano perfettamente.

Quindi ecco la prima fase del lavoro: usare il prodotto sotto windows, eseguire lo switch e nel frattempo osservare con un apposito comando i codici passati alla chiavetta e riportarli nel file di configurazione di usb_modeswitch; io sinceramente winzoz non l’ho installato su nessun computer, ma viene in aiuto la tecnologia di virtualizzazione chiamata VirtualBox (esiste la versione open source che però non ha il supporto per l’USB, quindi regolatevi). I passaggi da fare sono

  • apt-get install virtualbox
  • Nel caso in cui il modulo del kernel vboxdrv non sia installato correttamente usare /etc/init.d/vboxdrv setup e nel caso di errori regolatevi.
  • Nei sistemi debian può non montarsi correttamente il filesystem USB; in tal caso bisogna cambiare i permessi del filesystem virtuale proc relativamente alle periferiche USB in maniera tale che anche l’utente comune possa usare in virtualbox: in pratica nel file /etc/init.d/mountkernfs.sh bisogna cambiare la riga
    domount usbfs usbdevfs /proc/bus/usb -onoexec,nosuid,nodev

    in


    domount usbfs usbdevfs /proc/bus/usb usbfs -onodev,noexec,nosuid,devgid=1001,devmode=664

    come nel manuale a pg 148.

  • Installare winzoz (lo sappiamo tutti che hai una coppia pirata).
  • Far partire la macchina virtuale con il sistema Microcock installato, inserire la chiavetta ed installare i driver, disinserire la chiavetta.
  • Installare sniffusb e far si che logga sulla USB con vendor=0x19d2 e product=0x2000 (in pratica selezionate la riga della periferica corrispondente, fate "install" e riavviate la macchina virtuale).
  • Rinserire la chiavetta ed attivare il modem (nel frattempo sniffusb dovrebbe loggare il tutto).
Come si sniffano pacchetti USB su winzoz (qui emulato su virtualbox).

Il fatto che avenga lo switch è fondamentale in quanto la periferica cambia dal punto di vista del bus USB in modo fondamentale: il vendor rimane 0x19d2, mentre il product id passa da 0x2000 a 0x0002! Siccome usbsnoop logga solo un tipo di periferica, siamo fortunati che la fine del log corrisponderà effettivamente con i comandi per lo switching che io vi propongo di seguito

[1021508 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1021508 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=81d36520, IRQL=2
[1021508 ms]  >>>  URB 899 going down  >>>
— URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
  PipeHandle           = 822a77dc [endpoint 0x00000007]
  TransferFlags        = 00000000 (USBD_TRANSFER_DIRECTION_OUT, ~USBD_SHORT_TRANSFER_OK)
  TransferBufferLength = 0000001f
  TransferBuffer       = 81d243e8
  TransferBufferMDL    = 00000000
    00000000: 55 53 42 43 20 65 d3 81 20 00 00 00 80 00 0a 87
    00000010: 01 01 01 18 01 01 01 01 01 00 00 00 00 00 00
  UrbLink              = 00000000
[1021510 ms] UsbSnoop – MyInternalIOCTLCompletion(b2dd2126) : fido=82059ea0, Irp=81d36520, Context=8
21c6270, IRQL=2
[1021510 ms]  <<<  URB 899 coming back  <<<
….
[ROBA TOLTA]
….
[1023513 ms]  <<<  URB 901 coming back  <<<
— URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
  PipeHandle           = 822a77bc [endpoint 0x00000087]
  TransferFlags        = 00000001 (USBD_TRANSFER_DIRECTION_IN, ~USBD_SHORT_TRANSFER_OK)
  TransferBufferLength = 00000000
  TransferBuffer       = 81d243e8
  TransferBufferMDL    = 81defda0
  UrbLink              = 00000000
[1023513 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1023513 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=821d5008, IRQL=0
[1023513 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1023513 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=821d5008, IRQL=0
[1023548 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1023548 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=821d5008, IRQL=0
[1023548 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1023548 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=821d5008, IRQL=0
[1023593 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL

[1023593 ms] UsbSnoop – FilterDispatchAny(b2dd1fd2) : IRP_MJ_INTERNAL_DEVICE_CONTROL
[1023593 ms] UsbSnoop – FdoHookDispatchInternalIoctl(b2dd21ea) : fdo=822b59b0, Irp=821d5008, IRQL=0
[1023739 ms] UsbSnoop – FilterDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_QUERY_DEVICE_RELATIONS)
[1023740 ms] UsbSnoop – FdoHookDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_QUERY_DEVICE_RELATIONS)
[1023740 ms] UsbSnoop – FilterDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_QUERY_DEVICE_RELATIONS)
[1023740 ms] UsbSnoop – FdoHookDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_QUERY_DEVICE_RELATIONS)
[1023751 ms] UsbSnoop – FilterDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_SURPRISE_REMOVAL)
[1023751 ms] UsbSnoop – FdoHookDispatchPnp(b2dd645c) : IRP_MJ_PNP (IRP_MN_SURPRISE_REMOVAL)

In pratica si cerca la stringa IRP_MN_SURPRISE_REMOVAL (che sarà l’ultima) e si cerca a ritroso fino a che si trova un messaggio con TransferBufferLength = 0000001f (un po’ lungo insomma) e si ricopia i valori all’interno del buffer e l’endpoint (può non essere il primo che trovate, provatene qualcuno). Nel nostro caso sostituiremo i valori in usb_modeswitch in maniera tale da avere

DefaultVendor=  0x19d2
DefaultProduct= 0x2000

TargetVendor=   0x19d2
TargetProduct=  0x0002

MessageEndpoint=0x07
MessageContent="555342432065d3812000000080000a87010101180101010101000000000000"

Quindi sostituiamo i valori in usb_modeswitch in maniera da ottenere

DefaultVendor=  0x19d2
DefaultProduct= 0x2000

TargetVendor=   0x19d2
TargetProduct=  0x0002

MessageEndpoint=0x07
MessageContent="555342432065d3812000000080000a87010101180101010101000000000000"

 

Modulo

All’inizio i miei tentativi sono stati di usare usbserial con i parametri vendor=0x19d2 e product=0x0002 ma purtroppo, benché il modem rispondesse, la connessione non veniva effettuata correttamente; giusto ieri mi è balenata l’idea di provare ad usare il modulo option, utilizzato per altre periferiche di questo tipo e mi sono imbattuto in una patch già nel kernel attuale dal primo maggio (almeno nel repository git) che può essere ricopiata pari pari per il nostro caso

commit 4c7d3137fe4fce634d55a6e99c95dff4c6306702
Author: andreoli@xxxxxxxxxxx <andreoli@xxxxx.xxx.xxxxx.it>
Date:   Thu May 1 19:26:16 2008 +0200

    USB: Support for the ET502HS HDSPA modem in option driver
    
    the proposed patch allows the ET502HS HDSPA modem to be handled by the
    "option" driver. It has been tested for 1 month and works reliably (no
    oopses, no hangs, 300KB/s throughput).
    
    Signed-off-by: Mauro Andreolini <andreoli at weblab dot ing dot unimo dotit>
    Signed-off-by: Matthias Urlichs <matthias at urlichs dotde>
    Signed-off-by: Greg Kroah-Hartman <gregkh at suse dotde>

diff –git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 118dfe2..f56da4c 100644
— a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -184,6 +184,9 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define AXESSTEL_VENDOR_ID                     0x1726
 #define AXESSTEL_PRODUCT_MV110H                        0x1000
 
+#define ONDA_VENDOR_ID                         0x19d2
+#define ONDA_PRODUCT_ET502HS                   0x0002
+
 #define BANDRICH_VENDOR_ID                     0x1A8D
 #define BANDRICH_PRODUCT_C100_1                        0x1002
 #define BANDRICH_PRODUCT_C100_2                        0x1003
@@ -296,6 +299,7 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
+       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },

 Vi manca solo di compilarla ed installarla e qui arriva la chicca del secolo passato, presente e futuro e blasfemo: porcodio, non seguite i consigli di chi vi dice "per compilare un modulo devi fare make -C /lib/module/`uname -r`/build M=$PWD" perché va bene per i moduli extra (tipo quello di virtualbox ma non funge lo stesso), in questo caso devi usare rispettivamente i comandi se avete i sorgenti del kernel fate accossì

$ make SUBDIRS=drivers/usb/serial/ modules
# make SUBDIRS=drivers/usb/serial/ KERNEL_RELEASE=`uname -r`  modules_install

per compilare ed installare i moduli nella directory specificata tramite SUBDIRS (sia benedetta fino alla 5a generazione quelli che scrivono queste fiche cose nella mailing list del kernel). In realtà questi comandi fungono solo se si è già compilato i moduli precedentemente, altrimenti bisogna scaricare l’albero dei sorgenti del kernel, impostare una configurazione di base (make oldconfig && make prepar) ed infine make modules. Nel caso possediate invece il sorgente patchato e gli header del kernel potete evitare qualche ora di compilazione creandovi un Makefile il cui contenuto deve essere questo

obj-$(CONFIG_USB_SERIAL_OPTION)                 += option.o

(si solo una riga) e poi nella stessa directory lanciare

$ make -C /lib/modules/`uname -r`/build M=`pwd` modules
# make -C /lib/modules/`uname -r`/build M=`pwd` modules_install

quest’ultimo ve lo installa non so dove (adesso nn ho testa di indagare) quindi copiatelo a mano porco2…

Quanto avete fatto tutto potete provare il successo della vostra manovra informatica tramite un bel modprobe option e verificare tramite dmesg che avvenga qualcosa del tipo

Jun 19 12:42:37 durruti kernel: option 4-2:1.1: GSM modem (1-port) converter detected
Jun 19 12:42:37 durruti kernel: usb 4-2: GSM modem (1-port) converter now attached to ttyUSB0
Jun 19 12:42:37 durruti kernel: option 4-2:1.2: GSM modem (1-port) converter detected
Jun 19 12:42:37 durruti kernel: usb 4-2: GSM modem (1-port) converter now attached to ttyUSB1
Jun 19 12:42:37 durruti kernel: option 4-2:1.3: GSM modem (1-port) converter detected
Jun 19 12:42:37 durruti kernel: usb 4-2: GSM modem (1-port) converter now attached to ttyUSB2
Jun 19 12:42:37 durruti kernel: option 4-2:1.4: GSM modem (1-port) converter detected
Jun 19 12:42:37 durruti kernel: usb 4-2: GSM modem (1-port) converter now attached to ttyUSB3

PPP

Adesso dobbiamo instaurare la connessione con la rete UMTS di TIM ed è il terreno in cui ho avuto modo di conoscere le arcane regole di comunicazione con il modem; non penso possibile riprodurre tutti gli eventi e la sapienza con cui sono venuto a contatto se non con uso di sostanze psicotrope per cui mi limiterò a dei semplici consigli, idee, luoghi comuni relativi alla configurazione della connessione tramite pppd che può essere effettuata tramite programmi da vero hackerz come wvdial o chat, oppure usando programmi di altissimo livello come gnome-ppp; in particolare le cose da sapere ma non fondamentali sono:

  • /dev/ttyUSB1 è il modem (non so se dipende dal modello)
  • AT+ZOPRT=5 inizializza il modem
  • AT+CPIN=xxxx setta il PIN (magari impostate la scheda in modo che non lo chieda)
  • AT+CGDCONT=1,"IP","ibox.tim.it","",0,0 imposta il collegamento alla rete TIM
  • AT+COPS? restituisce gli operatori presenti nell’etere
  • AT+CREG? vi dice se siete registrati alla rete
  • AT+CSQ restituisce la potenza del campo
  • *99# oppure *99***1# è il numero da chiamare

nel caso siate interessati ai comandi potete trovarne alcuni in questa guida per un modello similare.

Udev

Udev è il programma accessorio al kernel, che si preoccupa di effettuare delle operazioni particolari nel momento in cui certe periferiche si rendono disponibili: può creare dei link simbolici, può fare in maniera tale che una certa periferica sia sempre montata in un determinato percorso oppure può eseguire certi comandi custom nel caso alcune periferiche abbiano bisogno di particolare attenzione; l’ultimo caso fa per noi. Prima di tutto necessitiamo di eseguire usb_modeswitch quando compare un supporto CDROM (visto dal sistema con emulazione SCSI); quindi necessitiamo di caricare il modulo option alla comparsa di una periferica USB con product id 0x19d2 e vendor id 0x0002 e con un tocco di raffinatezza vogliamo creare un link simbolico fra ttyUSB1 e modem (quest’ultima va proprio creata). Quindi la regola usata da me è la seguente

SUBSYSTEMS=="scsi", ATTRS{model}=="USB Storage     ", ATTRS{vendor}=="ONDA    ", RUN+="/sbin/usb_modeswitch"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0002", ATTRS{idVendor}=="19d2", RUN+="/sbin/modprobe option"
KERNEL=="ttyUSB1",SYMLINK+="modem"

 Per trovare gli attributi relativi al vostro modello potete usare dei programmi forniti da udev, cioé

udevinfo -a -p $(udevinfo -q path -n /dev/sr0)

e guardate il primo "parent device" e che caratteristiche ha (magari a voi il CD ve lo monta in un path diverso da sr0). Per la documentazione guardate il mitico "writing udev rules".

HAL&DBUS

L’ultimo passaggio della saga sarebbe avere una applicazione che unisce tutti i passi precedenti e che permetta all’utente finale di avere una applicazione che si avvi quando il modem è pronto all’uso. Ad un primo pensiero si potrebbe usare udev, ma il problema sarebbe principalmente che verrebbe aperto come root, avrebbe bisogno di conoscere le variabili relative al DISPLAY… quindi necessiatiamo di avere un programma a livello desktop che ci avverta della presenza di una periferica e questo è proprio il compito di Dbus in associazione con HAL.Dbus si preoccupa di passare tra i vari componenti del desktop messaggi di vario tipo (provate a lanciare dbus-manager mentre rythmbox suona una canzone) mentre HAL si preoccupa di gestire le informazioni e gli eventi relativi alle periferiche astraendole in parte. Quindi, senza entrare nel dettaglio (che neanche conosco tanto bene) ecco un programma in python che si preoccupa di visualizzare le info relative ad una periferica quando viene aggiunta al sistema… il passo a fare ciò che desidero è breve

#!/usr/bin/env python
# Example program for use of dbus
# <http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html>
# <http://lists.freedesktop.org/archives/hal/2005-January/001623.html>
#
# Look at example programs in the /python-dbus-doc/ directory
#
# Some HAL specifications about DBUS
# <http://people.freedesktop.org/~david/hal-spec/hal-spec.html#interfaces>
#
# To find DBUS message use
#    $ dbus-monitor
#
# DON’T CALL FILE LIKE LIBRARY IF YOU WANT TO LIVE HAPPY
#
# udi: Unique Device Idenfier

import sys
import gobject
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def device_added(udi):
    global bus,hal_manager
    # in this way works
    obj = bus.get_object(‘org.freedesktop.Hal’,udi)
    dev = dbus.Interface(obj,’org.freedesktop.Hal.Device’)
    props = dev.GetAllProperties()

    # This is the only way to discover
    # the real properties
    print "udi: ",udi
    for prop in props:
        p = dev.GetProperty(prop)
        print "t%s: %s" %(prop,p)

def device_removed(device_name):
    print "Removed: ",device_name

if __name__ == "__main__":
    DBusGMainLoop(set_as_default=True)
    bus = dbus.SystemBus()

    bus.add_signal_receiver(
            handler_function=device_added,
            signal_name="DeviceAdded",
            path="/org/freedesktop/Hal/Manager",
            dbus_interface="org.freedesktop.Hal.Manager" )
    bus.add_signal_receiver(
            handler_function=device_removed,
            signal_name="DeviceRemoved",
            path="/org/freedesktop/Hal/Manager",
            dbus_interface="org.freedesktop.Hal.Manager" )

    hal = bus.get_object(‘org.freedesktop.Hal’,
            ‘/org/freedesktop/Hal/Manager’)
    hal_manager = dbus.Interface(hal,’org.freedesktop.Hal.Manager’)

    loop = gobject.MainLoop()
    loop.run()

 E qui termina il viaggio del nostro eroe… se qualcuno ha trovato utili/interessanti/blasfeme/ortogonali queste cose scritte, lo faccia sapere in modo da sapere che qualcun’altro ha utilizzato in maniera proficua i miei 3 giorni di sclero.


One Comment on “Onda MT505UP”

  1. 1 scopare said at 7:40 pm on Luglio 26th, 2008:

    ottima guida, congratulazioni per la risoluzione del problema e la relativa ottima esposizione.