2 * Stuff used by all variants of the driver
4 * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de),
5 * Hansjoerg Lipp (hjlipp@web.de),
6 * Tilman Schmidt (tilman@imap.cc).
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 * =====================================================================
18 /* == Handling of I4L IO ============================================================================*/
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.
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
32 * number of accepted bytes
33 * 0 if temporarily unable to accept data (out of buffer space)
34 * <0 on error (eg. -EINVAL)
36 static int writebuf_from_LL(int driverID
, int channel
, int ack
, struct sk_buff
*skb
)
43 if (!(cs
= gigaset_get_cs_by_id(driverID
))) {
44 err("%s: invalid driver ID (%d)", __func__
, driverID
);
47 if (channel
< 0 || channel
>= cs
->channels
) {
48 err("%s: invalid channel ID (%d)", __func__
, channel
);
51 bcs
= &cs
->bcs
[channel
];
55 "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)",
56 driverID
, channel
, ack
, len
);
60 warn("not ACKing empty packet from LL");
63 if (len
> MAX_BUF_SIZE
) {
64 err("%s: packet too large (%d bytes)", __func__
, channel
);
68 if (!atomic_read(&cs
->connected
))
71 skblen
= ack
? len
: 0;
72 skb
->head
[0] = skblen
& 0xff;
73 skb
->head
[1] = skblen
>> 8;
74 dbg(DEBUG_MCMD
, "skb: len=%u, skblen=%u: %02x %02x", len
, skblen
,
75 (unsigned) skb
->head
[0], (unsigned) skb
->head
[1]);
77 /* pass to device-specific module */
78 return cs
->ops
->send_skb(bcs
, skb
);
81 void gigaset_skb_sent(struct bc_state
*bcs
, struct sk_buff
*skb
)
89 warn("%s: skb->len==%d", __func__
, skb
->len
);
91 len
= (unsigned char) skb
->head
[0] |
92 (unsigned) (unsigned char) skb
->head
[1] << 8;
95 "Acknowledge sending to LL (id: %d, channel: %d size: %u)",
96 bcs
->cs
->myid
, bcs
->channel
, len
);
98 response
.driver
= bcs
->cs
->myid
;
99 response
.command
= ISDN_STAT_BSENT
;
100 response
.arg
= bcs
->channel
;
101 response
.parm
.length
= len
;
102 bcs
->cs
->iif
.statcallb(&response
);
105 EXPORT_SYMBOL_GPL(gigaset_skb_sent
);
107 /* This function will be called by LL to send commands
108 * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
109 * so don't put too much effort into it.
111 static int command_from_LL(isdn_ctrl
*cntrl
)
113 struct cardstate
*cs
= gigaset_get_cs_by_id(cntrl
->driver
);
114 //isdn_ctrl response;
115 //unsigned long flags;
116 struct bc_state
*bcs
;
118 struct setup_parm
*sp
;
120 //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command");
121 gigaset_debugdrivers();
123 //FIXME "remove test for &connected"
124 if ((!cs
|| !atomic_read(&cs
->connected
))) {
125 warn("LL tried to access unknown device with nr. %d",
130 switch (cntrl
->command
) {
133 dbg(DEBUG_ANY
, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)",
134 cntrl
->driver
, cntrl
->arg
);
136 warn("ISDN_CMD_IOCTL is not supported.");
140 dbg(DEBUG_ANY
, "ISDN_CMD_DIAL (driver: %d, channel: %ld, "
141 "phone: %s,ownmsn: %s, si1: %d, si2: %d)",
142 cntrl
->driver
, cntrl
->arg
,
143 cntrl
->parm
.setup
.phone
, cntrl
->parm
.setup
.eazmsn
,
144 cntrl
->parm
.setup
.si1
, cntrl
->parm
.setup
.si2
);
146 if (cntrl
->arg
>= cs
->channels
) {
147 err("invalid channel (%d)", (int) cntrl
->arg
);
151 bcs
= cs
->bcs
+ cntrl
->arg
;
153 if (!gigaset_get_channel(bcs
)) {
154 err("channel not free");
158 sp
= kmalloc(sizeof *sp
, GFP_ATOMIC
);
160 gigaset_free_channel(bcs
);
161 err("ISDN_CMD_DIAL: out of memory");
164 *sp
= cntrl
->parm
.setup
;
166 if (!gigaset_add_event(cs
, &bcs
->at_state
, EV_DIAL
, sp
,
167 atomic_read(&bcs
->at_state
.seq_index
),
169 //FIXME what should we do?
171 gigaset_free_channel(bcs
);
175 dbg(DEBUG_CMD
, "scheduling DIAL");
176 gigaset_schedule_event(cs
);
178 case ISDN_CMD_ACCEPTD
: //FIXME
179 dbg(DEBUG_ANY
, "ISDN_CMD_ACCEPTD");
181 if (cntrl
->arg
>= cs
->channels
) {
182 err("invalid channel (%d)", (int) cntrl
->arg
);
186 if (!gigaset_add_event(cs
, &cs
->bcs
[cntrl
->arg
].at_state
,
187 EV_ACCEPT
, NULL
, 0, NULL
)) {
188 //FIXME what should we do?
192 dbg(DEBUG_CMD
, "scheduling ACCEPT");
193 gigaset_schedule_event(cs
);
196 case ISDN_CMD_ACCEPTB
:
197 dbg(DEBUG_ANY
, "ISDN_CMD_ACCEPTB");
199 case ISDN_CMD_HANGUP
:
201 "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl
->arg
);
203 if (cntrl
->arg
>= cs
->channels
) {
204 err("ISDN_CMD_HANGUP: invalid channel (%u)",
205 (unsigned) cntrl
->arg
);
209 if (!gigaset_add_event(cs
, &cs
->bcs
[cntrl
->arg
].at_state
,
210 EV_HUP
, NULL
, 0, NULL
)) {
211 //FIXME what should we do?
215 dbg(DEBUG_CMD
, "scheduling HUP");
216 gigaset_schedule_event(cs
);
219 case ISDN_CMD_CLREAZ
: /* Do not signal incoming signals */ //FIXME
220 dbg(DEBUG_ANY
, "ISDN_CMD_CLREAZ");
222 case ISDN_CMD_SETEAZ
: /* Signal incoming calls for given MSN */ //FIXME
224 "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)",
225 cntrl
->driver
, cntrl
->arg
, cntrl
->parm
.num
);
227 case ISDN_CMD_SETL2
: /* Set L2 to given protocol */
228 dbg(DEBUG_ANY
, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)",
229 cntrl
->arg
& 0xff, (cntrl
->arg
>> 8));
231 if ((cntrl
->arg
& 0xff) >= cs
->channels
) {
232 err("invalid channel (%u)",
233 (unsigned) cntrl
->arg
& 0xff);
237 if (!gigaset_add_event(cs
, &cs
->bcs
[cntrl
->arg
& 0xff].at_state
,
238 EV_PROTO_L2
, NULL
, cntrl
->arg
>> 8,
240 //FIXME what should we do?
244 dbg(DEBUG_CMD
, "scheduling PROTO_L2");
245 gigaset_schedule_event(cs
);
247 case ISDN_CMD_SETL3
: /* Set L3 to given protocol */
248 dbg(DEBUG_ANY
, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)",
249 cntrl
->arg
& 0xff, (cntrl
->arg
>> 8));
251 if ((cntrl
->arg
& 0xff) >= cs
->channels
) {
252 err("invalid channel (%u)",
253 (unsigned) cntrl
->arg
& 0xff);
257 if (cntrl
->arg
>> 8 != ISDN_PROTO_L3_TRANS
) {
258 err("invalid protocol %lu", cntrl
->arg
>> 8);
263 case ISDN_CMD_PROCEED
:
264 dbg(DEBUG_ANY
, "ISDN_CMD_PROCEED"); //FIXME
267 dbg(DEBUG_ANY
, "ISDN_CMD_ALERT"); //FIXME
268 if (cntrl
->arg
>= cs
->channels
) {
269 err("invalid channel (%d)", (int) cntrl
->arg
);
272 //bcs = cs->bcs + cntrl->arg;
277 dbg(DEBUG_ANY
, "ISDN_CMD_REDIR"); //FIXME
279 case ISDN_CMD_PROT_IO
:
280 dbg(DEBUG_ANY
, "ISDN_CMD_PROT_IO");
282 case ISDN_CMD_FAXCMD
:
283 dbg(DEBUG_ANY
, "ISDN_CMD_FAXCMD");
286 dbg(DEBUG_ANY
, "ISDN_CMD_GETL2");
289 dbg(DEBUG_ANY
, "ISDN_CMD_GETL3");
291 case ISDN_CMD_GETEAZ
:
292 dbg(DEBUG_ANY
, "ISDN_CMD_GETEAZ");
294 case ISDN_CMD_SETSIL
:
295 dbg(DEBUG_ANY
, "ISDN_CMD_SETSIL");
297 case ISDN_CMD_GETSIL
:
298 dbg(DEBUG_ANY
, "ISDN_CMD_GETSIL");
301 err("unknown command %d from LL",
309 void gigaset_i4l_cmd(struct cardstate
*cs
, int cmd
)
313 command
.driver
= cs
->myid
;
314 command
.command
= cmd
;
316 cs
->iif
.statcallb(&command
);
319 void gigaset_i4l_channel_cmd(struct bc_state
*bcs
, int cmd
)
323 command
.driver
= bcs
->cs
->myid
;
324 command
.command
= cmd
;
325 command
.arg
= bcs
->channel
;
326 bcs
->cs
->iif
.statcallb(&command
);
329 int gigaset_isdn_setup_dial(struct at_state_t
*at_state
, void *data
)
331 struct bc_state
*bcs
= at_state
->bcs
;
334 size_t length
[AT_NUM
];
337 struct setup_parm
*sp
= data
;
339 switch (bcs
->proto2
) {
340 case ISDN_PROTO_L2_HDLC
:
341 proto
= 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
343 case ISDN_PROTO_L2_TRANS
:
344 proto
= 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
347 err("invalid protocol: %u", bcs
->proto2
);
353 bc
= "9090A3"; /* 3.1 kHz audio, A-law */
356 default: /* hope the app knows what it is doing */
357 bc
= "8890"; /* unrestricted digital information */
359 //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC
361 length
[AT_DIAL
] = 1 + strlen(sp
->phone
) + 1 + 1;
362 l
= strlen(sp
->eazmsn
);
363 length
[AT_MSN
] = l
? 6 + l
+ 1 + 1 : 0;
364 length
[AT_BC
] = 5 + strlen(bc
) + 1 + 1;
365 length
[AT_PROTO
] = 6 + 1 + 1 + 1; /* proto: 1 character */
366 length
[AT_ISO
] = 6 + 1 + 1 + 1; /* channel: 1 character */
367 length
[AT_TYPE
] = 6 + 1 + 1 + 1; /* call type: 1 character */
370 for (i
= 0; i
< AT_NUM
; ++i
) {
371 kfree(bcs
->commands
[i
]);
372 bcs
->commands
[i
] = NULL
;
374 !(bcs
->commands
[i
] = kmalloc(length
[i
], GFP_ATOMIC
))) {
375 err("out of memory");
380 /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */
381 if (sp
->phone
[0] == '*' && sp
->phone
[1] == '*') {
382 /* internal call: translate ** prefix to CTP value */
383 snprintf(bcs
->commands
[AT_DIAL
], length
[AT_DIAL
],
384 "D%s\r", sp
->phone
+2);
385 strncpy(bcs
->commands
[AT_TYPE
], "^SCTP=0\r", length
[AT_TYPE
]);
387 snprintf(bcs
->commands
[AT_DIAL
], length
[AT_DIAL
],
389 strncpy(bcs
->commands
[AT_TYPE
], "^SCTP=1\r", length
[AT_TYPE
]);
392 if (bcs
->commands
[AT_MSN
])
393 snprintf(bcs
->commands
[AT_MSN
], length
[AT_MSN
],
394 "^SMSN=%s\r", sp
->eazmsn
);
395 snprintf(bcs
->commands
[AT_BC
], length
[AT_BC
],
397 snprintf(bcs
->commands
[AT_PROTO
], length
[AT_PROTO
],
398 "^SBPR=%u\r", proto
);
399 snprintf(bcs
->commands
[AT_ISO
], length
[AT_ISO
],
400 "^SISO=%u\r", (unsigned)bcs
->channel
+ 1);
405 int gigaset_isdn_setup_accept(struct at_state_t
*at_state
)
408 size_t length
[AT_NUM
];
410 struct bc_state
*bcs
= at_state
->bcs
;
412 switch (bcs
->proto2
) {
413 case ISDN_PROTO_L2_HDLC
:
414 proto
= 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
416 case ISDN_PROTO_L2_TRANS
:
417 proto
= 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
420 err("invalid protocol: %u", bcs
->proto2
);
424 length
[AT_DIAL
] = 0;
427 length
[AT_PROTO
] = 6 + 1 + 1 + 1; /* proto: 1 character */
428 length
[AT_ISO
] = 6 + 1 + 1 + 1; /* channel: 1 character */
429 length
[AT_TYPE
] = 0;
432 for (i
= 0; i
< AT_NUM
; ++i
) {
433 kfree(bcs
->commands
[i
]);
434 bcs
->commands
[i
] = NULL
;
436 !(bcs
->commands
[i
] = kmalloc(length
[i
], GFP_ATOMIC
))) {
437 err("out of memory");
442 snprintf(bcs
->commands
[AT_PROTO
], length
[AT_PROTO
],
443 "^SBPR=%u\r", proto
);
444 snprintf(bcs
->commands
[AT_ISO
], length
[AT_ISO
],
445 "^SISO=%u\r", (unsigned) bcs
->channel
+ 1);
450 int gigaset_isdn_icall(struct at_state_t
*at_state
)
452 struct cardstate
*cs
= at_state
->cs
;
453 struct bc_state
*bcs
= at_state
->bcs
;
457 /* fill ICALL structure */
458 response
.parm
.setup
.si1
= 0; /* default: unknown */
459 response
.parm
.setup
.si2
= 0;
460 response
.parm
.setup
.screen
= 0; //FIXME how to set these?
461 response
.parm
.setup
.plan
= 0;
462 if (!at_state
->str_var
[STR_ZBC
]) {
463 /* no BC (internal call): assume speech, A-law */
464 response
.parm
.setup
.si1
= 1;
465 } else if (!strcmp(at_state
->str_var
[STR_ZBC
], "8890")) {
466 /* unrestricted digital information */
467 response
.parm
.setup
.si1
= 7;
468 } else if (!strcmp(at_state
->str_var
[STR_ZBC
], "8090A3")) {
470 response
.parm
.setup
.si1
= 1;
471 } else if (!strcmp(at_state
->str_var
[STR_ZBC
], "9090A3")) {
472 /* 3,1 kHz audio, A-law */
473 response
.parm
.setup
.si1
= 1;
474 response
.parm
.setup
.si2
= 2;
476 warn("RING ignored - unsupported BC %s",
477 at_state
->str_var
[STR_ZBC
]);
480 if (at_state
->str_var
[STR_NMBR
]) {
481 strncpy(response
.parm
.setup
.phone
, at_state
->str_var
[STR_NMBR
],
482 sizeof response
.parm
.setup
.phone
- 1);
483 response
.parm
.setup
.phone
[sizeof response
.parm
.setup
.phone
- 1] = 0;
485 response
.parm
.setup
.phone
[0] = 0;
486 if (at_state
->str_var
[STR_ZCPN
]) {
487 strncpy(response
.parm
.setup
.eazmsn
, at_state
->str_var
[STR_ZCPN
],
488 sizeof response
.parm
.setup
.eazmsn
- 1);
489 response
.parm
.setup
.eazmsn
[sizeof response
.parm
.setup
.eazmsn
- 1] = 0;
491 response
.parm
.setup
.eazmsn
[0] = 0;
494 notice("no channel for incoming call");
495 dbg(DEBUG_CMD
, "Sending ICALLW");
496 response
.command
= ISDN_STAT_ICALLW
;
497 response
.arg
= 0; //FIXME
499 dbg(DEBUG_CMD
, "Sending ICALL");
500 response
.command
= ISDN_STAT_ICALL
;
501 response
.arg
= bcs
->channel
; //FIXME
503 response
.driver
= cs
->myid
;
504 retval
= cs
->iif
.statcallb(&response
);
505 dbg(DEBUG_CMD
, "Response: %d", retval
);
507 case 0: /* no takers */
509 case 1: /* alerting */
510 bcs
->chstate
|= CHS_NOTIFY_LL
;
514 case 3: /* incomplete */
515 warn("LL requested unsupported feature: Incomplete Number");
517 case 4: /* proceeding */
518 /* Gigaset will send ALERTING anyway.
519 * There doesn't seem to be a way to avoid this.
522 case 5: /* deflect */
523 warn("LL requested unsupported feature: Call Deflection");
526 err("LL error %d on ICALL", retval
);
531 /* Set Callback function pointer */
532 int gigaset_register_to_LL(struct cardstate
*cs
, const char *isdnid
)
534 isdn_if
*iif
= &cs
->iif
;
536 dbg(DEBUG_ANY
, "Register driver capabilities to LL");
538 //iif->id[sizeof(iif->id) - 1]=0;
539 //strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
540 if (snprintf(iif
->id
, sizeof iif
->id
, "%s_%u", isdnid
, cs
->minor_index
)
542 return -ENOMEM
; //FIXME EINVAL/...??
544 iif
->owner
= THIS_MODULE
;
545 iif
->channels
= cs
->channels
;
546 iif
->maxbufsize
= MAX_BUF_SIZE
;
547 iif
->features
= ISDN_FEATURE_L2_TRANS
|
548 ISDN_FEATURE_L2_HDLC
|
550 ISDN_FEATURE_L2_X75I
|
552 ISDN_FEATURE_L3_TRANS
|
554 iif
->hl_hdrlen
= HW_HDR_LEN
; /* Area for storing ack */
555 iif
->command
= command_from_LL
;
556 iif
->writebuf_skb
= writebuf_from_LL
;
557 iif
->writecmd
= NULL
; /* Don't support isdnctrl */
558 iif
->readstat
= NULL
; /* Don't support isdnctrl */
559 iif
->rcvcallb_skb
= NULL
; /* Will be set by LL */
560 iif
->statcallb
= NULL
; /* Will be set by LL */
562 if (!register_isdn(iif
))
565 cs
->myid
= iif
->channels
; /* Set my device id */