gigaset: add kerneldoc comments
[safe/jmp/linux-2.6] / 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
18 /* == Handling of I4L IO =====================================================*/
19
20 /* writebuf_from_LL
21  * called by LL to transmit data on an open channel
22  * inserts the buffer data into the send queue and starts the transmission
23  * Note that this operation must not sleep!
24  * When the buffer is processed completely, gigaset_skb_sent() should be called.
25  * parameters:
26  *      driverID        driver ID as assigned by LL
27  *      channel         channel number
28  *      ack             if != 0 LL wants to be notified on completion via
29  *                      statcallb(ISDN_STAT_BSENT)
30  *      skb             skb containing data to send
31  * return value:
32  *      number of accepted bytes
33  *      0 if temporarily unable to accept data (out of buffer space)
34  *      <0 on error (eg. -EINVAL)
35  */
36 static int writebuf_from_LL(int driverID, int channel, int ack,
37                             struct sk_buff *skb)
38 {
39         struct cardstate *cs;
40         struct bc_state *bcs;
41         unsigned len;
42         unsigned skblen;
43
44         if (!(cs = gigaset_get_cs_by_id(driverID))) {
45                 pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
46                 return -ENODEV;
47         }
48         if (channel < 0 || channel >= cs->channels) {
49                 dev_err(cs->dev, "%s: invalid channel ID (%d)\n",
50                         __func__, channel);
51                 return -ENODEV;
52         }
53         bcs = &cs->bcs[channel];
54
55         /* can only handle linear sk_buffs */
56         if (skb_linearize(skb) < 0) {
57                 dev_err(cs->dev, "%s: skb_linearize failed\n", __func__);
58                 return -ENOMEM;
59         }
60         len = skb->len;
61
62         gig_dbg(DEBUG_LLDATA,
63                 "Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)",
64                 driverID, channel, ack, len);
65
66         if (!len) {
67                 if (ack)
68                         dev_notice(cs->dev, "%s: not ACKing empty packet\n",
69                                    __func__);
70                 return 0;
71         }
72         if (len > MAX_BUF_SIZE) {
73                 dev_err(cs->dev, "%s: packet too large (%d bytes)\n",
74                         __func__, len);
75                 return -EINVAL;
76         }
77
78         skblen = ack ? len : 0;
79         skb->head[0] = skblen & 0xff;
80         skb->head[1] = skblen >> 8;
81         gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
82                 len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
83
84         /* pass to device-specific module */
85         return cs->ops->send_skb(bcs, skb);
86 }
87
88 /**
89  * gigaset_skb_sent() - acknowledge sending an skb
90  * @bcs:        B channel descriptor structure.
91  * @skb:        sent data.
92  *
93  * Called by hardware module {bas,ser,usb}_gigaset when the data in a
94  * skb has been successfully sent, for signalling completion to the LL.
95  */
96 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
97 {
98         unsigned len;
99         isdn_ctrl response;
100
101         ++bcs->trans_up;
102
103         if (skb->len)
104                 dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
105                          __func__, skb->len);
106
107         len = (unsigned char) skb->head[0] |
108               (unsigned) (unsigned char) skb->head[1] << 8;
109         if (len) {
110                 gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
111                         bcs->cs->myid, bcs->channel, len);
112
113                 response.driver = bcs->cs->myid;
114                 response.command = ISDN_STAT_BSENT;
115                 response.arg = bcs->channel;
116                 response.parm.length = len;
117                 bcs->cs->iif.statcallb(&response);
118         }
119 }
120 EXPORT_SYMBOL_GPL(gigaset_skb_sent);
121
122 /* This function will be called by LL to send commands
123  * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
124  * so don't put too much effort into it.
125  */
126 static int command_from_LL(isdn_ctrl *cntrl)
127 {
128         struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver);
129         struct bc_state *bcs;
130         int retval = 0;
131         struct setup_parm *sp;
132
133         gigaset_debugdrivers();
134
135         if (!cs) {
136                 pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
137                 return -ENODEV;
138         }
139
140         switch (cntrl->command) {
141         case ISDN_CMD_IOCTL:
142                 gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
143                         cntrl->driver, cntrl->arg);
144
145                 dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
146                 return -EINVAL;
147
148         case ISDN_CMD_DIAL:
149                 gig_dbg(DEBUG_ANY,
150                         "ISDN_CMD_DIAL (driver: %d, ch: %ld, "
151                         "phone: %s, ownmsn: %s, si1: %d, si2: %d)",
152                         cntrl->driver, cntrl->arg,
153                         cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
154                         cntrl->parm.setup.si1, cntrl->parm.setup.si2);
155
156                 if (cntrl->arg >= cs->channels) {
157                         dev_err(cs->dev,
158                                 "ISDN_CMD_DIAL: invalid channel (%d)\n",
159                                 (int) cntrl->arg);
160                         return -EINVAL;
161                 }
162
163                 bcs = cs->bcs + cntrl->arg;
164
165                 if (!gigaset_get_channel(bcs)) {
166                         dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
167                         return -EBUSY;
168                 }
169
170                 sp = kmalloc(sizeof *sp, GFP_ATOMIC);
171                 if (!sp) {
172                         gigaset_free_channel(bcs);
173                         dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
174                         return -ENOMEM;
175                 }
176                 *sp = cntrl->parm.setup;
177
178                 if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
179                                        bcs->at_state.seq_index, NULL)) {
180                         //FIXME what should we do?
181                         kfree(sp);
182                         gigaset_free_channel(bcs);
183                         return -ENOMEM;
184                 }
185
186                 gig_dbg(DEBUG_CMD, "scheduling DIAL");
187                 gigaset_schedule_event(cs);
188                 break;
189         case ISDN_CMD_ACCEPTD: //FIXME
190                 gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
191
192                 if (cntrl->arg >= cs->channels) {
193                         dev_err(cs->dev,
194                                 "ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
195                                 (int) cntrl->arg);
196                         return -EINVAL;
197                 }
198
199                 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
200                                        EV_ACCEPT, NULL, 0, NULL)) {
201                         //FIXME what should we do?
202                         return -ENOMEM;
203                 }
204
205                 gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
206                 gigaset_schedule_event(cs);
207
208                 break;
209         case ISDN_CMD_ACCEPTB:
210                 gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
211                 break;
212         case ISDN_CMD_HANGUP:
213                 gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
214                         (int) cntrl->arg);
215
216                 if (cntrl->arg >= cs->channels) {
217                         dev_err(cs->dev,
218                                 "ISDN_CMD_HANGUP: invalid channel (%d)\n",
219                                 (int) cntrl->arg);
220                         return -EINVAL;
221                 }
222
223                 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
224                                        EV_HUP, NULL, 0, NULL)) {
225                         //FIXME what should we do?
226                         return -ENOMEM;
227                 }
228
229                 gig_dbg(DEBUG_CMD, "scheduling HUP");
230                 gigaset_schedule_event(cs);
231
232                 break;
233         case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
234                 gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
235                 break;
236         case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
237                 gig_dbg(DEBUG_ANY,
238                         "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
239                         cntrl->driver, cntrl->arg, cntrl->parm.num);
240                 break;
241         case ISDN_CMD_SETL2: /* Set L2 to given protocol */
242                 gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
243                         cntrl->arg & 0xff, (cntrl->arg >> 8));
244
245                 if ((cntrl->arg & 0xff) >= cs->channels) {
246                         dev_err(cs->dev,
247                                 "ISDN_CMD_SETL2: invalid channel (%d)\n",
248                                 (int) cntrl->arg & 0xff);
249                         return -EINVAL;
250                 }
251
252                 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
253                                        EV_PROTO_L2, NULL, cntrl->arg >> 8,
254                                        NULL)) {
255                         //FIXME what should we do?
256                         return -ENOMEM;
257                 }
258
259                 gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
260                 gigaset_schedule_event(cs);
261                 break;
262         case ISDN_CMD_SETL3: /* Set L3 to given protocol */
263                 gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
264                         cntrl->arg & 0xff, (cntrl->arg >> 8));
265
266                 if ((cntrl->arg & 0xff) >= cs->channels) {
267                         dev_err(cs->dev,
268                                 "ISDN_CMD_SETL3: invalid channel (%d)\n",
269                                 (int) cntrl->arg & 0xff);
270                         return -EINVAL;
271                 }
272
273                 if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
274                         dev_err(cs->dev,
275                                 "ISDN_CMD_SETL3: invalid protocol %lu\n",
276                                 cntrl->arg >> 8);
277                         return -EINVAL;
278                 }
279
280                 break;
281         case ISDN_CMD_PROCEED:
282                 gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
283                 break;
284         case ISDN_CMD_ALERT:
285                 gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
286                 if (cntrl->arg >= cs->channels) {
287                         dev_err(cs->dev,
288                                 "ISDN_CMD_ALERT: invalid channel (%d)\n",
289                                 (int) cntrl->arg);
290                         return -EINVAL;
291                 }
292                 //bcs = cs->bcs + cntrl->arg;
293                 //bcs->proto2 = -1;
294                 // FIXME
295                 break;
296         case ISDN_CMD_REDIR:
297                 gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
298                 break;
299         case ISDN_CMD_PROT_IO:
300                 gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
301                 break;
302         case ISDN_CMD_FAXCMD:
303                 gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
304                 break;
305         case ISDN_CMD_GETL2:
306                 gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
307                 break;
308         case ISDN_CMD_GETL3:
309                 gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
310                 break;
311         case ISDN_CMD_GETEAZ:
312                 gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
313                 break;
314         case ISDN_CMD_SETSIL:
315                 gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
316                 break;
317         case ISDN_CMD_GETSIL:
318                 gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
319                 break;
320         default:
321                 dev_err(cs->dev, "unknown command %d from LL\n",
322                         cntrl->command);
323                 return -EINVAL;
324         }
325
326         return retval;
327 }
328
329 void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
330 {
331         isdn_ctrl command;
332
333         command.driver = cs->myid;
334         command.command = cmd;
335         command.arg = 0;
336         cs->iif.statcallb(&command);
337 }
338
339 void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
340 {
341         isdn_ctrl command;
342
343         command.driver = bcs->cs->myid;
344         command.command = cmd;
345         command.arg = bcs->channel;
346         bcs->cs->iif.statcallb(&command);
347 }
348
349 int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
350 {
351         struct bc_state *bcs = at_state->bcs;
352         unsigned proto;
353         const char *bc;
354         size_t length[AT_NUM];
355         size_t l;
356         int i;
357         struct setup_parm *sp = data;
358
359         switch (bcs->proto2) {
360         case ISDN_PROTO_L2_HDLC:
361                 proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
362                 break;
363         case ISDN_PROTO_L2_TRANS:
364                 proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
365                 break;
366         default:
367                 dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",
368                         __func__, bcs->proto2);
369                 return -EINVAL;
370         }
371
372         switch (sp->si1) {
373         case 1:         /* audio */
374                 bc = "9090A3";  /* 3.1 kHz audio, A-law */
375                 break;
376         case 7:         /* data */
377         default:        /* hope the app knows what it is doing */
378                 bc = "8890";    /* unrestricted digital information */
379         }
380         //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC
381
382         length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1;
383         l = strlen(sp->eazmsn);
384         length[AT_MSN  ] = l ? 6 + l + 1 + 1 : 0;
385         length[AT_BC   ] = 5 + strlen(bc) + 1 + 1;
386         length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
387         length[AT_ISO  ] = 6 + 1 + 1 + 1; /* channel: 1 character */
388         length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */
389         length[AT_HLC  ] = 0;
390
391         for (i = 0; i < AT_NUM; ++i) {
392                 kfree(bcs->commands[i]);
393                 bcs->commands[i] = NULL;
394                 if (length[i] &&
395                     !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
396                         dev_err(bcs->cs->dev, "out of memory\n");
397                         return -ENOMEM;
398                 }
399         }
400
401         /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */
402         if (sp->phone[0] == '*' && sp->phone[1] == '*') {
403                 /* internal call: translate ** prefix to CTP value */
404                 snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
405                          "D%s\r", sp->phone+2);
406                 strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]);
407         } else {
408                 snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
409                          "D%s\r", sp->phone);
410                 strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]);
411         }
412
413         if (bcs->commands[AT_MSN])
414                 snprintf(bcs->commands[AT_MSN], length[AT_MSN],
415                          "^SMSN=%s\r", sp->eazmsn);
416         snprintf(bcs->commands[AT_BC   ], length[AT_BC   ],
417                  "^SBC=%s\r", bc);
418         snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
419                  "^SBPR=%u\r", proto);
420         snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],
421                  "^SISO=%u\r", (unsigned)bcs->channel + 1);
422
423         return 0;
424 }
425
426 int gigaset_isdn_setup_accept(struct at_state_t *at_state)
427 {
428         unsigned proto;
429         size_t length[AT_NUM];
430         int i;
431         struct bc_state *bcs = at_state->bcs;
432
433         switch (bcs->proto2) {
434         case ISDN_PROTO_L2_HDLC:
435                 proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
436                 break;
437         case ISDN_PROTO_L2_TRANS:
438                 proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
439                 break;
440         default:
441                 dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",
442                         __func__, bcs->proto2);
443                 return -EINVAL;
444         }
445
446         length[AT_DIAL ] = 0;
447         length[AT_MSN  ] = 0;
448         length[AT_BC   ] = 0;
449         length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
450         length[AT_ISO  ] = 6 + 1 + 1 + 1; /* channel: 1 character */
451         length[AT_TYPE ] = 0;
452         length[AT_HLC  ] = 0;
453
454         for (i = 0; i < AT_NUM; ++i) {
455                 kfree(bcs->commands[i]);
456                 bcs->commands[i] = NULL;
457                 if (length[i] &&
458                     !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
459                         dev_err(at_state->cs->dev, "out of memory\n");
460                         return -ENOMEM;
461                 }
462         }
463
464         snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
465                  "^SBPR=%u\r", proto);
466         snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],
467                  "^SISO=%u\r", (unsigned) bcs->channel + 1);
468
469         return 0;
470 }
471
472 /**
473  * gigaset_isdn_icall() - signal incoming call
474  * @at_state:   connection state structure.
475  *
476  * Called by main module to notify the LL that an incoming call has been
477  * received. @at_state contains the parameters of the call.
478  *
479  * Return value: call disposition (ICALL_*)
480  */
481 int gigaset_isdn_icall(struct at_state_t *at_state)
482 {
483         struct cardstate *cs = at_state->cs;
484         struct bc_state *bcs = at_state->bcs;
485         isdn_ctrl response;
486         int retval;
487
488         /* fill ICALL structure */
489         response.parm.setup.si1 = 0;    /* default: unknown */
490         response.parm.setup.si2 = 0;
491         response.parm.setup.screen = 0; //FIXME how to set these?
492         response.parm.setup.plan = 0;
493         if (!at_state->str_var[STR_ZBC]) {
494                 /* no BC (internal call): assume speech, A-law */
495                 response.parm.setup.si1 = 1;
496         } else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) {
497                 /* unrestricted digital information */
498                 response.parm.setup.si1 = 7;
499         } else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) {
500                 /* speech, A-law */
501                 response.parm.setup.si1 = 1;
502         } else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) {
503                 /* 3,1 kHz audio, A-law */
504                 response.parm.setup.si1 = 1;
505                 response.parm.setup.si2 = 2;
506         } else {
507                 dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
508                      at_state->str_var[STR_ZBC]);
509                 return ICALL_IGNORE;
510         }
511         if (at_state->str_var[STR_NMBR]) {
512                 strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
513                         sizeof response.parm.setup.phone - 1);
514                 response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0;
515         } else
516                 response.parm.setup.phone[0] = 0;
517         if (at_state->str_var[STR_ZCPN]) {
518                 strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
519                         sizeof response.parm.setup.eazmsn - 1);
520                 response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0;
521         } else
522                 response.parm.setup.eazmsn[0] = 0;
523
524         if (!bcs) {
525                 dev_notice(cs->dev, "no channel for incoming call\n");
526                 response.command = ISDN_STAT_ICALLW;
527                 response.arg = 0; //FIXME
528         } else {
529                 gig_dbg(DEBUG_CMD, "Sending ICALL");
530                 response.command = ISDN_STAT_ICALL;
531                 response.arg = bcs->channel; //FIXME
532         }
533         response.driver = cs->myid;
534         retval = cs->iif.statcallb(&response);
535         gig_dbg(DEBUG_CMD, "Response: %d", retval);
536         switch (retval) {
537         case 0: /* no takers */
538                 return ICALL_IGNORE;
539         case 1: /* alerting */
540                 bcs->chstate |= CHS_NOTIFY_LL;
541                 return ICALL_ACCEPT;
542         case 2: /* reject */
543                 return ICALL_REJECT;
544         case 3: /* incomplete */
545                 dev_warn(cs->dev,
546                        "LL requested unsupported feature: Incomplete Number\n");
547                 return ICALL_IGNORE;
548         case 4: /* proceeding */
549                 /* Gigaset will send ALERTING anyway.
550                  * There doesn't seem to be a way to avoid this.
551                  */
552                 return ICALL_ACCEPT;
553         case 5: /* deflect */
554                 dev_warn(cs->dev,
555                          "LL requested unsupported feature: Call Deflection\n");
556                 return ICALL_IGNORE;
557         default:
558                 dev_err(cs->dev, "LL error %d on ICALL\n", retval);
559                 return ICALL_IGNORE;
560         }
561 }
562
563 /* Set Callback function pointer */
564 int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
565 {
566         isdn_if *iif = &cs->iif;
567
568         gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
569
570         if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
571             >= sizeof iif->id) {
572                 pr_err("ID too long: %s\n", isdnid);
573                 return 0;
574         }
575
576         iif->owner = THIS_MODULE;
577         iif->channels = cs->channels;
578         iif->maxbufsize = MAX_BUF_SIZE;
579         iif->features = ISDN_FEATURE_L2_TRANS |
580                 ISDN_FEATURE_L2_HDLC |
581 #ifdef GIG_X75
582                 ISDN_FEATURE_L2_X75I |
583 #endif
584                 ISDN_FEATURE_L3_TRANS |
585                 ISDN_FEATURE_P_EURO;
586         iif->hl_hdrlen = HW_HDR_LEN;            /* Area for storing ack */
587         iif->command = command_from_LL;
588         iif->writebuf_skb = writebuf_from_LL;
589         iif->writecmd = NULL;                   /* Don't support isdnctrl */
590         iif->readstat = NULL;                   /* Don't support isdnctrl */
591         iif->rcvcallb_skb = NULL;               /* Will be set by LL */
592         iif->statcallb = NULL;                  /* Will be set by LL */
593
594         if (!register_isdn(iif)) {
595                 pr_err("register_isdn failed\n");
596                 return 0;
597         }
598
599         cs->myid = iif->channels;               /* Set my device id */
600         return 1;
601 }