diff options
author | Tilman Schmidt <tilman@imap.cc> | 2010-06-21 09:55:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-26 00:17:00 -0400 |
commit | 1ce368ff288ed872a8fee93b8a2b7706111feb9a (patch) | |
tree | 51aa769fdf626c918382fd363bdb0019ea3f8e0a | |
parent | 23b36778b4c82577746d26e4ac0ae66c6f462475 (diff) |
isdn/gigaset: encode HLC and BC together
Adapt to buggy device firmware which accepts setting HLC only in the
same command line as BC, by encoding HLC and BC in a single command
if both are specified, and rejecting HLC without BC.
Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/isdn/gigaset/capi.c | 81 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 4 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 5 |
3 files changed, 52 insertions, 38 deletions
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index e685123fef48..665673f4d667 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -1166,7 +1166,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, | |||
1166 | char **commands; | 1166 | char **commands; |
1167 | char *s; | 1167 | char *s; |
1168 | u8 *pp; | 1168 | u8 *pp; |
1169 | int i, l; | 1169 | int i, l, lbc, lhlc; |
1170 | u16 info; | 1170 | u16 info; |
1171 | 1171 | ||
1172 | /* decode message */ | 1172 | /* decode message */ |
@@ -1293,42 +1293,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, | |||
1293 | goto error; | 1293 | goto error; |
1294 | } | 1294 | } |
1295 | 1295 | ||
1296 | /* check/encode parameter: BC */ | 1296 | /* |
1297 | if (cmsg->BC && cmsg->BC[0]) { | 1297 | * check/encode parameters: BC & HLC |
1298 | /* explicit BC overrides CIP */ | 1298 | * must be encoded together as device doesn't accept HLC separately |
1299 | l = 2*cmsg->BC[0] + 7; | 1299 | * explicit parameters override values derived from CIP |
1300 | */ | ||
1301 | |||
1302 | /* determine lengths */ | ||
1303 | if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ | ||
1304 | lbc = 2*cmsg->BC[0]; | ||
1305 | else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */ | ||
1306 | lbc = strlen(cip2bchlc[cmsg->CIPValue].bc); | ||
1307 | else /* no BC */ | ||
1308 | lbc = 0; | ||
1309 | if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */ | ||
1310 | lhlc = 2*cmsg->HLC[0]; | ||
1311 | else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */ | ||
1312 | lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc); | ||
1313 | else /* no HLC */ | ||
1314 | lhlc = 0; | ||
1315 | |||
1316 | if (lbc) { | ||
1317 | /* have BC: allocate and assemble command string */ | ||
1318 | l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */ | ||
1319 | if (lhlc) | ||
1320 | l += lhlc + 7; /* ";^SHLC=" + value */ | ||
1300 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | 1321 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); |
1301 | if (!commands[AT_BC]) | 1322 | if (!commands[AT_BC]) |
1302 | goto oom; | 1323 | goto oom; |
1303 | strcpy(commands[AT_BC], "^SBC="); | 1324 | strcpy(commands[AT_BC], "^SBC="); |
1304 | decode_ie(cmsg->BC, commands[AT_BC]+5); | 1325 | if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ |
1326 | decode_ie(cmsg->BC, commands[AT_BC] + 5); | ||
1327 | else /* BC derived from CIP */ | ||
1328 | strcpy(commands[AT_BC] + 5, | ||
1329 | cip2bchlc[cmsg->CIPValue].bc); | ||
1330 | if (lhlc) { | ||
1331 | strcpy(commands[AT_BC] + lbc + 5, ";^SHLC="); | ||
1332 | if (cmsg->HLC && cmsg->HLC[0]) | ||
1333 | /* HLC specified explicitly */ | ||
1334 | decode_ie(cmsg->HLC, | ||
1335 | commands[AT_BC] + lbc + 12); | ||
1336 | else /* HLC derived from CIP */ | ||
1337 | strcpy(commands[AT_BC] + lbc + 12, | ||
1338 | cip2bchlc[cmsg->CIPValue].hlc); | ||
1339 | } | ||
1305 | strcpy(commands[AT_BC] + l - 2, "\r"); | 1340 | strcpy(commands[AT_BC] + l - 2, "\r"); |
1306 | } else if (cip2bchlc[cmsg->CIPValue].bc) { | 1341 | } else { |
1307 | l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; | 1342 | /* no BC */ |
1308 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | 1343 | if (lhlc) { |
1309 | if (!commands[AT_BC]) | 1344 | dev_notice(cs->dev, "%s: cannot set HLC without BC\n", |
1310 | goto oom; | 1345 | "CONNECT_REQ"); |
1311 | snprintf(commands[AT_BC], l, "^SBC=%s\r", | 1346 | info = CapiIllMessageParmCoding; /* ? */ |
1312 | cip2bchlc[cmsg->CIPValue].bc); | 1347 | goto error; |
1313 | } | 1348 | } |
1314 | |||
1315 | /* check/encode parameter: HLC */ | ||
1316 | if (cmsg->HLC && cmsg->HLC[0]) { | ||
1317 | /* explicit HLC overrides CIP */ | ||
1318 | l = 2*cmsg->HLC[0] + 7; | ||
1319 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1320 | if (!commands[AT_HLC]) | ||
1321 | goto oom; | ||
1322 | strcpy(commands[AT_HLC], "^SHLC="); | ||
1323 | decode_ie(cmsg->HLC, commands[AT_HLC]+5); | ||
1324 | strcpy(commands[AT_HLC] + l - 2, "\r"); | ||
1325 | } else if (cip2bchlc[cmsg->CIPValue].hlc) { | ||
1326 | l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; | ||
1327 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1328 | if (!commands[AT_HLC]) | ||
1329 | goto oom; | ||
1330 | snprintf(commands[AT_HLC], l, "^SHLC=%s\r", | ||
1331 | cip2bchlc[cmsg->CIPValue].hlc); | ||
1332 | } | 1349 | } |
1333 | 1350 | ||
1334 | /* check/encode parameter: B Protocol */ | 1351 | /* check/encode parameter: B Protocol */ |
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 206c380c5235..ceaef9a04a42 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] = | |||
282 | /* dial */ | 282 | /* dial */ |
283 | {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, | 283 | {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, |
284 | {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, | 284 | {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, |
285 | {RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, | 285 | {RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD+AT_PROTO} }, |
286 | {RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, | ||
287 | {RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, | ||
288 | {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, | 286 | {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, |
289 | {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, | 287 | {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, |
290 | {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, | 288 | {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index f77ec54eb07d..c4e6c26897ea 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -186,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
186 | #define AT_BC 3 | 186 | #define AT_BC 3 |
187 | #define AT_PROTO 4 | 187 | #define AT_PROTO 4 |
188 | #define AT_TYPE 5 | 188 | #define AT_TYPE 5 |
189 | #define AT_HLC 6 | 189 | #define AT_CLIP 6 |
190 | #define AT_CLIP 7 | ||
191 | /* total number */ | 190 | /* total number */ |
192 | #define AT_NUM 8 | 191 | #define AT_NUM 7 |
193 | 192 | ||
194 | /* variables in struct at_state_t */ | 193 | /* variables in struct at_state_t */ |
195 | #define VAR_ZSAU 0 | 194 | #define VAR_ZSAU 0 |