diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 573 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 34 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 13 | ||||
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 69 |
4 files changed, 358 insertions, 331 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 | */ |
25 | static inline int muststuff(unsigned char c) | 25 | static 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 | */ |
42 | static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, | 46 | static 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 | 108 | exit: | |
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 | */ |
94 | static inline int lock_loop(unsigned char *src, int numbytes, | 118 | static 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 | */ | ||
129 | static 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 | */ |
114 | static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, | 155 | static 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 | } |
143 | byte_stuff: | 194 | byte_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 | */ |
259 | static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | 304 | static 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 | */ |
357 | static 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 | */ |
331 | void gigaset_m10x_input(struct inbuf_t *inbuf) | 426 | void 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 | } | ||
405 | nextbyte: | ||
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 | } |
423 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); | 463 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); |
@@ -563,6 +603,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb) | |||
563 | */ | 603 | */ |
564 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) | 604 | int 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 | } |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 1d2ae2e05e0b..690ac74c82a8 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -400,9 +400,9 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
400 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); | 400 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); |
401 | clear_at_state(&bcs->at_state); | 401 | clear_at_state(&bcs->at_state); |
402 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); | 402 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); |
403 | dev_kfree_skb(bcs->skb); | ||
404 | bcs->skb = NULL; | ||
403 | 405 | ||
404 | if (bcs->skb) | ||
405 | dev_kfree_skb(bcs->skb); | ||
406 | for (i = 0; i < AT_NUM; ++i) { | 406 | for (i = 0; i < AT_NUM; ++i) { |
407 | kfree(bcs->commands[i]); | 407 | kfree(bcs->commands[i]); |
408 | bcs->commands[i] = NULL; | 408 | bcs->commands[i] = NULL; |
@@ -560,16 +560,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | |||
560 | } | 560 | } |
561 | 561 | ||
562 | 562 | ||
563 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | 563 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) |
564 | struct cardstate *cs, int inputstate) | ||
565 | /* inbuf->read must be allocated before! */ | 564 | /* inbuf->read must be allocated before! */ |
566 | { | 565 | { |
567 | inbuf->head = 0; | 566 | inbuf->head = 0; |
568 | inbuf->tail = 0; | 567 | inbuf->tail = 0; |
569 | inbuf->cs = cs; | 568 | inbuf->cs = cs; |
570 | inbuf->bcs = bcs; /*base driver: NULL*/ | 569 | inbuf->inputstate = INS_command; |
571 | inbuf->rcvbuf = NULL; | ||
572 | inbuf->inputstate = inputstate; | ||
573 | } | 570 | } |
574 | 571 | ||
575 | /** | 572 | /** |
@@ -644,16 +641,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
644 | bcs->fcs = PPP_INITFCS; | 641 | bcs->fcs = PPP_INITFCS; |
645 | bcs->inputstate = 0; | 642 | bcs->inputstate = 0; |
646 | if (cs->ignoreframes) { | 643 | if (cs->ignoreframes) { |
647 | bcs->inputstate |= INS_skip_frame; | ||
648 | bcs->skb = NULL; | 644 | bcs->skb = NULL; |
649 | } else { | 645 | } else { |
650 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | 646 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
651 | if (bcs->skb != NULL) | 647 | if (bcs->skb != NULL) |
652 | skb_reserve(bcs->skb, cs->hw_hdr_len); | 648 | skb_reserve(bcs->skb, cs->hw_hdr_len); |
653 | else { | 649 | else |
654 | pr_err("out of memory\n"); | 650 | pr_err("out of memory\n"); |
655 | bcs->inputstate |= INS_skip_frame; | ||
656 | } | ||
657 | } | 651 | } |
658 | 652 | ||
659 | bcs->channel = channel; | 653 | bcs->channel = channel; |
@@ -674,8 +668,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
674 | gig_dbg(DEBUG_INIT, " failed"); | 668 | gig_dbg(DEBUG_INIT, " failed"); |
675 | 669 | ||
676 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); | 670 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); |
677 | if (bcs->skb) | 671 | dev_kfree_skb(bcs->skb); |
678 | dev_kfree_skb(bcs->skb); | 672 | bcs->skb = NULL; |
679 | 673 | ||
680 | return NULL; | 674 | return NULL; |
681 | } | 675 | } |
@@ -764,10 +758,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
764 | cs->cbytes = 0; | 758 | cs->cbytes = 0; |
765 | 759 | ||
766 | gig_dbg(DEBUG_INIT, "setting up inbuf"); | 760 | gig_dbg(DEBUG_INIT, "setting up inbuf"); |
767 | if (onechannel) { //FIXME distinction necessary? | 761 | gigaset_inbuf_init(cs->inbuf, cs); |
768 | gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); | ||
769 | } else | ||
770 | gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); | ||
771 | 762 | ||
772 | cs->connected = 0; | 763 | cs->connected = 0; |
773 | cs->isdn_up = 0; | 764 | cs->isdn_up = 0; |
@@ -854,9 +845,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs) | |||
854 | bcs->chstate = 0; | 845 | bcs->chstate = 0; |
855 | 846 | ||
856 | bcs->ignore = cs->ignoreframes; | 847 | bcs->ignore = cs->ignoreframes; |
857 | if (bcs->ignore) | 848 | if (bcs->ignore) { |
858 | bcs->inputstate |= INS_skip_frame; | 849 | dev_kfree_skb(bcs->skb); |
859 | 850 | bcs->skb = NULL; | |
851 | } | ||
860 | 852 | ||
861 | cs->ops->reinitbcshw(bcs); | 853 | cs->ops->reinitbcshw(bcs); |
862 | } | 854 | } |
@@ -877,8 +869,6 @@ static void cleanup_cs(struct cardstate *cs) | |||
877 | free_strings(&cs->at_state); | 869 | free_strings(&cs->at_state); |
878 | gigaset_at_init(&cs->at_state, NULL, cs, 0); | 870 | gigaset_at_init(&cs->at_state, NULL, cs, 0); |
879 | 871 | ||
880 | kfree(cs->inbuf->rcvbuf); | ||
881 | cs->inbuf->rcvbuf = NULL; | ||
882 | cs->inbuf->inputstate = INS_command; | 872 | cs->inbuf->inputstate = INS_command; |
883 | cs->inbuf->head = 0; | 873 | cs->inbuf->head = 0; |
884 | cs->inbuf->tail = 0; | 874 | cs->inbuf->tail = 0; |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index c59216b9c1d0..18bff9f80727 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -223,12 +223,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
223 | #define EV_BC_CLOSED -118 | 223 | #define EV_BC_CLOSED -118 |
224 | 224 | ||
225 | /* input state */ | 225 | /* input state */ |
226 | #define INS_command 0x0001 | 226 | #define INS_command 0x0001 /* receiving messages (not payload data) */ |
227 | #define INS_DLE_char 0x0002 | 227 | #define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ |
228 | #define INS_byte_stuff 0x0004 | 228 | #define INS_byte_stuff 0x0004 |
229 | #define INS_have_data 0x0008 | 229 | #define INS_have_data 0x0008 |
230 | #define INS_skip_frame 0x0010 | 230 | #define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */ |
231 | #define INS_DLE_command 0x0020 | ||
232 | #define INS_flag_hunt 0x0040 | 231 | #define INS_flag_hunt 0x0040 |
233 | 232 | ||
234 | /* channel state */ | 233 | /* channel state */ |
@@ -290,8 +289,6 @@ extern struct reply_t gigaset_tab_cid[]; | |||
290 | extern struct reply_t gigaset_tab_nocid[]; | 289 | extern struct reply_t gigaset_tab_nocid[]; |
291 | 290 | ||
292 | struct inbuf_t { | 291 | struct inbuf_t { |
293 | unsigned char *rcvbuf; /* usb-gigaset receive buffer */ | ||
294 | struct bc_state *bcs; | ||
295 | struct cardstate *cs; | 292 | struct cardstate *cs; |
296 | int inputstate; | 293 | int inputstate; |
297 | int head, tail; | 294 | int head, tail; |
@@ -483,8 +480,8 @@ struct cardstate { | |||
483 | 480 | ||
484 | struct timer_list timer; | 481 | struct timer_list timer; |
485 | int retry_count; | 482 | int retry_count; |
486 | int dle; /* !=0 if modem commands/responses are | 483 | int dle; /* !=0 if DLE mode is active |
487 | dle encoded */ | 484 | (ZDLE=1 received -- M10x only) */ |
488 | int cur_at_seq; /* sequence of AT commands being | 485 | int cur_at_seq; /* sequence of AT commands being |
489 | processed */ | 486 | processed */ |
490 | int curchannel; /* channel those commands are meant | 487 | int curchannel; /* channel those commands are meant |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4deb1ab0dbf8..f56b2a83793e 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
43 | #define GIGASET_MODULENAME "usb_gigaset" | 43 | #define GIGASET_MODULENAME "usb_gigaset" |
44 | #define GIGASET_DEVNAME "ttyGU" | 44 | #define GIGASET_DEVNAME "ttyGU" |
45 | 45 | ||
46 | #define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 | 46 | #define IF_WRITEBUF 2000 /* arbitrary limit */ |
47 | 47 | ||
48 | /* Values for the Gigaset M105 Data */ | 48 | /* Values for the Gigaset M105 Data */ |
49 | #define USB_M105_VENDOR_ID 0x0681 | 49 | #define USB_M105_VENDOR_ID 0x0681 |
50 | #define USB_M105_PRODUCT_ID 0x0009 | 50 | #define USB_M105_PRODUCT_ID 0x0009 |
51 | 51 | ||
52 | /* table of devices that work with this driver */ | 52 | /* table of devices that work with this driver */ |
53 | static const struct usb_device_id gigaset_table [] = { | 53 | static const struct usb_device_id gigaset_table[] = { |
54 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, | 54 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, |
55 | { } /* Terminating entry */ | 55 | { } /* Terminating entry */ |
56 | }; | 56 | }; |
@@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
97 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 | 97 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 |
98 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). | 98 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). |
99 | * xx is usually 0x00 but was 0x7e before starting data transfer | 99 | * xx is usually 0x00 but was 0x7e before starting data transfer |
100 | * in unimodem mode. So, this might be an array of characters that need | 100 | * in unimodem mode. So, this might be an array of characters that |
101 | * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. | 101 | * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. |
102 | * | 102 | * |
103 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two | 103 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two |
104 | * flags per packet. | 104 | * flags per packet. |
@@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | |||
114 | static int gigaset_resume(struct usb_interface *intf); | 114 | static int gigaset_resume(struct usb_interface *intf); |
115 | static int gigaset_pre_reset(struct usb_interface *intf); | 115 | static int gigaset_pre_reset(struct usb_interface *intf); |
116 | 116 | ||
117 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver; |
118 | 118 | ||
119 | /* usb specific object needed to register this driver with the usb subsystem */ | 119 | /* usb specific object needed to register this driver with the usb subsystem */ |
120 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -141,6 +141,7 @@ struct usb_cardstate { | |||
141 | struct urb *bulk_out_urb; | 141 | struct urb *bulk_out_urb; |
142 | 142 | ||
143 | /* Input buffer */ | 143 | /* Input buffer */ |
144 | unsigned char *rcvbuf; | ||
144 | int rcvbuf_size; | 145 | int rcvbuf_size; |
145 | struct urb *read_urb; | 146 | struct urb *read_urb; |
146 | __u8 int_in_endpointAddr; | 147 | __u8 int_in_endpointAddr; |
@@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, | |||
164 | val = tiocm_to_gigaset(new_state); | 165 | val = tiocm_to_gigaset(new_state); |
165 | 166 | ||
166 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); | 167 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); |
167 | // don't use this in an interrupt/BH | ||
168 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, | 168 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, |
169 | (val & 0xff) | ((mask & 0xff) << 8), 0, | 169 | (val & 0xff) | ((mask & 0xff) << 8), 0, |
170 | NULL, 0, 2000 /* timeout? */); | 170 | NULL, 0, 2000 /* timeout? */); |
171 | if (r < 0) | 171 | if (r < 0) |
172 | return r; | 172 | return r; |
173 | //.. | ||
174 | return 0; | 173 | return 0; |
175 | } | 174 | } |
176 | 175 | ||
@@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) | |||
220 | cflag &= CBAUD; | 219 | cflag &= CBAUD; |
221 | 220 | ||
222 | switch (cflag) { | 221 | switch (cflag) { |
223 | //FIXME more values? | ||
224 | case B300: rate = 300; break; | 222 | case B300: rate = 300; break; |
225 | case B600: rate = 600; break; | 223 | case B600: rate = 600; break; |
226 | case B1200: rate = 1200; break; | 224 | case B1200: rate = 1200; break; |
@@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
273 | /* set the number of stop bits */ | 271 | /* set the number of stop bits */ |
274 | if (cflag & CSTOPB) { | 272 | if (cflag & CSTOPB) { |
275 | if ((cflag & CSIZE) == CS5) | 273 | if ((cflag & CSIZE) == CS5) |
276 | val |= 1; /* 1.5 stop bits */ //FIXME is this okay? | 274 | val |= 1; /* 1.5 stop bits */ |
277 | else | 275 | else |
278 | val |= 2; /* 2 stop bits */ | 276 | val |= 2; /* 2 stop bits */ |
279 | } | 277 | } |
@@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
282 | } | 280 | } |
283 | 281 | ||
284 | 282 | ||
285 | /*================================================================================================================*/ | 283 | /*============================================================================*/ |
286 | static int gigaset_init_bchannel(struct bc_state *bcs) | 284 | static int gigaset_init_bchannel(struct bc_state *bcs) |
287 | { | 285 | { |
288 | /* nothing to do for M10x */ | 286 | /* nothing to do for M10x */ |
@@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data) | |||
344 | if (write_modem(cs) < 0) { | 342 | if (write_modem(cs) < 0) { |
345 | gig_dbg(DEBUG_OUTPUT, | 343 | gig_dbg(DEBUG_OUTPUT, |
346 | "modem_fill: write_modem failed"); | 344 | "modem_fill: write_modem failed"); |
347 | // FIXME should we tell the LL? | ||
348 | again = 1; /* no callback will be called! */ | 345 | again = 1; /* no callback will be called! */ |
349 | } | 346 | } |
350 | } | 347 | } |
@@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data) | |||
356 | */ | 353 | */ |
357 | static void gigaset_read_int_callback(struct urb *urb) | 354 | static void gigaset_read_int_callback(struct urb *urb) |
358 | { | 355 | { |
359 | struct inbuf_t *inbuf = urb->context; | 356 | struct cardstate *cs = urb->context; |
360 | struct cardstate *cs = inbuf->cs; | 357 | struct inbuf_t *inbuf = cs->inbuf; |
361 | int status = urb->status; | 358 | int status = urb->status; |
362 | int r; | 359 | int r; |
363 | unsigned numbytes; | 360 | unsigned numbytes; |
@@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
368 | numbytes = urb->actual_length; | 365 | numbytes = urb->actual_length; |
369 | 366 | ||
370 | if (numbytes) { | 367 | if (numbytes) { |
371 | src = inbuf->rcvbuf; | 368 | src = cs->hw.usb->rcvbuf; |
372 | if (unlikely(*src)) | 369 | if (unlikely(*src)) |
373 | dev_warn(cs->dev, | 370 | dev_warn(cs->dev, |
374 | "%s: There was no leading 0, but 0x%02x!\n", | 371 | "%s: There was no leading 0, but 0x%02x!\n", |
@@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
440 | struct cmdbuf_t *tcb; | 437 | struct cmdbuf_t *tcb; |
441 | unsigned long flags; | 438 | unsigned long flags; |
442 | int count; | 439 | int count; |
443 | int status = -ENOENT; // FIXME | 440 | int status = -ENOENT; |
444 | struct usb_cardstate *ucs = cs->hw.usb; | 441 | struct usb_cardstate *ucs = cs->hw.usb; |
445 | 442 | ||
446 | do { | 443 | do { |
@@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
480 | ucs->busy = 1; | 477 | ucs->busy = 1; |
481 | 478 | ||
482 | spin_lock_irqsave(&cs->lock, flags); | 479 | spin_lock_irqsave(&cs->lock, flags); |
483 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 480 | status = cs->connected ? |
481 | usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : | ||
482 | -ENODEV; | ||
484 | spin_unlock_irqrestore(&cs->lock, flags); | 483 | spin_unlock_irqrestore(&cs->lock, flags); |
485 | 484 | ||
486 | if (status) { | 485 | if (status) { |
@@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
510 | 509 | ||
511 | if (len <= 0) | 510 | if (len <= 0) |
512 | return 0; | 511 | return 0; |
513 | 512 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); | |
514 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 513 | if (!cb) { |
515 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 514 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
516 | return -ENOMEM; | 515 | return -ENOMEM; |
517 | } | 516 | } |
@@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs) | |||
637 | return -EINVAL; | 636 | return -EINVAL; |
638 | } | 637 | } |
639 | 638 | ||
640 | /* Copy data to bulk out buffer and // FIXME copying not necessary | 639 | /* Copy data to bulk out buffer and transmit data */ |
641 | * transmit data | ||
642 | */ | ||
643 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 640 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
644 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 641 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
645 | skb_pull(bcs->tx_skb, count); | 642 | skb_pull(bcs->tx_skb, count); |
@@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs) | |||
650 | if (cs->connected) { | 647 | if (cs->connected) { |
651 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, | 648 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, |
652 | usb_sndbulkpipe(ucs->udev, | 649 | usb_sndbulkpipe(ucs->udev, |
653 | ucs->bulk_out_endpointAddr & 0x0f), | 650 | ucs->bulk_out_endpointAddr & |
651 | 0x0f), | ||
654 | ucs->bulk_out_buffer, count, | 652 | ucs->bulk_out_buffer, count, |
655 | gigaset_write_bulk_callback, cs); | 653 | gigaset_write_bulk_callback, cs); |
656 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); | 654 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); |
@@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs) | |||
666 | 664 | ||
667 | if (!bcs->tx_skb->len) { | 665 | if (!bcs->tx_skb->len) { |
668 | /* skb sent completely */ | 666 | /* skb sent completely */ |
669 | gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? | 667 | gigaset_skb_sent(bcs, bcs->tx_skb); |
670 | 668 | ||
671 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", | 669 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", |
672 | (unsigned long) bcs->tx_skb); | 670 | (unsigned long) bcs->tx_skb); |
@@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
763 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 761 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
764 | ucs->rcvbuf_size = buffer_size; | 762 | ucs->rcvbuf_size = buffer_size; |
765 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; | 763 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; |
766 | cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); | 764 | ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); |
767 | if (!cs->inbuf[0].rcvbuf) { | 765 | if (!ucs->rcvbuf) { |
768 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); | 766 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); |
769 | retval = -ENOMEM; | 767 | retval = -ENOMEM; |
770 | goto error; | 768 | goto error; |
@@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface, | |||
773 | usb_fill_int_urb(ucs->read_urb, udev, | 771 | usb_fill_int_urb(ucs->read_urb, udev, |
774 | usb_rcvintpipe(udev, | 772 | usb_rcvintpipe(udev, |
775 | endpoint->bEndpointAddress & 0x0f), | 773 | endpoint->bEndpointAddress & 0x0f), |
776 | cs->inbuf[0].rcvbuf, buffer_size, | 774 | ucs->rcvbuf, buffer_size, |
777 | gigaset_read_int_callback, | 775 | gigaset_read_int_callback, |
778 | cs->inbuf + 0, endpoint->bInterval); | 776 | cs, endpoint->bInterval); |
779 | 777 | ||
780 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); | 778 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); |
781 | if (retval) { | 779 | if (retval) { |
@@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
789 | 787 | ||
790 | if (!gigaset_start(cs)) { | 788 | if (!gigaset_start(cs)) { |
791 | tasklet_kill(&cs->write_tasklet); | 789 | tasklet_kill(&cs->write_tasklet); |
792 | retval = -ENODEV; //FIXME | 790 | retval = -ENODEV; |
793 | goto error; | 791 | goto error; |
794 | } | 792 | } |
795 | return 0; | 793 | return 0; |
@@ -798,11 +796,11 @@ error: | |||
798 | usb_kill_urb(ucs->read_urb); | 796 | usb_kill_urb(ucs->read_urb); |
799 | kfree(ucs->bulk_out_buffer); | 797 | kfree(ucs->bulk_out_buffer); |
800 | usb_free_urb(ucs->bulk_out_urb); | 798 | usb_free_urb(ucs->bulk_out_urb); |
801 | kfree(cs->inbuf[0].rcvbuf); | 799 | kfree(ucs->rcvbuf); |
802 | usb_free_urb(ucs->read_urb); | 800 | usb_free_urb(ucs->read_urb); |
803 | usb_set_intfdata(interface, NULL); | 801 | usb_set_intfdata(interface, NULL); |
804 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 802 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
805 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 803 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
806 | usb_put_dev(ucs->udev); | 804 | usb_put_dev(ucs->udev); |
807 | ucs->udev = NULL; | 805 | ucs->udev = NULL; |
808 | ucs->interface = NULL; | 806 | ucs->interface = NULL; |
@@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | 829 | ||
832 | kfree(ucs->bulk_out_buffer); | 830 | kfree(ucs->bulk_out_buffer); |
833 | usb_free_urb(ucs->bulk_out_urb); | 831 | usb_free_urb(ucs->bulk_out_urb); |
834 | kfree(cs->inbuf[0].rcvbuf); | 832 | kfree(ucs->rcvbuf); |
835 | usb_free_urb(ucs->read_urb); | 833 | usb_free_urb(ucs->read_urb); |
836 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 834 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
837 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 835 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
838 | 836 | ||
839 | usb_put_dev(ucs->udev); | 837 | usb_put_dev(ucs->udev); |
840 | ucs->interface = NULL; | 838 | ucs->interface = NULL; |
@@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void) | |||
916 | int result; | 914 | int result; |
917 | 915 | ||
918 | /* allocate memory for our driver state and intialize it */ | 916 | /* allocate memory for our driver state and intialize it */ |
919 | if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 917 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
920 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 918 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
921 | &ops, THIS_MODULE)) == NULL) | 919 | &ops, THIS_MODULE); |
920 | if (driver == NULL) | ||
922 | goto error; | 921 | goto error; |
923 | 922 | ||
924 | /* register this driver with the USB subsystem */ | 923 | /* register this driver with the USB subsystem */ |