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