• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/isdn/gigaset/
1/*
2 * Stuff used by all variants of the driver
3 *
4 * Copyright (c) 2001 by Stefan Eilers,
5 *                       Hansjoerg Lipp <hjlipp@web.de>,
6 *                       Tilman Schmidt <tilman@imap.cc>.
7 *
8 * =====================================================================
9 *	This program is free software; you can redistribute it and/or
10 *	modify it under the terms of the GNU General Public License as
11 *	published by the Free Software Foundation; either version 2 of
12 *	the License, or (at your option) any later version.
13 * =====================================================================
14 */
15
16#include "gigaset.h"
17#include <linux/isdnif.h>
18
19#define SBUFSIZE	4096	/* sk_buff payload size */
20#define TRANSBUFSIZE	768	/* bytes per skb for transparent receive */
21#define HW_HDR_LEN	2	/* Header size used to store ack info */
22#define MAX_BUF_SIZE	(SBUFSIZE - HW_HDR_LEN)	/* max data packet from LL */
23
24/* == Handling of I4L IO =====================================================*/
25
26/* writebuf_from_LL
27 * called by LL to transmit data on an open channel
28 * inserts the buffer data into the send queue and starts the transmission
29 * Note that this operation must not sleep!
30 * When the buffer is processed completely, gigaset_skb_sent() should be called.
31 * parameters:
32 *	driverID	driver ID as assigned by LL
33 *	channel		channel number
34 *	ack		if != 0 LL wants to be notified on completion via
35 *			statcallb(ISDN_STAT_BSENT)
36 *	skb		skb containing data to send
37 * return value:
38 *	number of accepted bytes
39 *	0 if temporarily unable to accept data (out of buffer space)
40 *	<0 on error (eg. -EINVAL)
41 */
42static int writebuf_from_LL(int driverID, int channel, int ack,
43			    struct sk_buff *skb)
44{
45	struct cardstate *cs = gigaset_get_cs_by_id(driverID);
46	struct bc_state *bcs;
47	unsigned char *ack_header;
48	unsigned len;
49
50	if (!cs) {
51		pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
52		return -ENODEV;
53	}
54	if (channel < 0 || channel >= cs->channels) {
55		dev_err(cs->dev, "%s: invalid channel ID (%d)\n",
56			__func__, channel);
57		return -ENODEV;
58	}
59	bcs = &cs->bcs[channel];
60
61	/* can only handle linear sk_buffs */
62	if (skb_linearize(skb) < 0) {
63		dev_err(cs->dev, "%s: skb_linearize failed\n", __func__);
64		return -ENOMEM;
65	}
66	len = skb->len;
67
68	gig_dbg(DEBUG_LLDATA,
69		"Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)",
70		driverID, channel, ack, len);
71
72	if (!len) {
73		if (ack)
74			dev_notice(cs->dev, "%s: not ACKing empty packet\n",
75				   __func__);
76		return 0;
77	}
78	if (len > MAX_BUF_SIZE) {
79		dev_err(cs->dev, "%s: packet too large (%d bytes)\n",
80			__func__, len);
81		return -EINVAL;
82	}
83
84	/* set up acknowledgement header */
85	if (skb_headroom(skb) < HW_HDR_LEN) {
86		/* should never happen */
87		dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__);
88		return -ENOMEM;
89	}
90	skb_set_mac_header(skb, -HW_HDR_LEN);
91	skb->mac_len = HW_HDR_LEN;
92	ack_header = skb_mac_header(skb);
93	if (ack) {
94		ack_header[0] = len & 0xff;
95		ack_header[1] = len >> 8;
96	} else {
97		ack_header[0] = ack_header[1] = 0;
98	}
99	gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x",
100		len, ack, ack_header[0], ack_header[1]);
101
102	/* pass to device-specific module */
103	return cs->ops->send_skb(bcs, skb);
104}
105
106/**
107 * gigaset_skb_sent() - acknowledge sending an skb
108 * @bcs:	B channel descriptor structure.
109 * @skb:	sent data.
110 *
111 * Called by hardware module {bas,ser,usb}_gigaset when the data in a
112 * skb has been successfully sent, for signalling completion to the LL.
113 */
114void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
115{
116	isdn_if *iif = bcs->cs->iif;
117	unsigned char *ack_header = skb_mac_header(skb);
118	unsigned len;
119	isdn_ctrl response;
120
121	++bcs->trans_up;
122
123	if (skb->len)
124		dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
125			 __func__, skb->len);
126
127	len = ack_header[0] + ((unsigned) ack_header[1] << 8);
128	if (len) {
129		gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
130			bcs->cs->myid, bcs->channel, len);
131
132		response.driver = bcs->cs->myid;
133		response.command = ISDN_STAT_BSENT;
134		response.arg = bcs->channel;
135		response.parm.length = len;
136		iif->statcallb(&response);
137	}
138}
139EXPORT_SYMBOL_GPL(gigaset_skb_sent);
140
141/**
142 * gigaset_skb_rcvd() - pass received skb to LL
143 * @bcs:	B channel descriptor structure.
144 * @skb:	received data.
145 *
146 * Called by hardware module {bas,ser,usb}_gigaset when user data has
147 * been successfully received, for passing to the LL.
148 * Warning: skb must not be accessed anymore!
149 */
150void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
151{
152	isdn_if *iif = bcs->cs->iif;
153
154	iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb);
155	bcs->trans_down++;
156}
157EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);
158
159/**
160 * gigaset_isdn_rcv_err() - signal receive error
161 * @bcs:	B channel descriptor structure.
162 *
163 * Called by hardware module {bas,ser,usb}_gigaset when a receive error
164 * has occurred, for signalling to the LL.
165 */
166void gigaset_isdn_rcv_err(struct bc_state *bcs)
167{
168	isdn_if *iif = bcs->cs->iif;
169	isdn_ctrl response;
170
171	/* if currently ignoring packets, just count down */
172	if (bcs->ignore) {
173		bcs->ignore--;
174		return;
175	}
176
177	/* update statistics */
178	bcs->corrupted++;
179
180	/* error -> LL */
181	gig_dbg(DEBUG_CMD, "sending L1ERR");
182	response.driver = bcs->cs->myid;
183	response.command = ISDN_STAT_L1ERR;
184	response.arg = bcs->channel;
185	response.parm.errcode = ISDN_STAT_L1ERR_RECV;
186	iif->statcallb(&response);
187}
188EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err);
189
190/* This function will be called by LL to send commands
191 * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
192 * so don't put too much effort into it.
193 */
194static int command_from_LL(isdn_ctrl *cntrl)
195{
196	struct cardstate *cs;
197	struct bc_state *bcs;
198	int retval = 0;
199	char **commands;
200	int ch;
201	int i;
202	size_t l;
203
204	gigaset_debugdrivers();
205
206	gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
207		cntrl->driver, cntrl->command, cntrl->arg);
208
209	cs = gigaset_get_cs_by_id(cntrl->driver);
210	if (cs == NULL) {
211		pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
212		return -ENODEV;
213	}
214	ch = cntrl->arg & 0xff;
215
216	switch (cntrl->command) {
217	case ISDN_CMD_IOCTL:
218		dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
219		return -EINVAL;
220
221	case ISDN_CMD_DIAL:
222		gig_dbg(DEBUG_CMD,
223			"ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)",
224			cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
225			cntrl->parm.setup.si1, cntrl->parm.setup.si2);
226
227		if (ch >= cs->channels) {
228			dev_err(cs->dev,
229				"ISDN_CMD_DIAL: invalid channel (%d)\n", ch);
230			return -EINVAL;
231		}
232		bcs = cs->bcs + ch;
233		if (!gigaset_get_channel(bcs)) {
234			dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
235			return -EBUSY;
236		}
237		switch (bcs->proto2) {
238		case L2_HDLC:
239			bcs->rx_bufsize = SBUFSIZE;
240			break;
241		default:			/* assume transparent */
242			bcs->rx_bufsize = TRANSBUFSIZE;
243		}
244		dev_kfree_skb(bcs->rx_skb);
245		gigaset_new_rx_skb(bcs);
246
247		commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
248		if (!commands) {
249			gigaset_free_channel(bcs);
250			dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
251			return -ENOMEM;
252		}
253
254		l = 3 + strlen(cntrl->parm.setup.phone);
255		commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC);
256		if (!commands[AT_DIAL])
257			goto oom;
258		if (cntrl->parm.setup.phone[0] == '*' &&
259		    cntrl->parm.setup.phone[1] == '*') {
260			/* internal call: translate ** prefix to CTP value */
261			commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC);
262			if (!commands[AT_TYPE])
263				goto oom;
264			snprintf(commands[AT_DIAL], l,
265				 "D%s\r", cntrl->parm.setup.phone+2);
266		} else {
267			commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC);
268			if (!commands[AT_TYPE])
269				goto oom;
270			snprintf(commands[AT_DIAL], l,
271				 "D%s\r", cntrl->parm.setup.phone);
272		}
273
274		l = strlen(cntrl->parm.setup.eazmsn);
275		if (l) {
276			l += 8;
277			commands[AT_MSN] = kmalloc(l, GFP_ATOMIC);
278			if (!commands[AT_MSN])
279				goto oom;
280			snprintf(commands[AT_MSN], l, "^SMSN=%s\r",
281				 cntrl->parm.setup.eazmsn);
282		}
283
284		switch (cntrl->parm.setup.si1) {
285		case 1:		/* audio */
286			/* BC = 9090A3: 3.1 kHz audio, A-law */
287			commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC);
288			if (!commands[AT_BC])
289				goto oom;
290			break;
291		case 7:		/* data */
292		default:	/* hope the app knows what it is doing */
293			/* BC = 8890: unrestricted digital information */
294			commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC);
295			if (!commands[AT_BC])
296				goto oom;
297		}
298		/* ToDo: other si1 values, inspect si2, set HLC/LLC */
299
300		commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
301		if (!commands[AT_PROTO])
302			goto oom;
303		snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2);
304
305		commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
306		if (!commands[AT_ISO])
307			goto oom;
308		snprintf(commands[AT_ISO], 9, "^SISO=%u\r",
309			 (unsigned) bcs->channel + 1);
310
311		if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands,
312				       bcs->at_state.seq_index, NULL)) {
313			for (i = 0; i < AT_NUM; ++i)
314				kfree(commands[i]);
315			kfree(commands);
316			gigaset_free_channel(bcs);
317			return -ENOMEM;
318		}
319		gigaset_schedule_event(cs);
320		break;
321	case ISDN_CMD_ACCEPTD:
322		gig_dbg(DEBUG_CMD, "ISDN_CMD_ACCEPTD");
323		if (ch >= cs->channels) {
324			dev_err(cs->dev,
325				"ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch);
326			return -EINVAL;
327		}
328		bcs = cs->bcs + ch;
329		switch (bcs->proto2) {
330		case L2_HDLC:
331			bcs->rx_bufsize = SBUFSIZE;
332			break;
333		default:			/* assume transparent */
334			bcs->rx_bufsize = TRANSBUFSIZE;
335		}
336		dev_kfree_skb(bcs->rx_skb);
337		gigaset_new_rx_skb(bcs);
338		if (!gigaset_add_event(cs, &bcs->at_state,
339				       EV_ACCEPT, NULL, 0, NULL))
340			return -ENOMEM;
341		gigaset_schedule_event(cs);
342
343		break;
344	case ISDN_CMD_HANGUP:
345		gig_dbg(DEBUG_CMD, "ISDN_CMD_HANGUP");
346		if (ch >= cs->channels) {
347			dev_err(cs->dev,
348				"ISDN_CMD_HANGUP: invalid channel (%d)\n", ch);
349			return -EINVAL;
350		}
351		bcs = cs->bcs + ch;
352		if (!gigaset_add_event(cs, &bcs->at_state,
353				       EV_HUP, NULL, 0, NULL))
354			return -ENOMEM;
355		gigaset_schedule_event(cs);
356
357		break;
358	case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */
359		dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n");
360		break;
361	case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */
362		dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n",
363			 cntrl->parm.num);
364		break;
365	case ISDN_CMD_SETL2: /* Set L2 to given protocol */
366		if (ch >= cs->channels) {
367			dev_err(cs->dev,
368				"ISDN_CMD_SETL2: invalid channel (%d)\n", ch);
369			return -EINVAL;
370		}
371		bcs = cs->bcs + ch;
372		if (bcs->chstate & CHS_D_UP) {
373			dev_err(cs->dev,
374				"ISDN_CMD_SETL2: channel active (%d)\n", ch);
375			return -EINVAL;
376		}
377		switch (cntrl->arg >> 8) {
378		case ISDN_PROTO_L2_HDLC:
379			gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC");
380			bcs->proto2 = L2_HDLC;
381			break;
382		case ISDN_PROTO_L2_TRANS:
383			gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE");
384			bcs->proto2 = L2_VOICE;
385			break;
386		default:
387			dev_err(cs->dev,
388				"ISDN_CMD_SETL2: unsupported protocol (%lu)\n",
389				cntrl->arg >> 8);
390			return -EINVAL;
391		}
392		break;
393	case ISDN_CMD_SETL3: /* Set L3 to given protocol */
394		gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL3");
395		if (ch >= cs->channels) {
396			dev_err(cs->dev,
397				"ISDN_CMD_SETL3: invalid channel (%d)\n", ch);
398			return -EINVAL;
399		}
400
401		if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
402			dev_err(cs->dev,
403				"ISDN_CMD_SETL3: unsupported protocol (%lu)\n",
404				cntrl->arg >> 8);
405			return -EINVAL;
406		}
407
408		break;
409
410	default:
411		gig_dbg(DEBUG_CMD, "unknown command %d from LL",
412			cntrl->command);
413		return -EINVAL;
414	}
415
416	return retval;
417
418oom:
419	dev_err(bcs->cs->dev, "out of memory\n");
420	for (i = 0; i < AT_NUM; ++i)
421		kfree(commands[i]);
422	kfree(commands);
423	gigaset_free_channel(bcs);
424	return -ENOMEM;
425}
426
427static void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
428{
429	isdn_if *iif = cs->iif;
430	isdn_ctrl command;
431
432	command.driver = cs->myid;
433	command.command = cmd;
434	command.arg = 0;
435	iif->statcallb(&command);
436}
437
438static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
439{
440	isdn_if *iif = bcs->cs->iif;
441	isdn_ctrl command;
442
443	command.driver = bcs->cs->myid;
444	command.command = cmd;
445	command.arg = bcs->channel;
446	iif->statcallb(&command);
447}
448
449/**
450 * gigaset_isdn_icall() - signal incoming call
451 * @at_state:	connection state structure.
452 *
453 * Called by main module to notify the LL that an incoming call has been
454 * received. @at_state contains the parameters of the call.
455 *
456 * Return value: call disposition (ICALL_*)
457 */
458int gigaset_isdn_icall(struct at_state_t *at_state)
459{
460	struct cardstate *cs = at_state->cs;
461	struct bc_state *bcs = at_state->bcs;
462	isdn_if *iif = cs->iif;
463	isdn_ctrl response;
464	int retval;
465
466	/* fill ICALL structure */
467	response.parm.setup.si1 = 0;	/* default: unknown */
468	response.parm.setup.si2 = 0;
469	response.parm.setup.screen = 0;
470	response.parm.setup.plan = 0;
471	if (!at_state->str_var[STR_ZBC]) {
472		/* no BC (internal call): assume speech, A-law */
473		response.parm.setup.si1 = 1;
474	} else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) {
475		/* unrestricted digital information */
476		response.parm.setup.si1 = 7;
477	} else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) {
478		/* speech, A-law */
479		response.parm.setup.si1 = 1;
480	} else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) {
481		/* 3,1 kHz audio, A-law */
482		response.parm.setup.si1 = 1;
483		response.parm.setup.si2 = 2;
484	} else {
485		dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
486		     at_state->str_var[STR_ZBC]);
487		return ICALL_IGNORE;
488	}
489	if (at_state->str_var[STR_NMBR]) {
490		strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
491			sizeof response.parm.setup.phone);
492	} else
493		response.parm.setup.phone[0] = 0;
494	if (at_state->str_var[STR_ZCPN]) {
495		strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
496			sizeof response.parm.setup.eazmsn);
497	} else
498		response.parm.setup.eazmsn[0] = 0;
499
500	if (!bcs) {
501		dev_notice(cs->dev, "no channel for incoming call\n");
502		response.command = ISDN_STAT_ICALLW;
503		response.arg = 0;
504	} else {
505		gig_dbg(DEBUG_CMD, "Sending ICALL");
506		response.command = ISDN_STAT_ICALL;
507		response.arg = bcs->channel;
508	}
509	response.driver = cs->myid;
510	retval = iif->statcallb(&response);
511	gig_dbg(DEBUG_CMD, "Response: %d", retval);
512	switch (retval) {
513	case 0:	/* no takers */
514		return ICALL_IGNORE;
515	case 1:	/* alerting */
516		bcs->chstate |= CHS_NOTIFY_LL;
517		return ICALL_ACCEPT;
518	case 2:	/* reject */
519		return ICALL_REJECT;
520	case 3:	/* incomplete */
521		dev_warn(cs->dev,
522		       "LL requested unsupported feature: Incomplete Number\n");
523		return ICALL_IGNORE;
524	case 4:	/* proceeding */
525		/* Gigaset will send ALERTING anyway.
526		 * There doesn't seem to be a way to avoid this.
527		 */
528		return ICALL_ACCEPT;
529	case 5:	/* deflect */
530		dev_warn(cs->dev,
531			 "LL requested unsupported feature: Call Deflection\n");
532		return ICALL_IGNORE;
533	default:
534		dev_err(cs->dev, "LL error %d on ICALL\n", retval);
535		return ICALL_IGNORE;
536	}
537}
538
539/**
540 * gigaset_isdn_connD() - signal D channel connect
541 * @bcs:	B channel descriptor structure.
542 *
543 * Called by main module to notify the LL that the D channel connection has
544 * been established.
545 */
546void gigaset_isdn_connD(struct bc_state *bcs)
547{
548	gig_dbg(DEBUG_CMD, "sending DCONN");
549	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
550}
551
552/**
553 * gigaset_isdn_hupD() - signal D channel hangup
554 * @bcs:	B channel descriptor structure.
555 *
556 * Called by main module to notify the LL that the D channel connection has
557 * been shut down.
558 */
559void gigaset_isdn_hupD(struct bc_state *bcs)
560{
561	gig_dbg(DEBUG_CMD, "sending DHUP");
562	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
563}
564
565/**
566 * gigaset_isdn_connB() - signal B channel connect
567 * @bcs:	B channel descriptor structure.
568 *
569 * Called by main module to notify the LL that the B channel connection has
570 * been established.
571 */
572void gigaset_isdn_connB(struct bc_state *bcs)
573{
574	gig_dbg(DEBUG_CMD, "sending BCONN");
575	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
576}
577
578/**
579 * gigaset_isdn_hupB() - signal B channel hangup
580 * @bcs:	B channel descriptor structure.
581 *
582 * Called by main module to notify the LL that the B channel connection has
583 * been shut down.
584 */
585void gigaset_isdn_hupB(struct bc_state *bcs)
586{
587	gig_dbg(DEBUG_CMD, "sending BHUP");
588	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
589}
590
591/**
592 * gigaset_isdn_start() - signal device availability
593 * @cs:		device descriptor structure.
594 *
595 * Called by main module to notify the LL that the device is available for
596 * use.
597 */
598void gigaset_isdn_start(struct cardstate *cs)
599{
600	gig_dbg(DEBUG_CMD, "sending RUN");
601	gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
602}
603
604/**
605 * gigaset_isdn_stop() - signal device unavailability
606 * @cs:		device descriptor structure.
607 *
608 * Called by main module to notify the LL that the device is no longer
609 * available for use.
610 */
611void gigaset_isdn_stop(struct cardstate *cs)
612{
613	gig_dbg(DEBUG_CMD, "sending STOP");
614	gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
615}
616
617/**
618 * gigaset_isdn_regdev() - register to LL
619 * @cs:		device descriptor structure.
620 * @isdnid:	device name.
621 *
622 * Return value: 1 for success, 0 for failure
623 */
624int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
625{
626	isdn_if *iif;
627
628	pr_info("ISDN4Linux interface\n");
629
630	iif = kmalloc(sizeof *iif, GFP_KERNEL);
631	if (!iif) {
632		pr_err("out of memory\n");
633		return 0;
634	}
635
636	if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
637	    >= sizeof iif->id) {
638		pr_err("ID too long: %s\n", isdnid);
639		kfree(iif);
640		return 0;
641	}
642
643	iif->owner = THIS_MODULE;
644	iif->channels = cs->channels;
645	iif->maxbufsize = MAX_BUF_SIZE;
646	iif->features = ISDN_FEATURE_L2_TRANS |
647		ISDN_FEATURE_L2_HDLC |
648		ISDN_FEATURE_L2_X75I |
649		ISDN_FEATURE_L3_TRANS |
650		ISDN_FEATURE_P_EURO;
651	iif->hl_hdrlen = HW_HDR_LEN;		/* Area for storing ack */
652	iif->command = command_from_LL;
653	iif->writebuf_skb = writebuf_from_LL;
654	iif->writecmd = NULL;			/* Don't support isdnctrl */
655	iif->readstat = NULL;			/* Don't support isdnctrl */
656	iif->rcvcallb_skb = NULL;		/* Will be set by LL */
657	iif->statcallb = NULL;			/* Will be set by LL */
658
659	if (!register_isdn(iif)) {
660		pr_err("register_isdn failed\n");
661		kfree(iif);
662		return 0;
663	}
664
665	cs->iif = iif;
666	cs->myid = iif->channels;		/* Set my device id */
667	cs->hw_hdr_len = HW_HDR_LEN;
668	return 1;
669}
670
671/**
672 * gigaset_isdn_unregdev() - unregister device from LL
673 * @cs:		device descriptor structure.
674 */
675void gigaset_isdn_unregdev(struct cardstate *cs)
676{
677	gig_dbg(DEBUG_CMD, "sending UNLOAD");
678	gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
679	kfree(cs->iif);
680	cs->iif = NULL;
681}
682
683/**
684 * gigaset_isdn_regdrv() - register driver to LL
685 */
686void gigaset_isdn_regdrv(void)
687{
688	/* nothing to do */
689}
690
691/**
692 * gigaset_isdn_unregdrv() - unregister driver from LL
693 */
694void gigaset_isdn_unregdrv(void)
695{
696	/* nothing to do */
697}
698