| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Stuff used by all variants of the driver | 
 | 3 |  * | 
| Tilman Schmidt | 70440cf | 2006-04-10 22:55:14 -0700 | [diff] [blame] | 4 |  * Copyright (c) 2001 by Stefan Eilers, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 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 |  * ===================================================================== | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 14 |  */ | 
 | 15 |  | 
 | 16 | #include "gigaset.h" | 
 | 17 |  | 
 | 18 | /* ========================================================== */ | 
 | 19 | /* bit masks for pending commands */ | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 20 | #define PC_DIAL		0x001 | 
 | 21 | #define PC_HUP		0x002 | 
 | 22 | #define PC_INIT		0x004 | 
 | 23 | #define PC_DLE0		0x008 | 
 | 24 | #define PC_DLE1		0x010 | 
 | 25 | #define PC_SHUTDOWN	0x020 | 
 | 26 | #define PC_ACCEPT	0x040 | 
 | 27 | #define PC_CID		0x080 | 
 | 28 | #define PC_NOCID	0x100 | 
 | 29 | #define PC_CIDMODE	0x200 | 
 | 30 | #define PC_UMMODE	0x400 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 31 |  | 
 | 32 | /* types of modem responses */ | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 33 | #define RT_NOTHING	0 | 
 | 34 | #define RT_ZSAU		1 | 
 | 35 | #define RT_RING		2 | 
 | 36 | #define RT_NUMBER	3 | 
 | 37 | #define RT_STRING	4 | 
 | 38 | #define RT_HEX		5 | 
 | 39 | #define RT_ZCAU		6 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 40 |  | 
 | 41 | /* Possible ASCII responses */ | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 42 | #define RSP_OK		0 | 
 | 43 | //#define RSP_BUSY	1 | 
 | 44 | //#define RSP_CONNECT	2 | 
 | 45 | #define RSP_ZGCI	3 | 
 | 46 | #define RSP_RING	4 | 
 | 47 | #define RSP_ZAOC	5 | 
 | 48 | #define RSP_ZCSTR	6 | 
 | 49 | #define RSP_ZCFGT	7 | 
 | 50 | #define RSP_ZCFG	8 | 
 | 51 | #define RSP_ZCCR	9 | 
 | 52 | #define RSP_EMPTY	10 | 
 | 53 | #define RSP_ZLOG	11 | 
 | 54 | #define RSP_ZCAU	12 | 
 | 55 | #define RSP_ZMWI	13 | 
 | 56 | #define RSP_ZABINFO	14 | 
 | 57 | #define RSP_ZSMLSTCHG	15 | 
 | 58 | #define RSP_VAR		100 | 
 | 59 | #define RSP_ZSAU	(RSP_VAR + VAR_ZSAU) | 
 | 60 | #define RSP_ZDLE	(RSP_VAR + VAR_ZDLE) | 
 | 61 | #define RSP_ZVLS	(RSP_VAR + VAR_ZVLS) | 
 | 62 | #define RSP_ZCTP	(RSP_VAR + VAR_ZCTP) | 
 | 63 | #define RSP_STR		(RSP_VAR + VAR_NUM) | 
 | 64 | #define RSP_NMBR	(RSP_STR + STR_NMBR) | 
 | 65 | #define RSP_ZCPN	(RSP_STR + STR_ZCPN) | 
 | 66 | #define RSP_ZCON	(RSP_STR + STR_ZCON) | 
 | 67 | #define RSP_ZBC		(RSP_STR + STR_ZBC) | 
 | 68 | #define RSP_ZHLC	(RSP_STR + STR_ZHLC) | 
 | 69 | #define RSP_ERROR	-1	/* ERROR              */ | 
 | 70 | #define RSP_WRONG_CID	-2	/* unknown cid in cmd */ | 
 | 71 | //#define RSP_EMPTY	-3 | 
 | 72 | #define RSP_UNKNOWN	-4	/* unknown response   */ | 
 | 73 | #define RSP_FAIL	-5	/* internal error     */ | 
 | 74 | #define RSP_INVAL	-6	/* invalid response   */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 75 |  | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 76 | #define RSP_NONE	-19 | 
 | 77 | #define RSP_STRING	-20 | 
 | 78 | #define RSP_NULL	-21 | 
 | 79 | //#define RSP_RETRYFAIL	-22 | 
 | 80 | //#define RSP_RETRY	-23 | 
 | 81 | //#define RSP_SKIP	-24 | 
 | 82 | #define RSP_INIT	-27 | 
 | 83 | #define RSP_ANY		-26 | 
 | 84 | #define RSP_LAST	-28 | 
 | 85 | #define RSP_NODEV	-9 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 86 |  | 
 | 87 | /* actions for process_response */ | 
 | 88 | #define ACT_NOTHING		0 | 
 | 89 | #define ACT_SETDLE1		1 | 
 | 90 | #define ACT_SETDLE0		2 | 
 | 91 | #define ACT_FAILINIT		3 | 
 | 92 | #define ACT_HUPMODEM		4 | 
 | 93 | #define ACT_CONFIGMODE		5 | 
 | 94 | #define ACT_INIT		6 | 
 | 95 | #define ACT_DLE0		7 | 
 | 96 | #define ACT_DLE1		8 | 
 | 97 | #define ACT_FAILDLE0		9 | 
 | 98 | #define ACT_FAILDLE1		10 | 
 | 99 | #define ACT_RING		11 | 
 | 100 | #define ACT_CID			12 | 
 | 101 | #define ACT_FAILCID		13 | 
 | 102 | #define ACT_SDOWN		14 | 
 | 103 | #define ACT_FAILSDOWN		15 | 
 | 104 | #define ACT_DEBUG		16 | 
 | 105 | #define ACT_WARN		17 | 
 | 106 | #define ACT_DIALING		18 | 
 | 107 | #define ACT_ABORTDIAL		19 | 
 | 108 | #define ACT_DISCONNECT		20 | 
 | 109 | #define ACT_CONNECT		21 | 
 | 110 | #define ACT_REMOTEREJECT	22 | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 111 | #define ACT_CONNTIMEOUT		23 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 112 | #define ACT_REMOTEHUP		24 | 
 | 113 | #define ACT_ABORTHUP		25 | 
 | 114 | #define ACT_ICALL		26 | 
 | 115 | #define ACT_ACCEPTED		27 | 
 | 116 | #define ACT_ABORTACCEPT		28 | 
 | 117 | #define ACT_TIMEOUT		29 | 
 | 118 | #define ACT_GETSTRING		30 | 
 | 119 | #define ACT_SETVER		31 | 
 | 120 | #define ACT_FAILVER		32 | 
 | 121 | #define ACT_GOTVER		33 | 
 | 122 | #define ACT_TEST		34 | 
 | 123 | #define ACT_ERROR		35 | 
 | 124 | #define ACT_ABORTCID		36 | 
 | 125 | #define ACT_ZCAU		37 | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 126 | #define ACT_NOTIFY_BC_DOWN	38 | 
 | 127 | #define ACT_NOTIFY_BC_UP	39 | 
 | 128 | #define ACT_DIAL		40 | 
 | 129 | #define ACT_ACCEPT		41 | 
 | 130 | #define ACT_PROTO_L2		42 | 
 | 131 | #define ACT_HUP			43 | 
 | 132 | #define ACT_IF_LOCK		44 | 
 | 133 | #define ACT_START		45 | 
 | 134 | #define ACT_STOP		46 | 
 | 135 | #define ACT_FAKEDLE0		47 | 
 | 136 | #define ACT_FAKEHUP		48 | 
 | 137 | #define ACT_FAKESDOWN		49 | 
 | 138 | #define ACT_SHUTDOWN		50 | 
 | 139 | #define ACT_PROC_CIDMODE	51 | 
 | 140 | #define ACT_UMODESET		52 | 
 | 141 | #define ACT_FAILUMODE		53 | 
 | 142 | #define ACT_CMODESET		54 | 
 | 143 | #define ACT_FAILCMODE		55 | 
 | 144 | #define ACT_IF_VER		56 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 145 | #define ACT_CMD			100 | 
 | 146 |  | 
 | 147 | /* at command sequences */ | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 148 | #define SEQ_NONE	0 | 
 | 149 | #define SEQ_INIT	100 | 
 | 150 | #define SEQ_DLE0	200 | 
 | 151 | #define SEQ_DLE1	250 | 
 | 152 | #define SEQ_CID		300 | 
 | 153 | #define SEQ_NOCID	350 | 
 | 154 | #define SEQ_HUP		400 | 
 | 155 | #define SEQ_DIAL	600 | 
 | 156 | #define SEQ_ACCEPT	720 | 
 | 157 | #define SEQ_SHUTDOWN	500 | 
 | 158 | #define SEQ_CIDMODE	10 | 
 | 159 | #define SEQ_UMMODE	11 | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 160 |  | 
 | 161 |  | 
 | 162 | // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring | 
