Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ce368ff authored by Tilman Schmidt's avatar Tilman Schmidt Committed by David S. Miller
Browse files

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: default avatarTilman Schmidt <tilman@imap.cc>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23b36778
Loading
Loading
Loading
Loading
+49 −32
Original line number Diff line number Diff line
@@ -1166,7 +1166,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
	char **commands;
	char *s;
	u8 *pp;
	int i, l;
	int i, l, lbc, lhlc;
	u16 info;

	/* decode message */
@@ -1293,43 +1293,60 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
		goto error;
	}

	/* check/encode parameter: BC */
	if (cmsg->BC && cmsg->BC[0]) {
		/* explicit BC overrides CIP */
		l = 2*cmsg->BC[0] + 7;
	/*
	 * check/encode parameters: BC & HLC
	 * must be encoded together as device doesn't accept HLC separately
	 * explicit parameters override values derived from CIP
	 */

	/* determine lengths */
	if (cmsg->BC && cmsg->BC[0])		/* BC specified explicitly */
		lbc = 2*cmsg->BC[0];
	else if (cip2bchlc[cmsg->CIPValue].bc)	/* BC derived from CIP */
		lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
	else					/* no BC */
		lbc = 0;
	if (cmsg->HLC && cmsg->HLC[0])		/* HLC specified explicitly */
		lhlc = 2*cmsg->HLC[0];
	else if (cip2bchlc[cmsg->CIPValue].hlc)	/* HLC derived from CIP */
		lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
	else					/* no HLC */
		lhlc = 0;

	if (lbc) {
		/* have BC: allocate and assemble command string */
		l = lbc + 7;		/* "^SBC=" + value + "\r" + null byte */
		if (lhlc)
			l += lhlc + 7;	/* ";^SHLC=" + value */
		commands[AT_BC] = kmalloc(l, GFP_KERNEL);
		if (!commands[AT_BC])
			goto oom;
		strcpy(commands[AT_BC], "^SBC=");
		if (cmsg->BC && cmsg->BC[0])	/* BC specified explicitly */
			decode_ie(cmsg->BC, commands[AT_BC] + 5);
		strcpy(commands[AT_BC] + l - 2, "\r");
	} else if (cip2bchlc[cmsg->CIPValue].bc) {
		l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
		commands[AT_BC] = kmalloc(l, GFP_KERNEL);
		if (!commands[AT_BC])
			goto oom;
		snprintf(commands[AT_BC], l, "^SBC=%s\r",
		else				/* BC derived from CIP */
			strcpy(commands[AT_BC] + 5,
			       cip2bchlc[cmsg->CIPValue].bc);
	}

	/* check/encode parameter: HLC */
	if (cmsg->HLC && cmsg->HLC[0]) {
		/* explicit HLC overrides CIP */
		l = 2*cmsg->HLC[0] + 7;
		commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
		if (!commands[AT_HLC])
			goto oom;
		strcpy(commands[AT_HLC], "^SHLC=");
		decode_ie(cmsg->HLC, commands[AT_HLC]+5);
		strcpy(commands[AT_HLC] + l - 2, "\r");
	} else if (cip2bchlc[cmsg->CIPValue].hlc) {
		l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
		commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
		if (!commands[AT_HLC])
			goto oom;
		snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
		if (lhlc) {
			strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
			if (cmsg->HLC && cmsg->HLC[0])
				/* HLC specified explicitly */
				decode_ie(cmsg->HLC,
					  commands[AT_BC] + lbc + 12);
			else	/* HLC derived from CIP */
				strcpy(commands[AT_BC] + lbc + 12,
				       cip2bchlc[cmsg->CIPValue].hlc);
		}
		strcpy(commands[AT_BC] + l - 2, "\r");
	} else {
		/* no BC */
		if (lhlc) {
			dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
				   "CONNECT_REQ");
			info = CapiIllMessageParmCoding; /* ? */
			goto error;
		}
	}

	/* check/encode parameter: B Protocol */
	if (cmsg->BProtocol == CAPI_DEFAULT) {
+1 −3
Original line number Diff line number Diff line
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =
/* dial */
{EV_DIAL,	 -1,  -1, -1,			 -1, -1, {ACT_DIAL} },
{RSP_INIT,	  0,   0, SEQ_DIAL,		601,  5, {ACT_CMD+AT_BC} },
{RSP_OK,	601, 601, -1,			602,  5, {ACT_CMD+AT_HLC} },
{RSP_NULL,	602, 602, -1,			603,  5, {ACT_CMD+AT_PROTO} },
{RSP_OK,	602, 602, -1,			603,  5, {ACT_CMD+AT_PROTO} },
{RSP_OK,	601, 601, -1,			603,  5, {ACT_CMD+AT_PROTO} },
{RSP_OK,	603, 603, -1,			604,  5, {ACT_CMD+AT_TYPE} },
{RSP_OK,	604, 604, -1,			605,  5, {ACT_CMD+AT_MSN} },
{RSP_NULL,	605, 605, -1,			606,  5, {ACT_CMD+AT_CLIP} },
+2 −3
Original line number Diff line number Diff line
@@ -186,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define AT_BC		3
#define AT_PROTO	4
#define AT_TYPE		5
#define AT_HLC		6
#define AT_CLIP		7
#define AT_CLIP		6
/* total number */
#define AT_NUM		8
#define AT_NUM		7

/* variables in struct at_state_t */
#define VAR_ZSAU	0