1/* $Id: isdnloop.c,v 1.11.6.7 2001/11/11 19:54:31 kai Exp $
2 *
3 * ISDN low-level module implementing a dummy loop driver.
4 *
5 * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/slab.h>
15#include <linux/init.h>
16#include <linux/sched.h>
17#include "isdnloop.h"
18
19static char *isdnloop_id = "loop0";
20
21MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
22MODULE_AUTHOR("Fritz Elfert");
23MODULE_LICENSE("GPL");
24module_param(isdnloop_id, charp, 0);
25MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
26
27static int isdnloop_addcard(char *);
28
29/*
30 * Free queue completely.
31 *
32 * Parameter:
33 *   card    = pointer to card struct
34 *   channel = channel number
35 */
36static void
37isdnloop_free_queue(isdnloop_card *card, int channel)
38{
39	struct sk_buff_head *queue = &card->bqueue[channel];
40
41	skb_queue_purge(queue);
42	card->sndcount[channel] = 0;
43}
44
45/*
46 * Send B-Channel data to another virtual card.
47 * This routine is called via timer-callback from isdnloop_pollbchan().
48 *
49 * Parameter:
50 *   card = pointer to card struct.
51 *   ch   = channel number (0-based)
52 */
53static void
54isdnloop_bchan_send(isdnloop_card *card, int ch)
55{
56	isdnloop_card *rcard = card->rcard[ch];
57	int rch = card->rch[ch], len, ack;
58	struct sk_buff *skb;
59	isdn_ctrl cmd;
60
61	while (card->sndcount[ch]) {
62		skb = skb_dequeue(&card->bqueue[ch]);
63		if (skb) {
64			len = skb->len;
65			card->sndcount[ch] -= len;
66			ack = *(skb->head); /* used as scratch area */
67			cmd.driver = card->myid;
68			cmd.arg = ch;
69			if (rcard) {
70				rcard->interface.rcvcallb_skb(rcard->myid, rch, skb);
71			} else {
72				printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n");
73				dev_kfree_skb(skb);
74
75			};
76			cmd.command = ISDN_STAT_BSENT;
77			cmd.parm.length = len;
78			card->interface.statcallb(&cmd);
79		} else
80			card->sndcount[ch] = 0;
81	}
82}
83
84/*
85 * Send/Receive Data to/from the B-Channel.
86 * This routine is called via timer-callback.
87 * It schedules itself while any B-Channel is open.
88 *
89 * Parameter:
90 *   data = pointer to card struct, set by kernel timer.data
91 */
92static void
93isdnloop_pollbchan(unsigned long data)
94{
95	isdnloop_card *card = (isdnloop_card *) data;
96	unsigned long flags;
97
98	if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE)
99		isdnloop_bchan_send(card, 0);
100	if (card->flags & ISDNLOOP_FLAGS_B2ACTIVE)
101		isdnloop_bchan_send(card, 1);
102	if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) {
103		/* schedule b-channel polling again */
104		spin_lock_irqsave(&card->isdnloop_lock, flags);
105		card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
106		add_timer(&card->rb_timer);
107		card->flags |= ISDNLOOP_FLAGS_RBTIMER;
108		spin_unlock_irqrestore(&card->isdnloop_lock, flags);
109	} else
110		card->flags &= ~ISDNLOOP_FLAGS_RBTIMER;
111}
112
113/*
114 * Parse ICN-type setup string and fill fields of setup-struct
115 * with parsed data.
116 *
117 * Parameter:
118 *   setup = setup string, format: [caller-id],si1,si2,[called-id]
119 *   cmd   = pointer to struct to be filled.
120 */
121static void
122isdnloop_parse_setup(char *setup, isdn_ctrl *cmd)
123{
124	char *t = setup;
125	char *s = strchr(t, ',');
126
127	*s++ = '\0';
128	strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone));
129	s = strchr(t = s, ',');
130	*s++ = '\0';
131	if (!strlen(t))
132		cmd->parm.setup.si1 = 0;
133	else
134		cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10);
135	s = strchr(t = s, ',');
136	*s++ = '\0';
137	if (!strlen(t))
138		cmd->parm.setup.si2 = 0;
139	else
140		cmd->parm.setup.si2 =
141			simple_strtoul(t, NULL, 10);
142	strlcpy(cmd->parm.setup.eazmsn, s, sizeof(cmd->parm.setup.eazmsn));
143	cmd->parm.setup.plan = 0;
144	cmd->parm.setup.screen = 0;
145}
146
147typedef struct isdnloop_stat {
148	char *statstr;
149	int command;
150	int action;
151} isdnloop_stat;
152/* *INDENT-OFF* */
153static isdnloop_stat isdnloop_stat_table[] = {
154	{"BCON_",          ISDN_STAT_BCONN, 1}, /* B-Channel connected        */
155	{"BDIS_",          ISDN_STAT_BHUP,  2}, /* B-Channel disconnected     */
156	{"DCON_",          ISDN_STAT_DCONN, 0}, /* D-Channel connected        */
157	{"DDIS_",          ISDN_STAT_DHUP,  0}, /* D-Channel disconnected     */
158	{"DCAL_I",         ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line  */
159	{"DSCA_I",         ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV     */
160	{"FCALL",          ISDN_STAT_ICALL, 4}, /* Leased line connection up  */
161	{"CIF",            ISDN_STAT_CINF,  5}, /* Charge-info, 1TR6-type     */
162	{"AOC",            ISDN_STAT_CINF,  6}, /* Charge-info, DSS1-type     */
163	{"CAU",            ISDN_STAT_CAUSE, 7}, /* Cause code                 */
164	{"TEI OK",         ISDN_STAT_RUN,   0}, /* Card connected to wallplug */
165	{"E_L1: ACT FAIL", ISDN_STAT_BHUP,  8}, /* Layer-1 activation failed  */
166	{"E_L2: DATA LIN", ISDN_STAT_BHUP,  8}, /* Layer-2 data link lost     */
167	{"E_L1: ACTIVATION FAILED",
168	 ISDN_STAT_BHUP,  8},         /* Layer-1 activation failed  */
169	{NULL, 0, -1}
170};
171/* *INDENT-ON* */
172
173
174/*
175 * Parse Status message-strings from virtual card.
176 * Depending on status, call statcallb for sending messages to upper
177 * levels. Also set/reset B-Channel active-flags.
178 *
179 * Parameter:
180 *   status  = status string to parse.
181 *   channel = channel where message comes from.
182 *   card    = card where message comes from.
183 */
184static void
185isdnloop_parse_status(u_char *status, int channel, isdnloop_card *card)
186{
187	isdnloop_stat *s = isdnloop_stat_table;
188	int action = -1;
189	isdn_ctrl cmd;
190
191	while (s->statstr) {
192		if (!strncmp(status, s->statstr, strlen(s->statstr))) {
193			cmd.command = s->command;
194			action = s->action;
195			break;
196		}
197		s++;
198	}
199	if (action == -1)
200		return;
201	cmd.driver = card->myid;
202	cmd.arg = channel;
203	switch (action) {
204	case 1:
205		/* BCON_x */
206		card->flags |= (channel) ?
207			ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE;
208		break;
209	case 2:
210		/* BDIS_x */
211		card->flags &= ~((channel) ?
212				 ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE);
213		isdnloop_free_queue(card, channel);
214		break;
215	case 3:
216		/* DCAL_I and DSCA_I */
217		isdnloop_parse_setup(status + 6, &cmd);
218		break;
219	case 4:
220		/* FCALL */
221		sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
222		sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
223		cmd.parm.setup.si1 = 7;
224		cmd.parm.setup.si2 = 0;
225		cmd.parm.setup.plan = 0;
226		cmd.parm.setup.screen = 0;
227		break;
228	case 5:
229		/* CIF */
230		strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num));
231		break;
232	case 6:
233		/* AOC */
234		snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d",
235			 (int) simple_strtoul(status + 7, NULL, 16));
236		break;
237	case 7:
238		/* CAU */
239		status += 3;
240		if (strlen(status) == 4)
241			snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c",
242				 status + 2, *status, *(status + 1));
243		else
244			strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num));
245		break;
246	case 8:
247		/* Misc Errors on L1 and L2 */
248		card->flags &= ~ISDNLOOP_FLAGS_B1ACTIVE;
249		isdnloop_free_queue(card, 0);
250		cmd.arg = 0;
251		cmd.driver = card->myid;
252		card->interface.statcallb(&cmd);
253		cmd.command = ISDN_STAT_DHUP;
254		cmd.arg = 0;
255		cmd.driver = card->myid;
256		card->interface.statcallb(&cmd);
257		cmd.command = ISDN_STAT_BHUP;
258		card->flags &= ~ISDNLOOP_FLAGS_B2ACTIVE;
259		isdnloop_free_queue(card, 1);
260		cmd.arg = 1;
261		cmd.driver = card->myid;
262		card->interface.statcallb(&cmd);
263		cmd.command = ISDN_STAT_DHUP;
264		cmd.arg = 1;
265		cmd.driver = card->myid;
266		break;
267	}
268	card->interface.statcallb(&cmd);
269}
270
271/*
272 * Store a cwcharacter into ringbuffer for reading from /dev/isdnctrl
273 *
274 * Parameter:
275 *   card = pointer to card struct.
276 *   c    = char to store.
277 */
278static void
279isdnloop_putmsg(isdnloop_card *card, unsigned char c)
280{
281	ulong flags;
282
283	spin_lock_irqsave(&card->isdnloop_lock, flags);
284	*card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
285	if (card->msg_buf_write == card->msg_buf_read) {
286		if (++card->msg_buf_read > card->msg_buf_end)
287			card->msg_buf_read = card->msg_buf;
288	}
289	if (card->msg_buf_write > card->msg_buf_end)
290		card->msg_buf_write = card->msg_buf;
291	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
292}
293
294/*
295 * Poll a virtual cards message queue.
296 * If there are new status-replies from the card, copy them to
297 * ringbuffer for reading on /dev/isdnctrl and call
298 * isdnloop_parse_status() for processing them. Watch for special
299 * Firmware bootmessage and parse it, to get the D-Channel protocol.
300 * If there are B-Channels open, initiate a timer-callback to
301 * isdnloop_pollbchan().
302 * This routine is called periodically via timer interrupt.
303 *
304 * Parameter:
305 *   data = pointer to card struct
306 */
307static void
308isdnloop_polldchan(unsigned long data)
309{
310	isdnloop_card *card = (isdnloop_card *) data;
311	struct sk_buff *skb;
312	int avail;
313	int left;
314	u_char c;
315	int ch;
316	unsigned long flags;
317	u_char *p;
318	isdn_ctrl cmd;
319
320	skb = skb_dequeue(&card->dqueue);
321	if (skb)
322		avail = skb->len;
323	else
324		avail = 0;
325	for (left = avail; left > 0; left--) {
326		c = *skb->data;
327		skb_pull(skb, 1);
328		isdnloop_putmsg(card, c);
329		card->imsg[card->iptr] = c;
330		if (card->iptr < 59)
331			card->iptr++;
332		if (!skb->len) {
333			avail++;
334			isdnloop_putmsg(card, '\n');
335			card->imsg[card->iptr] = 0;
336			card->iptr = 0;
337			if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
338			    card->imsg[1] <= '2' && card->imsg[2] == ';') {
339				ch = (card->imsg[1] - '0') - 1;
340				p = &card->imsg[3];
341				isdnloop_parse_status(p, ch, card);
342			} else {
343				p = card->imsg;
344				if (!strncmp(p, "DRV1.", 5)) {
345					printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p);
346					if (!strncmp(p + 7, "TC", 2)) {
347						card->ptype = ISDN_PTYPE_1TR6;
348						card->interface.features |= ISDN_FEATURE_P_1TR6;
349						printk(KERN_INFO
350						       "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID);
351					}
352					if (!strncmp(p + 7, "EC", 2)) {
353						card->ptype = ISDN_PTYPE_EURO;
354						card->interface.features |= ISDN_FEATURE_P_EURO;
355						printk(KERN_INFO
356						       "isdnloop: (%s) Euro-Protocol loaded and running\n", CID);
357					}
358					continue;
359
360				}
361			}
362		}
363	}
364	if (avail) {
365		cmd.command = ISDN_STAT_STAVAIL;
366		cmd.driver = card->myid;
367		cmd.arg = avail;
368		card->interface.statcallb(&cmd);
369	}
370	if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE))
371		if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) {
372			/* schedule b-channel polling */
373			card->flags |= ISDNLOOP_FLAGS_RBTIMER;
374			spin_lock_irqsave(&card->isdnloop_lock, flags);
375			del_timer(&card->rb_timer);
376			card->rb_timer.function = isdnloop_pollbchan;
377			card->rb_timer.data = (unsigned long) card;
378			card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
379			add_timer(&card->rb_timer);
380			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
381		}
382	/* schedule again */
383	spin_lock_irqsave(&card->isdnloop_lock, flags);
384	card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
385	add_timer(&card->st_timer);
386	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
387}
388
389/*
390 * Append a packet to the transmit buffer-queue.
391 *
392 * Parameter:
393 *   channel = Number of B-channel
394 *   skb     = packet to send.
395 *   card    = pointer to card-struct
396 * Return:
397 *   Number of bytes transferred, -E??? on error
398 */
399static int
400isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card *card)
401{
402	int len = skb->len;
403	unsigned long flags;
404	struct sk_buff *nskb;
405
406	if (len > 4000) {
407		printk(KERN_WARNING
408		       "isdnloop: Send packet too large\n");
409		return -EINVAL;
410	}
411	if (len) {
412		if (!(card->flags & (channel) ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE))
413			return 0;
414		if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE)
415			return 0;
416		spin_lock_irqsave(&card->isdnloop_lock, flags);
417		nskb = dev_alloc_skb(skb->len);
418		if (nskb) {
419			skb_copy_from_linear_data(skb,
420						  skb_put(nskb, len), len);
421			skb_queue_tail(&card->bqueue[channel], nskb);
422			dev_kfree_skb(skb);
423		} else
424			len = 0;
425		card->sndcount[channel] += len;
426		spin_unlock_irqrestore(&card->isdnloop_lock, flags);
427	}
428	return len;
429}
430
431/*
432 * Read the messages from the card's ringbuffer
433 *
434 * Parameter:
435 *   buf  = pointer to buffer.
436 *   len  = number of bytes to read.
437 *   user = flag, 1: called from userlevel 0: called from kernel.
438 *   card = pointer to card struct.
439 * Return:
440 *   number of bytes actually transferred.
441 */
442static int
443isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card *card)
444{
445	int count;
446	u_char __user *p;
447
448	for (p = buf, count = 0; count < len; p++, count++) {
449		if (card->msg_buf_read == card->msg_buf_write)
450			return count;
451		if (put_user(*card->msg_buf_read++, p))
452			return -EFAULT;
453		if (card->msg_buf_read > card->msg_buf_end)
454			card->msg_buf_read = card->msg_buf;
455	}
456	return count;
457}
458
459/*
460 * Simulate a card's response by appending it to the cards
461 * message queue.
462 *
463 * Parameter:
464 *   card = pointer to card struct.
465 *   s    = pointer to message-string.
466 *   ch   = channel: 0 = generic messages, 1 and 2 = D-channel messages.
467 * Return:
468 *   0 on success, 1 on memory squeeze.
469 */
470static int
471isdnloop_fake(isdnloop_card *card, char *s, int ch)
472{
473	struct sk_buff *skb;
474	int len = strlen(s) + ((ch >= 0) ? 3 : 0);
475	skb = dev_alloc_skb(len);
476	if (!skb) {
477		printk(KERN_WARNING "isdnloop: Out of memory in isdnloop_fake\n");
478		return 1;
479	}
480	if (ch >= 0)
481		sprintf(skb_put(skb, 3), "%02d;", ch);
482	memcpy(skb_put(skb, strlen(s)), s, strlen(s));
483	skb_queue_tail(&card->dqueue, skb);
484	return 0;
485}
486/* *INDENT-OFF* */
487static isdnloop_stat isdnloop_cmd_table[] = {
488	{"BCON_R",         0,  1},	/* B-Channel connect        */
489	{"BCON_I",         0, 17},	/* B-Channel connect ind    */
490	{"BDIS_R",         0,  2},	/* B-Channel disconnect     */
491	{"DDIS_R",         0,  3},	/* D-Channel disconnect     */
492	{"DCON_R",         0, 16},	/* D-Channel connect        */
493	{"DSCA_R",         0,  4},	/* Dial 1TR6-SPV     */
494	{"DCAL_R",         0,  5},	/* Dial */
495	{"EAZC",           0,  6},	/* Clear EAZ listener */
496	{"EAZ",            0,  7},	/* Set EAZ listener */
497	{"SEEAZ",          0,  8},	/* Get EAZ listener */
498	{"MSN",            0,  9},	/* Set/Clear MSN listener */
499	{"MSALL",          0, 10},	/* Set multi MSN listeners */
500	{"SETSIL",         0, 11},	/* Set SI list     */
501	{"SEESIL",         0, 12},	/* Get SI list     */
502	{"SILC",           0, 13},	/* Clear SI list     */
503	{"LOCK",           0, -1},	/* LOCK channel     */
504	{"UNLOCK",         0, -1},	/* UNLOCK channel     */
505	{"FV2ON",          1, 14},	/* Leased mode on               */
506	{"FV2OFF",         1, 15},	/* Leased mode off              */
507	{NULL, 0, -1}
508};
509/* *INDENT-ON* */
510
511
512/*
513 * Simulate an error-response from a card.
514 *
515 * Parameter:
516 *   card = pointer to card struct.
517 */
518static void
519isdnloop_fake_err(isdnloop_card *card)
520{
521	char buf[64];
522
523	snprintf(buf, sizeof(buf), "E%s", card->omsg);
524	isdnloop_fake(card, buf, -1);
525	isdnloop_fake(card, "NAK", -1);
526}
527
528static u_char ctable_eu[] = {0x00, 0x11, 0x01, 0x12};
529static u_char ctable_1t[] = {0x00, 0x3b, 0x01, 0x3a};
530
531/*
532 * Assemble a simplified cause message depending on the
533 * D-channel protocol used.
534 *
535 * Parameter:
536 *   card = pointer to card struct.
537 *   loc  = location: 0 = local, 1 = remote.
538 *   cau  = cause: 1 = busy, 2 = nonexistent callerid, 3 = no user responding.
539 * Return:
540 *   Pointer to buffer containing the assembled message.
541 */
542static char *
543isdnloop_unicause(isdnloop_card *card, int loc, int cau)
544{
545	static char buf[6];
546
547	switch (card->ptype) {
548	case ISDN_PTYPE_EURO:
549		sprintf(buf, "E%02X%02X", (loc) ? 4 : 2, ctable_eu[cau]);
550		break;
551	case ISDN_PTYPE_1TR6:
552		sprintf(buf, "%02X44", ctable_1t[cau]);
553		break;
554	default:
555		return "0000";
556	}
557	return buf;
558}
559
560/*
561 * Release a virtual connection. Called from timer interrupt, when
562 * called party did not respond.
563 *
564 * Parameter:
565 *   card = pointer to card struct.
566 *   ch   = channel (0-based)
567 */
568static void
569isdnloop_atimeout(isdnloop_card *card, int ch)
570{
571	unsigned long flags;
572	char buf[60];
573
574	spin_lock_irqsave(&card->isdnloop_lock, flags);
575	if (card->rcard) {
576		isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1);
577		card->rcard[ch]->rcard[card->rch[ch]] = NULL;
578		card->rcard[ch] = NULL;
579	}
580	isdnloop_fake(card, "DDIS_I", ch + 1);
581	/* No user responding */
582	sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3));
583	isdnloop_fake(card, buf, ch + 1);
584	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
585}
586
587/*
588 * Wrapper for isdnloop_atimeout().
589 */
590static void
591isdnloop_atimeout0(unsigned long data)
592{
593	isdnloop_card *card = (isdnloop_card *) data;
594	isdnloop_atimeout(card, 0);
595}
596
597/*
598 * Wrapper for isdnloop_atimeout().
599 */
600static void
601isdnloop_atimeout1(unsigned long data)
602{
603	isdnloop_card *card = (isdnloop_card *) data;
604	isdnloop_atimeout(card, 1);
605}
606
607/*
608 * Install a watchdog for a user, not responding.
609 *
610 * Parameter:
611 *   card = pointer to card struct.
612 *   ch   = channel to watch for.
613 */
614static void
615isdnloop_start_ctimer(isdnloop_card *card, int ch)
616{
617	unsigned long flags;
618
619	spin_lock_irqsave(&card->isdnloop_lock, flags);
620	init_timer(&card->c_timer[ch]);
621	card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT;
622	if (ch)
623		card->c_timer[ch].function = isdnloop_atimeout1;
624	else
625		card->c_timer[ch].function = isdnloop_atimeout0;
626	card->c_timer[ch].data = (unsigned long) card;
627	add_timer(&card->c_timer[ch]);
628	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
629}
630
631/*
632 * Kill a pending channel watchdog.
633 *
634 * Parameter:
635 *   card = pointer to card struct.
636 *   ch   = channel (0-based).
637 */
638static void
639isdnloop_kill_ctimer(isdnloop_card *card, int ch)
640{
641	unsigned long flags;
642
643	spin_lock_irqsave(&card->isdnloop_lock, flags);
644	del_timer(&card->c_timer[ch]);
645	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
646}
647
648static u_char si2bit[] = {0, 1, 0, 0, 0, 2, 0, 4, 0, 0};
649static u_char bit2si[] = {1, 5, 7};
650
651/*
652 * Try finding a listener for an outgoing call.
653 *
654 * Parameter:
655 *   card = pointer to calling card.
656 *   p    = pointer to ICN-type setup-string.
657 *   lch  = channel of calling card.
658 *   cmd  = pointer to struct to be filled when parsing setup.
659 * Return:
660 *   0 = found match, alerting should happen.
661 *   1 = found matching number but it is busy.
662 *   2 = no matching listener.
663 *   3 = found matching number but SI does not match.
664 */
665static int
666isdnloop_try_call(isdnloop_card *card, char *p, int lch, isdn_ctrl *cmd)
667{
668	isdnloop_card *cc = cards;
669	unsigned long flags;
670	int ch;
671	int num_match;
672	int i;
673	char *e;
674	char nbuf[32];
675
676	isdnloop_parse_setup(p, cmd);
677	while (cc) {
678		for (ch = 0; ch < 2; ch++) {
679			/* Exclude ourself */
680			if ((cc == card) && (ch == lch))
681				continue;
682			num_match = 0;
683			switch (cc->ptype) {
684			case ISDN_PTYPE_EURO:
685				for (i = 0; i < 3; i++)
686					if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone)))
687						num_match = 1;
688				break;
689			case ISDN_PTYPE_1TR6:
690				e = cc->eazlist[ch];
691				while (*e) {
692					sprintf(nbuf, "%s%c", cc->s0num[0], *e);
693					if (!(strcmp(nbuf, cmd->parm.setup.phone)))
694						num_match = 1;
695					e++;
696				}
697			}
698			if (num_match) {
699				spin_lock_irqsave(&card->isdnloop_lock, flags);
700				/* channel idle? */
701				if (!(cc->rcard[ch])) {
702					/* Check SI */
703					if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) {
704						spin_unlock_irqrestore(&card->isdnloop_lock, flags);
705						return 3;
706					}
707					/* ch is idle, si and number matches */
708					cc->rcard[ch] = card;
709					cc->rch[ch] = lch;
710					card->rcard[lch] = cc;
711					card->rch[lch] = ch;
712					spin_unlock_irqrestore(&card->isdnloop_lock, flags);
713					return 0;
714				} else {
715					spin_unlock_irqrestore(&card->isdnloop_lock, flags);
716					/* num matches, but busy */
717					if (ch == 1)
718						return 1;
719				}
720			}
721		}
722		cc = cc->next;
723	}
724	return 2;
725}
726
727/*
728 * Depending on D-channel protocol and caller/called, modify
729 * phone number.
730 *
731 * Parameter:
732 *   card   = pointer to card struct.
733 *   phone  = pointer phone number.
734 *   caller = flag: 1 = caller, 0 = called.
735 * Return:
736 *   pointer to new phone number.
737 */
738static char *
739isdnloop_vstphone(isdnloop_card *card, char *phone, int caller)
740{
741	int i;
742	static char nphone[30];
743
744	if (!card) {
745		printk("BUG!!!\n");
746		return "";
747	}
748	switch (card->ptype) {
749	case ISDN_PTYPE_EURO:
750		if (caller) {
751			for (i = 0; i < 2; i++)
752				if (!(strcmp(card->s0num[i], phone)))
753					return phone;
754			return card->s0num[0];
755		}
756		return phone;
757		break;
758	case ISDN_PTYPE_1TR6:
759		if (caller) {
760			sprintf(nphone, "%s%c", card->s0num[0], phone[0]);
761			return nphone;
762		} else
763			return &phone[strlen(phone) - 1];
764		break;
765	}
766	return "";
767}
768
769/*
770 * Parse an ICN-type command string sent to the 'card'.
771 * Perform misc. actions depending on the command.
772 *
773 * Parameter:
774 *   card = pointer to card struct.
775 */
776static void
777isdnloop_parse_cmd(isdnloop_card *card)
778{
779	char *p = card->omsg;
780	isdn_ctrl cmd;
781	char buf[60];
782	isdnloop_stat *s = isdnloop_cmd_table;
783	int action = -1;
784	int i;
785	int ch;
786
787	if ((card->omsg[0] != '0') && (card->omsg[2] != ';')) {
788		isdnloop_fake_err(card);
789		return;
790	}
791	ch = card->omsg[1] - '0';
792	if ((ch < 0) || (ch > 2)) {
793		isdnloop_fake_err(card);
794		return;
795	}
796	p += 3;
797	while (s->statstr) {
798		if (!strncmp(p, s->statstr, strlen(s->statstr))) {
799			action = s->action;
800			if (s->command && (ch != 0)) {
801				isdnloop_fake_err(card);
802				return;
803			}
804			break;
805		}
806		s++;
807	}
808	if (action == -1)
809		return;
810	switch (action) {
811	case 1:
812		/* 0x;BCON_R */
813		if (card->rcard[ch - 1]) {
814			isdnloop_fake(card->rcard[ch - 1], "BCON_I",
815				      card->rch[ch - 1] + 1);
816			isdnloop_fake(card, "BCON_C", ch);
817		}
818		break;
819	case 17:
820		/* 0x;BCON_I */
821		if (card->rcard[ch - 1]) {
822			isdnloop_fake(card->rcard[ch - 1], "BCON_C",
823				      card->rch[ch - 1] + 1);
824		}
825		break;
826	case 2:
827		/* 0x;BDIS_R */
828		isdnloop_fake(card, "BDIS_C", ch);
829		if (card->rcard[ch - 1]) {
830			isdnloop_fake(card->rcard[ch - 1], "BDIS_I",
831				      card->rch[ch - 1] + 1);
832		}
833		break;
834	case 16:
835		/* 0x;DCON_R */
836		isdnloop_kill_ctimer(card, ch - 1);
837		if (card->rcard[ch - 1]) {
838			isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
839			isdnloop_fake(card->rcard[ch - 1], "DCON_C",
840				      card->rch[ch - 1] + 1);
841			isdnloop_fake(card, "DCON_C", ch);
842		}
843		break;
844	case 3:
845		/* 0x;DDIS_R */
846		isdnloop_kill_ctimer(card, ch - 1);
847		if (card->rcard[ch - 1]) {
848			isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
849			isdnloop_fake(card->rcard[ch - 1], "DDIS_I",
850				      card->rch[ch - 1] + 1);
851			card->rcard[ch - 1] = NULL;
852		}
853		isdnloop_fake(card, "DDIS_C", ch);
854		break;
855	case 4:
856		/* 0x;DSCA_Rdd,yy,zz,oo */
857		if (card->ptype != ISDN_PTYPE_1TR6) {
858			isdnloop_fake_err(card);
859			return;
860		}
861		/* Fall through */
862	case 5:
863		/* 0x;DCAL_Rdd,yy,zz,oo */
864		p += 6;
865		switch (isdnloop_try_call(card, p, ch - 1, &cmd)) {
866		case 0:
867			/* Alerting */
868			sprintf(buf, "D%s_I%s,%02d,%02d,%s",
869				(action == 4) ? "SCA" : "CAL",
870				isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
871				cmd.parm.setup.si1,
872				cmd.parm.setup.si2,
873				isdnloop_vstphone(card->rcard[ch - 1],
874						  cmd.parm.setup.phone, 0));
875			isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
876			/* Fall through */
877		case 3:
878			/* si1 does not match, don't alert but start timer */
879			isdnloop_start_ctimer(card, ch - 1);
880			break;
881		case 1:
882			/* Remote busy */
883			isdnloop_fake(card, "DDIS_I", ch);
884			sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 1));
885			isdnloop_fake(card, buf, ch);
886			break;
887		case 2:
888			/* No such user */
889			isdnloop_fake(card, "DDIS_I", ch);
890			sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 2));
891			isdnloop_fake(card, buf, ch);
892			break;
893		}
894		break;
895	case 6:
896		/* 0x;EAZC */
897		card->eazlist[ch - 1][0] = '\0';
898		break;
899	case 7:
900		/* 0x;EAZ */
901		p += 3;
902		if (strlen(p) >= sizeof(card->eazlist[0]))
903			break;
904		strcpy(card->eazlist[ch - 1], p);
905		break;
906	case 8:
907		/* 0x;SEEAZ */
908		sprintf(buf, "EAZ-LIST: %s", card->eazlist[ch - 1]);
909		isdnloop_fake(card, buf, ch + 1);
910		break;
911	case 9:
912		/* 0x;MSN */
913		break;
914	case 10:
915		/* 0x;MSNALL */
916		break;
917	case 11:
918		/* 0x;SETSIL */
919		p += 6;
920		i = 0;
921		while (strchr("0157", *p)) {
922			if (i)
923				card->sil[ch - 1] |= si2bit[*p - '0'];
924			i = (*p++ == '0');
925		}
926		if (*p)
927			isdnloop_fake_err(card);
928		break;
929	case 12:
930		/* 0x;SEESIL */
931		sprintf(buf, "SIN-LIST: ");
932		p = buf + 10;
933		for (i = 0; i < 3; i++)
934			if (card->sil[ch - 1] & (1 << i))
935				p += sprintf(p, "%02d", bit2si[i]);
936		isdnloop_fake(card, buf, ch + 1);
937		break;
938	case 13:
939		/* 0x;SILC */
940		card->sil[ch - 1] = 0;
941		break;
942	case 14:
943		/* 00;FV2ON */
944		break;
945	case 15:
946		/* 00;FV2OFF */
947		break;
948	}
949}
950
951/*
952 * Put command-strings into the of the 'card'. In reality, execute them
953 * right in place by calling isdnloop_parse_cmd(). Also copy every
954 * command to the read message ringbuffer, preceding it with a '>'.
955 * These mesagges can be read at /dev/isdnctrl.
956 *
957 * Parameter:
958 *   buf  = pointer to command buffer.
959 *   len  = length of buffer data.
960 *   user = flag: 1 = called form userlevel, 0 called from kernel.
961 *   card = pointer to card struct.
962 * Return:
963 *   number of bytes transferred (currently always equals len).
964 */
965static int
966isdnloop_writecmd(const u_char *buf, int len, int user, isdnloop_card *card)
967{
968	int xcount = 0;
969	int ocount = 1;
970	isdn_ctrl cmd;
971
972	while (len) {
973		int count = len;
974		u_char *p;
975		u_char msg[0x100];
976
977		if (count > 255)
978			count = 255;
979		if (user) {
980			if (copy_from_user(msg, buf, count))
981				return -EFAULT;
982		} else
983			memcpy(msg, buf, count);
984		isdnloop_putmsg(card, '>');
985		for (p = msg; count > 0; count--, p++) {
986			len--;
987			xcount++;
988			isdnloop_putmsg(card, *p);
989			card->omsg[card->optr] = *p;
990			if (*p == '\n') {
991				card->omsg[card->optr] = '\0';
992				card->optr = 0;
993				isdnloop_parse_cmd(card);
994				if (len) {
995					isdnloop_putmsg(card, '>');
996					ocount++;
997				}
998			} else {
999				if (card->optr < 59)
1000					card->optr++;
1001			}
1002			ocount++;
1003		}
1004	}
1005	cmd.command = ISDN_STAT_STAVAIL;
1006	cmd.driver = card->myid;
1007	cmd.arg = ocount;
1008	card->interface.statcallb(&cmd);
1009	return xcount;
1010}
1011
1012/*
1013 * Delete card's pending timers, send STOP to linklevel
1014 */
1015static void
1016isdnloop_stopcard(isdnloop_card *card)
1017{
1018	unsigned long flags;
1019	isdn_ctrl cmd;
1020
1021	spin_lock_irqsave(&card->isdnloop_lock, flags);
1022	if (card->flags & ISDNLOOP_FLAGS_RUNNING) {
1023		card->flags &= ~ISDNLOOP_FLAGS_RUNNING;
1024		del_timer(&card->st_timer);
1025		del_timer(&card->rb_timer);
1026		del_timer(&card->c_timer[0]);
1027		del_timer(&card->c_timer[1]);
1028		cmd.command = ISDN_STAT_STOP;
1029		cmd.driver = card->myid;
1030		card->interface.statcallb(&cmd);
1031	}
1032	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1033}
1034
1035/*
1036 * Stop all cards before unload.
1037 */
1038static void
1039isdnloop_stopallcards(void)
1040{
1041	isdnloop_card *p = cards;
1042
1043	while (p) {
1044		isdnloop_stopcard(p);
1045		p = p->next;
1046	}
1047}
1048
1049/*
1050 * Start a 'card'. Simulate card's boot message and set the phone
1051 * number(s) of the virtual 'S0-Interface'. Install D-channel
1052 * poll timer.
1053 *
1054 * Parameter:
1055 *   card  = pointer to card struct.
1056 *   sdefp = pointer to struct holding ioctl parameters.
1057 * Return:
1058 *   0 on success, -E??? otherwise.
1059 */
1060static int
1061isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
1062{
1063	unsigned long flags;
1064	isdnloop_sdef sdef;
1065	int i;
1066
1067	if (card->flags & ISDNLOOP_FLAGS_RUNNING)
1068		return -EBUSY;
1069	if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
1070		return -EFAULT;
1071
1072	for (i = 0; i < 3; i++) {
1073		if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
1074			return -EINVAL;
1075	}
1076
1077	spin_lock_irqsave(&card->isdnloop_lock, flags);
1078	switch (sdef.ptype) {
1079	case ISDN_PTYPE_EURO:
1080		if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96",
1081				  -1)) {
1082			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1083			return -ENOMEM;
1084		}
1085		card->sil[0] = card->sil[1] = 4;
1086		if (isdnloop_fake(card, "TEI OK", 0)) {
1087			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1088			return -ENOMEM;
1089		}
1090		for (i = 0; i < 3; i++) {
1091			strlcpy(card->s0num[i], sdef.num[i],
1092				sizeof(card->s0num[0]));
1093		}
1094		break;
1095	case ISDN_PTYPE_1TR6:
1096		if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
1097				  -1)) {
1098			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1099			return -ENOMEM;
1100		}
1101		card->sil[0] = card->sil[1] = 4;
1102		if (isdnloop_fake(card, "TEI OK", 0)) {
1103			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1104			return -ENOMEM;
1105		}
1106		strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
1107		card->s0num[1][0] = '\0';
1108		card->s0num[2][0] = '\0';
1109		break;
1110	default:
1111		spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1112		printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n",
1113		       sdef.ptype);
1114		return -EINVAL;
1115	}
1116	init_timer(&card->st_timer);
1117	card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
1118	card->st_timer.function = isdnloop_polldchan;
1119	card->st_timer.data = (unsigned long) card;
1120	add_timer(&card->st_timer);
1121	card->flags |= ISDNLOOP_FLAGS_RUNNING;
1122	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1123	return 0;
1124}
1125
1126/*
1127 * Main handler for commands sent by linklevel.
1128 */
1129static int
1130isdnloop_command(isdn_ctrl *c, isdnloop_card *card)
1131{
1132	ulong a;
1133	int i;
1134	char cbuf[80];
1135	isdn_ctrl cmd;
1136	isdnloop_cdef cdef;
1137
1138	switch (c->command) {
1139	case ISDN_CMD_IOCTL:
1140		memcpy(&a, c->parm.num, sizeof(ulong));
1141		switch (c->arg) {
1142		case ISDNLOOP_IOCTL_DEBUGVAR:
1143			return (ulong) card;
1144		case ISDNLOOP_IOCTL_STARTUP:
1145			if (!access_ok(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef)))
1146				return -EFAULT;
1147			return isdnloop_start(card, (isdnloop_sdef *) a);
1148			break;
1149		case ISDNLOOP_IOCTL_ADDCARD:
1150			if (copy_from_user((char *)&cdef,
1151					   (char *)a,
1152					   sizeof(cdef)))
1153				return -EFAULT;
1154			return isdnloop_addcard(cdef.id1);
1155			break;
1156		case ISDNLOOP_IOCTL_LEASEDCFG:
1157			if (a) {
1158				if (!card->leased) {
1159					card->leased = 1;
1160					while (card->ptype == ISDN_PTYPE_UNKNOWN)
1161						schedule_timeout_interruptible(10);
1162					schedule_timeout_interruptible(10);
1163					sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");
1164					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1165					printk(KERN_INFO
1166					       "isdnloop: (%s) Leased-line mode enabled\n",
1167					       CID);
1168					cmd.command = ISDN_STAT_RUN;
1169					cmd.driver = card->myid;
1170					cmd.arg = 0;
1171					card->interface.statcallb(&cmd);
1172				}
1173			} else {
1174				if (card->leased) {
1175					card->leased = 0;
1176					sprintf(cbuf, "00;FV2OFF\n");
1177					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1178					printk(KERN_INFO
1179					       "isdnloop: (%s) Leased-line mode disabled\n",
1180					       CID);
1181					cmd.command = ISDN_STAT_RUN;
1182					cmd.driver = card->myid;
1183					cmd.arg = 0;
1184					card->interface.statcallb(&cmd);
1185				}
1186			}
1187			return 0;
1188		default:
1189			return -EINVAL;
1190		}
1191		break;
1192	case ISDN_CMD_DIAL:
1193		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1194			return -ENODEV;
1195		if (card->leased)
1196			break;
1197		if ((c->arg & 255) < ISDNLOOP_BCH) {
1198			char *p;
1199			char dcode[4];
1200
1201			a = c->arg;
1202			p = c->parm.setup.phone;
1203			if (*p == 's' || *p == 'S') {
1204				/* Dial for SPV */
1205				p++;
1206				strcpy(dcode, "SCA");
1207			} else
1208				/* Normal Dial */
1209				strcpy(dcode, "CAL");
1210			snprintf(cbuf, sizeof(cbuf),
1211				 "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
1212				 dcode, p, c->parm.setup.si1,
1213				 c->parm.setup.si2, c->parm.setup.eazmsn);
1214			i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1215		}
1216		break;
1217	case ISDN_CMD_ACCEPTD:
1218		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1219			return -ENODEV;
1220		if (c->arg < ISDNLOOP_BCH) {
1221			a = c->arg + 1;
1222			cbuf[0] = 0;
1223			switch (card->l2_proto[a - 1]) {
1224			case ISDN_PROTO_L2_X75I:
1225				sprintf(cbuf, "%02d;BX75\n", (int) a);
1226				break;
1227#ifdef CONFIG_ISDN_X25
1228			case ISDN_PROTO_L2_X25DTE:
1229				sprintf(cbuf, "%02d;BX2T\n", (int) a);
1230				break;
1231			case ISDN_PROTO_L2_X25DCE:
1232				sprintf(cbuf, "%02d;BX2C\n", (int) a);
1233				break;
1234#endif
1235			case ISDN_PROTO_L2_HDLC:
1236				sprintf(cbuf, "%02d;BTRA\n", (int) a);
1237				break;
1238			}
1239			if (strlen(cbuf))
1240				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1241			sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1242			i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1243		}
1244		break;
1245	case ISDN_CMD_ACCEPTB:
1246		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1247			return -ENODEV;
1248		if (c->arg < ISDNLOOP_BCH) {
1249			a = c->arg + 1;
1250			switch (card->l2_proto[a - 1]) {
1251			case ISDN_PROTO_L2_X75I:
1252				sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
1253				break;
1254#ifdef CONFIG_ISDN_X25
1255			case ISDN_PROTO_L2_X25DTE:
1256				sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a);
1257				break;
1258			case ISDN_PROTO_L2_X25DCE:
1259				sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a);
1260				break;
1261#endif
1262			case ISDN_PROTO_L2_HDLC:
1263				sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
1264				break;
1265			default:
1266				sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1267			}
1268			printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf);
1269			i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1270			break;
1271		case ISDN_CMD_HANGUP:
1272			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1273				return -ENODEV;
1274			if (c->arg < ISDNLOOP_BCH) {
1275				a = c->arg + 1;
1276				sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1277				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1278			}
1279			break;
1280		case ISDN_CMD_SETEAZ:
1281			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1282				return -ENODEV;
1283			if (card->leased)
1284				break;
1285			if (c->arg < ISDNLOOP_BCH) {
1286				a = c->arg + 1;
1287				if (card->ptype == ISDN_PTYPE_EURO) {
1288					sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
1289						c->parm.num[0] ? "N" : "ALL", c->parm.num);
1290				} else
1291					sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
1292						c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
1293				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1294			}
1295			break;
1296		case ISDN_CMD_CLREAZ:
1297			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1298				return -ENODEV;
1299			if (card->leased)
1300				break;
1301			if (c->arg < ISDNLOOP_BCH) {
1302				a = c->arg + 1;
1303				if (card->ptype == ISDN_PTYPE_EURO)
1304					sprintf(cbuf, "%02d;MSNC\n", (int) a);
1305				else
1306					sprintf(cbuf, "%02d;EAZC\n", (int) a);
1307				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1308			}
1309			break;
1310		case ISDN_CMD_SETL2:
1311			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1312				return -ENODEV;
1313			if ((c->arg & 255) < ISDNLOOP_BCH) {
1314				a = c->arg;
1315				switch (a >> 8) {
1316				case ISDN_PROTO_L2_X75I:
1317					sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1318					break;
1319#ifdef CONFIG_ISDN_X25
1320				case ISDN_PROTO_L2_X25DTE:
1321					sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1);
1322					break;
1323				case ISDN_PROTO_L2_X25DCE:
1324					sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1);
1325					break;
1326#endif
1327				case ISDN_PROTO_L2_HDLC:
1328					sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1329					break;
1330				case ISDN_PROTO_L2_TRANS:
1331					sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1332					break;
1333				default:
1334					return -EINVAL;
1335				}
1336				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1337				card->l2_proto[a & 255] = (a >> 8);
1338			}
1339			break;
1340		case ISDN_CMD_SETL3:
1341			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1342				return -ENODEV;
1343			return 0;
1344		default:
1345			return -EINVAL;
1346		}
1347	}
1348	return 0;
1349}
1350
1351/*
1352 * Find card with given driverId
1353 */
1354static inline isdnloop_card *
1355isdnloop_findcard(int driverid)
1356{
1357	isdnloop_card *p = cards;
1358
1359	while (p) {
1360		if (p->myid == driverid)
1361			return p;
1362		p = p->next;
1363	}
1364	return (isdnloop_card *) 0;
1365}
1366
1367/*
1368 * Wrapper functions for interface to linklevel
1369 */
1370static int
1371if_command(isdn_ctrl *c)
1372{
1373	isdnloop_card *card = isdnloop_findcard(c->driver);
1374
1375	if (card)
1376		return isdnloop_command(c, card);
1377	printk(KERN_ERR
1378	       "isdnloop: if_command called with invalid driverId!\n");
1379	return -ENODEV;
1380}
1381
1382static int
1383if_writecmd(const u_char __user *buf, int len, int id, int channel)
1384{
1385	isdnloop_card *card = isdnloop_findcard(id);
1386
1387	if (card) {
1388		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1389			return -ENODEV;
1390		return isdnloop_writecmd(buf, len, 1, card);
1391	}
1392	printk(KERN_ERR
1393	       "isdnloop: if_writecmd called with invalid driverId!\n");
1394	return -ENODEV;
1395}
1396
1397static int
1398if_readstatus(u_char __user *buf, int len, int id, int channel)
1399{
1400	isdnloop_card *card = isdnloop_findcard(id);
1401
1402	if (card) {
1403		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1404			return -ENODEV;
1405		return isdnloop_readstatus(buf, len, card);
1406	}
1407	printk(KERN_ERR
1408	       "isdnloop: if_readstatus called with invalid driverId!\n");
1409	return -ENODEV;
1410}
1411
1412static int
1413if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
1414{
1415	isdnloop_card *card = isdnloop_findcard(id);
1416
1417	if (card) {
1418		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1419			return -ENODEV;
1420		/* ack request stored in skb scratch area */
1421		*(skb->head) = ack;
1422		return isdnloop_sendbuf(channel, skb, card);
1423	}
1424	printk(KERN_ERR
1425	       "isdnloop: if_sendbuf called with invalid driverId!\n");
1426	return -ENODEV;
1427}
1428
1429/*
1430 * Allocate a new card-struct, initialize it
1431 * link it into cards-list and register it at linklevel.
1432 */
1433static isdnloop_card *
1434isdnloop_initcard(char *id)
1435{
1436	isdnloop_card *card;
1437	int i;
1438	card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL);
1439	if (!card) {
1440		printk(KERN_WARNING
1441		       "isdnloop: (%s) Could not allocate card-struct.\n", id);
1442		return (isdnloop_card *) 0;
1443	}
1444	card->interface.owner = THIS_MODULE;
1445	card->interface.channels = ISDNLOOP_BCH;
1446	card->interface.hl_hdrlen  = 1; /* scratch area for storing ack flag*/
1447	card->interface.maxbufsize = 4000;
1448	card->interface.command = if_command;
1449	card->interface.writebuf_skb = if_sendbuf;
1450	card->interface.writecmd = if_writecmd;
1451	card->interface.readstat = if_readstatus;
1452	card->interface.features = ISDN_FEATURE_L2_X75I |
1453#ifdef CONFIG_ISDN_X25
1454		ISDN_FEATURE_L2_X25DTE |
1455		ISDN_FEATURE_L2_X25DCE |
1456#endif
1457		ISDN_FEATURE_L2_HDLC |
1458		ISDN_FEATURE_L3_TRANS |
1459		ISDN_FEATURE_P_UNKNOWN;
1460	card->ptype = ISDN_PTYPE_UNKNOWN;
1461	strlcpy(card->interface.id, id, sizeof(card->interface.id));
1462	card->msg_buf_write = card->msg_buf;
1463	card->msg_buf_read = card->msg_buf;
1464	card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
1465	for (i = 0; i < ISDNLOOP_BCH; i++) {
1466		card->l2_proto[i] = ISDN_PROTO_L2_X75I;
1467		skb_queue_head_init(&card->bqueue[i]);
1468	}
1469	skb_queue_head_init(&card->dqueue);
1470	spin_lock_init(&card->isdnloop_lock);
1471	card->next = cards;
1472	cards = card;
1473	if (!register_isdn(&card->interface)) {
1474		cards = cards->next;
1475		printk(KERN_WARNING
1476		       "isdnloop: Unable to register %s\n", id);
1477		kfree(card);
1478		return (isdnloop_card *) 0;
1479	}
1480	card->myid = card->interface.channels;
1481	return card;
1482}
1483
1484static int
1485isdnloop_addcard(char *id1)
1486{
1487	isdnloop_card *card;
1488	card = isdnloop_initcard(id1);
1489	if (!card) {
1490		return -EIO;
1491	}
1492	printk(KERN_INFO
1493	       "isdnloop: (%s) virtual card added\n",
1494	       card->interface.id);
1495	return 0;
1496}
1497
1498static int __init
1499isdnloop_init(void)
1500{
1501	if (isdnloop_id)
1502		return isdnloop_addcard(isdnloop_id);
1503
1504	return 0;
1505}
1506
1507static void __exit
1508isdnloop_exit(void)
1509{
1510	isdn_ctrl cmd;
1511	isdnloop_card *card = cards;
1512	isdnloop_card *last;
1513	int i;
1514
1515	isdnloop_stopallcards();
1516	while (card) {
1517		cmd.command = ISDN_STAT_UNLOAD;
1518		cmd.driver = card->myid;
1519		card->interface.statcallb(&cmd);
1520		for (i = 0; i < ISDNLOOP_BCH; i++)
1521			isdnloop_free_queue(card, i);
1522		card = card->next;
1523	}
1524	card = cards;
1525	while (card) {
1526		last = card;
1527		skb_queue_purge(&card->dqueue);
1528		card = card->next;
1529		kfree(last);
1530	}
1531	printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n");
1532}
1533
1534module_init(isdnloop_init);
1535module_exit(isdnloop_exit);
1536