]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/isdn/gigaset/i4l.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[mv-sheeva.git] / drivers / isdn / gigaset / i4l.c
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  */
42 static 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  */
114 void 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 }
139 EXPORT_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  */
150 void 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 }
157 EXPORT_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  */
166 void 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 }
188 EXPORT_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  */
194 static 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         gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
205                 cntrl->driver, cntrl->command, cntrl->arg);
206
207         cs = gigaset_get_cs_by_id(cntrl->driver);
208         if (cs == NULL) {
209                 pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
210                 return -ENODEV;
211         }
212         ch = cntrl->arg & 0xff;
213
214         switch (cntrl->command) {
215         case ISDN_CMD_IOCTL:
216                 dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
217                 return -EINVAL;
218
219         case ISDN_CMD_DIAL:
220                 gig_dbg(DEBUG_CMD,
221                         "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)",
222                         cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
223                         cntrl->parm.setup.si1, cntrl->parm.setup.si2);
224
225                 if (ch >= cs->channels) {
226                         dev_err(cs->dev,
227                                 "ISDN_CMD_DIAL: invalid channel (%d)\n", ch);
228                         return -EINVAL;
229                 }
230                 bcs = cs->bcs + ch;
231                 if (!gigaset_get_channel(bcs)) {
232                         dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
233                         return -EBUSY;
234                 }
235                 switch (bcs->proto2) {
236                 case L2_HDLC:
237                         bcs->rx_bufsize = SBUFSIZE;
238                         break;
239                 default:                        /* assume transparent */
240                         bcs->rx_bufsize = TRANSBUFSIZE;
241                 }
242                 dev_kfree_skb(bcs->rx_skb);
243                 gigaset_new_rx_skb(bcs);
244
245                 commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
246                 if (!commands) {
247                         gigaset_free_channel(bcs);
248                         dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
249                         return -ENOMEM;
250                 }
251
252                 l = 3 + strlen(cntrl->parm.setup.phone);
253                 commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC);
254                 if (!commands[AT_DIAL])
255                         goto oom;
256                 if (cntrl->parm.setup.phone[0] == '*' &&
257                     cntrl->parm.setup.phone[1] == '*') {
258                         /* internal call: translate ** prefix to CTP value */
259                         commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC);
260                         if (!commands[AT_TYPE])
261                                 goto oom;
262                         snprintf(commands[AT_DIAL], l,
263                                  "D%s\r", cntrl->parm.setup.phone+2);
264                 } else {
265                         commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC);
266                         if (!commands[AT_TYPE])
267                                 goto oom;
268                         snprintf(commands[AT_DIAL], l,
269                                  "D%s\r", cntrl->parm.setup.phone);
270                 }
271
272                 l = strlen(cntrl->parm.setup.eazmsn);
273                 if (l) {
274                         l += 8;
275                         commands[AT_MSN] = kmalloc(l, GFP_ATOMIC);
276                         if (!commands[AT_MSN])
277                                 goto oom;
278                         snprintf(commands[AT_MSN], l, "^SMSN=%s\r",
279                                  cntrl->parm.setup.eazmsn);
280                 }
281
282                 switch (cntrl->parm.setup.si1) {
283                 case 1:         /* audio */
284                         /* BC = 9090A3: 3.1 kHz audio, A-law */
285                         commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC);
286                         if (!commands[AT_BC])
287                                 goto oom;
288                         break;
289                 case 7:         /* data */
290                 default:        /* hope the app knows what it is doing */
291                         /* BC = 8890: unrestricted digital information */
292                         commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC);
293                         if (!commands[AT_BC])
294                                 goto oom;
295                 }
296                 /* ToDo: other si1 values, inspect si2, set HLC/LLC */
297
298                 commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
299                 if (!commands[AT_PROTO])
300                         goto oom;
301                 snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2);
302
303                 commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
304                 if (!commands[AT_ISO])
305                         goto oom;
306                 snprintf(commands[AT_ISO], 9, "^SISO=%u\r",
307                          (unsigned) bcs->channel + 1);
308
309                 if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands,
310                                        bcs->at_state.seq_index, NULL)) {
311                         for (i = 0; i < AT_NUM; ++i)
312                                 kfree(commands[i]);
313                         kfree(commands);
314                         gigaset_free_channel(bcs);
315                         return -ENOMEM;
316                 }
317                 gigaset_schedule_event(cs);
318                 break;
319         case ISDN_CMD_ACCEPTD:
320                 gig_dbg(DEBUG_CMD, "ISDN_CMD_ACCEPTD");
321                 if (ch >= cs->channels) {
322                         dev_err(cs->dev,
323                                 "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch);
324                         return -EINVAL;
325                 }
326                 bcs = cs->bcs + ch;
327                 switch (bcs->proto2) {
328                 case L2_HDLC:
329                         bcs->rx_bufsize = SBUFSIZE;
330                         break;
331                 default:                        /* assume transparent */
332                         bcs->rx_bufsize = TRANSBUFSIZE;
333                 }
334                 dev_kfree_skb(bcs->rx_skb);
335                 gigaset_new_rx_skb(bcs);
336                 if (!gigaset_add_event(cs, &bcs->at_state,
337                                        EV_ACCEPT, NULL, 0, NULL))
338                         return -ENOMEM;
339                 gigaset_schedule_event(cs);
340
341                 break;
342         case ISDN_CMD_HANGUP:
343                 gig_dbg(DEBUG_CMD, "ISDN_CMD_HANGUP");
344                 if (ch >= cs->channels) {
345                         dev_err(cs->dev,
346                                 "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch);
347                         return -EINVAL;
348                 }
349                 bcs = cs->bcs + ch;
350                 if (!gigaset_add_event(cs, &bcs->at_state,
351                                        EV_HUP, NULL, 0, NULL))
352                         return -ENOMEM;
353                 gigaset_schedule_event(cs);
354
355                 break;
356         case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */
357                 dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n");
358                 break;
359         case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */
360                 dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n",
361                          cntrl->parm.num);
362                 break;
363         case ISDN_CMD_SETL2: /* Set L2 to given protocol */
364                 if (ch >= cs->channels) {
365                         dev_err(cs->dev,
366                                 "ISDN_CMD_SETL2: invalid channel (%d)\n", ch);
367                         return -EINVAL;
368                 }
369                 bcs = cs->bcs + ch;
370                 if (bcs->chstate & CHS_D_UP) {
371                         dev_err(cs->dev,
372                                 "ISDN_CMD_SETL2: channel active (%d)\n", ch);
373                         return -EINVAL;
374                 }
375                 switch (cntrl->arg >> 8) {
376                 case ISDN_PROTO_L2_HDLC:
377                         gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC");
378                         bcs->proto2 = L2_HDLC;
379                         break;
380                 case ISDN_PROTO_L2_TRANS:
381                         gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE");
382                         bcs->proto2 = L2_VOICE;
383                         break;
384                 default:
385                         dev_err(cs->dev,
386                                 "ISDN_CMD_SETL2: unsupported protocol (%lu)\n",
387                                 cntrl->arg >> 8);
388                         return -EINVAL;
389                 }
390                 break;
391         case ISDN_CMD_SETL3: /* Set L3 to given protocol */
392                 gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL3");
393                 if (ch >= cs->channels) {
394                         dev_err(cs->dev,
395                                 "ISDN_CMD_SETL3: invalid channel (%d)\n", ch);
396                         return -EINVAL;
397                 }
398
399                 if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
400                         dev_err(cs->dev,
401                                 "ISDN_CMD_SETL3: unsupported protocol (%lu)\n",
402                                 cntrl->arg >> 8);
403                         return -EINVAL;
404                 }
405
406                 break;
407
408         default:
409                 gig_dbg(DEBUG_CMD, "unknown command %d from LL",
410                         cntrl->command);
411                 return -EINVAL;
412         }
413
414         return retval;
415
416 oom:
417         dev_err(bcs->cs->dev, "out of memory\n");
418         for (i = 0; i < AT_NUM; ++i)
419                 kfree(commands[i]);
420         kfree(commands);
421         gigaset_free_channel(bcs);
422         return -ENOMEM;
423 }
424
425 static void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
426 {
427         isdn_if *iif = cs->iif;
428         isdn_ctrl command;
429
430         command.driver = cs->myid;
431         command.command = cmd;
432         command.arg = 0;
433         iif->statcallb(&command);
434 }
435
436 static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
437 {
438         isdn_if *iif = bcs->cs->iif;
439         isdn_ctrl command;
440
441         command.driver = bcs->cs->myid;
442         command.command = cmd;
443         command.arg = bcs->channel;
444         iif->statcallb(&command);
445 }
446
447 /**
448  * gigaset_isdn_icall() - signal incoming call
449  * @at_state:   connection state structure.
450  *
451  * Called by main module to notify the LL that an incoming call has been
452  * received. @at_state contains the parameters of the call.
453  *
454  * Return value: call disposition (ICALL_*)
455  */
456 int gigaset_isdn_icall(struct at_state_t *at_state)
457 {
458         struct cardstate *cs = at_state->cs;
459         struct bc_state *bcs = at_state->bcs;
460         isdn_if *iif = cs->iif;
461         isdn_ctrl response;
462         int retval;
463
464         /* fill ICALL structure */
465         response.parm.setup.si1 = 0;    /* default: unknown */
466         response.parm.setup.si2 = 0;
467         response.parm.setup.screen = 0;
468         response.parm.setup.plan = 0;
469         if (!at_state->str_var[STR_ZBC]) {
470                 /* no BC (internal call): assume speech, A-law */
471                 response.parm.setup.si1 = 1;
472         } else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) {
473                 /* unrestricted digital information */
474                 response.parm.setup.si1 = 7;
475         } else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) {
476                 /* speech, A-law */
477                 response.parm.setup.si1 = 1;
478         } else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) {
479                 /* 3,1 kHz audio, A-law */
480                 response.parm.setup.si1 = 1;
481                 response.parm.setup.si2 = 2;
482         } else {
483                 dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
484                      at_state->str_var[STR_ZBC]);
485                 return ICALL_IGNORE;
486         }
487         if (at_state->str_var[STR_NMBR]) {
488                 strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
489                         sizeof response.parm.setup.phone);
490         } else
491                 response.parm.setup.phone[0] = 0;
492         if (at_state->str_var[STR_ZCPN]) {
493                 strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
494                         sizeof response.parm.setup.eazmsn);
495         } else
496                 response.parm.setup.eazmsn[0] = 0;
497
498         if (!bcs) {
499                 dev_notice(cs->dev, "no channel for incoming call\n");
500                 response.command = ISDN_STAT_ICALLW;
501                 response.arg = 0;
502         } else {
503                 gig_dbg(DEBUG_CMD, "Sending ICALL");
504                 response.command = ISDN_STAT_ICALL;
505                 response.arg = bcs->channel;
506         }
507         response.driver = cs->myid;
508         retval = iif->statcallb(&response);
509         gig_dbg(DEBUG_CMD, "Response: %d", retval);
510         switch (retval) {
511         case 0: /* no takers */
512                 return ICALL_IGNORE;
513         case 1: /* alerting */
514                 bcs->chstate |= CHS_NOTIFY_LL;
515                 return ICALL_ACCEPT;
516         case 2: /* reject */
517                 return ICALL_REJECT;
518         case 3: /* incomplete */
519                 dev_warn(cs->dev,
520                        "LL requested unsupported feature: Incomplete Number\n");
521                 return ICALL_IGNORE;
522         case 4: /* proceeding */
523                 /* Gigaset will send ALERTING anyway.
524                  * There doesn't seem to be a way to avoid this.
525                  */
526                 return ICALL_ACCEPT;
527         case 5: /* deflect */
528                 dev_warn(cs->dev,
529                          "LL requested unsupported feature: Call Deflection\n");
530                 return ICALL_IGNORE;
531         default:
532                 dev_err(cs->dev, "LL error %d on ICALL\n", retval);
533                 return ICALL_IGNORE;
534         }
535 }
536
537 /**
538  * gigaset_isdn_connD() - signal D channel connect
539  * @bcs:        B channel descriptor structure.
540  *
541  * Called by main module to notify the LL that the D channel connection has
542  * been established.
543  */
544 void gigaset_isdn_connD(struct bc_state *bcs)
545 {
546         gig_dbg(DEBUG_CMD, "sending DCONN");
547         gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
548 }
549
550 /**
551  * gigaset_isdn_hupD() - signal D channel hangup
552  * @bcs:        B channel descriptor structure.
553  *
554  * Called by main module to notify the LL that the D channel connection has
555  * been shut down.
556  */
557 void gigaset_isdn_hupD(struct bc_state *bcs)
558 {
559         gig_dbg(DEBUG_CMD, "sending DHUP");
560         gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
561 }
562
563 /**
564  * gigaset_isdn_connB() - signal B channel connect
565  * @bcs:        B channel descriptor structure.
566  *
567  * Called by main module to notify the LL that the B channel connection has
568  * been established.
569  */
570 void gigaset_isdn_connB(struct bc_state *bcs)
571 {
572         gig_dbg(DEBUG_CMD, "sending BCONN");
573         gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
574 }
575
576 /**
577  * gigaset_isdn_hupB() - signal B channel hangup
578  * @bcs:        B channel descriptor structure.
579  *
580  * Called by main module to notify the LL that the B channel connection has
581  * been shut down.
582  */
583 void gigaset_isdn_hupB(struct bc_state *bcs)
584 {
585         gig_dbg(DEBUG_CMD, "sending BHUP");
586         gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
587 }
588
589 /**
590  * gigaset_isdn_start() - signal device availability
591  * @cs:         device descriptor structure.
592  *
593  * Called by main module to notify the LL that the device is available for
594  * use.
595  */
596 void gigaset_isdn_start(struct cardstate *cs)
597 {
598         gig_dbg(DEBUG_CMD, "sending RUN");
599         gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
600 }
601
602 /**
603  * gigaset_isdn_stop() - signal device unavailability
604  * @cs:         device descriptor structure.
605  *
606  * Called by main module to notify the LL that the device is no longer
607  * available for use.
608  */
609 void gigaset_isdn_stop(struct cardstate *cs)
610 {
611         gig_dbg(DEBUG_CMD, "sending STOP");
612         gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
613 }
614
615 /**
616  * gigaset_isdn_regdev() - register to LL
617  * @cs:         device descriptor structure.
618  * @isdnid:     device name.
619  *
620  * Return value: 1 for success, 0 for failure
621  */
622 int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
623 {
624         isdn_if *iif;
625
626         pr_info("ISDN4Linux interface\n");
627
628         iif = kmalloc(sizeof *iif, GFP_KERNEL);
629         if (!iif) {
630                 pr_err("out of memory\n");
631                 return 0;
632         }
633
634         if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
635             >= sizeof iif->id) {
636                 pr_err("ID too long: %s\n", isdnid);
637                 kfree(iif);
638                 return 0;
639         }
640
641         iif->owner = THIS_MODULE;
642         iif->channels = cs->channels;
643         iif->maxbufsize = MAX_BUF_SIZE;
644         iif->features = ISDN_FEATURE_L2_TRANS |
645                 ISDN_FEATURE_L2_HDLC |
646                 ISDN_FEATURE_L2_X75I |
647                 ISDN_FEATURE_L3_TRANS |
648                 ISDN_FEATURE_P_EURO;
649         iif->hl_hdrlen = HW_HDR_LEN;            /* Area for storing ack */
650         iif->command = command_from_LL;
651         iif->writebuf_skb = writebuf_from_LL;
652         iif->writecmd = NULL;                   /* Don't support isdnctrl */
653         iif->readstat = NULL;                   /* Don't support isdnctrl */
654         iif->rcvcallb_skb = NULL;               /* Will be set by LL */
655         iif->statcallb = NULL;                  /* Will be set by LL */
656
657         if (!register_isdn(iif)) {
658                 pr_err("register_isdn failed\n");
659                 kfree(iif);
660                 return 0;
661         }
662
663         cs->iif = iif;
664         cs->myid = iif->channels;               /* Set my device id */
665         cs->hw_hdr_len = HW_HDR_LEN;
666         return 1;
667 }
668
669 /**
670  * gigaset_isdn_unregdev() - unregister device from LL
671  * @cs:         device descriptor structure.
672  */
673 void gigaset_isdn_unregdev(struct cardstate *cs)
674 {
675         gig_dbg(DEBUG_CMD, "sending UNLOAD");
676         gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
677         kfree(cs->iif);
678         cs->iif = NULL;
679 }
680
681 /**
682  * gigaset_isdn_regdrv() - register driver to LL
683  */
684 void gigaset_isdn_regdrv(void)
685 {
686         /* nothing to do */
687 }
688
689 /**
690  * gigaset_isdn_unregdrv() - unregister driver from LL
691  */
692 void gigaset_isdn_unregdrv(void)
693 {
694         /* nothing to do */
695 }