aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/asyncdata.c
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2009-10-25 05:30:07 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-29 04:37:10 -0400
commit2032e2c2309de02cd67b1d26aa701c2a57c4639f (patch)
treeee0f953f4afb7d98e3e27a32310d92bf0765b00b /drivers/isdn/gigaset/asyncdata.c
parent4dd8230acd20cb456cae02696b3da2986faad258 (diff)
usb_gigaset: code cleanup
Reorganize the code of the Gigaset M10x driver to make it more readable, less redundant, better aligned to the style of other parts of the driver, and cause fewer checkpatch.pl complaints. Impact: code reorganization, no functional change Signed-off-by: Tilman Schmidt <tilman@imap.cc> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/gigaset/asyncdata.c')
-rw-r--r--drivers/isdn/gigaset/asyncdata.c573
1 files changed, 307 insertions, 266 deletions
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 256fc4809c81..ccb2a7b7c41d 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -19,7 +19,7 @@
19 19
20/* check if byte must be stuffed/escaped 20/* check if byte must be stuffed/escaped
21 * I'm not sure which data should be encoded. 21 * I'm not sure which data should be encoded.
22 * Therefore I will go the hard way and decode every value 22 * Therefore I will go the hard way and encode every value
23 * less than 0x20, the flag sequence and the control escape char. 23 * less than 0x20, the flag sequence and the control escape char.
24 */ 24 */
25static inline int muststuff(unsigned char c) 25static inline int muststuff(unsigned char c)
@@ -35,288 +35,383 @@ static inline int muststuff(unsigned char c)
35 35
36/* == data input =========================================================== */ 36/* == data input =========================================================== */
37 37
38/* process a block of received bytes in command mode (modem response) 38/* process a block of received bytes in command mode
39 * (mstate != MS_LOCKED && (inputstate & INS_command))
40 * Append received bytes to the command response buffer and forward them
41 * line by line to the response handler. Exit whenever a mode/state change
42 * might have occurred.
39 * Return value: 43 * Return value:
40 * number of processed bytes 44 * number of processed bytes
41 */ 45 */
42static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, 46static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf)
43 struct inbuf_t *inbuf)
44{ 47{
48 unsigned char *src = inbuf->data + inbuf->head;
45 struct cardstate *cs = inbuf->cs; 49 struct cardstate *cs = inbuf->cs;
46 unsigned cbytes = cs->cbytes; 50 unsigned cbytes = cs->cbytes;
47 int inputstate = inbuf->inputstate; 51 unsigned procbytes = 0;
48 int startbytes = numbytes; 52 unsigned char c;
49 53
50 for (;;) { 54 while (procbytes < numbytes) {
51 cs->respdata[cbytes] = c; 55 c = *src++;
52 if (c == 10 || c == 13) { 56 procbytes++;
53 gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", 57
58 switch (c) {
59 case '\n':
60 if (cbytes == 0 && cs->respdata[0] == '\r') {
61 /* collapse LF with preceding CR */
62 cs->respdata[0] = 0;
63 break;
64 }
65 /* --v-- fall through --v-- */
66 case '\r':
67 /* end of message line, pass to response handler */
68 gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)",
54 __func__, cbytes); 69 __func__, cbytes);
70 if (cbytes >= MAX_RESP_SIZE) {
71 dev_warn(cs->dev, "response too large (%d)\n",
72 cbytes);
73 cbytes = MAX_RESP_SIZE;
74 }
55 cs->cbytes = cbytes; 75 cs->cbytes = cbytes;
56 gigaset_handle_modem_response(cs); /* can change 76 gigaset_handle_modem_response(cs);
57 cs->dle */
58 cbytes = 0; 77 cbytes = 0;
59 78
60 if (cs->dle && 79 /* store EOL byte for CRLF collapsing */
61 !(inputstate & INS_DLE_command)) { 80 cs->respdata[0] = c;
62 inputstate &= ~INS_command;
63 break;
64 }
65 } else {
66 /* advance in line buffer, checking for overflow */
67 if (cbytes < MAX_RESP_SIZE - 1)
68 cbytes++;
69 else
70 dev_warn(cs->dev, "response too large\n");
71 }
72 81
73 if (!numbytes) 82 /* cs->dle may have changed */
74 break; 83 if (cs->dle && !(inbuf->inputstate & INS_DLE_command))
75 c = *src++; 84 inbuf->inputstate &= ~INS_command;
76 --numbytes; 85
77 if (c == DLE_FLAG && 86 /* return for reevaluating state */
78 (cs->dle || inputstate & INS_DLE_command)) { 87 goto exit;
79 inputstate |= INS_DLE_char; 88
80 break; 89 case DLE_FLAG:
90 if (inbuf->inputstate & INS_DLE_char) {
91 /* quoted DLE: clear quote flag */
92 inbuf->inputstate &= ~INS_DLE_char;
93 } else if (cs->dle ||
94 (inbuf->inputstate & INS_DLE_command)) {
95 /* DLE escape, pass up for handling */
96 inbuf->inputstate |= INS_DLE_char;
97 goto exit;
98 }
99 /* quoted or not in DLE mode: treat as regular data */
100 /* --v-- fall through --v-- */
101 default:
102 /* append to line buffer if possible */
103 if (cbytes < MAX_RESP_SIZE)
104 cs->respdata[cbytes] = c;
105 cbytes++;
81 } 106 }
82 } 107 }
83 108exit:
84 cs->cbytes = cbytes; 109 cs->cbytes = cbytes;
85 inbuf->inputstate = inputstate; 110 return procbytes;
86
87 return startbytes - numbytes;
88} 111}
89 112
90/* process a block of received bytes in lock mode (tty i/f) 113/* process a block of received bytes in lock mode
114 * All received bytes are passed unmodified to the tty i/f.
91 * Return value: 115 * Return value:
92 * number of processed bytes 116 * number of processed bytes
93 */ 117 */
94static inline int lock_loop(unsigned char *src, int numbytes, 118static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
95 struct inbuf_t *inbuf)
96{ 119{
97 struct cardstate *cs = inbuf->cs; 120 unsigned char *src = inbuf->data + inbuf->head;
98
99 gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
100 numbytes, src);
101 gigaset_if_receive(cs, src, numbytes);
102 121
122 gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src);
123 gigaset_if_receive(inbuf->cs, src, numbytes);
103 return numbytes; 124 return numbytes;
104} 125}
105 126
127/* set up next receive skb for data mode
128 */
129static void new_rcv_skb(struct bc_state *bcs)
130{
131 struct cardstate *cs = bcs->cs;
132 unsigned short hw_hdr_len = cs->hw_hdr_len;
133
134 if (bcs->ignore) {
135 bcs->skb = NULL;
136 return;
137 }
138
139 bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
140 if (bcs->skb == NULL) {
141 dev_warn(cs->dev, "could not allocate new skb\n");
142 return;
143 }
144 skb_reserve(bcs->skb, hw_hdr_len);
145}
146
106/* process a block of received bytes in HDLC data mode 147/* process a block of received bytes in HDLC data mode
148 * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
107 * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. 149 * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
108 * When a frame is complete, check the FCS and pass valid frames to the LL. 150 * When a frame is complete, check the FCS and pass valid frames to the LL.
109 * If DLE is encountered, return immediately to let the caller handle it. 151 * If DLE is encountered, return immediately to let the caller handle it.
110 * Return value: 152 * Return value:
111 * number of processed bytes 153 * number of processed bytes
112 * numbytes (all bytes processed) on error --FIXME
113 */ 154 */
114static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, 155static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
115 struct inbuf_t *inbuf)
116{ 156{
117 struct cardstate *cs = inbuf->cs; 157 struct cardstate *cs = inbuf->cs;
118 struct bc_state *bcs = inbuf->bcs; 158 struct bc_state *bcs = cs->bcs;
119 int inputstate = bcs->inputstate; 159 int inputstate = bcs->inputstate;
120 __u16 fcs = bcs->fcs; 160 __u16 fcs = bcs->fcs;
121 struct sk_buff *skb = bcs->skb; 161 struct sk_buff *skb = bcs->skb;
122 int startbytes = numbytes; 162 unsigned char *src = inbuf->data + inbuf->head;
163 unsigned procbytes = 0;
164 unsigned char c;
123 165
124 if (unlikely(inputstate & INS_byte_stuff)) { 166 if (inputstate & INS_byte_stuff) {
167 if (!numbytes)
168 return 0;
125 inputstate &= ~INS_byte_stuff; 169 inputstate &= ~INS_byte_stuff;
126 goto byte_stuff; 170 goto byte_stuff;
127 } 171 }
128 for (;;) { 172
129 if (unlikely(c == PPP_ESCAPE)) { 173 while (procbytes < numbytes) {
130 if (unlikely(!numbytes)) { 174 c = *src++;
131 inputstate |= INS_byte_stuff; 175 procbytes++;
176 if (c == DLE_FLAG) {
177 if (inputstate & INS_DLE_char) {
178 /* quoted DLE: clear quote flag */
179 inputstate &= ~INS_DLE_char;
180 } else if (cs->dle || (inputstate & INS_DLE_command)) {
181 /* DLE escape, pass up for handling */
182 inputstate |= INS_DLE_char;
132 break; 183 break;
133 } 184 }
134 c = *src++; 185 }
135 --numbytes; 186
136 if (unlikely(c == DLE_FLAG && 187 if (c == PPP_ESCAPE) {
137 (cs->dle || 188 /* byte stuffing indicator: pull in next byte */
138 inbuf->inputstate & INS_DLE_command))) { 189 if (procbytes >= numbytes) {
139 inbuf->inputstate |= INS_DLE_char; 190 /* end of buffer, save for later processing */
140 inputstate |= INS_byte_stuff; 191 inputstate |= INS_byte_stuff;
141 break; 192 break;
142 } 193 }
143byte_stuff: 194byte_stuff:
195 c = *src++;
196 procbytes++;
197 if (c == DLE_FLAG) {
198 if (inputstate & INS_DLE_char) {
199 /* quoted DLE: clear quote flag */
200 inputstate &= ~INS_DLE_char;
201 } else if (cs->dle ||
202 (inputstate & INS_DLE_command)) {
203 /* DLE escape, pass up for handling */
204 inputstate |=
205 INS_DLE_char | INS_byte_stuff;
206 break;
207 }
208 }
144 c ^= PPP_TRANS; 209 c ^= PPP_TRANS;
145 if (unlikely(!muststuff(c)))
146 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
147 } else if (unlikely(c == PPP_FLAG)) {
148 if (unlikely(inputstate & INS_skip_frame)) {
149#ifdef CONFIG_GIGASET_DEBUG 210#ifdef CONFIG_GIGASET_DEBUG
150 if (!(inputstate & INS_have_data)) { /* 7E 7E */ 211 if (!muststuff(c))
151 ++bcs->emptycount; 212 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
152 } else
153 gig_dbg(DEBUG_HDLC,
154 "7e----------------------------");
155#endif
156
157 /* end of frame */
158 gigaset_isdn_rcv_err(bcs);
159 dev_kfree_skb_any(skb);
160 } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
161#ifdef CONFIG_GIGASET_DEBUG
162 ++bcs->emptycount;
163#endif 213#endif
164 break; 214 } else if (c == PPP_FLAG) {
165 } else { 215 /* end of frame: process content if any */
216 if (inputstate & INS_have_data) {
166 gig_dbg(DEBUG_HDLC, 217 gig_dbg(DEBUG_HDLC,
167 "7e----------------------------"); 218 "7e----------------------------");
168 219
169 /* end of frame */ 220 /* check and pass received frame */
170 if (unlikely(fcs != PPP_GOODFCS)) { 221 if (!skb) {
222 /* skipped frame */
223 gigaset_isdn_rcv_err(bcs);
224 } else if (skb->len < 2) {
225 /* frame too short for FCS */
226 dev_warn(cs->dev,
227 "short frame (%d)\n",
228 skb->len);
229 gigaset_isdn_rcv_err(bcs);
230 dev_kfree_skb_any(skb);
231 } else if (fcs != PPP_GOODFCS) {
232 /* frame check error */
171 dev_err(cs->dev, 233 dev_err(cs->dev,
172 "Checksum failed, %u bytes corrupted!\n", 234 "Checksum failed, %u bytes corrupted!\n",
173 skb->len); 235 skb->len);
174 gigaset_isdn_rcv_err(bcs); 236 gigaset_isdn_rcv_err(bcs);
175 dev_kfree_skb_any(skb); 237 dev_kfree_skb_any(skb);
176 } else if (likely(skb->len > 2)) { 238 } else {
239 /* good frame */
177 __skb_trim(skb, skb->len - 2); 240 __skb_trim(skb, skb->len - 2);
178 gigaset_skb_rcvd(bcs, skb); 241 gigaset_skb_rcvd(bcs, skb);
179 } else {
180 if (skb->len) {
181 dev_err(cs->dev,
182 "invalid packet size (%d)\n", skb->len);
183 gigaset_isdn_rcv_err(bcs);
184 }
185 dev_kfree_skb_any(skb);
186 } 242 }
187 }
188 243
189 fcs = PPP_INITFCS; 244 /* prepare reception of next frame */
190 inputstate &= ~(INS_have_data | INS_skip_frame); 245 inputstate &= ~INS_have_data;
191 if (unlikely(bcs->ignore)) { 246 new_rcv_skb(bcs);
192 inputstate |= INS_skip_frame; 247 skb = bcs->skb;
193 skb = NULL;
194 } else { 248 } else {
195 skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); 249 /* empty frame (7E 7E) */
196 if (skb != NULL) { 250#ifdef CONFIG_GIGASET_DEBUG
197 skb_reserve(skb, cs->hw_hdr_len); 251 ++bcs->emptycount;
198 } else { 252#endif
199 dev_warn(cs->dev, 253 if (!skb) {
200 "could not allocate new skb\n"); 254 /* skipped (?) */
201 inputstate |= INS_skip_frame; 255 gigaset_isdn_rcv_err(bcs);
256 new_rcv_skb(bcs);
257 skb = bcs->skb;
202 } 258 }
203 } 259 }
204 260
205 break; 261 fcs = PPP_INITFCS;
206 } else if (unlikely(muststuff(c))) { 262 continue;
263#ifdef CONFIG_GIGASET_DEBUG
264 } else if (muststuff(c)) {
207 /* Should not happen. Possible after ZDLE=1<CR><LF>. */ 265 /* Should not happen. Possible after ZDLE=1<CR><LF>. */
208 gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); 266 gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
267#endif
209 } 268 }
210 269
211 /* add character */ 270 /* regular data byte, append to skb */
212
213#ifdef CONFIG_GIGASET_DEBUG 271#ifdef CONFIG_GIGASET_DEBUG
214 if (unlikely(!(inputstate & INS_have_data))) { 272 if (!(inputstate & INS_have_data)) {
215 gig_dbg(DEBUG_HDLC, "7e (%d x) ================", 273 gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
216 bcs->emptycount); 274 bcs->emptycount);
217 bcs->emptycount = 0; 275 bcs->emptycount = 0;
218 } 276 }
219#endif 277#endif
220
221 inputstate |= INS_have_data; 278 inputstate |= INS_have_data;
222 279 if (skb) {
223 if (likely(!(inputstate & INS_skip_frame))) { 280 if (skb->len == SBUFSIZE) {
224 if (unlikely(skb->len == SBUFSIZE)) {
225 dev_warn(cs->dev, "received packet too long\n"); 281 dev_warn(cs->dev, "received packet too long\n");
226 dev_kfree_skb_any(skb); 282 dev_kfree_skb_any(skb);
227 skb = NULL; 283 /* skip remainder of packet */
228 inputstate |= INS_skip_frame; 284 bcs->skb = skb = NULL;
229 break; 285 } else {
286 *__skb_put(skb, 1) = c;
287 fcs = crc_ccitt_byte(fcs, c);
230 } 288 }
231 *__skb_put(skb, 1) = c;
232 fcs = crc_ccitt_byte(fcs, c);
233 }
234
235 if (unlikely(!numbytes))
236 break;
237 c = *src++;
238 --numbytes;
239 if (unlikely(c == DLE_FLAG &&
240 (cs->dle ||
241 inbuf->inputstate & INS_DLE_command))) {
242 inbuf->inputstate |= INS_DLE_char;
243 break;
244 } 289 }
245 } 290 }
291
246 bcs->inputstate = inputstate; 292 bcs->inputstate = inputstate;
247 bcs->fcs = fcs; 293 bcs->fcs = fcs;
248 bcs->skb = skb; 294 return procbytes;
249 return startbytes - numbytes;
250} 295}
251 296
252/* process a block of received bytes in transparent data mode 297/* process a block of received bytes in transparent data mode
298 * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC)
253 * Invert bytes, undoing byte stuffing and watching for DLE escapes. 299 * Invert bytes, undoing byte stuffing and watching for DLE escapes.
254 * If DLE is encountered, return immediately to let the caller handle it. 300 * If DLE is encountered, return immediately to let the caller handle it.
255 * Return value: 301 * Return value:
256 * number of processed bytes 302 * number of processed bytes
257 * numbytes (all bytes processed) on error --FIXME
258 */ 303 */
259static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, 304static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
260 struct inbuf_t *inbuf)
261{ 305{
262 struct cardstate *cs = inbuf->cs; 306 struct cardstate *cs = inbuf->cs;
263 struct bc_state *bcs = inbuf->bcs; 307 struct bc_state *bcs = cs->bcs;
264 int inputstate = bcs->inputstate; 308 int inputstate = bcs->inputstate;
265 struct sk_buff *skb = bcs->skb; 309 struct sk_buff *skb = bcs->skb;
266 int startbytes = numbytes; 310 unsigned char *src = inbuf->data + inbuf->head;
311 unsigned procbytes = 0;
312 unsigned char c;
267 313
268 for (;;) { 314 if (!skb) {
269 /* add character */ 315 /* skip this block */
270 inputstate |= INS_have_data; 316 new_rcv_skb(bcs);
317 return numbytes;
318 }
271 319
272 if (likely(!(inputstate & INS_skip_frame))) { 320 while (procbytes < numbytes && skb->len < SBUFSIZE) {
273 if (unlikely(skb->len == SBUFSIZE)) { 321 c = *src++;
274 //FIXME just pass skb up and allocate a new one 322 procbytes++;
275 dev_warn(cs->dev, "received packet too long\n"); 323
276 dev_kfree_skb_any(skb); 324 if (c == DLE_FLAG) {
277 skb = NULL; 325 if (inputstate & INS_DLE_char) {
278 inputstate |= INS_skip_frame; 326 /* quoted DLE: clear quote flag */
327 inputstate &= ~INS_DLE_char;
328 } else if (cs->dle || (inputstate & INS_DLE_command)) {
329 /* DLE escape, pass up for handling */
330 inputstate |= INS_DLE_char;
279 break; 331 break;
280 } 332 }
281 *__skb_put(skb, 1) = bitrev8(c);
282 } 333 }
283 334
284 if (unlikely(!numbytes)) 335 /* regular data byte: append to current skb */
285 break; 336 inputstate |= INS_have_data;
286 c = *src++; 337 *__skb_put(skb, 1) = bitrev8(c);
287 --numbytes;
288 if (unlikely(c == DLE_FLAG &&
289 (cs->dle ||
290 inbuf->inputstate & INS_DLE_command))) {
291 inbuf->inputstate |= INS_DLE_char;
292 break;
293 }
294 } 338 }
295 339
296 /* pass data up */ 340 /* pass data up */
297 if (likely(inputstate & INS_have_data)) { 341 if (inputstate & INS_have_data) {
298 if (likely(!(inputstate & INS_skip_frame))) { 342 gigaset_skb_rcvd(bcs, skb);
299 gigaset_skb_rcvd(bcs, skb); 343 inputstate &= ~INS_have_data;
300 } 344 new_rcv_skb(bcs);
301 inputstate &= ~(INS_have_data | INS_skip_frame); 345 }
302 if (unlikely(bcs->ignore)) { 346
303 inputstate |= INS_skip_frame; 347 bcs->inputstate = inputstate;
304 skb = NULL; 348 return procbytes;
305 } else { 349}
306 skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); 350
307 if (skb != NULL) { 351/* process DLE escapes
308 skb_reserve(skb, cs->hw_hdr_len); 352 * Called whenever a DLE sequence might be encountered in the input stream.
309 } else { 353 * Either processes the entire DLE sequence or, if that isn't possible,
310 dev_warn(cs->dev, 354 * notes the fact that an initial DLE has been received in the INS_DLE_char
311 "could not allocate new skb\n"); 355 * inputstate flag and resumes processing of the sequence on the next call.
312 inputstate |= INS_skip_frame; 356 */
357static void handle_dle(struct inbuf_t *inbuf)
358{
359 struct cardstate *cs = inbuf->cs;
360
361 if (cs->mstate == MS_LOCKED)
362 return; /* no DLE processing in lock mode */
363
364 if (!(inbuf->inputstate & INS_DLE_char)) {
365 /* no DLE pending */
366 if (inbuf->data[inbuf->head] == DLE_FLAG &&
367 (cs->dle || inbuf->inputstate & INS_DLE_command)) {
368 /* start of DLE sequence */
369 inbuf->head++;
370 if (inbuf->head == inbuf->tail ||
371 inbuf->head == RBUFSIZE) {
372 /* end of buffer, save for later processing */
373 inbuf->inputstate |= INS_DLE_char;
374 return;
313 } 375 }
376 } else {
377 /* regular data byte */
378 return;
314 } 379 }
315 } 380 }
316 381
317 bcs->inputstate = inputstate; 382 /* consume pending DLE */
318 bcs->skb = skb; 383 inbuf->inputstate &= ~INS_DLE_char;
319 return startbytes - numbytes; 384
385 switch (inbuf->data[inbuf->head]) {
386 case 'X': /* begin of event message */
387 if (inbuf->inputstate & INS_command)
388 dev_notice(cs->dev,
389 "received <DLE>X in command mode\n");
390 inbuf->inputstate |= INS_command | INS_DLE_command;
391 inbuf->head++; /* byte consumed */
392 break;
393 case '.': /* end of event message */
394 if (!(inbuf->inputstate & INS_DLE_command))
395 dev_notice(cs->dev,
396 "received <DLE>. without <DLE>X\n");
397 inbuf->inputstate &= ~INS_DLE_command;
398 /* return to data mode if in DLE mode */
399 if (cs->dle)
400 inbuf->inputstate &= ~INS_command;
401 inbuf->head++; /* byte consumed */
402 break;
403 case DLE_FLAG: /* DLE in data stream */
404 /* mark as quoted */
405 inbuf->inputstate |= INS_DLE_char;
406 if (!(cs->dle || inbuf->inputstate & INS_DLE_command))
407 dev_notice(cs->dev,
408 "received <DLE><DLE> not in DLE mode\n");
409 break; /* quoted byte left in buffer */
410 default:
411 dev_notice(cs->dev, "received <DLE><%02x>\n",
412 inbuf->data[inbuf->head]);
413 /* quoted byte left in buffer */
414 }
320} 415}
321 416
322/** 417/**
@@ -330,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
330 */ 425 */
331void gigaset_m10x_input(struct inbuf_t *inbuf) 426void gigaset_m10x_input(struct inbuf_t *inbuf)
332{ 427{
333 struct cardstate *cs; 428 struct cardstate *cs = inbuf->cs;
334 unsigned tail, head, numbytes; 429 unsigned numbytes, procbytes;
335 unsigned char *src, c;
336 int procbytes;
337
338 head = inbuf->head;
339 tail = inbuf->tail;
340 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
341
342 if (head != tail) {
343 cs = inbuf->cs;
344 src = inbuf->data + head;
345 numbytes = (head > tail ? RBUFSIZE : tail) - head;
346 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
347 430
348 while (numbytes) { 431 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail);
349 if (cs->mstate == MS_LOCKED) {
350 procbytes = lock_loop(src, numbytes, inbuf);
351 src += procbytes;
352 numbytes -= procbytes;
353 } else {
354 c = *src++;
355 --numbytes;
356 if (c == DLE_FLAG && (cs->dle ||
357 inbuf->inputstate & INS_DLE_command)) {
358 if (!(inbuf->inputstate & INS_DLE_char)) {
359 inbuf->inputstate |= INS_DLE_char;
360 goto nextbyte;
361 }
362 /* <DLE> <DLE> => <DLE> in data stream */
363 inbuf->inputstate &= ~INS_DLE_char;
364 }
365 432
366 if (!(inbuf->inputstate & INS_DLE_char)) { 433 while (inbuf->head != inbuf->tail) {
367 434 /* check for DLE escape */
368 /* FIXME use function pointers? */ 435 handle_dle(inbuf);
369 if (inbuf->inputstate & INS_command)
370 procbytes = cmd_loop(c, src, numbytes, inbuf);
371 else if (inbuf->bcs->proto2 == L2_HDLC)
372 procbytes = hdlc_loop(c, src, numbytes, inbuf);
373 else
374 procbytes = iraw_loop(c, src, numbytes, inbuf);
375
376 src += procbytes;
377 numbytes -= procbytes;
378 } else { /* DLE char */
379 inbuf->inputstate &= ~INS_DLE_char;
380 switch (c) {
381 case 'X': /*begin of command*/
382 if (inbuf->inputstate & INS_command)
383 dev_warn(cs->dev,
384 "received <DLE> 'X' in command mode\n");
385 inbuf->inputstate |=
386 INS_command | INS_DLE_command;
387 break;
388 case '.': /*end of command*/
389 if (!(inbuf->inputstate & INS_command))
390 dev_warn(cs->dev,
391 "received <DLE> '.' in hdlc mode\n");
392 inbuf->inputstate &= cs->dle ?
393 ~(INS_DLE_command|INS_command)
394 : ~INS_DLE_command;
395 break;
396 //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
397 default:
398 dev_err(cs->dev,
399 "received 0x10 0x%02x!\n",
400 (int) c);
401 /* FIXME: reset driver?? */
402 }
403 }
404 }
405nextbyte:
406 if (!numbytes) {
407 /* end of buffer, check for wrap */
408 if (head > tail) {
409 head = 0;
410 src = inbuf->data;
411 numbytes = tail;
412 } else {
413 head = tail;
414 break;
415 }
416 }
417 }
418 436
419 gig_dbg(DEBUG_INTR, "setting head to %u", head); 437 /* process a contiguous block of bytes */
420 inbuf->head = head; 438 numbytes = (inbuf->head > inbuf->tail ?
439 RBUFSIZE : inbuf->tail) - inbuf->head;
440 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
441 /*
442 * numbytes may be 0 if handle_dle() ate the last byte.
443 * This does no harm, *_loop() will just return 0 immediately.
444 */
445
446 if (cs->mstate == MS_LOCKED)
447 procbytes = lock_loop(numbytes, inbuf);
448 else if (inbuf->inputstate & INS_command)
449 procbytes = cmd_loop(numbytes, inbuf);
450 else if (cs->bcs->proto2 == L2_HDLC)
451 procbytes = hdlc_loop(numbytes, inbuf);
452 else
453 procbytes = iraw_loop(numbytes, inbuf);
454 inbuf->head += procbytes;
455
456 /* check for buffer wraparound */
457 if (inbuf->head >= RBUFSIZE)
458 inbuf->head = 0;
459
460 gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head);
421 } 461 }
422} 462}
423EXPORT_SYMBOL_GPL(gigaset_m10x_input); 463EXPORT_SYMBOL_GPL(gigaset_m10x_input);
@@ -563,6 +603,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb)
563 */ 603 */
564int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) 604int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
565{ 605{
606 struct cardstate *cs = bcs->cs;
566 unsigned len = skb->len; 607 unsigned len = skb->len;
567 unsigned long flags; 608 unsigned long flags;
568 609
@@ -571,16 +612,16 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
571 else 612 else
572 skb = iraw_encode(skb); 613 skb = iraw_encode(skb);
573 if (!skb) { 614 if (!skb) {
574 dev_err(bcs->cs->dev, 615 dev_err(cs->dev,
575 "unable to allocate memory for encoding!\n"); 616 "unable to allocate memory for encoding!\n");
576 return -ENOMEM; 617 return -ENOMEM;
577 } 618 }
578 619
579 skb_queue_tail(&bcs->squeue, skb); 620 skb_queue_tail(&bcs->squeue, skb);
580 spin_lock_irqsave(&bcs->cs->lock, flags); 621 spin_lock_irqsave(&cs->lock, flags);
581 if (bcs->cs->connected) 622 if (cs->connected)
582 tasklet_schedule(&bcs->cs->write_tasklet); 623 tasklet_schedule(&cs->write_tasklet);
583 spin_unlock_irqrestore(&bcs->cs->lock, flags); 624 spin_unlock_irqrestore(&cs->lock, flags);
584 625
585 return len; /* ok so far */ 626 return len; /* ok so far */
586} 627}