1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#undef DEBUG
24#include <linux/usb.h>
25#include "auerchain.h"
26#include <linux/slab.h>
27
28
29static void auerchain_complete(struct urb *urb)
30{
31 unsigned long flags;
32 int result;
33
34
35 struct auerchainelement *acep =
36 (struct auerchainelement *) urb->context;
37 struct auerchain *acp = acep->chain;
38
39
40 urb->context = acep->context;
41 urb->complete = acep->complete;
42
43 dbg("auerchain_complete called");
44
45
46
47
48
49 urb->complete(urb);
50
51
52 spin_lock_irqsave(&acp->lock, flags);
53 if (acp->active != acep)
54 dbg("auerchain_complete: completion on non-active element called!");
55 else
56 acp->active = NULL;
57
58
59 list_add_tail(&acep->list, &acp->free_list);
60 acep = NULL;
61
62
63 if (!acp->active && !list_empty(&acp->waiting_list)) {
64
65 struct list_head *tmp = acp->waiting_list.next;
66 list_del(tmp);
67 acep = list_entry(tmp, struct auerchainelement, list);
68 acp->active = acep;
69 }
70 spin_unlock_irqrestore(&acp->lock, flags);
71
72
73 if (acep) {
74 urb = acep->urbp;
75 dbg("auerchain_complete: submitting next urb from chain");
76 urb->status = 0;
77 result = usb_submit_urb(urb);
78
79
80 if (result) {
81 urb->status = result;
82 dbg("auerchain_complete: usb_submit_urb with error code %d", result);
83
84 auerchain_complete(urb);
85 }
86 } else {
87
88
89 };
90}
91
92
93
94
95
96int auerchain_submit_urb_list(struct auerchain *acp, struct urb *urb,
97 int early)
98{
99 int result;
100 unsigned long flags;
101 struct auerchainelement *acep = NULL;
102
103 dbg("auerchain_submit_urb called");
104
105
106 spin_lock_irqsave(&acp->lock, flags);
107 if (!list_empty(&acp->free_list)) {
108
109 struct list_head *tmp = acp->free_list.next;
110 list_del(tmp);
111 acep = list_entry(tmp, struct auerchainelement, list);
112 }
113 spin_unlock_irqrestore(&acp->lock, flags);
114
115
116 if (!acep) {
117 return -ENOMEM;
118 }
119
120
121 acep->chain = acp;
122 acep->context = urb->context;
123 acep->complete = urb->complete;
124 acep->urbp = urb;
125 INIT_LIST_HEAD(&acep->list);
126
127
128 urb->context = acep;
129 urb->complete = auerchain_complete;
130 urb->status = -EINPROGRESS;
131
132
133 spin_lock_irqsave(&acp->lock, flags);
134 if (acp->active) {
135
136 if (early) {
137 dbg("adding new urb to head of chain");
138 list_add(&acep->list, &acp->waiting_list);
139 } else {
140 dbg("adding new urb to end of chain");
141 list_add_tail(&acep->list, &acp->waiting_list);
142 }
143 acep = NULL;
144 } else {
145
146 acp->active = acep;
147 }
148
149 spin_unlock_irqrestore(&acp->lock, flags);
150
151
152 if (acep) {
153 dbg("submitting urb immediate");
154 urb->status = 0;
155 result = usb_submit_urb(urb);
156
157 if (result) {
158 urb->status = result;
159 dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
160
161 auerchain_complete(urb);
162 }
163 }
164
165 return 0;
166}
167
168
169
170
171int auerchain_submit_urb(struct auerchain *acp, struct urb *urb)
172{
173 return auerchain_submit_urb_list(acp, urb, 0);
174}
175
176
177
178
179
180int auerchain_unlink_urb(struct auerchain *acp, struct urb *urb)
181{
182 unsigned long flags;
183 struct urb *urbp;
184 struct auerchainelement *acep;
185 struct list_head *tmp;
186
187 dbg("auerchain_unlink_urb called");
188
189
190 spin_lock_irqsave(&acp->lock, flags);
191 list_for_each(tmp, &acp->waiting_list) {
192 acep = list_entry(tmp, struct auerchainelement, list);
193 if (acep->urbp == urb) {
194 list_del(tmp);
195 urb->context = acep->context;
196 urb->complete = acep->complete;
197 list_add_tail(&acep->list, &acp->free_list);
198 spin_unlock_irqrestore(&acp->lock, flags);
199 dbg("unlink waiting urb");
200 urb->status = -ENOENT;
201 urb->complete(urb);
202 return 0;
203 }
204 }
205
206 spin_unlock_irqrestore(&acp->lock, flags);
207
208
209 acep = acp->active;
210 if (acep) {
211 urbp = acep->urbp;
212
213
214 if (urbp == urb) {
215
216
217
218
219
220
221 dbg("unlink active urb");
222 return usb_unlink_urb(urbp);
223 }
224 }
225
226
227
228
229 dbg("urb to unlink not found in chain");
230 return 0;
231}
232
233
234
235
236void auerchain_unlink_all(struct auerchain *acp)
237{
238 unsigned long flags;
239 struct urb *urbp;
240 struct auerchainelement *acep;
241
242 dbg("auerchain_unlink_all called");
243
244
245 spin_lock_irqsave(&acp->lock, flags);
246 while (!list_empty(&acp->waiting_list)) {
247
248 struct list_head *tmp = acp->waiting_list.next;
249 list_del(tmp);
250 acep = list_entry(tmp, struct auerchainelement, list);
251 urbp = acep->urbp;
252 urbp->context = acep->context;
253 urbp->complete = acep->complete;
254 list_add_tail(&acep->list, &acp->free_list);
255 spin_unlock_irqrestore(&acp->lock, flags);
256 dbg("unlink waiting urb");
257 urbp->status = -ENOENT;
258 urbp->complete(urbp);
259 spin_lock_irqsave(&acp->lock, flags);
260 }
261 spin_unlock_irqrestore(&acp->lock, flags);
262
263
264 acep = acp->active;
265 if (acep) {
266 urbp = acep->urbp;
267 urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
268 dbg("unlink active urb");
269 usb_unlink_urb(urbp);
270 }
271}
272
273
274
275
276
277void auerchain_free(struct auerchain *acp)
278{
279 unsigned long flags;
280 struct auerchainelement *acep;
281
282 dbg("auerchain_free called");
283
284
285 auerchain_unlink_all(acp);
286
287
288 spin_lock_irqsave(&acp->lock, flags);
289 while (!list_empty(&acp->free_list)) {
290
291 struct list_head *tmp = acp->free_list.next;
292 list_del(tmp);
293 spin_unlock_irqrestore(&acp->lock, flags);
294 acep = list_entry(tmp, struct auerchainelement, list);
295 kfree(acep);
296 spin_lock_irqsave(&acp->lock, flags);
297 }
298 spin_unlock_irqrestore(&acp->lock, flags);
299}
300
301
302
303void auerchain_init(struct auerchain *acp)
304{
305
306 acp->active = NULL;
307 spin_lock_init(&acp->lock);
308 INIT_LIST_HEAD(&acp->waiting_list);
309 INIT_LIST_HEAD(&acp->free_list);
310}
311
312
313
314
315
316int auerchain_setup(struct auerchain *acp, unsigned int numElements)
317{
318 struct auerchainelement *acep;
319
320 dbg("auerchain_setup called with %d elements", numElements);
321
322
323 for (; numElements; numElements--) {
324 acep =
325 (struct auerchainelement *)
326 kmalloc(sizeof(struct auerchainelement), GFP_KERNEL);
327 if (!acep)
328 goto ac_fail;
329 memset(acep, 0, sizeof(struct auerchainelement));
330 INIT_LIST_HEAD(&acep->list);
331 list_add_tail(&acep->list, &acp->free_list);
332 }
333 return 0;
334
335 ac_fail:
336 while (!list_empty(&acp->free_list)) {
337
338 struct list_head *tmp = acp->free_list.next;
339 list_del(tmp);
340 acep = list_entry(tmp, struct auerchainelement, list);
341 kfree(acep);
342 }
343 return -ENOMEM;
344}
345
346
347
348static void auerchain_blocking_completion(struct urb *urb)
349{
350 struct auerchain_chs *pchs = (struct auerchain_chs *) urb->context;
351 pchs->done = 1;
352 wmb();
353 wake_up(&pchs->wqh);
354}
355
356
357
358static int auerchain_start_wait_urb(struct auerchain *acp, struct urb *urb,
359 int timeout, int *actual_length)
360{
361 DECLARE_WAITQUEUE(wait, current);
362 struct auerchain_chs chs;
363 int status;
364
365 dbg("auerchain_start_wait_urb called");
366 init_waitqueue_head(&chs.wqh);
367 chs.done = 0;
368
369 set_current_state(TASK_UNINTERRUPTIBLE);
370 add_wait_queue(&chs.wqh, &wait);
371 urb->context = &chs;
372 status = auerchain_submit_urb(acp, urb);
373 if (status) {
374
375 set_current_state(TASK_RUNNING);
376 remove_wait_queue(&chs.wqh, &wait);
377 return status;
378 }
379
380 while (timeout && !chs.done) {
381 timeout = schedule_timeout(timeout);
382 set_current_state(TASK_UNINTERRUPTIBLE);
383 rmb();
384 }
385
386 set_current_state(TASK_RUNNING);
387 remove_wait_queue(&chs.wqh, &wait);
388
389 if (!timeout && !chs.done) {
390 if (urb->status != -EINPROGRESS) {
391 dbg("auerchain_start_wait_urb: raced timeout");
392 status = urb->status;
393 } else {
394 dbg("auerchain_start_wait_urb: timeout");
395 auerchain_unlink_urb(acp, urb);
396 status = -ETIMEDOUT;
397 }
398 } else
399 status = urb->status;
400
401 if (actual_length)
402 *actual_length = urb->actual_length;
403
404 return status;
405}
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429int auerchain_control_msg(struct auerchain *acp, struct usb_device *dev,
430 unsigned int pipe, __u8 request,
431 __u8 requesttype, __u16 value, __u16 index,
432 void *data, __u16 size, int timeout)
433{
434 int ret;
435 struct usb_ctrlrequest *dr;
436 struct urb *urb;
437 int length;
438
439 dbg("auerchain_control_msg");
440 dr = (struct usb_ctrlrequest *)
441 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
442 if (!dr)
443 return -ENOMEM;
444 urb = usb_alloc_urb(0);
445 if (!urb) {
446 kfree(dr);
447 return -ENOMEM;
448 }
449
450 dr->bRequestType = requesttype;
451 dr->bRequest = request;
452 dr->wValue = cpu_to_le16(value);
453 dr->wIndex = cpu_to_le16(index);
454 dr->wLength = cpu_to_le16(size);
455
456 FILL_CONTROL_URB(urb, dev, pipe, (unsigned char *) dr, data, size,
457 (usb_complete_t) auerchain_blocking_completion,
458 0);
459 ret = auerchain_start_wait_urb(acp, urb, timeout, &length);
460
461 usb_free_urb(urb);
462 kfree(dr);
463
464 if (ret < 0)
465 return ret;
466 else
467 return length;
468}
469