Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[sfrench/cifs-2.6.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         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
418 oom:
419         dev_err(bcs->cs->dev, "out of memory\n");
420         for (i = 0; i < AT_NUM; ++i)
421                 kfree(commands[i]);
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 #ifdef GIG_X75
647                 ISDN_FEATURE_L2_X75I |
648 #endif
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  */
675 void 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  */
686 void gigaset_isdn_regdrv(void)
687 {
688         /* nothing to do */
689 }
690
691 /**
692  * gigaset_isdn_unregdrv() - unregister driver from LL
693  */
694 void gigaset_isdn_unregdrv(void)
695 {
696         /* nothing to do */
697 }