| Tilman Schmidt | 528efc6 | 2009-05-13 12:44:17 +0000 | [diff] [blame] | 163 | struct reply_t gigaset_tab_nocid[] = | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 164 | { | 
 | 165 | 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 
 | 166 |  | 
 | 167 | 	/* initialize device, set cid mode if possible */ | 
 | 168 | 	//{RSP_INIT,     -1, -1,100,                900, 0, {ACT_TEST}}, | 
 | 169 | 	//{RSP_ERROR,   900,900, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 170 | 	//{RSP_OK,      900,900, -1,                100, INIT_TIMEOUT, | 
 | 171 | 	//                                                  {ACT_TIMEOUT}}, | 
 | 172 |  | 
 | 173 | 	{RSP_INIT,     -1, -1,SEQ_INIT,           100, INIT_TIMEOUT, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 174 | 							  {ACT_TIMEOUT}},                /* wait until device is ready */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 175 |  | 
 | 176 | 	{EV_TIMEOUT,  100,100, -1,                101, 3, {0},             "Z\r"},       /* device in transparent mode? try to initialize it. */ | 
 | 177 | 	{RSP_OK,      101,103, -1,                120, 5, {ACT_GETSTRING}, "+GMR\r"},    /* get version */ | 
 | 178 |  | 
 | 179 | 	{EV_TIMEOUT,  101,101, -1,                102, 5, {0},             "Z\r"},       /* timeout => try once again. */ | 
 | 180 | 	{RSP_ERROR,   101,101, -1,                102, 5, {0},             "Z\r"},       /* error => try once again. */ | 
 | 181 |  | 
 | 182 | 	{EV_TIMEOUT,  102,102, -1,                108, 5, {ACT_SETDLE1},   "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ | 
 | 183 | 	{RSP_OK,      108,108, -1,                104,-1}, | 
 | 184 | 	{RSP_ZDLE,    104,104,  0,                103, 5, {0},             "Z\r"}, | 
 | 185 | 	{EV_TIMEOUT,  104,104, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 186 | 	{RSP_ERROR,   108,108, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 187 |  | 
 | 188 | 	{EV_TIMEOUT,  108,108, -1,                105, 2, {ACT_SETDLE0, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 189 | 							   ACT_HUPMODEM, | 
 | 190 | 							   ACT_TIMEOUT}},                /* still timeout => connection in unimodem mode? */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 191 | 	{EV_TIMEOUT,  105,105, -1,                103, 5, {0},             "Z\r"}, | 
 | 192 |  | 
 | 193 | 	{RSP_ERROR,   102,102, -1,                107, 5, {0},             "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ | 
 | 194 | 	{RSP_OK,      107,107, -1,                  0, 0, {ACT_CONFIGMODE}}, | 
 | 195 | 	{RSP_ERROR,   107,107, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 196 | 	{EV_TIMEOUT,  107,107, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 197 |  | 
 | 198 | 	{RSP_ERROR,   103,103, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 199 | 	{EV_TIMEOUT,  103,103, -1,                  0, 0, {ACT_FAILINIT}}, | 
 | 200 |  | 
 | 201 | 	{RSP_STRING,  120,120, -1,                121,-1, {ACT_SETVER}}, | 
 | 202 |  | 
 | 203 | 	{EV_TIMEOUT,  120,121, -1,                  0, 0, {ACT_FAILVER, ACT_INIT}}, | 
 | 204 | 	{RSP_ERROR,   120,121, -1,                  0, 0, {ACT_FAILVER, ACT_INIT}}, | 
 | 205 | 	{RSP_OK,      121,121, -1,                  0, 0, {ACT_GOTVER,  ACT_INIT}}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 206 |  | 
 | 207 | 	/* leave dle mode */ | 
 | 208 | 	{RSP_INIT,      0,  0,SEQ_DLE0,           201, 5, {0},             "^SDLE=0\r"}, | 
 | 209 | 	{RSP_OK,      201,201, -1,                202,-1}, | 
 | 210 | 	//{RSP_ZDLE,    202,202,  0,                202, 0, {ACT_ERROR}},//DELETE | 
 | 211 | 	{RSP_ZDLE,    202,202,  0,                  0, 0, {ACT_DLE0}}, | 
 | 212 | 	{RSP_NODEV,   200,249, -1,                  0, 0, {ACT_FAKEDLE0}}, | 
 | 213 | 	{RSP_ERROR,   200,249, -1,                  0, 0, {ACT_FAILDLE0}}, | 
 | 214 | 	{EV_TIMEOUT,  200,249, -1,                  0, 0, {ACT_FAILDLE0}}, | 
 | 215 |  | 
 | 216 | 	/* enter dle mode */ | 
 | 217 | 	{RSP_INIT,      0,  0,SEQ_DLE1,           251, 5, {0},             "^SDLE=1\r"}, | 
 | 218 | 	{RSP_OK,      251,251, -1,                252,-1}, | 
 | 219 | 	{RSP_ZDLE,    252,252,  1,                  0, 0, {ACT_DLE1}}, | 
 | 220 | 	{RSP_ERROR,   250,299, -1,                  0, 0, {ACT_FAILDLE1}}, | 
 | 221 | 	{EV_TIMEOUT,  250,299, -1,                  0, 0, {ACT_FAILDLE1}}, | 
 | 222 |  | 
 | 223 | 	/* incoming call */ | 
 | 224 | 	{RSP_RING,     -1, -1, -1,                 -1,-1, {ACT_RING}}, | 
 | 225 |  | 
 | 226 | 	/* get cid */ | 
 | 227 | 	//{RSP_INIT,      0,  0,300,                901, 0, {ACT_TEST}}, | 
 | 228 | 	//{RSP_ERROR,   901,901, -1,                  0, 0, {ACT_FAILCID}}, | 
 | 229 | 	//{RSP_OK,      901,901, -1,                301, 5, {0},             "^SGCI?\r"}, | 
 | 230 |  | 
 | 231 | 	{RSP_INIT,      0,  0,SEQ_CID,            301, 5, {0},             "^SGCI?\r"}, | 
 | 232 | 	{RSP_OK,      301,301, -1,                302,-1}, | 
 | 233 | 	{RSP_ZGCI,    302,302, -1,                  0, 0, {ACT_CID}}, | 
 | 234 | 	{RSP_ERROR,   301,349, -1,                  0, 0, {ACT_FAILCID}}, | 
 | 235 | 	{EV_TIMEOUT,  301,349, -1,                  0, 0, {ACT_FAILCID}}, | 
 | 236 |  | 
 | 237 | 	/* enter cid mode */ | 
 | 238 | 	{RSP_INIT,      0,  0,SEQ_CIDMODE,        150, 5, {0},             "^SGCI=1\r"}, | 
 | 239 | 	{RSP_OK,      150,150, -1,                  0, 0, {ACT_CMODESET}}, | 
 | 240 | 	{RSP_ERROR,   150,150, -1,                  0, 0, {ACT_FAILCMODE}}, | 
 | 241 | 	{EV_TIMEOUT,  150,150, -1,                  0, 0, {ACT_FAILCMODE}}, | 
 | 242 |  | 
 | 243 | 	/* leave cid mode */ | 
 | 244 | 	//{RSP_INIT,      0,  0,SEQ_UMMODE,         160, 5, {0},             "^SGCI=0\r"}, | 
 | 245 | 	{RSP_INIT,      0,  0,SEQ_UMMODE,         160, 5, {0},             "Z\r"}, | 
 | 246 | 	{RSP_OK,      160,160, -1,                  0, 0, {ACT_UMODESET}}, | 
 | 247 | 	{RSP_ERROR,   160,160, -1,                  0, 0, {ACT_FAILUMODE}}, | 
 | 248 | 	{EV_TIMEOUT,  160,160, -1,                  0, 0, {ACT_FAILUMODE}}, | 
 | 249 |  | 
 | 250 | 	/* abort getting cid */ | 
 | 251 | 	{RSP_INIT,      0,  0,SEQ_NOCID,            0, 0, {ACT_ABORTCID}}, | 
 | 252 |  | 
 | 253 | 	/* reset */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 254 | 	{RSP_INIT,      0,  0,SEQ_SHUTDOWN,       504, 5, {0},             "Z\r"}, | 
 | 255 | 	{RSP_OK,      504,504, -1,                  0, 0, {ACT_SDOWN}}, | 
 | 256 | 	{RSP_ERROR,   501,599, -1,                  0, 0, {ACT_FAILSDOWN}}, | 
 | 257 | 	{EV_TIMEOUT,  501,599, -1,                  0, 0, {ACT_FAILSDOWN}}, | 
 | 258 | 	{RSP_NODEV,   501,599, -1,                  0, 0, {ACT_FAKESDOWN}}, | 
 | 259 |  | 
 | 260 | 	{EV_PROC_CIDMODE,-1, -1, -1,               -1,-1, {ACT_PROC_CIDMODE}}, //FIXME | 
 | 261 | 	{EV_IF_LOCK,   -1, -1, -1,                 -1,-1, {ACT_IF_LOCK}}, //FIXME | 
 | 262 | 	{EV_IF_VER,    -1, -1, -1,                 -1,-1, {ACT_IF_VER}}, //FIXME | 
 | 263 | 	{EV_START,     -1, -1, -1,                 -1,-1, {ACT_START}}, //FIXME | 
 | 264 | 	{EV_STOP,      -1, -1, -1,                 -1,-1, {ACT_STOP}}, //FIXME | 
 | 265 | 	{EV_SHUTDOWN,  -1, -1, -1,                 -1,-1, {ACT_SHUTDOWN}}, //FIXME | 
 | 266 |  | 
 | 267 | 	/* misc. */ | 
 | 268 | 	{RSP_EMPTY,    -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 269 | 	{RSP_ZCFGT,    -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 270 | 	{RSP_ZCFG,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 271 | 	{RSP_ZLOG,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 272 | 	{RSP_ZMWI,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 273 | 	{RSP_ZABINFO,  -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 274 | 	{RSP_ZSMLSTCHG,-1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 275 |  | 
 | 276 | 	{RSP_ZCAU,     -1, -1, -1,                 -1,-1, {ACT_ZCAU}}, | 
 | 277 | 	{RSP_NONE,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, | 
 | 278 | 	{RSP_ANY,      -1, -1, -1,                 -1,-1, {ACT_WARN}}, | 
 | 279 | 	{RSP_LAST} | 
 | 280 | }; | 
 | 281 |  | 
 | 282 | // 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall | 
| Tilman Schmidt | 528efc6 | 2009-05-13 12:44:17 +0000 | [diff] [blame] | 283 | struct reply_t gigaset_tab_cid[] = | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 284 | { | 
 | 285 | 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 
 | 286 |  | 
 | 287 | 	/* dial */ | 
 | 288 | 	{EV_DIAL,      -1, -1, -1,                 -1,-1, {ACT_DIAL}}, //FIXME | 
 | 289 | 	{RSP_INIT,      0,  0,SEQ_DIAL,           601, 5, {ACT_CMD+AT_BC}}, | 
 | 290 | 	{RSP_OK,      601,601, -1,                602, 5, {ACT_CMD+AT_HLC}}, | 
 | 291 | 	{RSP_NULL,    602,602, -1,                603, 5, {ACT_CMD+AT_PROTO}}, | 
 | 292 | 	{RSP_OK,      602,602, -1,                603, 5, {ACT_CMD+AT_PROTO}}, | 
 | 293 | 	{RSP_OK,      603,603, -1,                604, 5, {ACT_CMD+AT_TYPE}}, | 
 | 294 | 	{RSP_OK,      604,604, -1,                605, 5, {ACT_CMD+AT_MSN}}, | 
 | 295 | 	{RSP_OK,      605,605, -1,                606, 5, {ACT_CMD+AT_ISO}}, | 
 | 296 | 	{RSP_NULL,    605,605, -1,                606, 5, {ACT_CMD+AT_ISO}}, | 
| Tilman Schmidt | bceb0f1 | 2009-07-01 11:20:57 +0000 | [diff] [blame] | 297 | 	{RSP_OK,      606,606, -1,                607, 5, {0}, "+VLS=17\r"}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 298 | 	{RSP_OK,      607,607, -1,                608,-1}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 299 | 	{RSP_ZSAU,    608,608,ZSAU_PROCEEDING,    609, 5, {ACT_CMD+AT_DIAL}}, | 
 | 300 | 	{RSP_OK,      609,609, -1,                650, 0, {ACT_DIALING}}, | 
 | 301 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 302 | 	{RSP_ERROR,   601,609, -1,                  0, 0, {ACT_ABORTDIAL}}, | 
 | 303 | 	{EV_TIMEOUT,  601,609, -1,                  0, 0, {ACT_ABORTDIAL}}, | 
 | 304 |  | 
| Tilman Schmidt | bceb0f1 | 2009-07-01 11:20:57 +0000 | [diff] [blame] | 305 | 	/* optional dialing responses */ | 
 | 306 | 	{EV_BC_OPEN,  650,650, -1,                651,-1}, | 
 | 307 | 	{RSP_ZVLS,    608,651, 17,                 -1,-1, {ACT_DEBUG}}, | 
 | 308 | 	{RSP_ZCTP,    609,651, -1,                 -1,-1, {ACT_DEBUG}}, | 
 | 309 | 	{RSP_ZCPN,    609,651, -1,                 -1,-1, {ACT_DEBUG}}, | 
 | 310 | 	{RSP_ZSAU,    650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 311 |  | 
| Tilman Schmidt | bceb0f1 | 2009-07-01 11:20:57 +0000 | [diff] [blame] | 312 | 	/* connect */ | 
 | 313 | 	{RSP_ZSAU,    650,650,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}}, | 
 | 314 | 	{RSP_ZSAU,    651,651,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT, | 
 | 315 | 							   ACT_NOTIFY_BC_UP}}, | 
 | 316 | 	{RSP_ZSAU,    750,750,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}}, | 
 | 317 | 	{RSP_ZSAU,    751,751,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT, | 
 | 318 | 							   ACT_NOTIFY_BC_UP}}, | 
 | 319 | 	{EV_BC_OPEN,  800,800, -1,                800,-1, {ACT_NOTIFY_BC_UP}}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 320 |  | 
 | 321 | 	/* remote hangup */ | 
| Tilman Schmidt | bceb0f1 | 2009-07-01 11:20:57 +0000 | [diff] [blame] | 322 | 	{RSP_ZSAU,    650,651,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEREJECT}}, | 
 | 323 | 	{RSP_ZSAU,    750,751,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 324 | 	{RSP_ZSAU,    800,800,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}}, | 
 | 325 |  | 
 | 326 | 	/* hangup */ | 
 | 327 | 	{EV_HUP,       -1, -1, -1,                 -1,-1, {ACT_HUP}}, //FIXME | 
 | 328 | 	{RSP_INIT,     -1, -1,SEQ_HUP,            401, 5, {0},             "+VLS=0\r"}, /* hang up */ //-1,-1? | 
 | 329 | 	{RSP_OK,      401,401, -1,                402, 5}, | 
 | 330 | 	{RSP_ZVLS,    402,402,  0,                403, 5}, | 
 | 331 | 	{RSP_ZSAU,    403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */ | 
 | 332 | 	//{RSP_ZSAU,    403,403,ZSAU_NULL,          401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver? | 
 | 333 | 	{RSP_ZSAU,    403,403,ZSAU_NULL,            0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? | 
 | 334 | 	{RSP_NODEV,   401,403, -1,                  0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? | 
 | 335 | 	{RSP_ERROR,   401,401, -1,                  0, 0, {ACT_ABORTHUP}}, | 
 | 336 | 	{EV_TIMEOUT,  401,403, -1,                  0, 0, {ACT_ABORTHUP}}, | 
 | 337 |  | 
 | 338 | 	{EV_BC_CLOSED,  0,  0, -1,                  0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout | 
 | 339 |  | 
 | 340 | 	/* ring */ | 
 | 341 | 	{RSP_ZBC,     700,700, -1,                 -1,-1, {0}}, | 
 | 342 | 	{RSP_ZHLC,    700,700, -1,                 -1,-1, {0}}, | 
 | 343 | 	{RSP_NMBR,    700,700, -1,                 -1,-1, {0}}, | 
 | 344 | 	{RSP_ZCPN,    700,700, -1,                 -1,-1, {0}}, | 
 | 345 | 	{RSP_ZCTP,    700,700, -1,                 -1,-1, {0}}, | 
 | 346 | 	{EV_TIMEOUT,  700,700, -1,               720,720, {ACT_ICALL}}, | 
 | 347 | 	{EV_BC_CLOSED,720,720, -1,                  0,-1, {ACT_NOTIFY_BC_DOWN}}, | 
 | 348 |  | 
 | 349 | 	/*accept icall*/ | 
 | 350 | 	{EV_ACCEPT,    -1, -1, -1,                 -1,-1, {ACT_ACCEPT}}, //FIXME | 
 | 351 | 	{RSP_INIT,    720,720,SEQ_ACCEPT,         721, 5, {ACT_CMD+AT_PROTO}}, | 
 | 352 | 	{RSP_OK,      721,721, -1,                722, 5, {ACT_CMD+AT_ISO}}, | 
 | 353 | 	{RSP_OK,      722,722, -1,                723, 5, {0},             "+VLS=17\r"}, /* set "Endgeraetemodus" */ | 
 | 354 | 	{RSP_OK,      723,723, -1,                724, 5, {0}}, | 
 | 355 | 	{RSP_ZVLS,    724,724, 17,                750,50, {ACT_ACCEPTED}}, | 
 | 356 | 	{RSP_ERROR,   721,729, -1,                  0, 0, {ACT_ABORTACCEPT}}, | 
 | 357 | 	{EV_TIMEOUT,  721,729, -1,                  0, 0, {ACT_ABORTACCEPT}}, | 
 | 358 | 	{RSP_ZSAU,    700,729,ZSAU_NULL,            0, 0, {ACT_ABORTACCEPT}}, | 
 | 359 | 	{RSP_ZSAU,    700,729,ZSAU_ACTIVE,          0, 0, {ACT_ABORTACCEPT}}, | 
 | 360 | 	{RSP_ZSAU,    700,729,ZSAU_DISCONNECT_IND,  0, 0, {ACT_ABORTACCEPT}}, | 
 | 361 |  | 
| Tilman Schmidt | bceb0f1 | 2009-07-01 11:20:57 +0000 | [diff] [blame] | 362 | 	{EV_BC_OPEN,  750,750, -1,                751,-1}, | 
 | 363 | 	{EV_TIMEOUT,  750,751, -1,                  0, 0, {ACT_CONNTIMEOUT}}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 364 |  | 
| Tilman Schmidt | 73a8881 | 2006-04-22 02:35:30 -0700 | [diff] [blame] | 365 | 	/* B channel closed (general case) */ | 
 | 366 | 	{EV_BC_CLOSED, -1, -1, -1,                 -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | 
 | 367 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 368 | 	/* misc. */ | 
 | 369 | 	{EV_PROTO_L2,  -1, -1, -1,                 -1,-1, {ACT_PROTO_L2}}, //FIXME | 
 | 370 |  | 
 | 371 | 	{RSP_ZCON,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 372 | 	{RSP_ZCCR,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 373 | 	{RSP_ZAOC,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 374 | 	{RSP_ZCSTR,    -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME | 
 | 375 |  | 
 | 376 | 	{RSP_ZCAU,     -1, -1, -1,                 -1,-1, {ACT_ZCAU}}, | 
 | 377 | 	{RSP_NONE,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, | 
 | 378 | 	{RSP_ANY,      -1, -1, -1,                 -1,-1, {ACT_WARN}}, | 
 | 379 | 	{RSP_LAST} | 
 | 380 | }; | 
 | 381 |  | 
 | 382 |  | 
| Tilman Schmidt | 35dc845 | 2007-03-29 01:20:34 -0700 | [diff] [blame] | 383 | static const struct resp_type_t resp_type[] = | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 384 | { | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 385 | 	/*{"",		RSP_EMPTY,	RT_NOTHING},*/ | 
 | 386 | 	{"OK",		RSP_OK,		RT_NOTHING}, | 
 | 387 | 	{"ERROR",	RSP_ERROR,	RT_NOTHING}, | 
 | 388 | 	{"ZSAU",	RSP_ZSAU,	RT_ZSAU}, | 
 | 389 | 	{"ZCAU",	RSP_ZCAU,	RT_ZCAU}, | 
 | 390 | 	{"RING",	RSP_RING,	RT_RING}, | 
 | 391 | 	{"ZGCI",	RSP_ZGCI,	RT_NUMBER}, | 
 | 392 | 	{"ZVLS",	RSP_ZVLS,	RT_NUMBER}, | 
 | 393 | 	{"ZCTP",	RSP_ZCTP,	RT_NUMBER}, | 
 | 394 | 	{"ZDLE",	RSP_ZDLE,	RT_NUMBER}, | 
 | 395 | 	{"ZCFGT",	RSP_ZCFGT,	RT_NUMBER}, | 
 | 396 | 	{"ZCCR",	RSP_ZCCR,	RT_NUMBER}, | 
 | 397 | 	{"ZMWI",	RSP_ZMWI,	RT_NUMBER}, | 
 | 398 | 	{"ZHLC",	RSP_ZHLC,	RT_STRING}, | 
 | 399 | 	{"ZBC",		RSP_ZBC,	RT_STRING}, | 
 | 400 | 	{"NMBR",	RSP_NMBR,	RT_STRING}, | 
 | 401 | 	{"ZCPN",	RSP_ZCPN,	RT_STRING}, | 
 | 402 | 	{"ZCON",	RSP_ZCON,	RT_STRING}, | 
 | 403 | 	{"ZAOC",	RSP_ZAOC,	RT_STRING}, | 
 | 404 | 	{"ZCSTR",	RSP_ZCSTR,	RT_STRING}, | 
 | 405 | 	{"ZCFG",	RSP_ZCFG,	RT_HEX}, | 
 | 406 | 	{"ZLOG",	RSP_ZLOG,	RT_NOTHING}, | 
 | 407 | 	{"ZABINFO",	RSP_ZABINFO,	RT_NOTHING}, | 
 | 408 | 	{"ZSMLSTCHG",	RSP_ZSMLSTCHG,	RT_NOTHING}, | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 409 | 	{NULL,0,0} | 
 | 410 | }; | 
 | 411 |  | 
 | 412 | /* | 
 | 413 |  * Get integer from char-pointer | 
 | 414 |  */ | 
 | 415 | static int isdn_getnum(char *p) | 
 | 416 | { | 
 | 417 | 	int v = -1; | 
 | 418 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 419 | 	gig_dbg(DEBUG_TRANSCMD, "string: %s", p); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 420 |  | 
 | 421 | 	while (*p >= '0' && *p <= '9') | 
 | 422 | 		v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); | 
 | 423 | 	if (*p) | 
 | 424 | 		v = -1; /* invalid Character */ | 
 | 425 | 	return v; | 
 | 426 | } | 
 | 427 |  | 
 | 428 | /* | 
 | 429 |  * Get integer from char-pointer | 
 | 430 |  */ | 
 | 431 | static int isdn_gethex(char *p) | 
 | 432 | { | 
 | 433 | 	int v = 0; | 
 | 434 | 	int c; | 
 | 435 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 436 | 	gig_dbg(DEBUG_TRANSCMD, "string: %s", p); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 437 |  | 
 | 438 | 	if (!*p) | 
 | 439 | 		return -1; | 
 | 440 |  | 
 | 441 | 	do { | 
 | 442 | 		if (v > (INT_MAX - 15) / 16) | 
 | 443 | 			return -1; | 
 | 444 | 		c = *p; | 
 | 445 | 		if (c >= '0' && c <= '9') | 
 | 446 | 			c -= '0'; | 
 | 447 | 		else if (c >= 'a' && c <= 'f') | 
 | 448 | 			c -= 'a' - 10; | 
 | 449 | 		else if (c >= 'A' && c <= 'F') | 
 | 450 | 			c -= 'A' - 10; | 
 | 451 | 		else | 
 | 452 | 			return -1; | 
 | 453 | 		v = v * 16 + c; | 
 | 454 | 	} while (*++p); | 
 | 455 |  | 
 | 456 | 	return v; | 
 | 457 | } | 
 | 458 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 459 | /* retrieve CID from parsed response | 
 | 460 |  * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535 | 
 | 461 |  */ | 
 | 462 | static int cid_of_response(char *s) | 
 | 463 | { | 
 | 464 | 	int cid; | 
 | 465 |  | 
 | 466 | 	if (s[-1] != ';') | 
 | 467 | 		return 0;	/* no CID separator */ | 
 | 468 | 	cid = isdn_getnum(s); | 
 | 469 | 	if (cid < 0) | 
 | 470 | 		return 0;	/* CID not numeric */ | 
 | 471 | 	if (cid < 1 || cid > 65535) | 
 | 472 | 		return -1;	/* CID out of range */ | 
 | 473 | 	return cid; | 
 | 474 | 	//FIXME is ;<digit>+ at end of non-CID response really impossible? | 
 | 475 | } | 
 | 476 |  | 
 | 477 | /* This function will be called via task queue from the callback handler. | 
 | 478 |  * We received a modem response and have to handle it.. | 
 | 479 |  */ | 
 | 480 | void gigaset_handle_modem_response(struct cardstate *cs) | 
 | 481 | { | 
 | 482 | 	unsigned char *argv[MAX_REC_PARAMS + 1]; | 
 | 483 | 	int params; | 
 | 484 | 	int i, j; | 
| Tilman Schmidt | 35dc845 | 2007-03-29 01:20:34 -0700 | [diff] [blame] | 485 | 	const struct resp_type_t *rt; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 486 | 	int curarg; | 
 | 487 | 	unsigned long flags; | 
 | 488 | 	unsigned next, tail, head; | 
 | 489 | 	struct event_t *event; | 
 | 490 | 	int resp_code; | 
 | 491 | 	int param_type; | 
 | 492 | 	int abort; | 
 | 493 | 	size_t len; | 
 | 494 | 	int cid; | 
 | 495 | 	int rawstring; | 
 | 496 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 497 | 	len = cs->cbytes; | 
 | 498 | 	if (!len) { | 
 | 499 | 		/* ignore additional LFs/CRs (M10x config mode or cx100) */ | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 500 | 		gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 501 | 		return; | 
 | 502 | 	} | 
 | 503 | 	cs->respdata[len] = 0; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 504 | 	gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 505 | 	argv[0] = cs->respdata; | 
 | 506 | 	params = 1; | 
 | 507 | 	if (cs->at_state.getstring) { | 
 | 508 | 		/* getstring only allowed without cid at the moment */ | 
 | 509 | 		cs->at_state.getstring = 0; | 
 | 510 | 		rawstring = 1; | 
 | 511 | 		cid = 0; | 
 | 512 | 	} else { | 
 | 513 | 		/* parse line */ | 
 | 514 | 		for (i = 0; i < len; i++) | 
 | 515 | 			switch (cs->respdata[i]) { | 
 | 516 | 			case ';': | 
 | 517 | 			case ',': | 
 | 518 | 			case '=': | 
 | 519 | 				if (params > MAX_REC_PARAMS) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 520 | 					dev_warn(cs->dev, | 
 | 521 | 					   "too many parameters in response\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 522 | 					/* need last parameter (might be CID) */ | 
 | 523 | 					params--; | 
 | 524 | 				} | 
 | 525 | 				argv[params++] = cs->respdata + i + 1; | 
 | 526 | 			} | 
 | 527 |  | 
 | 528 | 		rawstring = 0; | 
 | 529 | 		cid = params > 1 ? cid_of_response(argv[params-1]) : 0; | 
 | 530 | 		if (cid < 0) { | 
 | 531 | 			gigaset_add_event(cs, &cs->at_state, RSP_INVAL, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 532 | 					  NULL, 0, NULL); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 533 | 			return; | 
 | 534 | 		} | 
 | 535 |  | 
 | 536 | 		for (j = 1; j < params; ++j) | 
 | 537 | 			argv[j][-1] = 0; | 
 | 538 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 539 | 		gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 540 | 		if (cid) { | 
 | 541 | 			--params; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 542 | 			gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 543 | 		} | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 544 | 		gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 545 | 		for (j = 1; j < params; j++) | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 546 | 			gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 547 | 	} | 
 | 548 |  | 
 | 549 | 	spin_lock_irqsave(&cs->ev_lock, flags); | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 550 | 	head = cs->ev_head; | 
 | 551 | 	tail = cs->ev_tail; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 552 |  | 
 | 553 | 	abort = 1; | 
 | 554 | 	curarg = 0; | 
 | 555 | 	while (curarg < params) { | 
 | 556 | 		next = (tail + 1) % MAX_EVENTS; | 
 | 557 | 		if (unlikely(next == head)) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 558 | 			dev_err(cs->dev, "event queue full\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 559 | 			break; | 
 | 560 | 		} | 
 | 561 |  | 
 | 562 | 		event = cs->events + tail; | 
 | 563 | 		event->at_state = NULL; | 
 | 564 | 		event->cid = cid; | 
 | 565 | 		event->ptr = NULL; | 
 | 566 | 		event->arg = NULL; | 
 | 567 | 		tail = next; | 
 | 568 |  | 
 | 569 | 		if (rawstring) { | 
 | 570 | 			resp_code = RSP_STRING; | 
 | 571 | 			param_type = RT_STRING; | 
 | 572 | 		} else { | 
 | 573 | 			for (rt = resp_type; rt->response; ++rt) | 
 | 574 | 				if (!strcmp(argv[curarg], rt->response)) | 
 | 575 | 					break; | 
 | 576 |  | 
 | 577 | 			if (!rt->response) { | 
 | 578 | 				event->type = RSP_UNKNOWN; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 579 | 				dev_warn(cs->dev, | 
 | 580 | 					 "unknown modem response: %s\n", | 
 | 581 | 					 argv[curarg]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 582 | 				break; | 
 | 583 | 			} | 
 | 584 |  | 
 | 585 | 			resp_code = rt->resp_code; | 
 | 586 | 			param_type = rt->type; | 
 | 587 | 			++curarg; | 
 | 588 | 		} | 
 | 589 |  | 
 | 590 | 		event->type = resp_code; | 
 | 591 |  | 
 | 592 | 		switch (param_type) { | 
 | 593 | 		case RT_NOTHING: | 
 | 594 | 			break; | 
 | 595 | 		case RT_RING: | 
 | 596 | 			if (!cid) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 597 | 				dev_err(cs->dev, | 
 | 598 | 					"received RING without CID!\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 599 | 				event->type = RSP_INVAL; | 
 | 600 | 				abort = 1; | 
 | 601 | 			} else { | 
 | 602 | 				event->cid = 0; | 
 | 603 | 				event->parameter = cid; | 
 | 604 | 				abort = 0; | 
 | 605 | 			} | 
 | 606 | 			break; | 
 | 607 | 		case RT_ZSAU: | 
 | 608 | 			if (curarg >= params) { | 
 | 609 | 				event->parameter = ZSAU_NONE; | 
 | 610 | 				break; | 
 | 611 | 			} | 
 | 612 | 			if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) | 
 | 613 | 				event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; | 
 | 614 | 			else if (!strcmp(argv[curarg], "CALL_DELIVERED")) | 
 | 615 | 				event->parameter = ZSAU_CALL_DELIVERED; | 
 | 616 | 			else if (!strcmp(argv[curarg], "ACTIVE")) | 
 | 617 | 				event->parameter = ZSAU_ACTIVE; | 
 | 618 | 			else if (!strcmp(argv[curarg], "DISCONNECT_IND")) | 
 | 619 | 				event->parameter = ZSAU_DISCONNECT_IND; | 
 | 620 | 			else if (!strcmp(argv[curarg], "NULL")) | 
 | 621 | 				event->parameter = ZSAU_NULL; | 
 | 622 | 			else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) | 
 | 623 | 				event->parameter = ZSAU_DISCONNECT_REQ; | 
 | 624 | 			else { | 
 | 625 | 				event->parameter = ZSAU_UNKNOWN; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 626 | 				dev_warn(cs->dev, | 
 | 627 | 					"%s: unknown parameter %s after ZSAU\n", | 
 | 628 | 					 __func__, argv[curarg]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 629 | 			} | 
 | 630 | 			++curarg; | 
 | 631 | 			break; | 
 | 632 | 		case RT_STRING: | 
 | 633 | 			if (curarg < params) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 634 | 				event->ptr = kstrdup(argv[curarg], GFP_ATOMIC); | 
 | 635 | 				if (!event->ptr) | 
 | 636 | 					dev_err(cs->dev, "out of memory\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 637 | 				++curarg; | 
 | 638 | 			} | 
| Tilman Schmidt | 236b87c | 2008-12-26 01:22:03 -0800 | [diff] [blame] | 639 | 			gig_dbg(DEBUG_CMD, "string==%s", | 
 | 640 | 				event->ptr ? (char *) event->ptr : "NULL"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 641 | 			break; | 
 | 642 | 		case RT_ZCAU: | 
 | 643 | 			event->parameter = -1; | 
 | 644 | 			if (curarg + 1 < params) { | 
 | 645 | 				i = isdn_gethex(argv[curarg]); | 
 | 646 | 				j = isdn_gethex(argv[curarg + 1]); | 
 | 647 | 				if (i >= 0 && i < 256 && j >= 0 && j < 256) | 
 | 648 | 					event->parameter = (unsigned) i << 8 | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 649 | 							   | j; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 650 | 				curarg += 2; | 
 | 651 | 			} else | 
 | 652 | 				curarg = params - 1; | 
 | 653 | 			break; | 
 | 654 | 		case RT_NUMBER: | 
 | 655 | 		case RT_HEX: | 
 | 656 | 			if (curarg < params) { | 
 | 657 | 				if (param_type == RT_HEX) | 
 | 658 | 					event->parameter = | 
 | 659 | 						isdn_gethex(argv[curarg]); | 
 | 660 | 				else | 
 | 661 | 					event->parameter = | 
 | 662 | 						isdn_getnum(argv[curarg]); | 
 | 663 | 				++curarg; | 
 | 664 | 			} else | 
 | 665 | 				event->parameter = -1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 666 | 			gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 667 | 			break; | 
 | 668 | 		} | 
 | 669 |  | 
 | 670 | 		if (resp_code == RSP_ZDLE) | 
 | 671 | 			cs->dle = event->parameter; | 
 | 672 |  | 
 | 673 | 		if (abort) | 
 | 674 | 			break; | 
 | 675 | 	} | 
 | 676 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 677 | 	cs->ev_tail = tail; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 678 | 	spin_unlock_irqrestore(&cs->ev_lock, flags); | 
 | 679 |  | 
 | 680 | 	if (curarg != params) | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 681 | 		gig_dbg(DEBUG_ANY, | 
 | 682 | 			"invalid number of processed parameters: %d/%d", | 
 | 683 | 			curarg, params); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 684 | } | 
 | 685 | EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); | 
 | 686 |  | 
 | 687 | /* disconnect | 
 | 688 |  * process closing of connection associated with given AT state structure | 
 | 689 |  */ | 
 | 690 | static void disconnect(struct at_state_t **at_state_p) | 
 | 691 | { | 
 | 692 | 	unsigned long flags; | 
| Tilman Schmidt | d48c778 | 2006-04-10 22:55:08 -0700 | [diff] [blame] | 693 | 	struct bc_state *bcs = (*at_state_p)->bcs; | 
 | 694 | 	struct cardstate *cs = (*at_state_p)->cs; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 695 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 696 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 697 | 	++(*at_state_p)->seq_index; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 698 |  | 
 | 699 | 	/* revert to selected idle mode */ | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 700 | 	if (!cs->cidmode) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 701 | 		cs->at_state.pending_commands |= PC_UMMODE; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 702 | 		cs->commands_pending = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 703 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 704 | 	} | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 705 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 706 |  | 
 | 707 | 	if (bcs) { | 
 | 708 | 		/* B channel assigned: invoke hardware specific handler */ | 
 | 709 | 		cs->ops->close_bchannel(bcs); | 
 | 710 | 	} else { | 
 | 711 | 		/* no B channel assigned: just deallocate */ | 
 | 712 | 		spin_lock_irqsave(&cs->lock, flags); | 
 | 713 | 		list_del(&(*at_state_p)->list); | 
 | 714 | 		kfree(*at_state_p); | 
 | 715 | 		*at_state_p = NULL; | 
 | 716 | 		spin_unlock_irqrestore(&cs->lock, flags); | 
 | 717 | 	} | 
 | 718 | } | 
 | 719 |  | 
 | 720 | /* get_free_channel | 
 | 721 |  * get a free AT state structure: either one of those associated with the | 
 | 722 |  * B channels of the Gigaset device, or if none of those is available, | 
 | 723 |  * a newly allocated one with bcs=NULL | 
 | 724 |  * The structure should be freed by calling disconnect() after use. | 
 | 725 |  */ | 
 | 726 | static inline struct at_state_t *get_free_channel(struct cardstate *cs, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 727 | 						  int cid) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 728 | /* cids: >0: siemens-cid | 
 | 729 | 	  0: without cid | 
 | 730 | 	 -1: no cid assigned yet | 
 | 731 | */ | 
 | 732 | { | 
 | 733 | 	unsigned long flags; | 
 | 734 | 	int i; | 
 | 735 | 	struct at_state_t *ret; | 
 | 736 |  | 
 | 737 | 	for (i = 0; i < cs->channels; ++i) | 
 | 738 | 		if (gigaset_get_channel(cs->bcs + i)) { | 
 | 739 | 			ret = &cs->bcs[i].at_state; | 
 | 740 | 			ret->cid = cid; | 
 | 741 | 			return ret; | 
 | 742 | 		} | 
 | 743 |  | 
 | 744 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 745 | 	ret = kmalloc(sizeof(struct at_state_t), GFP_ATOMIC); | 
 | 746 | 	if (ret) { | 
 | 747 | 		gigaset_at_init(ret, NULL, cs, cid); | 
 | 748 | 		list_add(&ret->list, &cs->temp_at_states); | 
 | 749 | 	} | 
 | 750 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
 | 751 | 	return ret; | 
 | 752 | } | 
 | 753 |  | 
 | 754 | static void init_failed(struct cardstate *cs, int mode) | 
 | 755 | { | 
 | 756 | 	int i; | 
 | 757 | 	struct at_state_t *at_state; | 
 | 758 |  | 
 | 759 | 	cs->at_state.pending_commands &= ~PC_INIT; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 760 | 	cs->mode = mode; | 
 | 761 | 	cs->mstate = MS_UNINITIALIZED; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 762 | 	gigaset_free_channels(cs); | 
 | 763 | 	for (i = 0; i < cs->channels; ++i) { | 
 | 764 | 		at_state = &cs->bcs[i].at_state; | 
 | 765 | 		if (at_state->pending_commands & PC_CID) { | 
 | 766 | 			at_state->pending_commands &= ~PC_CID; | 
 | 767 | 			at_state->pending_commands |= PC_NOCID; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 768 | 			cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 769 | 		} | 
 | 770 | 	} | 
 | 771 | } | 
 | 772 |  | 
 | 773 | static void schedule_init(struct cardstate *cs, int state) | 
 | 774 | { | 
 | 775 | 	if (cs->at_state.pending_commands & PC_INIT) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 776 | 		gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 777 | 		return; | 
 | 778 | 	} | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 779 | 	cs->mstate = state; | 
 | 780 | 	cs->mode = M_UNKNOWN; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 781 | 	gigaset_block_channels(cs); | 
 | 782 | 	cs->at_state.pending_commands |= PC_INIT; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 783 | 	cs->commands_pending = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 784 | 	gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 785 | } | 
 | 786 |  | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 787 | /* Add "AT" to a command, add the cid, dle encode it, send the result to the | 
 | 788 |    hardware. */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 789 | static void send_command(struct cardstate *cs, const char *cmd, int cid, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 790 | 			 int dle, gfp_t kmallocflags) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 791 | { | 
 | 792 | 	size_t cmdlen, buflen; | 
 | 793 | 	char *cmdpos, *cmdbuf, *cmdtail; | 
 | 794 |  | 
 | 795 | 	cmdlen = strlen(cmd); | 
 | 796 | 	buflen = 11 + cmdlen; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 797 | 	if (unlikely(buflen <= cmdlen)) { | 
 | 798 | 		dev_err(cs->dev, "integer overflow in buflen\n"); | 
 | 799 | 		return; | 
 | 800 | 	} | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 801 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 802 | 	cmdbuf = kmalloc(buflen, kmallocflags); | 
 | 803 | 	if (unlikely(!cmdbuf)) { | 
 | 804 | 		dev_err(cs->dev, "out of memory\n"); | 
 | 805 | 		return; | 
 | 806 | 	} | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 807 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 808 | 	cmdpos = cmdbuf + 9; | 
 | 809 | 	cmdtail = cmdpos + cmdlen; | 
 | 810 | 	memcpy(cmdpos, cmd, cmdlen); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 811 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 812 | 	if (cid > 0 && cid <= 65535) { | 
 | 813 | 		do { | 
 | 814 | 			*--cmdpos = '0' + cid % 10; | 
 | 815 | 			cid /= 10; | 
 | 816 | 			++cmdlen; | 
 | 817 | 		} while (cid); | 
 | 818 | 	} | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 819 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 820 | 	cmdlen += 2; | 
 | 821 | 	*--cmdpos = 'T'; | 
 | 822 | 	*--cmdpos = 'A'; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 823 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 824 | 	if (dle) { | 
 | 825 | 		cmdlen += 4; | 
 | 826 | 		*--cmdpos = '('; | 
 | 827 | 		*--cmdpos = 0x10; | 
 | 828 | 		*cmdtail++ = 0x10; | 
 | 829 | 		*cmdtail++ = ')'; | 
 | 830 | 	} | 
 | 831 |  | 
 | 832 | 	cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); | 
 | 833 | 	kfree(cmdbuf); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 834 | } | 
 | 835 |  | 
 | 836 | static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) | 
 | 837 | { | 
 | 838 | 	struct at_state_t *at_state; | 
 | 839 | 	int i; | 
 | 840 | 	unsigned long flags; | 
 | 841 |  | 
 | 842 | 	if (cid == 0) | 
 | 843 | 		return &cs->at_state; | 
 | 844 |  | 
 | 845 | 	for (i = 0; i < cs->channels; ++i) | 
 | 846 | 		if (cid == cs->bcs[i].at_state.cid) | 
 | 847 | 			return &cs->bcs[i].at_state; | 
 | 848 |  | 
 | 849 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 850 |  | 
 | 851 | 	list_for_each_entry(at_state, &cs->temp_at_states, list) | 
 | 852 | 		if (cid == at_state->cid) { | 
 | 853 | 			spin_unlock_irqrestore(&cs->lock, flags); | 
 | 854 | 			return at_state; | 
 | 855 | 		} | 
 | 856 |  | 
 | 857 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
 | 858 |  | 
 | 859 | 	return NULL; | 
 | 860 | } | 
 | 861 |  | 
 | 862 | static void bchannel_down(struct bc_state *bcs) | 
 | 863 | { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 864 | 	if (bcs->chstate & CHS_B_UP) { | 
 | 865 | 		bcs->chstate &= ~CHS_B_UP; | 
 | 866 | 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); | 
 | 867 | 	} | 
 | 868 |  | 
 | 869 | 	if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { | 
 | 870 | 		bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); | 
 | 871 | 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | 
 | 872 | 	} | 
 | 873 |  | 
 | 874 | 	gigaset_free_channel(bcs); | 
 | 875 |  | 
 | 876 | 	gigaset_bcs_reinit(bcs); | 
 | 877 | } | 
 | 878 |  | 
 | 879 | static void bchannel_up(struct bc_state *bcs) | 
 | 880 | { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 881 | 	if (bcs->chstate & CHS_B_UP) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 882 | 		dev_notice(bcs->cs->dev, "%s: B channel already up\n", | 
 | 883 | 			   __func__); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 884 | 		return; | 
 | 885 | 	} | 
 | 886 |  | 
 | 887 | 	bcs->chstate |= CHS_B_UP; | 
 | 888 | 	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); | 
 | 889 | } | 
 | 890 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 891 | static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 892 | { | 
 | 893 | 	struct bc_state *bcs = at_state->bcs; | 
 | 894 | 	struct cardstate *cs = at_state->cs; | 
 | 895 | 	int retval; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 896 | 	unsigned long flags; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 897 |  | 
 | 898 | 	bcs->chstate |= CHS_NOTIFY_LL; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 899 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 900 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 901 | 	if (at_state->seq_index != seq_index) { | 
 | 902 | 		spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 903 | 		goto error; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 904 | 	} | 
 | 905 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 906 |  | 
 | 907 | 	retval = gigaset_isdn_setup_dial(at_state, data); | 
 | 908 | 	if (retval != 0) | 
 | 909 | 		goto error; | 
 | 910 |  | 
 | 911 |  | 
 | 912 | 	at_state->pending_commands |= PC_CID; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 913 | 	gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 914 | 	cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 915 | 	return; | 
 | 916 |  | 
 | 917 | error: | 
 | 918 | 	at_state->pending_commands |= PC_NOCID; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 919 | 	gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 920 | 	cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 921 | 	return; | 
 | 922 | } | 
 | 923 |  | 
 | 924 | static void start_accept(struct at_state_t *at_state) | 
 | 925 | { | 
 | 926 | 	struct cardstate *cs = at_state->cs; | 
 | 927 | 	int retval; | 
 | 928 |  | 
 | 929 | 	retval = gigaset_isdn_setup_accept(at_state); | 
 | 930 |  | 
 | 931 | 	if (retval == 0) { | 
 | 932 | 		at_state->pending_commands |= PC_ACCEPT; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 933 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 934 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 935 | 	} else { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 936 | 		/* error reset */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 937 | 		at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 938 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 939 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 940 | 	} | 
 | 941 | } | 
 | 942 |  | 
 | 943 | static void do_start(struct cardstate *cs) | 
 | 944 | { | 
 | 945 | 	gigaset_free_channels(cs); | 
 | 946 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 947 | 	if (cs->mstate != MS_LOCKED) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 948 | 		schedule_init(cs, MS_INIT); | 
 | 949 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 950 | 	cs->isdn_up = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 951 | 	gigaset_i4l_cmd(cs, ISDN_STAT_RUN); | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 952 | 					// FIXME: not in locked mode | 
 | 953 | 					// FIXME 2: only after init sequence | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 954 |  | 
 | 955 | 	cs->waiting = 0; | 
 | 956 | 	wake_up(&cs->waitqueue); | 
 | 957 | } | 
 | 958 |  | 
 | 959 | static void finish_shutdown(struct cardstate *cs) | 
 | 960 | { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 961 | 	if (cs->mstate != MS_LOCKED) { | 
 | 962 | 		cs->mstate = MS_UNINITIALIZED; | 
 | 963 | 		cs->mode = M_UNKNOWN; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 964 | 	} | 
 | 965 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 966 | 	/* Tell the LL that the device is not available .. */ | 
 | 967 | 	if (cs->isdn_up) { | 
 | 968 | 		cs->isdn_up = 0; | 
 | 969 | 		gigaset_i4l_cmd(cs, ISDN_STAT_STOP); | 
 | 970 | 	} | 
 | 971 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 972 | 	/* The rest is done by cleanup_cs () in user mode. */ | 
 | 973 |  | 
 | 974 | 	cs->cmd_result = -ENODEV; | 
 | 975 | 	cs->waiting = 0; | 
| Tilman Schmidt | 2869b23 | 2007-02-12 00:52:34 -0800 | [diff] [blame] | 976 | 	wake_up(&cs->waitqueue); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 977 | } | 
 | 978 |  | 
 | 979 | static void do_shutdown(struct cardstate *cs) | 
 | 980 | { | 
 | 981 | 	gigaset_block_channels(cs); | 
 | 982 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 983 | 	if (cs->mstate == MS_READY) { | 
 | 984 | 		cs->mstate = MS_SHUTDOWN; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 985 | 		cs->at_state.pending_commands |= PC_SHUTDOWN; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 986 | 		cs->commands_pending = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 987 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 988 | 	} else | 
 | 989 | 		finish_shutdown(cs); | 
 | 990 | } | 
 | 991 |  | 
 | 992 | static void do_stop(struct cardstate *cs) | 
 | 993 | { | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 994 | 	unsigned long flags; | 
 | 995 |  | 
 | 996 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 997 | 	cs->connected = 0; | 
 | 998 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
 | 999 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1000 | 	do_shutdown(cs); | 
 | 1001 | } | 
 | 1002 |  | 
 | 1003 | /* Entering cid mode or getting a cid failed: | 
 | 1004 |  * try to initialize the device and try again. | 
 | 1005 |  * | 
 | 1006 |  * channel >= 0: getting cid for the channel failed | 
 | 1007 |  * channel < 0:  entering cid mode failed | 
 | 1008 |  * | 
 | 1009 |  * returns 0 on failure | 
 | 1010 |  */ | 
 | 1011 | static int reinit_and_retry(struct cardstate *cs, int channel) | 
 | 1012 | { | 
 | 1013 | 	int i; | 
 | 1014 |  | 
 | 1015 | 	if (--cs->retry_count <= 0) | 
 | 1016 | 		return 0; | 
 | 1017 |  | 
 | 1018 | 	for (i = 0; i < cs->channels; ++i) | 
 | 1019 | 		if (cs->bcs[i].at_state.cid > 0) | 
 | 1020 | 			return 0; | 
 | 1021 |  | 
 | 1022 | 	if (channel < 0) | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1023 | 		dev_warn(cs->dev, | 
 | 1024 | 		    "Could not enter cid mode. Reinit device and try again.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1025 | 	else { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1026 | 		dev_warn(cs->dev, | 
 | 1027 | 		    "Could not get a call id. Reinit device and try again.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1028 | 		cs->bcs[channel].at_state.pending_commands |= PC_CID; | 
 | 1029 | 	} | 
 | 1030 | 	schedule_init(cs, MS_INIT); | 
 | 1031 | 	return 1; | 
 | 1032 | } | 
 | 1033 |  | 
 | 1034 | static int at_state_invalid(struct cardstate *cs, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1035 | 			    struct at_state_t *test_ptr) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1036 | { | 
 | 1037 | 	unsigned long flags; | 
 | 1038 | 	unsigned channel; | 
 | 1039 | 	struct at_state_t *at_state; | 
 | 1040 | 	int retval = 0; | 
 | 1041 |  | 
 | 1042 | 	spin_lock_irqsave(&cs->lock, flags); | 
 | 1043 |  | 
 | 1044 | 	if (test_ptr == &cs->at_state) | 
 | 1045 | 		goto exit; | 
 | 1046 |  | 
 | 1047 | 	list_for_each_entry(at_state, &cs->temp_at_states, list) | 
 | 1048 | 		if (at_state == test_ptr) | 
 | 1049 | 			goto exit; | 
 | 1050 |  | 
 | 1051 | 	for (channel = 0; channel < cs->channels; ++channel) | 
 | 1052 | 		if (&cs->bcs[channel].at_state == test_ptr) | 
 | 1053 | 			goto exit; | 
 | 1054 |  | 
 | 1055 | 	retval = 1; | 
 | 1056 | exit: | 
 | 1057 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
 | 1058 | 	return retval; | 
 | 1059 | } | 
 | 1060 |  | 
 | 1061 | static void handle_icall(struct cardstate *cs, struct bc_state *bcs, | 
 | 1062 | 			 struct at_state_t **p_at_state) | 
 | 1063 | { | 
 | 1064 | 	int retval; | 
 | 1065 | 	struct at_state_t *at_state = *p_at_state; | 
 | 1066 |  | 
 | 1067 | 	retval = gigaset_isdn_icall(at_state); | 
 | 1068 | 	switch (retval) { | 
 | 1069 | 	case ICALL_ACCEPT: | 
 | 1070 | 		break; | 
 | 1071 | 	default: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1072 | 		dev_err(cs->dev, "internal error: disposition=%d\n", retval); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1073 | 		/* --v-- fall through --v-- */ | 
 | 1074 | 	case ICALL_IGNORE: | 
 | 1075 | 	case ICALL_REJECT: | 
 | 1076 | 		/* hang up actively | 
 | 1077 | 		 * Device doc says that would reject the call. | 
 | 1078 | 		 * In fact it doesn't. | 
 | 1079 | 		 */ | 
 | 1080 | 		at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1081 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1082 | 		break; | 
 | 1083 | 	} | 
 | 1084 | } | 
 | 1085 |  | 
 | 1086 | static int do_lock(struct cardstate *cs) | 
 | 1087 | { | 
 | 1088 | 	int mode; | 
 | 1089 | 	int i; | 
 | 1090 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1091 | 	switch (cs->mstate) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1092 | 	case MS_UNINITIALIZED: | 
 | 1093 | 	case MS_READY: | 
 | 1094 | 		if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || | 
 | 1095 | 		    cs->at_state.pending_commands) | 
 | 1096 | 			return -EBUSY; | 
 | 1097 |  | 
 | 1098 | 		for (i = 0; i < cs->channels; ++i) | 
 | 1099 | 			if (cs->bcs[i].at_state.pending_commands) | 
 | 1100 | 				return -EBUSY; | 
 | 1101 |  | 
 | 1102 | 		if (!gigaset_get_channels(cs)) | 
 | 1103 | 			return -EBUSY; | 
 | 1104 |  | 
 | 1105 | 		break; | 
 | 1106 | 	case MS_LOCKED: | 
 | 1107 | 		//retval = -EACCES; | 
 | 1108 | 		break; | 
 | 1109 | 	default: | 
 | 1110 | 		return -EBUSY; | 
 | 1111 | 	} | 
 | 1112 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1113 | 	mode = cs->mode; | 
 | 1114 | 	cs->mstate = MS_LOCKED; | 
 | 1115 | 	cs->mode = M_UNKNOWN; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1116 |  | 
 | 1117 | 	return mode; | 
 | 1118 | } | 
 | 1119 |  | 
 | 1120 | static int do_unlock(struct cardstate *cs) | 
 | 1121 | { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1122 | 	if (cs->mstate != MS_LOCKED) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1123 | 		return -EINVAL; | 
 | 1124 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1125 | 	cs->mstate = MS_UNINITIALIZED; | 
 | 1126 | 	cs->mode = M_UNKNOWN; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1127 | 	gigaset_free_channels(cs); | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1128 | 	if (cs->connected) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1129 | 		schedule_init(cs, MS_INIT); | 
 | 1130 |  | 
 | 1131 | 	return 0; | 
 | 1132 | } | 
 | 1133 |  | 
 | 1134 | static void do_action(int action, struct cardstate *cs, | 
 | 1135 | 		      struct bc_state *bcs, | 
 | 1136 | 		      struct at_state_t **p_at_state, char **pp_command, | 
 | 1137 | 		      int *p_genresp, int *p_resp_code, | 
 | 1138 | 		      struct event_t *ev) | 
 | 1139 | { | 
 | 1140 | 	struct at_state_t *at_state = *p_at_state; | 
 | 1141 | 	struct at_state_t *at_state2; | 
 | 1142 | 	unsigned long flags; | 
 | 1143 |  | 
 | 1144 | 	int channel; | 
 | 1145 |  | 
 | 1146 | 	unsigned char *s, *e; | 
 | 1147 | 	int i; | 
 | 1148 | 	unsigned long val; | 
 | 1149 |  | 
 | 1150 | 	switch (action) { | 
 | 1151 | 	case ACT_NOTHING: | 
 | 1152 | 		break; | 
 | 1153 | 	case ACT_TIMEOUT: | 
 | 1154 | 		at_state->waiting = 1; | 
 | 1155 | 		break; | 
 | 1156 | 	case ACT_INIT: | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1157 | 		cs->at_state.pending_commands &= ~PC_INIT; | 
 | 1158 | 		cs->cur_at_seq = SEQ_NONE; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1159 | 		cs->mode = M_UNIMODEM; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1160 | 		spin_lock_irqsave(&cs->lock, flags); | 
 | 1161 | 		if (!cs->cidmode) { | 
 | 1162 | 			spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1163 | 			gigaset_free_channels(cs); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1164 | 			cs->mstate = MS_READY; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1165 | 			break; | 
 | 1166 | 		} | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1167 | 		spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1168 | 		cs->at_state.pending_commands |= PC_CIDMODE; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1169 | 		cs->commands_pending = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1170 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1171 | 		break; | 
 | 1172 | 	case ACT_FAILINIT: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1173 | 		dev_warn(cs->dev, "Could not initialize the device.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1174 | 		cs->dle = 0; | 
 | 1175 | 		init_failed(cs, M_UNKNOWN); | 
 | 1176 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1177 | 		break; | 
 | 1178 | 	case ACT_CONFIGMODE: | 
 | 1179 | 		init_failed(cs, M_CONFIG); | 
 | 1180 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1181 | 		break; | 
 | 1182 | 	case ACT_SETDLE1: | 
 | 1183 | 		cs->dle = 1; | 
 | 1184 | 		/* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */ | 
 | 1185 | 		cs->inbuf[0].inputstate &= | 
 | 1186 | 			~(INS_command | INS_DLE_command); | 
 | 1187 | 		break; | 
 | 1188 | 	case ACT_SETDLE0: | 
 | 1189 | 		cs->dle = 0; | 
 | 1190 | 		cs->inbuf[0].inputstate = | 
 | 1191 | 			(cs->inbuf[0].inputstate & ~INS_DLE_command) | 
 | 1192 | 			| INS_command; | 
 | 1193 | 		break; | 
 | 1194 | 	case ACT_CMODESET: | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1195 | 		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1196 | 			gigaset_free_channels(cs); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1197 | 			cs->mstate = MS_READY; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1198 | 		} | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1199 | 		cs->mode = M_CID; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1200 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1201 | 		break; | 
 | 1202 | 	case ACT_UMODESET: | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1203 | 		cs->mode = M_UNIMODEM; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1204 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1205 | 		break; | 
 | 1206 | 	case ACT_FAILCMODE: | 
 | 1207 | 		cs->cur_at_seq = SEQ_NONE; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1208 | 		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1209 | 			init_failed(cs, M_UNKNOWN); | 
 | 1210 | 			break; | 
 | 1211 | 		} | 
 | 1212 | 		if (!reinit_and_retry(cs, -1)) | 
 | 1213 | 			schedule_init(cs, MS_RECOVER); | 
 | 1214 | 		break; | 
 | 1215 | 	case ACT_FAILUMODE: | 
 | 1216 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1217 | 		schedule_init(cs, MS_RECOVER); | 
 | 1218 | 		break; | 
 | 1219 | 	case ACT_HUPMODEM: | 
 | 1220 | 		/* send "+++" (hangup in unimodem mode) */ | 
| Tilman Schmidt | 698e3ed | 2006-06-26 00:25:34 -0700 | [diff] [blame] | 1221 | 		if (cs->connected) | 
 | 1222 | 			cs->ops->write_cmd(cs, "+++", 3, NULL); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1223 | 		break; | 
 | 1224 | 	case ACT_RING: | 
 | 1225 | 		/* get fresh AT state structure for new CID */ | 
 | 1226 | 		at_state2 = get_free_channel(cs, ev->parameter); | 
 | 1227 | 		if (!at_state2) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1228 | 			dev_warn(cs->dev, | 
 | 1229 | 			"RING ignored: could not allocate channel structure\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1230 | 			break; | 
 | 1231 | 		} | 
 | 1232 |  | 
 | 1233 | 		/* initialize AT state structure | 
 | 1234 | 		 * note that bcs may be NULL if no B channel is free | 
 | 1235 | 		 */ | 
 | 1236 | 		at_state2->ConState = 700; | 
 | 1237 | 		kfree(at_state2->str_var[STR_NMBR]); | 
 | 1238 | 		at_state2->str_var[STR_NMBR] = NULL; | 
 | 1239 | 		kfree(at_state2->str_var[STR_ZCPN]); | 
 | 1240 | 		at_state2->str_var[STR_ZCPN] = NULL; | 
 | 1241 | 		kfree(at_state2->str_var[STR_ZBC]); | 
 | 1242 | 		at_state2->str_var[STR_ZBC] = NULL; | 
 | 1243 | 		kfree(at_state2->str_var[STR_ZHLC]); | 
 | 1244 | 		at_state2->str_var[STR_ZHLC] = NULL; | 
 | 1245 | 		at_state2->int_var[VAR_ZCTP] = -1; | 
 | 1246 |  | 
 | 1247 | 		spin_lock_irqsave(&cs->lock, flags); | 
 | 1248 | 		at_state2->timer_expires = RING_TIMEOUT; | 
 | 1249 | 		at_state2->timer_active = 1; | 
 | 1250 | 		spin_unlock_irqrestore(&cs->lock, flags); | 
 | 1251 | 		break; | 
 | 1252 | 	case ACT_ICALL: | 
 | 1253 | 		handle_icall(cs, bcs, p_at_state); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1254 | 		break; | 
 | 1255 | 	case ACT_FAILSDOWN: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1256 | 		dev_warn(cs->dev, "Could not shut down the device.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1257 | 		/* fall through */ | 
 | 1258 | 	case ACT_FAKESDOWN: | 
 | 1259 | 	case ACT_SDOWN: | 
 | 1260 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1261 | 		finish_shutdown(cs); | 
 | 1262 | 		break; | 
 | 1263 | 	case ACT_CONNECT: | 
 | 1264 | 		if (cs->onechannel) { | 
 | 1265 | 			at_state->pending_commands |= PC_DLE1; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1266 | 			cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1267 | 			break; | 
 | 1268 | 		} | 
 | 1269 | 		bcs->chstate |= CHS_D_UP; | 
 | 1270 | 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 
 | 1271 | 		cs->ops->init_bchannel(bcs); | 
 | 1272 | 		break; | 
 | 1273 | 	case ACT_DLE1: | 
 | 1274 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1275 | 		bcs = cs->bcs + cs->curchannel; | 
 | 1276 |  | 
 | 1277 | 		bcs->chstate |= CHS_D_UP; | 
 | 1278 | 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 
 | 1279 | 		cs->ops->init_bchannel(bcs); | 
 | 1280 | 		break; | 
 | 1281 | 	case ACT_FAKEHUP: | 
 | 1282 | 		at_state->int_var[VAR_ZSAU] = ZSAU_NULL; | 
 | 1283 | 		/* fall through */ | 
 | 1284 | 	case ACT_DISCONNECT: | 
 | 1285 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1286 | 		at_state->cid = -1; | 
 | 1287 | 		if (bcs && cs->onechannel && cs->dle) { | 
 | 1288 | 			/* Check for other open channels not needed: | 
 | 1289 | 			 * DLE only used for M10x with one B channel. | 
 | 1290 | 			 */ | 
 | 1291 | 			at_state->pending_commands |= PC_DLE0; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1292 | 			cs->commands_pending = 1; | 
| Tilman Schmidt | 698e3ed | 2006-06-26 00:25:34 -0700 | [diff] [blame] | 1293 | 		} else | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1294 | 			disconnect(p_at_state); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1295 | 		break; | 
 | 1296 | 	case ACT_FAKEDLE0: | 
 | 1297 | 		at_state->int_var[VAR_ZDLE] = 0; | 
 | 1298 | 		cs->dle = 0; | 
 | 1299 | 		/* fall through */ | 
 | 1300 | 	case ACT_DLE0: | 
 | 1301 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1302 | 		at_state2 = &cs->bcs[cs->curchannel].at_state; | 
 | 1303 | 		disconnect(&at_state2); | 
 | 1304 | 		break; | 
 | 1305 | 	case ACT_ABORTHUP: | 
 | 1306 | 		cs->cur_at_seq = SEQ_NONE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1307 | 		dev_warn(cs->dev, "Could not hang up.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1308 | 		at_state->cid = -1; | 
 | 1309 | 		if (bcs && cs->onechannel) | 
 | 1310 | 			at_state->pending_commands |= PC_DLE0; | 
| Tilman Schmidt | 698e3ed | 2006-06-26 00:25:34 -0700 | [diff] [blame] | 1311 | 		else | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1312 | 			disconnect(p_at_state); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1313 | 		schedule_init(cs, MS_RECOVER); | 
 | 1314 | 		break; | 
 | 1315 | 	case ACT_FAILDLE0: | 
 | 1316 | 		cs->cur_at_seq = SEQ_NONE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1317 | 		dev_warn(cs->dev, "Could not leave DLE mode.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1318 | 		at_state2 = &cs->bcs[cs->curchannel].at_state; | 
 | 1319 | 		disconnect(&at_state2); | 
 | 1320 | 		schedule_init(cs, MS_RECOVER); | 
 | 1321 | 		break; | 
 | 1322 | 	case ACT_FAILDLE1: | 
 | 1323 | 		cs->cur_at_seq = SEQ_NONE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1324 | 		dev_warn(cs->dev, | 
 | 1325 | 			 "Could not enter DLE mode. Trying to hang up.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1326 | 		channel = cs->curchannel; | 
 | 1327 | 		cs->bcs[channel].at_state.pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1328 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1329 | 		break; | 
 | 1330 |  | 
 | 1331 | 	case ACT_CID: /* got cid; start dialing */ | 
 | 1332 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1333 | 		channel = cs->curchannel; | 
 | 1334 | 		if (ev->parameter > 0 && ev->parameter <= 65535) { | 
 | 1335 | 			cs->bcs[channel].at_state.cid = ev->parameter; | 
 | 1336 | 			cs->bcs[channel].at_state.pending_commands |= | 
 | 1337 | 				PC_DIAL; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1338 | 			cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1339 | 			break; | 
 | 1340 | 		} | 
 | 1341 | 		/* fall through */ | 
 | 1342 | 	case ACT_FAILCID: | 
 | 1343 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1344 | 		channel = cs->curchannel; | 
 | 1345 | 		if (!reinit_and_retry(cs, channel)) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1346 | 			dev_warn(cs->dev, | 
 | 1347 | 				 "Could not get a call ID. Cannot dial.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1348 | 			at_state2 = &cs->bcs[channel].at_state; | 
 | 1349 | 			disconnect(&at_state2); | 
 | 1350 | 		} | 
 | 1351 | 		break; | 
 | 1352 | 	case ACT_ABORTCID: | 
 | 1353 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1354 | 		at_state2 = &cs->bcs[cs->curchannel].at_state; | 
 | 1355 | 		disconnect(&at_state2); | 
 | 1356 | 		break; | 
 | 1357 |  | 
 | 1358 | 	case ACT_DIALING: | 
 | 1359 | 	case ACT_ACCEPTED: | 
 | 1360 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1361 | 		break; | 
 | 1362 |  | 
 | 1363 | 	case ACT_ABORTACCEPT:	/* hangup/error/timeout during ICALL processing */ | 
 | 1364 | 		disconnect(p_at_state); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1365 | 		break; | 
 | 1366 |  | 
 | 1367 | 	case ACT_ABORTDIAL:	/* error/timeout during dial preparation */ | 
 | 1368 | 		cs->cur_at_seq = SEQ_NONE; | 
 | 1369 | 		at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1370 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1371 | 		break; | 
 | 1372 |  | 
 | 1373 | 	case ACT_REMOTEREJECT:	/* DISCONNECT_IND after dialling */ | 
 | 1374 | 	case ACT_CONNTIMEOUT:	/* timeout waiting for ZSAU=ACTIVE */ | 
 | 1375 | 	case ACT_REMOTEHUP:	/* DISCONNECT_IND with established connection */ | 
 | 1376 | 		at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1377 | 		cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1378 | 		break; | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 1379 | 	case ACT_GETSTRING: /* warning: RING, ZDLE, ... | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1380 | 			       are not handled properly anymore */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1381 | 		at_state->getstring = 1; | 
 | 1382 | 		break; | 
 | 1383 | 	case ACT_SETVER: | 
 | 1384 | 		if (!ev->ptr) { | 
 | 1385 | 			*p_genresp = 1; | 
 | 1386 | 			*p_resp_code = RSP_ERROR; | 
 | 1387 | 			break; | 
 | 1388 | 		} | 
 | 1389 | 		s = ev->ptr; | 
 | 1390 |  | 
 | 1391 | 		if (!strcmp(s, "OK")) { | 
 | 1392 | 			*p_genresp = 1; | 
 | 1393 | 			*p_resp_code = RSP_ERROR; | 
 | 1394 | 			break; | 
 | 1395 | 		} | 
 | 1396 |  | 
 | 1397 | 		for (i = 0; i < 4; ++i) { | 
 | 1398 | 			val = simple_strtoul(s, (char **) &e, 10); | 
 | 1399 | 			if (val > INT_MAX || e == s) | 
 | 1400 | 				break; | 
 | 1401 | 			if (i == 3) { | 
 | 1402 | 				if (*e) | 
 | 1403 | 					break; | 
 | 1404 | 			} else if (*e != '.') | 
 | 1405 | 				break; | 
 | 1406 | 			else | 
 | 1407 | 				s = e + 1; | 
 | 1408 | 			cs->fwver[i] = val; | 
 | 1409 | 		} | 
 | 1410 | 		if (i != 4) { | 
 | 1411 | 			*p_genresp = 1; | 
 | 1412 | 			*p_resp_code = RSP_ERROR; | 
 | 1413 | 			break; | 
 | 1414 | 		} | 
 | 1415 | 		/*at_state->getstring = 1;*/ | 
 | 1416 | 		cs->gotfwver = 0; | 
 | 1417 | 		break; | 
 | 1418 | 	case ACT_GOTVER: | 
 | 1419 | 		if (cs->gotfwver == 0) { | 
 | 1420 | 			cs->gotfwver = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1421 | 			gig_dbg(DEBUG_ANY, | 
 | 1422 | 				"firmware version %02d.%03d.%02d.%02d", | 
 | 1423 | 				cs->fwver[0], cs->fwver[1], | 
 | 1424 | 				cs->fwver[2], cs->fwver[3]); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1425 | 			break; | 
 | 1426 | 		} | 
 | 1427 | 		/* fall through */ | 
 | 1428 | 	case ACT_FAILVER: | 
 | 1429 | 		cs->gotfwver = -1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1430 | 		dev_err(cs->dev, "could not read firmware version.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1431 | 		break; | 
 | 1432 | #ifdef CONFIG_GIGASET_DEBUG | 
 | 1433 | 	case ACT_ERROR: | 
 | 1434 | 		*p_genresp = 1; | 
 | 1435 | 		*p_resp_code = RSP_ERROR; | 
 | 1436 | 		break; | 
 | 1437 | 	case ACT_TEST: | 
 | 1438 | 		{ | 
 | 1439 | 			static int count = 3; //2; //1; | 
 | 1440 | 			*p_genresp = 1; | 
 | 1441 | 			*p_resp_code = count ? RSP_ERROR : RSP_OK; | 
 | 1442 | 			if (count > 0) | 
 | 1443 | 				--count; | 
 | 1444 | 		} | 
 | 1445 | 		break; | 
 | 1446 | #endif | 
 | 1447 | 	case ACT_DEBUG: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1448 | 		gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1449 | 			__func__, ev->type, at_state->ConState); | 
 | 1450 | 		break; | 
 | 1451 | 	case ACT_WARN: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1452 | 		dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n", | 
 | 1453 | 			 __func__, ev->type, at_state->ConState); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1454 | 		break; | 
 | 1455 | 	case ACT_ZCAU: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1456 | 		dev_warn(cs->dev, "cause code %04x in connection state %d.\n", | 
 | 1457 | 			 ev->parameter, at_state->ConState); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1458 | 		break; | 
 | 1459 |  | 
 | 1460 | 	/* events from the LL */ | 
 | 1461 | 	case ACT_DIAL: | 
 | 1462 | 		start_dial(at_state, ev->ptr, ev->parameter); | 
 | 1463 | 		break; | 
 | 1464 | 	case ACT_ACCEPT: | 
 | 1465 | 		start_accept(at_state); | 
 | 1466 | 		break; | 
 | 1467 | 	case ACT_PROTO_L2: | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1468 | 		gig_dbg(DEBUG_CMD, "set protocol to %u", | 
 | 1469 | 			(unsigned) ev->parameter); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1470 | 		at_state->bcs->proto2 = ev->parameter; | 
 | 1471 | 		break; | 
 | 1472 | 	case ACT_HUP: | 
 | 1473 | 		at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1474 | 		cs->commands_pending = 1; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1475 | 		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1476 | 		break; | 
 | 1477 |  | 
 | 1478 | 	/* hotplug events */ | 
 | 1479 | 	case ACT_STOP: | 
 | 1480 | 		do_stop(cs); | 
 | 1481 | 		break; | 
 | 1482 | 	case ACT_START: | 
 | 1483 | 		do_start(cs); | 
 | 1484 | 		break; | 
 | 1485 |  | 
 | 1486 | 	/* events from the interface */ // FIXME without ACT_xxxx? | 
 | 1487 | 	case ACT_IF_LOCK: | 
 | 1488 | 		cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); | 
 | 1489 | 		cs->waiting = 0; | 
 | 1490 | 		wake_up(&cs->waitqueue); | 
 | 1491 | 		break; | 
 | 1492 | 	case ACT_IF_VER: | 
 | 1493 | 		if (ev->parameter != 0) | 
 | 1494 | 			cs->cmd_result = -EINVAL; | 
 | 1495 | 		else if (cs->gotfwver != 1) { | 
 | 1496 | 			cs->cmd_result = -ENOENT; | 
 | 1497 | 		} else { | 
 | 1498 | 			memcpy(ev->arg, cs->fwver, sizeof cs->fwver); | 
 | 1499 | 			cs->cmd_result = 0; | 
 | 1500 | 		} | 
 | 1501 | 		cs->waiting = 0; | 
 | 1502 | 		wake_up(&cs->waitqueue); | 
 | 1503 | 		break; | 
 | 1504 |  | 
 | 1505 | 	/* events from the proc file system */ // FIXME without ACT_xxxx? | 
 | 1506 | 	case ACT_PROC_CIDMODE: | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1507 | 		spin_lock_irqsave(&cs->lock, flags); | 
 | 1508 | 		if (ev->parameter != cs->cidmode) { | 
 | 1509 | 			cs->cidmode = ev->parameter; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1510 | 			if (ev->parameter) { | 
 | 1511 | 				cs->at_state.pending_commands |= PC_CIDMODE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1512 | 				gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1513 | 			} else { | 
 | 1514 | 				cs->at_state.pending_commands |= PC_UMMODE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1515 | 				gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1516 | 			} | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1517 | 			cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1518 | 		} | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1519 | 		spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1520 | 		cs->waiting = 0; | 
 | 1521 | 		wake_up(&cs->waitqueue); | 
 | 1522 | 		break; | 
 | 1523 |  | 
 | 1524 | 	/* events from the hardware drivers */ | 
 | 1525 | 	case ACT_NOTIFY_BC_DOWN: | 
 | 1526 | 		bchannel_down(bcs); | 
 | 1527 | 		break; | 
 | 1528 | 	case ACT_NOTIFY_BC_UP: | 
 | 1529 | 		bchannel_up(bcs); | 
 | 1530 | 		break; | 
 | 1531 | 	case ACT_SHUTDOWN: | 
 | 1532 | 		do_shutdown(cs); | 
 | 1533 | 		break; | 
 | 1534 |  | 
 | 1535 |  | 
 | 1536 | 	default: | 
 | 1537 | 		if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) { | 
 | 1538 | 			*pp_command = at_state->bcs->commands[action - ACT_CMD]; | 
 | 1539 | 			if (!*pp_command) { | 
 | 1540 | 				*p_genresp = 1; | 
 | 1541 | 				*p_resp_code = RSP_NULL; | 
 | 1542 | 			} | 
 | 1543 | 		} else | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1544 | 			dev_err(cs->dev, "%s: action==%d!\n", __func__, action); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1545 | 	} | 
 | 1546 | } | 
 | 1547 |  | 
 | 1548 | /* State machine to do the calling and hangup procedure */ | 
 | 1549 | static void process_event(struct cardstate *cs, struct event_t *ev) | 
 | 1550 | { | 
 | 1551 | 	struct bc_state *bcs; | 
 | 1552 | 	char *p_command = NULL; | 
 | 1553 | 	struct reply_t *rep; | 
 | 1554 | 	int rcode; | 
 | 1555 | 	int genresp = 0; | 
 | 1556 | 	int resp_code = RSP_ERROR; | 
 | 1557 | 	int sendcid; | 
 | 1558 | 	struct at_state_t *at_state; | 
 | 1559 | 	int index; | 
 | 1560 | 	int curact; | 
 | 1561 | 	unsigned long flags; | 
 | 1562 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1563 | 	if (ev->cid >= 0) { | 
 | 1564 | 		at_state = at_state_from_cid(cs, ev->cid); | 
 | 1565 | 		if (!at_state) { | 
 | 1566 | 			gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1567 | 					  NULL, 0, NULL); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1568 | 			return; | 
 | 1569 | 		} | 
 | 1570 | 	} else { | 
 | 1571 | 		at_state = ev->at_state; | 
 | 1572 | 		if (at_state_invalid(cs, at_state)) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1573 | 			gig_dbg(DEBUG_ANY, "event for invalid at_state %p", | 
 | 1574 | 				at_state); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1575 | 			return; | 
 | 1576 | 		} | 
 | 1577 | 	} | 
 | 1578 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1579 | 	gig_dbg(DEBUG_CMD, "connection state %d, event %d", | 
 | 1580 | 		at_state->ConState, ev->type); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1581 |  | 
 | 1582 | 	bcs = at_state->bcs; | 
 | 1583 | 	sendcid = at_state->cid; | 
 | 1584 |  | 
 | 1585 | 	/* Setting the pointer to the dial array */ | 
 | 1586 | 	rep = at_state->replystruct; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1587 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1588 | 	spin_lock_irqsave(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1589 | 	if (ev->type == EV_TIMEOUT) { | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1590 | 		if (ev->parameter != at_state->timer_index | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1591 | 		    || !at_state->timer_active) { | 
 | 1592 | 			ev->type = RSP_NONE; /* old timeout */ | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1593 | 			gig_dbg(DEBUG_ANY, "old timeout"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1594 | 		} else if (!at_state->waiting) | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1595 | 			gig_dbg(DEBUG_ANY, "timeout occurred"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1596 | 		else | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1597 | 			gig_dbg(DEBUG_ANY, "stopped waiting"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1598 | 	} | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1599 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1600 |  | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 1601 | 	/* if the response belongs to a variable in at_state->int_var[VAR_XXXX] | 
 | 1602 | 	   or at_state->str_var[STR_XXXX], set it */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1603 | 	if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { | 
 | 1604 | 		index = ev->type - RSP_VAR; | 
 | 1605 | 		at_state->int_var[index] = ev->parameter; | 
 | 1606 | 	} else if (ev->type >= RSP_STR && ev->type < RSP_STR + STR_NUM) { | 
 | 1607 | 		index = ev->type - RSP_STR; | 
 | 1608 | 		kfree(at_state->str_var[index]); | 
 | 1609 | 		at_state->str_var[index] = ev->ptr; | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 1610 | 		ev->ptr = NULL; /* prevent process_events() from | 
 | 1611 | 				   deallocating ptr */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1612 | 	} | 
 | 1613 |  | 
 | 1614 | 	if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) | 
 | 1615 | 		at_state->getstring = 0; | 
 | 1616 |  | 
| Tilman Schmidt | 917f508 | 2006-04-10 22:55:00 -0700 | [diff] [blame] | 1617 | 	/* Search row in dial array which matches modem response and current | 
 | 1618 | 	   constate */ | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1619 | 	for (;; rep++) { | 
 | 1620 | 		rcode = rep->resp_code; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1621 | 		if (rcode == RSP_LAST) { | 
 | 1622 | 			/* found nothing...*/ | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1623 | 			dev_warn(cs->dev, "%s: rcode=RSP_LAST: " | 
 | 1624 | 					"resp_code %d in ConState %d!\n", | 
 | 1625 | 				 __func__, ev->type, at_state->ConState); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1626 | 			return; | 
 | 1627 | 		} | 
 | 1628 | 		if ((rcode == RSP_ANY || rcode == ev->type) | 
 | 1629 | 		  && ((int) at_state->ConState >= rep->min_ConState) | 
 | 1630 | 		  && (rep->max_ConState < 0 | 
 | 1631 | 		      || (int) at_state->ConState <= rep->max_ConState) | 
 | 1632 | 		  && (rep->parameter < 0 || rep->parameter == ev->parameter)) | 
 | 1633 | 			break; | 
 | 1634 | 	} | 
 | 1635 |  | 
 | 1636 | 	p_command = rep->command; | 
 | 1637 |  | 
 | 1638 | 	at_state->waiting = 0; | 
 | 1639 | 	for (curact = 0; curact < MAXACT; ++curact) { | 
 | 1640 | 		/* The row tells us what we should do  .. | 
 | 1641 | 		 */ | 
 | 1642 | 		do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); | 
 | 1643 | 		if (!at_state) | 
 | 1644 | 			break; /* may be freed after disconnect */ | 
 | 1645 | 	} | 
 | 1646 |  | 
 | 1647 | 	if (at_state) { | 
 | 1648 | 		/* Jump to the next con-state regarding the array */ | 
 | 1649 | 		if (rep->new_ConState >= 0) | 
 | 1650 | 			at_state->ConState = rep->new_ConState; | 
 | 1651 |  | 
 | 1652 | 		if (genresp) { | 
 | 1653 | 			spin_lock_irqsave(&cs->lock, flags); | 
 | 1654 | 			at_state->timer_expires = 0; //FIXME | 
 | 1655 | 			at_state->timer_active = 0; //FIXME | 
 | 1656 | 			spin_unlock_irqrestore(&cs->lock, flags); | 
 | 1657 | 			gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); | 
 | 1658 | 		} else { | 
 | 1659 | 			/* Send command to modem if not NULL... */ | 
 | 1660 | 			if (p_command/*rep->command*/) { | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1661 | 				if (cs->connected) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1662 | 					send_command(cs, p_command, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1663 | 						     sendcid, cs->dle, | 
 | 1664 | 						     GFP_ATOMIC); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1665 | 				else | 
 | 1666 | 					gigaset_add_event(cs, at_state, | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1667 | 							  RSP_NODEV, | 
 | 1668 | 							  NULL, 0, NULL); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1669 | 			} | 
 | 1670 |  | 
 | 1671 | 			spin_lock_irqsave(&cs->lock, flags); | 
 | 1672 | 			if (!rep->timeout) { | 
 | 1673 | 				at_state->timer_expires = 0; | 
 | 1674 | 				at_state->timer_active = 0; | 
 | 1675 | 			} else if (rep->timeout > 0) { /* new timeout */ | 
 | 1676 | 				at_state->timer_expires = rep->timeout * 10; | 
 | 1677 | 				at_state->timer_active = 1; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1678 | 				++at_state->timer_index; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1679 | 			} | 
 | 1680 | 			spin_unlock_irqrestore(&cs->lock, flags); | 
 | 1681 | 		} | 
 | 1682 | 	} | 
 | 1683 | } | 
 | 1684 |  | 
 | 1685 | static void schedule_sequence(struct cardstate *cs, | 
 | 1686 | 			      struct at_state_t *at_state, int sequence) | 
 | 1687 | { | 
 | 1688 | 	cs->cur_at_seq = sequence; | 
 | 1689 | 	gigaset_add_event(cs, at_state, RSP_INIT, NULL, sequence, NULL); | 
 | 1690 | } | 
 | 1691 |  | 
 | 1692 | static void process_command_flags(struct cardstate *cs) | 
 | 1693 | { | 
 | 1694 | 	struct at_state_t *at_state = NULL; | 
 | 1695 | 	struct bc_state *bcs; | 
 | 1696 | 	int i; | 
 | 1697 | 	int sequence; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1698 | 	unsigned long flags; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1699 |  | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1700 | 	cs->commands_pending = 0; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1701 |  | 
 | 1702 | 	if (cs->cur_at_seq) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1703 | 		gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1704 | 		return; | 
 | 1705 | 	} | 
 | 1706 |  | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1707 | 	gig_dbg(DEBUG_CMD, "searching scheduled commands"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1708 |  | 
 | 1709 | 	sequence = SEQ_NONE; | 
 | 1710 |  | 
 | 1711 | 	/* clear pending_commands and hangup channels on shutdown */ | 
 | 1712 | 	if (cs->at_state.pending_commands & PC_SHUTDOWN) { | 
 | 1713 | 		cs->at_state.pending_commands &= ~PC_CIDMODE; | 
 | 1714 | 		for (i = 0; i < cs->channels; ++i) { | 
 | 1715 | 			bcs = cs->bcs + i; | 
 | 1716 | 			at_state = &bcs->at_state; | 
 | 1717 | 			at_state->pending_commands &= | 
 | 1718 | 				~(PC_DLE1 | PC_ACCEPT | PC_DIAL); | 
 | 1719 | 			if (at_state->cid > 0) | 
 | 1720 | 				at_state->pending_commands |= PC_HUP; | 
 | 1721 | 			if (at_state->pending_commands & PC_CID) { | 
 | 1722 | 				at_state->pending_commands |= PC_NOCID; | 
 | 1723 | 				at_state->pending_commands &= ~PC_CID; | 
 | 1724 | 			} | 
 | 1725 | 		} | 
 | 1726 | 	} | 
 | 1727 |  | 
 | 1728 | 	/* clear pending_commands and hangup channels on reset */ | 
 | 1729 | 	if (cs->at_state.pending_commands & PC_INIT) { | 
 | 1730 | 		cs->at_state.pending_commands &= ~PC_CIDMODE; | 
 | 1731 | 		for (i = 0; i < cs->channels; ++i) { | 
 | 1732 | 			bcs = cs->bcs + i; | 
 | 1733 | 			at_state = &bcs->at_state; | 
 | 1734 | 			at_state->pending_commands &= | 
 | 1735 | 				~(PC_DLE1 | PC_ACCEPT | PC_DIAL); | 
 | 1736 | 			if (at_state->cid > 0) | 
 | 1737 | 				at_state->pending_commands |= PC_HUP; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1738 | 			if (cs->mstate == MS_RECOVER) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1739 | 				if (at_state->pending_commands & PC_CID) { | 
 | 1740 | 					at_state->pending_commands |= PC_NOCID; | 
 | 1741 | 					at_state->pending_commands &= ~PC_CID; | 
 | 1742 | 				} | 
 | 1743 | 			} | 
 | 1744 | 		} | 
 | 1745 | 	} | 
 | 1746 |  | 
 | 1747 | 	/* only switch back to unimodem mode, if no commands are pending and no channels are up */ | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1748 | 	spin_lock_irqsave(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1749 | 	if (cs->at_state.pending_commands == PC_UMMODE | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1750 | 	    && !cs->cidmode | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1751 | 	    && list_empty(&cs->temp_at_states) | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1752 | 	    && cs->mode == M_CID) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1753 | 		sequence = SEQ_UMMODE; | 
 | 1754 | 		at_state = &cs->at_state; | 
 | 1755 | 		for (i = 0; i < cs->channels; ++i) { | 
 | 1756 | 			bcs = cs->bcs + i; | 
 | 1757 | 			if (bcs->at_state.pending_commands || | 
 | 1758 | 			    bcs->at_state.cid > 0) { | 
 | 1759 | 				sequence = SEQ_NONE; | 
 | 1760 | 				break; | 
 | 1761 | 			} | 
 | 1762 | 		} | 
 | 1763 | 	} | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1764 | 	spin_unlock_irqrestore(&cs->lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1765 | 	cs->at_state.pending_commands &= ~PC_UMMODE; | 
 | 1766 | 	if (sequence != SEQ_NONE) { | 
 | 1767 | 		schedule_sequence(cs, at_state, sequence); | 
 | 1768 | 		return; | 
 | 1769 | 	} | 
 | 1770 |  | 
 | 1771 | 	for (i = 0; i < cs->channels; ++i) { | 
 | 1772 | 		bcs = cs->bcs + i; | 
 | 1773 | 		if (bcs->at_state.pending_commands & PC_HUP) { | 
 | 1774 | 			bcs->at_state.pending_commands &= ~PC_HUP; | 
 | 1775 | 			if (bcs->at_state.pending_commands & PC_CID) { | 
 | 1776 | 				/* not yet dialing: PC_NOCID is sufficient */ | 
 | 1777 | 				bcs->at_state.pending_commands |= PC_NOCID; | 
 | 1778 | 				bcs->at_state.pending_commands &= ~PC_CID; | 
 | 1779 | 			} else { | 
 | 1780 | 				schedule_sequence(cs, &bcs->at_state, SEQ_HUP); | 
 | 1781 | 				return; | 
 | 1782 | 			} | 
 | 1783 | 		} | 
 | 1784 | 		if (bcs->at_state.pending_commands & PC_NOCID) { | 
 | 1785 | 			bcs->at_state.pending_commands &= ~PC_NOCID; | 
 | 1786 | 			cs->curchannel = bcs->channel; | 
 | 1787 | 			schedule_sequence(cs, &cs->at_state, SEQ_NOCID); | 
 | 1788 | 			return; | 
 | 1789 | 		} else if (bcs->at_state.pending_commands & PC_DLE0) { | 
 | 1790 | 			bcs->at_state.pending_commands &= ~PC_DLE0; | 
 | 1791 | 			cs->curchannel = bcs->channel; | 
 | 1792 | 			schedule_sequence(cs, &cs->at_state, SEQ_DLE0); | 
 | 1793 | 			return; | 
 | 1794 | 		} | 
 | 1795 | 	} | 
 | 1796 |  | 
 | 1797 | 	list_for_each_entry(at_state, &cs->temp_at_states, list) | 
 | 1798 | 		if (at_state->pending_commands & PC_HUP) { | 
 | 1799 | 			at_state->pending_commands &= ~PC_HUP; | 
 | 1800 | 			schedule_sequence(cs, at_state, SEQ_HUP); | 
 | 1801 | 			return; | 
 | 1802 | 		} | 
 | 1803 |  | 
 | 1804 | 	if (cs->at_state.pending_commands & PC_INIT) { | 
 | 1805 | 		cs->at_state.pending_commands &= ~PC_INIT; | 
 | 1806 | 		cs->dle = 0; //FIXME | 
 | 1807 | 		cs->inbuf->inputstate = INS_command; | 
 | 1808 | 		//FIXME reset card state (or -> LOCK0)? | 
 | 1809 | 		schedule_sequence(cs, &cs->at_state, SEQ_INIT); | 
 | 1810 | 		return; | 
 | 1811 | 	} | 
 | 1812 | 	if (cs->at_state.pending_commands & PC_SHUTDOWN) { | 
 | 1813 | 		cs->at_state.pending_commands &= ~PC_SHUTDOWN; | 
 | 1814 | 		schedule_sequence(cs, &cs->at_state, SEQ_SHUTDOWN); | 
 | 1815 | 		return; | 
 | 1816 | 	} | 
 | 1817 | 	if (cs->at_state.pending_commands & PC_CIDMODE) { | 
 | 1818 | 		cs->at_state.pending_commands &= ~PC_CIDMODE; | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1819 | 		if (cs->mode == M_UNIMODEM) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1820 | 			cs->retry_count = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1821 | 			schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); | 
 | 1822 | 			return; | 
 | 1823 | 		} | 
 | 1824 | 	} | 
 | 1825 |  | 
 | 1826 | 	for (i = 0; i < cs->channels; ++i) { | 
 | 1827 | 		bcs = cs->bcs + i; | 
 | 1828 | 		if (bcs->at_state.pending_commands & PC_DLE1) { | 
 | 1829 | 			bcs->at_state.pending_commands &= ~PC_DLE1; | 
 | 1830 | 			cs->curchannel = bcs->channel; | 
 | 1831 | 			schedule_sequence(cs, &cs->at_state, SEQ_DLE1); | 
 | 1832 | 			return; | 
 | 1833 | 		} | 
 | 1834 | 		if (bcs->at_state.pending_commands & PC_ACCEPT) { | 
 | 1835 | 			bcs->at_state.pending_commands &= ~PC_ACCEPT; | 
 | 1836 | 			schedule_sequence(cs, &bcs->at_state, SEQ_ACCEPT); | 
 | 1837 | 			return; | 
 | 1838 | 		} | 
 | 1839 | 		if (bcs->at_state.pending_commands & PC_DIAL) { | 
 | 1840 | 			bcs->at_state.pending_commands &= ~PC_DIAL; | 
 | 1841 | 			schedule_sequence(cs, &bcs->at_state, SEQ_DIAL); | 
 | 1842 | 			return; | 
 | 1843 | 		} | 
 | 1844 | 		if (bcs->at_state.pending_commands & PC_CID) { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1845 | 			switch (cs->mode) { | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1846 | 			case M_UNIMODEM: | 
 | 1847 | 				cs->at_state.pending_commands |= PC_CIDMODE; | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1848 | 				gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1849 | 				cs->commands_pending = 1; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1850 | 				return; | 
 | 1851 | #ifdef GIG_MAYINITONDIAL | 
 | 1852 | 			case M_UNKNOWN: | 
 | 1853 | 				schedule_init(cs, MS_INIT); | 
 | 1854 | 				return; | 
 | 1855 | #endif | 
 | 1856 | 			} | 
 | 1857 | 			bcs->at_state.pending_commands &= ~PC_CID; | 
 | 1858 | 			cs->curchannel = bcs->channel; | 
 | 1859 | #ifdef GIG_RETRYCID | 
 | 1860 | 			cs->retry_count = 2; | 
 | 1861 | #else | 
 | 1862 | 			cs->retry_count = 1; | 
 | 1863 | #endif | 
 | 1864 | 			schedule_sequence(cs, &cs->at_state, SEQ_CID); | 
 | 1865 | 			return; | 
 | 1866 | 		} | 
 | 1867 | 	} | 
 | 1868 | } | 
 | 1869 |  | 
 | 1870 | static void process_events(struct cardstate *cs) | 
 | 1871 | { | 
 | 1872 | 	struct event_t *ev; | 
 | 1873 | 	unsigned head, tail; | 
 | 1874 | 	int i; | 
 | 1875 | 	int check_flags = 0; | 
 | 1876 | 	int was_busy; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1877 | 	unsigned long flags; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1878 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1879 | 	spin_lock_irqsave(&cs->ev_lock, flags); | 
 | 1880 | 	head = cs->ev_head; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1881 |  | 
 | 1882 | 	for (i = 0; i < 2 * MAX_EVENTS; ++i) { | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1883 | 		tail = cs->ev_tail; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1884 | 		if (tail == head) { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1885 | 			if (!check_flags && !cs->commands_pending) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1886 | 				break; | 
 | 1887 | 			check_flags = 0; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1888 | 			spin_unlock_irqrestore(&cs->ev_lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1889 | 			process_command_flags(cs); | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1890 | 			spin_lock_irqsave(&cs->ev_lock, flags); | 
 | 1891 | 			tail = cs->ev_tail; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1892 | 			if (tail == head) { | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1893 | 				if (!cs->commands_pending) | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1894 | 					break; | 
 | 1895 | 				continue; | 
 | 1896 | 			} | 
 | 1897 | 		} | 
 | 1898 |  | 
 | 1899 | 		ev = cs->events + head; | 
 | 1900 | 		was_busy = cs->cur_at_seq != SEQ_NONE; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1901 | 		spin_unlock_irqrestore(&cs->ev_lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1902 | 		process_event(cs, ev); | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1903 | 		spin_lock_irqsave(&cs->ev_lock, flags); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1904 | 		kfree(ev->ptr); | 
 | 1905 | 		ev->ptr = NULL; | 
 | 1906 | 		if (was_busy && cs->cur_at_seq == SEQ_NONE) | 
 | 1907 | 			check_flags = 1; | 
 | 1908 |  | 
 | 1909 | 		head = (head + 1) % MAX_EVENTS; | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1910 | 		cs->ev_head = head; | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1911 | 	} | 
 | 1912 |  | 
| Tilman Schmidt | 69049cc | 2006-04-10 22:55:16 -0700 | [diff] [blame] | 1913 | 	spin_unlock_irqrestore(&cs->ev_lock, flags); | 
 | 1914 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1915 | 	if (i == 2 * MAX_EVENTS) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1916 | 		dev_err(cs->dev, | 
 | 1917 | 			"infinite loop in process_events; aborting.\n"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1918 | 	} | 
 | 1919 | } | 
 | 1920 |  | 
 | 1921 | /* tasklet scheduled on any event received from the Gigaset device | 
 | 1922 |  * parameter: | 
 | 1923 |  *	data	ISDN controller state structure | 
 | 1924 |  */ | 
 | 1925 | void gigaset_handle_event(unsigned long data) | 
 | 1926 | { | 
 | 1927 | 	struct cardstate *cs = (struct cardstate *) data; | 
 | 1928 |  | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1929 | 	/* handle incoming data on control/common channel */ | 
| Tilman Schmidt | 9d4bee2 | 2008-02-06 01:38:28 -0800 | [diff] [blame] | 1930 | 	if (cs->inbuf->head != cs->inbuf->tail) { | 
| Tilman Schmidt | 784d585 | 2006-04-10 22:55:04 -0700 | [diff] [blame] | 1931 | 		gig_dbg(DEBUG_INTR, "processing new data"); | 
| Hansjoerg Lipp | 14fa73a | 2006-03-26 01:38:30 -0800 | [diff] [blame] | 1932 | 		cs->ops->handle_input(cs->inbuf); | 
 | 1933 | 	} | 
 | 1934 |  | 
 | 1935 | 	process_events(cs); | 
 | 1936 | } |