Corbammims
Wir bauen ein /dev/isdncti im Linux- Kern
Grundvorstellung
Um andere nützliche Programme nicht zu stören (isdnlog,imon,...)
und es einfach zu haben, wollen wir ein /dev/isdncti bauen.
Alle Anrufe, egal ob unser Rechner beteiligt ist oder nicht, sollen
in /dev/isdncti gemeldet werden.
Ein Prozeß soll dann auf /dev/isdncti lesen und dann die Informationen
weiter verarbeiten. Die Funktionsweise soll also genau so sein wie von
/dev/isdninfo.
Wichtige Entdeckung
Die low-Level-Treiber rufen die Funktion isdn_status_callback in
isdn_common.c auf, wenn z.B. ein Anruf ankommt (ISDN_STAT_ICALL).
Im Falle des ankommenden Anrufes wird dann das passende Netzwerkinterface
oder der passende tty gesucht.
Vor dem Beginn der Suche ist der richtige Ort um die Information
in unser /dev/isdncti zu übergeben. In der Struktur setup_parm
(isdnif.h) stehen sie schön aufbereitet drin, unabhängig von der verwendeten
Karte und dem Protokoll.
Kernmechanismen
Wir ergänzen in include/isdn.h:
/* CTI-data */
struct isdn_cti
{
struct sk_buff_head blockliste;
struct wait_queue *cti_waitq;
int o; /* offene Dateien */
};
struct isdn_devt
{ /* ... */
struct isdn_cti cti;
/* ... */
};
sk_buff ist eine Listenstruktur, die Nachrichtenpakete (für die Netzwerkimplementierung) verwaltet. Diese wird auch für den Datentransfer beim lesen des B-Channels verwendet:
-
Blöcke werden mit dev_kfree_skb(skb) nach dem ausliefern freigegeben
(vgl. isdn_recieve_skb_callback )
- Initialisieren:
- skb_queue_head_init(&waitq);
- Abfrage nach Länge:
-
if(skb_queue_empty(waitq)) { ... }
- Aushängen:
-
skb=skb_dequeue(&waitq);
skb->data , skb->len;
dev_kfree_skb(skb);
- Einhängen: vgl isdn_writebuf_stub
-
struct sk_buff *skb = alloc_skb(len,GFP_ATOMIC);
if(!skb) fehler ...
skb_reserve(skb, hl);
if (user)
copy_from_user(skb_put(skb, len), buf, len);
else
memcpy(skb_put(skb, len), buf, len);
- skb_queue_tail hängt Paket am Ende an
- skb_queue_head hängt Paket am Anfang an
ulong flags
save_flags(flags);
cli();
/* Aktion */
restore_flags(flags);
// Warteschlangenverwaltung
if(!(wq = ((struct wait_queue **)
kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL)))
{
printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
}
memset((char *)wq,0,sizeof(struct wait_queue *));
interruptible_sleep_on(waitq); /*vgl. isdn_read_bchan()*/
wake_up_interruptible(waitq);
Neues in Kern 2.4
Allgemeinere Funktion skb_queue_purge ersetzt isdn_free_queue.
Diese Funktion löscht eine skb_buff_ - Liste
cti_waitq hat nun einen anderen Typ bekommen: statt struct wait_queue
haben wir nun: wait_queue_head_t
Wir müssen acht geben, daß kernel_lock() wieder freigegeben wird.
Format aus /dev/isdncti
Felder sind durch Leerzeichen getrennt, die Zeile wird mit dem Zeilentrenner
\n getrennt. Ein read liefert genau ein Ereignis.
Das erste Feld ist der Ereignisname:
- ICALL
- Incomming Call
bei ICALL kommen dann sämtliche Werte aus der Struktur setup_parm
aus /usr/src/linux/isdn/isdnif.h:
- phone
- die Telefonnummer des Anrufers, dieses ist eine Folge von Ziffern
oder unknown, falls diese nicht übermittelt wird.
- eazmsn
- die lokale msn, ebenfalls eine Ziffernfolge
- si1 Service Indicator 1 , hexadezimal codiert
- Register 18 bei ttyIx, aber umcodiert.
Nach kurzer Analyse des Codes stimmen diese mit den Angaben in
ttyIx(4) überein:
1 | audio, gewöhnliche Telefonanrufe, emprisch bestätigt |
5 | BTX |
7 |
data, Code in isdn_net.c:2091 |
- si2 Service Indicator 2, hexadezimal codiert
- bei DSS1 immer 0 , entspricht Register 19 bei ttyIx
- plan Numbering plan, hexadezimal codiert
- laut isdn_tty.c entspricht es Register 21 bei ttyI(4),
value of octet 3 of calling party number Information Element (Numbering plan). See section 4.5.10 of ITU Q.931.
- screen Screening info , hexadezimal codiert
laut isdn_tty.c entspricht es Register 22 bei ttyI(4),
value of octet 3a of calling party number Information Element
(Screening info). See section 4.5.10 of ITU Q.931.
Beobachtung: bei ISDN (zumindest intern) plan=0x21 screen=0x81
analog plan=0 screen=0xa3
Installation
- Hier ist der patch für Linux 2.2.x und
für Linux-2.4.x
- Kern patchen
Getestet mit Kern 2.2.13,2.2.14 und 2.2.15 sowie mit Kern 2.4.8
(diff und patch sind toll!!!)
cd /usr/src/linux
patch -b -p0 < /tmp/ctipatch.txt
make modules
make modules_install
- Device einrichten
mknod -m 444 /dev/isdncti c 45 254
- Sicherstellen, daß unser neues modul auch geladen wird
init 1 ; depmod -a ; init 2
- Test
cat < /dev/isdncti
Wenn nun angerufen wird, wird eine Zeile geliefert ...
Rudolf Weber
Informatik- und Netzwerkverein Ravensburg e.V