aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/i4l.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/gigaset/i4l.c')
-rw-r--r--drivers/isdn/gigaset/i4l.c506
1 files changed, 301 insertions, 205 deletions
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 654489d836cd..aca72a06184e 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -14,6 +14,9 @@
14 */ 14 */
15 15
16#include "gigaset.h" 16#include "gigaset.h"
17#include <linux/isdnif.h>
18
19#define HW_HDR_LEN 2 /* Header size used to store ack info */
17 20
18/* == Handling of I4L IO =====================================================*/ 21/* == Handling of I4L IO =====================================================*/
19 22
@@ -95,6 +98,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
95 */ 98 */
96void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) 99void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
97{ 100{
101 isdn_if *iif = bcs->cs->iif;
98 unsigned len; 102 unsigned len;
99 isdn_ctrl response; 103 isdn_ctrl response;
100 104
@@ -114,71 +118,177 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
114 response.command = ISDN_STAT_BSENT; 118 response.command = ISDN_STAT_BSENT;
115 response.arg = bcs->channel; 119 response.arg = bcs->channel;
116 response.parm.length = len; 120 response.parm.length = len;
117 bcs->cs->iif.statcallb(&response); 121 iif->statcallb(&response);
118 } 122 }
119} 123}
120EXPORT_SYMBOL_GPL(gigaset_skb_sent); 124EXPORT_SYMBOL_GPL(gigaset_skb_sent);
121 125
126/**
127 * gigaset_skb_rcvd() - pass received skb to LL
128 * @bcs: B channel descriptor structure.
129 * @skb: received data.
130 *
131 * Called by hardware module {bas,ser,usb}_gigaset when user data has
132 * been successfully received, for passing to the LL.
133 * Warning: skb must not be accessed anymore!
134 */
135void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
136{
137 isdn_if *iif = bcs->cs->iif;
138
139 iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb);
140 bcs->trans_down++;
141}
142EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);
143
144/**
145 * gigaset_isdn_rcv_err() - signal receive error
146 * @bcs: B channel descriptor structure.
147 *
148 * Called by hardware module {bas,ser,usb}_gigaset when a receive error
149 * has occurred, for signalling to the LL.
150 */
151void gigaset_isdn_rcv_err(struct bc_state *bcs)
152{
153 isdn_if *iif = bcs->cs->iif;
154 isdn_ctrl response;
155
156 /* if currently ignoring packets, just count down */
157 if (bcs->ignore) {
158 bcs->ignore--;
159 return;
160 }
161
162 /* update statistics */
163 bcs->corrupted++;
164
165 /* error -> LL */
166 gig_dbg(DEBUG_CMD, "sending L1ERR");
167 response.driver = bcs->cs->myid;
168 response.command = ISDN_STAT_L1ERR;
169 response.arg = bcs->channel;
170 response.parm.errcode = ISDN_STAT_L1ERR_RECV;
171 iif->statcallb(&response);
172}
173EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err);
174
122/* This function will be called by LL to send commands 175/* This function will be called by LL to send commands
123 * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, 176 * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
124 * so don't put too much effort into it. 177 * so don't put too much effort into it.
125 */ 178 */
126static int command_from_LL(isdn_ctrl *cntrl) 179static int command_from_LL(isdn_ctrl *cntrl)
127{ 180{
128 struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); 181 struct cardstate *cs;
129 struct bc_state *bcs; 182 struct bc_state *bcs;
130 int retval = 0; 183 int retval = 0;
131 struct setup_parm *sp; 184 char **commands;
185 int ch;
186 int i;
187 size_t l;
132 188
133 gigaset_debugdrivers(); 189 gigaset_debugdrivers();
134 190
135 if (!cs) { 191 gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
192 cntrl->driver, cntrl->command, cntrl->arg);
193
194 cs = gigaset_get_cs_by_id(cntrl->driver);
195 if (cs == NULL) {
136 pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); 196 pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
137 return -ENODEV; 197 return -ENODEV;
138 } 198 }
199 ch = cntrl->arg & 0xff;
139 200
140 switch (cntrl->command) { 201 switch (cntrl->command) {
141 case ISDN_CMD_IOCTL: 202 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"); 203 dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
146 return -EINVAL; 204 return -EINVAL;
147 205
148 case ISDN_CMD_DIAL: 206 case ISDN_CMD_DIAL:
149 gig_dbg(DEBUG_ANY, 207 gig_dbg(DEBUG_ANY,
150 "ISDN_CMD_DIAL (driver: %d, ch: %ld, " 208 "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)",
151 "phone: %s, ownmsn: %s, si1: %d, si2: %d)",
152 cntrl->driver, cntrl->arg,
153 cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, 209 cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
154 cntrl->parm.setup.si1, cntrl->parm.setup.si2); 210 cntrl->parm.setup.si1, cntrl->parm.setup.si2);
155 211
156 if (cntrl->arg >= cs->channels) { 212 if (ch >= cs->channels) {
157 dev_err(cs->dev, 213 dev_err(cs->dev,
158 "ISDN_CMD_DIAL: invalid channel (%d)\n", 214 "ISDN_CMD_DIAL: invalid channel (%d)\n", ch);
159 (int) cntrl->arg);
160 return -EINVAL; 215 return -EINVAL;
161 } 216 }
162 217 bcs = cs->bcs + ch;
163 bcs = cs->bcs + cntrl->arg;
164
165 if (!gigaset_get_channel(bcs)) { 218 if (!gigaset_get_channel(bcs)) {
166 dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); 219 dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
167 return -EBUSY; 220 return -EBUSY;
168 } 221 }
169 222
170 sp = kmalloc(sizeof *sp, GFP_ATOMIC); 223 commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
171 if (!sp) { 224 if (!commands) {
172 gigaset_free_channel(bcs); 225 gigaset_free_channel(bcs);
173 dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); 226 dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
174 return -ENOMEM; 227 return -ENOMEM;
175 } 228 }
176 *sp = cntrl->parm.setup;
177 229
178 if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, 230 l = 3 + strlen(cntrl->parm.setup.phone);
231 commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC);
232 if (!commands[AT_DIAL])
233 goto oom;
234 if (cntrl->parm.setup.phone[0] == '*' &&
235 cntrl->parm.setup.phone[1] == '*') {
236 /* internal call: translate ** prefix to CTP value */
237 commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC);
238 if (!commands[AT_TYPE])
239 goto oom;
240 snprintf(commands[AT_DIAL], l,
241 "D%s\r", cntrl->parm.setup.phone+2);
242 } else {
243 commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC);
244 if (!commands[AT_TYPE])
245 goto oom;
246 snprintf(commands[AT_DIAL], l,
247 "D%s\r", cntrl->parm.setup.phone);
248 }
249
250 l = strlen(cntrl->parm.setup.eazmsn);
251 if (l) {
252 l += 8;
253 commands[AT_MSN] = kmalloc(l, GFP_ATOMIC);
254 if (!commands[AT_MSN])
255 goto oom;
256 snprintf(commands[AT_MSN], l, "^SMSN=%s\r",
257 cntrl->parm.setup.eazmsn);
258 }
259
260 switch (cntrl->parm.setup.si1) {
261 case 1: /* audio */
262 /* BC = 9090A3: 3.1 kHz audio, A-law */
263 commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC);
264 if (!commands[AT_BC])
265 goto oom;
266 break;
267 case 7: /* data */
268 default: /* hope the app knows what it is doing */
269 /* BC = 8890: unrestricted digital information */
270 commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC);
271 if (!commands[AT_BC])
272 goto oom;
273 }
274 /* ToDo: other si1 values, inspect si2, set HLC/LLC */
275
276 commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
277 if (!commands[AT_PROTO])
278 goto oom;
279 snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2);
280
281 commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
282 if (!commands[AT_ISO])
283 goto oom;
284 snprintf(commands[AT_ISO], 9, "^SISO=%u\r",
285 (unsigned) bcs->channel + 1);
286
287 if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands,
179 bcs->at_state.seq_index, NULL)) { 288 bcs->at_state.seq_index, NULL)) {
180 //FIXME what should we do? 289 for (i = 0; i < AT_NUM; ++i)
181 kfree(sp); 290 kfree(commands[i]);
291 kfree(commands);
182 gigaset_free_channel(bcs); 292 gigaset_free_channel(bcs);
183 return -ENOMEM; 293 return -ENOMEM;
184 } 294 }
@@ -186,93 +296,83 @@ static int command_from_LL(isdn_ctrl *cntrl)
186 gig_dbg(DEBUG_CMD, "scheduling DIAL"); 296 gig_dbg(DEBUG_CMD, "scheduling DIAL");
187 gigaset_schedule_event(cs); 297 gigaset_schedule_event(cs);
188 break; 298 break;
189 case ISDN_CMD_ACCEPTD: //FIXME 299 case ISDN_CMD_ACCEPTD:
190 gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); 300 if (ch >= cs->channels) {
191
192 if (cntrl->arg >= cs->channels) {
193 dev_err(cs->dev, 301 dev_err(cs->dev,
194 "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", 302 "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch);
195 (int) cntrl->arg);
196 return -EINVAL; 303 return -EINVAL;
197 } 304 }
198 305 bcs = cs->bcs + ch;
199 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, 306 if (!gigaset_add_event(cs, &bcs->at_state,
200 EV_ACCEPT, NULL, 0, NULL)) { 307 EV_ACCEPT, NULL, 0, NULL))
201 //FIXME what should we do?
202 return -ENOMEM; 308 return -ENOMEM;
203 }
204 309
205 gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); 310 gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
206 gigaset_schedule_event(cs); 311 gigaset_schedule_event(cs);
207 312
208 break; 313 break;
209 case ISDN_CMD_ACCEPTB: 314 case ISDN_CMD_ACCEPTB:
210 gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
211 break; 315 break;
212 case ISDN_CMD_HANGUP: 316 case ISDN_CMD_HANGUP:
213 gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", 317 if (ch >= cs->channels) {
214 (int) cntrl->arg);
215
216 if (cntrl->arg >= cs->channels) {
217 dev_err(cs->dev, 318 dev_err(cs->dev,
218 "ISDN_CMD_HANGUP: invalid channel (%d)\n", 319 "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch);
219 (int) cntrl->arg);
220 return -EINVAL; 320 return -EINVAL;
221 } 321 }
222 322 bcs = cs->bcs + ch;
223 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, 323 if (!gigaset_add_event(cs, &bcs->at_state,
224 EV_HUP, NULL, 0, NULL)) { 324 EV_HUP, NULL, 0, NULL))
225 //FIXME what should we do?
226 return -ENOMEM; 325 return -ENOMEM;
227 }
228 326
229 gig_dbg(DEBUG_CMD, "scheduling HUP"); 327 gig_dbg(DEBUG_CMD, "scheduling HUP");
230 gigaset_schedule_event(cs); 328 gigaset_schedule_event(cs);
231 329
232 break; 330 break;
233 case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME 331 case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */
234 gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); 332 dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n");
235 break; 333 break;
236 case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME 334 case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */
237 gig_dbg(DEBUG_ANY, 335 dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n",
238 "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", 336 cntrl->parm.num);
239 cntrl->driver, cntrl->arg, cntrl->parm.num);
240 break; 337 break;
241 case ISDN_CMD_SETL2: /* Set L2 to given protocol */ 338 case ISDN_CMD_SETL2: /* Set L2 to given protocol */
242 gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", 339 if (ch >= cs->channels) {
243 cntrl->arg & 0xff, (cntrl->arg >> 8));
244
245 if ((cntrl->arg & 0xff) >= cs->channels) {
246 dev_err(cs->dev, 340 dev_err(cs->dev,
247 "ISDN_CMD_SETL2: invalid channel (%d)\n", 341 "ISDN_CMD_SETL2: invalid channel (%d)\n", ch);
248 (int) cntrl->arg & 0xff);
249 return -EINVAL; 342 return -EINVAL;
250 } 343 }
251 344 bcs = cs->bcs + ch;
252 if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, 345 if (bcs->chstate & CHS_D_UP) {
253 EV_PROTO_L2, NULL, cntrl->arg >> 8, 346 dev_err(cs->dev,
254 NULL)) { 347 "ISDN_CMD_SETL2: channel active (%d)\n", ch);
255 //FIXME what should we do? 348 return -EINVAL;
256 return -ENOMEM; 349 }
350 switch (cntrl->arg >> 8) {
351 case ISDN_PROTO_L2_HDLC:
352 gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC");
353 bcs->proto2 = L2_HDLC;
354 break;
355 case ISDN_PROTO_L2_TRANS:
356 gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE");
357 bcs->proto2 = L2_VOICE;
358 break;
359 default:
360 dev_err(cs->dev,
361 "ISDN_CMD_SETL2: unsupported protocol (%lu)\n",
362 cntrl->arg >> 8);
363 return -EINVAL;
257 } 364 }
258
259 gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
260 gigaset_schedule_event(cs);
261 break; 365 break;
262 case ISDN_CMD_SETL3: /* Set L3 to given protocol */ 366 case ISDN_CMD_SETL3: /* Set L3 to given protocol */
263 gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", 367 if (ch >= cs->channels) {
264 cntrl->arg & 0xff, (cntrl->arg >> 8));
265
266 if ((cntrl->arg & 0xff) >= cs->channels) {
267 dev_err(cs->dev, 368 dev_err(cs->dev,
268 "ISDN_CMD_SETL3: invalid channel (%d)\n", 369 "ISDN_CMD_SETL3: invalid channel (%d)\n", ch);
269 (int) cntrl->arg & 0xff);
270 return -EINVAL; 370 return -EINVAL;
271 } 371 }
272 372
273 if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { 373 if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
274 dev_err(cs->dev, 374 dev_err(cs->dev,
275 "ISDN_CMD_SETL3: invalid protocol %lu\n", 375 "ISDN_CMD_SETL3: unsupported protocol (%lu)\n",
276 cntrl->arg >> 8); 376 cntrl->arg >> 8);
277 return -EINVAL; 377 return -EINVAL;
278 } 378 }
@@ -324,149 +424,34 @@ static int command_from_LL(isdn_ctrl *cntrl)
324 } 424 }
325 425
326 return retval; 426 return retval;
427
428oom:
429 dev_err(bcs->cs->dev, "out of memory\n");
430 for (i = 0; i < AT_NUM; ++i)
431 kfree(commands[i]);
432 return -ENOMEM;
327} 433}
328 434
329void gigaset_i4l_cmd(struct cardstate *cs, int cmd) 435static void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
330{ 436{
437 isdn_if *iif = cs->iif;
331 isdn_ctrl command; 438 isdn_ctrl command;
332 439
333 command.driver = cs->myid; 440 command.driver = cs->myid;
334 command.command = cmd; 441 command.command = cmd;
335 command.arg = 0; 442 command.arg = 0;
336 cs->iif.statcallb(&command); 443 iif->statcallb(&command);
337} 444}
338 445
339void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) 446static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
340{ 447{
448 isdn_if *iif = bcs->cs->iif;
341 isdn_ctrl command; 449 isdn_ctrl command;
342 450
343 command.driver = bcs->cs->myid; 451 command.driver = bcs->cs->myid;
344 command.command = cmd; 452 command.command = cmd;
345 command.arg = bcs->channel; 453 command.arg = bcs->channel;
346 bcs->cs->iif.statcallb(&command); 454 iif->statcallb(&command);
347}
348
349int 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
426int 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} 455}
471 456
472/** 457/**
@@ -482,6 +467,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
482{ 467{
483 struct cardstate *cs = at_state->cs; 468 struct cardstate *cs = at_state->cs;
484 struct bc_state *bcs = at_state->bcs; 469 struct bc_state *bcs = at_state->bcs;
470 isdn_if *iif = cs->iif;
485 isdn_ctrl response; 471 isdn_ctrl response;
486 int retval; 472 int retval;
487 473
@@ -531,7 +517,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
531 response.arg = bcs->channel; //FIXME 517 response.arg = bcs->channel; //FIXME
532 } 518 }
533 response.driver = cs->myid; 519 response.driver = cs->myid;
534 retval = cs->iif.statcallb(&response); 520 retval = iif->statcallb(&response);
535 gig_dbg(DEBUG_CMD, "Response: %d", retval); 521 gig_dbg(DEBUG_CMD, "Response: %d", retval);
536 switch (retval) { 522 switch (retval) {
537 case 0: /* no takers */ 523 case 0: /* no takers */
@@ -560,16 +546,109 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
560 } 546 }
561} 547}
562 548
563/* Set Callback function pointer */ 549/**
564int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) 550 * gigaset_isdn_connD() - signal D channel connect
551 * @bcs: B channel descriptor structure.
552 *
553 * Called by main module to notify the LL that the D channel connection has
554 * been established.
555 */
556void gigaset_isdn_connD(struct bc_state *bcs)
565{ 557{
566 isdn_if *iif = &cs->iif; 558 gig_dbg(DEBUG_CMD, "sending DCONN");
559 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
560}
567 561
568 gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); 562/**
563 * gigaset_isdn_hupD() - signal D channel hangup
564 * @bcs: B channel descriptor structure.
565 *
566 * Called by main module to notify the LL that the D channel connection has
567 * been shut down.
568 */
569void gigaset_isdn_hupD(struct bc_state *bcs)
570{
571 gig_dbg(DEBUG_CMD, "sending DHUP");
572 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
573}
574
575/**
576 * gigaset_isdn_connB() - signal B channel connect
577 * @bcs: B channel descriptor structure.
578 *
579 * Called by main module to notify the LL that the B channel connection has
580 * been established.
581 */
582void gigaset_isdn_connB(struct bc_state *bcs)
583{
584 gig_dbg(DEBUG_CMD, "sending BCONN");
585 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
586}
587
588/**
589 * gigaset_isdn_hupB() - signal B channel hangup
590 * @bcs: B channel descriptor structure.
591 *
592 * Called by main module to notify the LL that the B channel connection has
593 * been shut down.
594 */
595void gigaset_isdn_hupB(struct bc_state *bcs)
596{
597 gig_dbg(DEBUG_CMD, "sending BHUP");
598 gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
599}
600
601/**
602 * gigaset_isdn_start() - signal device availability
603 * @cs: device descriptor structure.
604 *
605 * Called by main module to notify the LL that the device is available for
606 * use.
607 */
608void gigaset_isdn_start(struct cardstate *cs)
609{
610 gig_dbg(DEBUG_CMD, "sending RUN");
611 gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
612}
613
614/**
615 * gigaset_isdn_stop() - signal device unavailability
616 * @cs: device descriptor structure.
617 *
618 * Called by main module to notify the LL that the device is no longer
619 * available for use.
620 */
621void gigaset_isdn_stop(struct cardstate *cs)
622{
623 gig_dbg(DEBUG_CMD, "sending STOP");
624 gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
625}
626
627/**
628 * gigaset_isdn_register() - register to LL
629 * @cs: device descriptor structure.
630 * @isdnid: device name.
631 *
632 * Called by main module to register the device with the LL.
633 *
634 * Return value: 1 for success, 0 for failure
635 */
636int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
637{
638 isdn_if *iif;
639
640 pr_info("ISDN4Linux interface\n");
641
642 iif = kmalloc(sizeof *iif, GFP_KERNEL);
643 if (!iif) {
644 pr_err("out of memory\n");
645 return 0;
646 }
569 647
570 if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) 648 if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
571 >= sizeof iif->id) { 649 >= sizeof iif->id) {
572 pr_err("ID too long: %s\n", isdnid); 650 pr_err("ID too long: %s\n", isdnid);
651 kfree(iif);
573 return 0; 652 return 0;
574 } 653 }
575 654
@@ -593,9 +672,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
593 672
594 if (!register_isdn(iif)) { 673 if (!register_isdn(iif)) {
595 pr_err("register_isdn failed\n"); 674 pr_err("register_isdn failed\n");
675 kfree(iif);
596 return 0; 676 return 0;
597 } 677 }
598 678
679 cs->iif = iif;
599 cs->myid = iif->channels; /* Set my device id */ 680 cs->myid = iif->channels; /* Set my device id */
681 cs->hw_hdr_len = HW_HDR_LEN;
600 return 1; 682 return 1;
601} 683}
684
685/**
686 * gigaset_isdn_unregister() - unregister from LL
687 * @cs: device descriptor structure.
688 *
689 * Called by main module to unregister the device from the LL.
690 */
691void gigaset_isdn_unregister(struct cardstate *cs)
692{
693 gig_dbg(DEBUG_CMD, "sending UNLOAD");
694 gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
695 kfree(cs->iif);
696 cs->iif = NULL;
697}