1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de> |
4 | */ |
5 | |
6 | #include <linux/usb.h> |
7 | #include <linux/gfp.h> |
8 | |
9 | #include "usb_stream.h" |
10 | |
11 | /* setup */ |
12 | |
13 | static unsigned int usb_stream_next_packet_size(struct usb_stream_kernel *sk) |
14 | { |
15 | struct usb_stream *s = sk->s; |
16 | |
17 | sk->out_phase_peeked = (sk->out_phase & 0xffff) + sk->freqn; |
18 | return (sk->out_phase_peeked >> 16) * s->cfg.frame_size; |
19 | } |
20 | |
21 | static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) |
22 | { |
23 | struct usb_stream *s = sk->s; |
24 | int pack, lb = 0; |
25 | |
26 | for (pack = 0; pack < sk->n_o_ps; pack++) { |
27 | int l = usb_stream_next_packet_size(sk); |
28 | |
29 | if (s->idle_outsize + lb + l > s->period_size) |
30 | goto check; |
31 | |
32 | sk->out_phase = sk->out_phase_peeked; |
33 | urb->iso_frame_desc[pack].offset = lb; |
34 | urb->iso_frame_desc[pack].length = l; |
35 | lb += l; |
36 | } |
37 | snd_printdd(KERN_DEBUG "%i\n" , lb); |
38 | |
39 | check: |
40 | urb->number_of_packets = pack; |
41 | urb->transfer_buffer_length = lb; |
42 | s->idle_outsize += lb - s->period_size; |
43 | snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n" , s->idle_outsize, |
44 | lb, s->period_size); |
45 | } |
46 | |
47 | static int init_pipe_urbs(struct usb_stream_kernel *sk, |
48 | unsigned int use_packsize, |
49 | struct urb **urbs, char *transfer, |
50 | struct usb_device *dev, int pipe) |
51 | { |
52 | int u, p; |
53 | int maxpacket = use_packsize ? |
54 | use_packsize : usb_maxpacket(udev: dev, pipe); |
55 | int transfer_length = maxpacket * sk->n_o_ps; |
56 | |
57 | for (u = 0; u < USB_STREAM_NURBS; |
58 | ++u, transfer += transfer_length) { |
59 | struct urb *urb = urbs[u]; |
60 | struct usb_iso_packet_descriptor *desc; |
61 | |
62 | urb->transfer_buffer = transfer; |
63 | urb->dev = dev; |
64 | urb->pipe = pipe; |
65 | urb->number_of_packets = sk->n_o_ps; |
66 | urb->context = sk; |
67 | urb->interval = 1; |
68 | if (usb_pipeout(pipe)) |
69 | continue; |
70 | if (usb_urb_ep_type_check(urb)) |
71 | return -EINVAL; |
72 | |
73 | urb->transfer_buffer_length = transfer_length; |
74 | desc = urb->iso_frame_desc; |
75 | desc->offset = 0; |
76 | desc->length = maxpacket; |
77 | for (p = 1; p < sk->n_o_ps; ++p) { |
78 | desc[p].offset = desc[p - 1].offset + maxpacket; |
79 | desc[p].length = maxpacket; |
80 | } |
81 | } |
82 | |
83 | return 0; |
84 | } |
85 | |
86 | static int init_urbs(struct usb_stream_kernel *sk, unsigned int use_packsize, |
87 | struct usb_device *dev, int in_pipe, int out_pipe) |
88 | { |
89 | struct usb_stream *s = sk->s; |
90 | char *indata = |
91 | (char *)s + sizeof(*s) + sizeof(struct usb_stream_packet) * s->inpackets; |
92 | int u; |
93 | |
94 | for (u = 0; u < USB_STREAM_NURBS; ++u) { |
95 | sk->inurb[u] = usb_alloc_urb(iso_packets: sk->n_o_ps, GFP_KERNEL); |
96 | if (!sk->inurb[u]) |
97 | return -ENOMEM; |
98 | |
99 | sk->outurb[u] = usb_alloc_urb(iso_packets: sk->n_o_ps, GFP_KERNEL); |
100 | if (!sk->outurb[u]) |
101 | return -ENOMEM; |
102 | } |
103 | |
104 | if (init_pipe_urbs(sk, use_packsize, urbs: sk->inurb, transfer: indata, dev, pipe: in_pipe) || |
105 | init_pipe_urbs(sk, use_packsize, urbs: sk->outurb, transfer: sk->write_page, dev, |
106 | pipe: out_pipe)) |
107 | return -EINVAL; |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | /* |
113 | * convert a sampling rate into our full speed format (fs/1000 in Q16.16) |
114 | * this will overflow at approx 524 kHz |
115 | */ |
116 | static inline unsigned int get_usb_full_speed_rate(unsigned int rate) |
117 | { |
118 | return ((rate << 13) + 62) / 125; |
119 | } |
120 | |
121 | /* |
122 | * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) |
123 | * this will overflow at approx 4 MHz |
124 | */ |
125 | static inline unsigned int get_usb_high_speed_rate(unsigned int rate) |
126 | { |
127 | return ((rate << 10) + 62) / 125; |
128 | } |
129 | |
130 | void usb_stream_free(struct usb_stream_kernel *sk) |
131 | { |
132 | struct usb_stream *s; |
133 | unsigned int u; |
134 | |
135 | for (u = 0; u < USB_STREAM_NURBS; ++u) { |
136 | usb_free_urb(urb: sk->inurb[u]); |
137 | sk->inurb[u] = NULL; |
138 | usb_free_urb(urb: sk->outurb[u]); |
139 | sk->outurb[u] = NULL; |
140 | } |
141 | |
142 | s = sk->s; |
143 | if (!s) |
144 | return; |
145 | |
146 | if (sk->write_page) { |
147 | free_pages_exact(virt: sk->write_page, size: s->write_size); |
148 | sk->write_page = NULL; |
149 | } |
150 | |
151 | free_pages_exact(virt: s, size: s->read_size); |
152 | sk->s = NULL; |
153 | } |
154 | |
155 | struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, |
156 | struct usb_device *dev, |
157 | unsigned int in_endpoint, |
158 | unsigned int out_endpoint, |
159 | unsigned int sample_rate, |
160 | unsigned int use_packsize, |
161 | unsigned int period_frames, |
162 | unsigned int frame_size) |
163 | { |
164 | int packets, max_packsize; |
165 | int in_pipe, out_pipe; |
166 | int read_size = sizeof(struct usb_stream); |
167 | int write_size; |
168 | int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000; |
169 | |
170 | in_pipe = usb_rcvisocpipe(dev, in_endpoint); |
171 | out_pipe = usb_sndisocpipe(dev, out_endpoint); |
172 | |
173 | max_packsize = use_packsize ? |
174 | use_packsize : usb_maxpacket(udev: dev, pipe: in_pipe); |
175 | |
176 | /* |
177 | t_period = period_frames / sample_rate |
178 | iso_packs = t_period / t_iso_frame |
179 | = (period_frames / sample_rate) * (1 / t_iso_frame) |
180 | */ |
181 | |
182 | packets = period_frames * usb_frames / sample_rate + 1; |
183 | |
184 | if (dev->speed == USB_SPEED_HIGH) |
185 | packets = (packets + 7) & ~7; |
186 | |
187 | read_size += packets * USB_STREAM_URBDEPTH * |
188 | (max_packsize + sizeof(struct usb_stream_packet)); |
189 | |
190 | max_packsize = usb_maxpacket(udev: dev, pipe: out_pipe); |
191 | write_size = max_packsize * packets * USB_STREAM_URBDEPTH; |
192 | |
193 | if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) { |
194 | snd_printk(KERN_WARNING "a size exceeds 128*PAGE_SIZE\n" ); |
195 | goto out; |
196 | } |
197 | |
198 | sk->s = alloc_pages_exact(size: read_size, |
199 | GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); |
200 | if (!sk->s) { |
201 | pr_warn("us122l: couldn't allocate read buffer\n" ); |
202 | goto out; |
203 | } |
204 | sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; |
205 | |
206 | sk->s->read_size = read_size; |
207 | |
208 | sk->s->cfg.sample_rate = sample_rate; |
209 | sk->s->cfg.frame_size = frame_size; |
210 | sk->n_o_ps = packets; |
211 | sk->s->inpackets = packets * USB_STREAM_URBDEPTH; |
212 | sk->s->cfg.period_frames = period_frames; |
213 | sk->s->period_size = frame_size * period_frames; |
214 | |
215 | sk->s->write_size = write_size; |
216 | |
217 | sk->write_page = alloc_pages_exact(size: write_size, |
218 | GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); |
219 | if (!sk->write_page) { |
220 | pr_warn("us122l: couldn't allocate write buffer\n" ); |
221 | usb_stream_free(sk); |
222 | return NULL; |
223 | } |
224 | |
225 | /* calculate the frequency in 16.16 format */ |
226 | if (dev->speed == USB_SPEED_FULL) |
227 | sk->freqn = get_usb_full_speed_rate(rate: sample_rate); |
228 | else |
229 | sk->freqn = get_usb_high_speed_rate(rate: sample_rate); |
230 | |
231 | if (init_urbs(sk, use_packsize, dev, in_pipe, out_pipe) < 0) { |
232 | usb_stream_free(sk); |
233 | return NULL; |
234 | } |
235 | |
236 | sk->s->state = usb_stream_stopped; |
237 | out: |
238 | return sk->s; |
239 | } |
240 | |
241 | /* start */ |
242 | |
243 | static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb) |
244 | { |
245 | bool r; |
246 | |
247 | if (unlikely(urb->status)) { |
248 | if (urb->status != -ESHUTDOWN && urb->status != -ENOENT) |
249 | snd_printk(KERN_WARNING "status=%i\n" , urb->status); |
250 | sk->iso_frame_balance = 0x7FFFFFFF; |
251 | return false; |
252 | } |
253 | r = sk->iso_frame_balance == 0; |
254 | if (!r) |
255 | sk->i_urb = urb; |
256 | return r; |
257 | } |
258 | |
259 | static bool balance_playback(struct usb_stream_kernel *sk, struct urb *urb) |
260 | { |
261 | sk->iso_frame_balance += urb->number_of_packets; |
262 | return balance_check(sk, urb); |
263 | } |
264 | |
265 | static bool balance_capture(struct usb_stream_kernel *sk, struct urb *urb) |
266 | { |
267 | sk->iso_frame_balance -= urb->number_of_packets; |
268 | return balance_check(sk, urb); |
269 | } |
270 | |
271 | static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) |
272 | { |
273 | int u; |
274 | |
275 | for (u = 0; u < USB_STREAM_NURBS; u++) { |
276 | struct urb *urb = urbs[u]; |
277 | |
278 | urb->complete = complete; |
279 | } |
280 | } |
281 | |
282 | static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, |
283 | struct urb *inurb) |
284 | { |
285 | struct usb_stream *s = sk->s; |
286 | struct urb *io; |
287 | struct usb_iso_packet_descriptor *id, *od; |
288 | int p = 0, lb = 0, l = 0; |
289 | |
290 | io = sk->idle_outurb; |
291 | od = io->iso_frame_desc; |
292 | |
293 | for (; s->sync_packet < 0; ++p, ++s->sync_packet) { |
294 | struct urb *ii = sk->completed_inurb; |
295 | |
296 | id = ii->iso_frame_desc + |
297 | ii->number_of_packets + s->sync_packet; |
298 | l = id->actual_length; |
299 | |
300 | od[p].length = l; |
301 | od[p].offset = lb; |
302 | lb += l; |
303 | } |
304 | |
305 | for (; |
306 | s->sync_packet < inurb->number_of_packets && p < sk->n_o_ps; |
307 | ++p, ++s->sync_packet) { |
308 | l = inurb->iso_frame_desc[s->sync_packet].actual_length; |
309 | |
310 | if (s->idle_outsize + lb + l > s->period_size) |
311 | goto check_ok; |
312 | |
313 | od[p].length = l; |
314 | od[p].offset = lb; |
315 | lb += l; |
316 | } |
317 | |
318 | check_ok: |
319 | s->sync_packet -= inurb->number_of_packets; |
320 | if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) { |
321 | snd_printk(KERN_WARNING "invalid sync_packet = %i;" |
322 | " p=%i nop=%i %i %x %x %x > %x\n" , |
323 | s->sync_packet, p, inurb->number_of_packets, |
324 | s->idle_outsize + lb + l, |
325 | s->idle_outsize, lb, l, |
326 | s->period_size); |
327 | return -1; |
328 | } |
329 | if (unlikely(lb % s->cfg.frame_size)) { |
330 | snd_printk(KERN_WARNING"invalid outsize = %i\n" , |
331 | lb); |
332 | return -1; |
333 | } |
334 | s->idle_outsize += lb - s->period_size; |
335 | io->number_of_packets = p; |
336 | io->transfer_buffer_length = lb; |
337 | if (s->idle_outsize <= 0) |
338 | return 0; |
339 | |
340 | snd_printk(KERN_WARNING "idle=%i\n" , s->idle_outsize); |
341 | return -1; |
342 | } |
343 | |
344 | static void prepare_inurb(int number_of_packets, struct urb *iu) |
345 | { |
346 | struct usb_iso_packet_descriptor *id; |
347 | int p; |
348 | |
349 | iu->number_of_packets = number_of_packets; |
350 | id = iu->iso_frame_desc; |
351 | id->offset = 0; |
352 | for (p = 0; p < iu->number_of_packets - 1; ++p) |
353 | id[p + 1].offset = id[p].offset + id[p].length; |
354 | |
355 | iu->transfer_buffer_length = |
356 | id[0].length * iu->number_of_packets; |
357 | } |
358 | |
359 | static int submit_urbs(struct usb_stream_kernel *sk, |
360 | struct urb *inurb, struct urb *outurb) |
361 | { |
362 | int err; |
363 | |
364 | prepare_inurb(number_of_packets: sk->idle_outurb->number_of_packets, iu: sk->idle_inurb); |
365 | err = usb_submit_urb(urb: sk->idle_inurb, GFP_ATOMIC); |
366 | if (err < 0) |
367 | goto report_failure; |
368 | |
369 | sk->idle_inurb = sk->completed_inurb; |
370 | sk->completed_inurb = inurb; |
371 | err = usb_submit_urb(urb: sk->idle_outurb, GFP_ATOMIC); |
372 | if (err < 0) |
373 | goto report_failure; |
374 | |
375 | sk->idle_outurb = sk->completed_outurb; |
376 | sk->completed_outurb = outurb; |
377 | return 0; |
378 | |
379 | report_failure: |
380 | snd_printk(KERN_ERR "%i\n" , err); |
381 | return err; |
382 | } |
383 | |
384 | #ifdef DEBUG_LOOP_BACK |
385 | /* |
386 | This loop_back() shows how to read/write the period data. |
387 | */ |
388 | static void loop_back(struct usb_stream *s) |
389 | { |
390 | char *i, *o; |
391 | int il, ol, l, p; |
392 | struct urb *iu; |
393 | struct usb_iso_packet_descriptor *id; |
394 | |
395 | o = s->playback1st_to; |
396 | ol = s->playback1st_size; |
397 | l = 0; |
398 | |
399 | if (s->insplit_pack >= 0) { |
400 | iu = sk->idle_inurb; |
401 | id = iu->iso_frame_desc; |
402 | p = s->insplit_pack; |
403 | } else |
404 | goto second; |
405 | loop: |
406 | for (; p < iu->number_of_packets && l < s->period_size; ++p) { |
407 | i = iu->transfer_buffer + id[p].offset; |
408 | il = id[p].actual_length; |
409 | if (l + il > s->period_size) |
410 | il = s->period_size - l; |
411 | if (il <= ol) { |
412 | memcpy(o, i, il); |
413 | o += il; |
414 | ol -= il; |
415 | } else { |
416 | memcpy(o, i, ol); |
417 | singen_6pack(o, ol); |
418 | o = s->playback_to; |
419 | memcpy(o, i + ol, il - ol); |
420 | o += il - ol; |
421 | ol = s->period_size - s->playback1st_size; |
422 | } |
423 | l += il; |
424 | } |
425 | if (iu == sk->completed_inurb) { |
426 | if (l != s->period_size) |
427 | printk(KERN_DEBUG"%s:%i %i\n" , __func__, __LINE__, |
428 | l/(int)s->cfg.frame_size); |
429 | |
430 | return; |
431 | } |
432 | second: |
433 | iu = sk->completed_inurb; |
434 | id = iu->iso_frame_desc; |
435 | p = 0; |
436 | goto loop; |
437 | |
438 | } |
439 | #else |
440 | static void loop_back(struct usb_stream *s) |
441 | { |
442 | } |
443 | #endif |
444 | |
445 | static void stream_idle(struct usb_stream_kernel *sk, |
446 | struct urb *inurb, struct urb *outurb) |
447 | { |
448 | struct usb_stream *s = sk->s; |
449 | int l, p; |
450 | int insize = s->idle_insize; |
451 | int urb_size = 0; |
452 | |
453 | s->inpacket_split = s->next_inpacket_split; |
454 | s->inpacket_split_at = s->next_inpacket_split_at; |
455 | s->next_inpacket_split = -1; |
456 | s->next_inpacket_split_at = 0; |
457 | |
458 | for (p = 0; p < inurb->number_of_packets; ++p) { |
459 | struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc; |
460 | |
461 | l = id[p].actual_length; |
462 | if (unlikely(l == 0 || id[p].status)) { |
463 | snd_printk(KERN_WARNING "underrun, status=%u\n" , |
464 | id[p].status); |
465 | goto err_out; |
466 | } |
467 | s->inpacket_head++; |
468 | s->inpacket_head %= s->inpackets; |
469 | if (s->inpacket_split == -1) |
470 | s->inpacket_split = s->inpacket_head; |
471 | |
472 | s->inpacket[s->inpacket_head].offset = |
473 | id[p].offset + (inurb->transfer_buffer - (void *)s); |
474 | s->inpacket[s->inpacket_head].length = l; |
475 | if (insize + l > s->period_size && |
476 | s->next_inpacket_split == -1) { |
477 | s->next_inpacket_split = s->inpacket_head; |
478 | s->next_inpacket_split_at = s->period_size - insize; |
479 | } |
480 | insize += l; |
481 | urb_size += l; |
482 | } |
483 | s->idle_insize += urb_size - s->period_size; |
484 | if (s->idle_insize < 0) { |
485 | snd_printk(KERN_WARNING "%i\n" , |
486 | (s->idle_insize)/(int)s->cfg.frame_size); |
487 | goto err_out; |
488 | } |
489 | s->insize_done += urb_size; |
490 | |
491 | l = s->idle_outsize; |
492 | s->outpacket[0].offset = (sk->idle_outurb->transfer_buffer - |
493 | sk->write_page) - l; |
494 | |
495 | if (usb_stream_prepare_playback(sk, inurb) < 0) |
496 | goto err_out; |
497 | |
498 | s->outpacket[0].length = sk->idle_outurb->transfer_buffer_length + l; |
499 | s->outpacket[1].offset = sk->completed_outurb->transfer_buffer - |
500 | sk->write_page; |
501 | |
502 | if (submit_urbs(sk, inurb, outurb) < 0) |
503 | goto err_out; |
504 | |
505 | loop_back(s); |
506 | s->periods_done++; |
507 | wake_up_all(&sk->sleep); |
508 | return; |
509 | err_out: |
510 | s->state = usb_stream_xrun; |
511 | wake_up_all(&sk->sleep); |
512 | } |
513 | |
514 | static void i_capture_idle(struct urb *urb) |
515 | { |
516 | struct usb_stream_kernel *sk = urb->context; |
517 | |
518 | if (balance_capture(sk, urb)) |
519 | stream_idle(sk, inurb: urb, outurb: sk->i_urb); |
520 | } |
521 | |
522 | static void i_playback_idle(struct urb *urb) |
523 | { |
524 | struct usb_stream_kernel *sk = urb->context; |
525 | |
526 | if (balance_playback(sk, urb)) |
527 | stream_idle(sk, inurb: sk->i_urb, outurb: urb); |
528 | } |
529 | |
530 | static void stream_start(struct usb_stream_kernel *sk, |
531 | struct urb *inurb, struct urb *outurb) |
532 | { |
533 | struct usb_stream *s = sk->s; |
534 | |
535 | if (s->state >= usb_stream_sync1) { |
536 | int l, p, max_diff, max_diff_0; |
537 | int urb_size = 0; |
538 | unsigned int frames_per_packet, min_frames = 0; |
539 | |
540 | frames_per_packet = (s->period_size - s->idle_insize); |
541 | frames_per_packet <<= 8; |
542 | frames_per_packet /= |
543 | s->cfg.frame_size * inurb->number_of_packets; |
544 | frames_per_packet++; |
545 | |
546 | max_diff_0 = s->cfg.frame_size; |
547 | if (s->cfg.period_frames >= 256) |
548 | max_diff_0 <<= 1; |
549 | if (s->cfg.period_frames >= 1024) |
550 | max_diff_0 <<= 1; |
551 | max_diff = max_diff_0; |
552 | for (p = 0; p < inurb->number_of_packets; ++p) { |
553 | int diff; |
554 | |
555 | l = inurb->iso_frame_desc[p].actual_length; |
556 | urb_size += l; |
557 | |
558 | min_frames += frames_per_packet; |
559 | diff = urb_size - |
560 | (min_frames >> 8) * s->cfg.frame_size; |
561 | if (diff < max_diff) { |
562 | snd_printdd(KERN_DEBUG "%i %i %i %i\n" , |
563 | s->insize_done, |
564 | urb_size / (int)s->cfg.frame_size, |
565 | inurb->number_of_packets, diff); |
566 | max_diff = diff; |
567 | } |
568 | } |
569 | s->idle_insize -= max_diff - max_diff_0; |
570 | s->idle_insize += urb_size - s->period_size; |
571 | if (s->idle_insize < 0) { |
572 | snd_printk(KERN_WARNING "%i %i %i\n" , |
573 | s->idle_insize, urb_size, s->period_size); |
574 | return; |
575 | } else if (s->idle_insize == 0) { |
576 | s->next_inpacket_split = |
577 | (s->inpacket_head + 1) % s->inpackets; |
578 | s->next_inpacket_split_at = 0; |
579 | } else { |
580 | unsigned int split = s->inpacket_head; |
581 | |
582 | l = s->idle_insize; |
583 | while (l > s->inpacket[split].length) { |
584 | l -= s->inpacket[split].length; |
585 | if (split == 0) |
586 | split = s->inpackets - 1; |
587 | else |
588 | split--; |
589 | } |
590 | s->next_inpacket_split = split; |
591 | s->next_inpacket_split_at = |
592 | s->inpacket[split].length - l; |
593 | } |
594 | |
595 | s->insize_done += urb_size; |
596 | |
597 | if (usb_stream_prepare_playback(sk, inurb) < 0) |
598 | return; |
599 | |
600 | } else |
601 | playback_prep_freqn(sk, urb: sk->idle_outurb); |
602 | |
603 | if (submit_urbs(sk, inurb, outurb) < 0) |
604 | return; |
605 | |
606 | if (s->state == usb_stream_sync1 && s->insize_done > 360000) { |
607 | /* just guesswork ^^^^^^ */ |
608 | s->state = usb_stream_ready; |
609 | subs_set_complete(urbs: sk->inurb, complete: i_capture_idle); |
610 | subs_set_complete(urbs: sk->outurb, complete: i_playback_idle); |
611 | } |
612 | } |
613 | |
614 | static void i_capture_start(struct urb *urb) |
615 | { |
616 | struct usb_iso_packet_descriptor *id = urb->iso_frame_desc; |
617 | struct usb_stream_kernel *sk = urb->context; |
618 | struct usb_stream *s = sk->s; |
619 | int p; |
620 | int empty = 0; |
621 | |
622 | if (urb->status) { |
623 | snd_printk(KERN_WARNING "status=%i\n" , urb->status); |
624 | return; |
625 | } |
626 | |
627 | for (p = 0; p < urb->number_of_packets; ++p) { |
628 | int l = id[p].actual_length; |
629 | |
630 | if (l < s->cfg.frame_size) { |
631 | ++empty; |
632 | if (s->state >= usb_stream_sync0) { |
633 | snd_printk(KERN_WARNING "%i\n" , l); |
634 | return; |
635 | } |
636 | } |
637 | s->inpacket_head++; |
638 | s->inpacket_head %= s->inpackets; |
639 | s->inpacket[s->inpacket_head].offset = |
640 | id[p].offset + (urb->transfer_buffer - (void *)s); |
641 | s->inpacket[s->inpacket_head].length = l; |
642 | } |
643 | #ifdef SHOW_EMPTY |
644 | if (empty) { |
645 | printk(KERN_DEBUG"%s:%i: %i" , __func__, __LINE__, |
646 | urb->iso_frame_desc[0].actual_length); |
647 | for (pack = 1; pack < urb->number_of_packets; ++pack) { |
648 | int l = urb->iso_frame_desc[pack].actual_length; |
649 | |
650 | printk(KERN_CONT " %i" , l); |
651 | } |
652 | printk(KERN_CONT "\n" ); |
653 | } |
654 | #endif |
655 | if (!empty && s->state < usb_stream_sync1) |
656 | ++s->state; |
657 | |
658 | if (balance_capture(sk, urb)) |
659 | stream_start(sk, inurb: urb, outurb: sk->i_urb); |
660 | } |
661 | |
662 | static void i_playback_start(struct urb *urb) |
663 | { |
664 | struct usb_stream_kernel *sk = urb->context; |
665 | |
666 | if (balance_playback(sk, urb)) |
667 | stream_start(sk, inurb: sk->i_urb, outurb: urb); |
668 | } |
669 | |
670 | int usb_stream_start(struct usb_stream_kernel *sk) |
671 | { |
672 | struct usb_stream *s = sk->s; |
673 | int frame = 0, iters = 0; |
674 | int u, err; |
675 | int try = 0; |
676 | |
677 | if (s->state != usb_stream_stopped) |
678 | return -EAGAIN; |
679 | |
680 | subs_set_complete(urbs: sk->inurb, complete: i_capture_start); |
681 | subs_set_complete(urbs: sk->outurb, complete: i_playback_start); |
682 | memset(sk->write_page, 0, s->write_size); |
683 | dotry: |
684 | s->insize_done = 0; |
685 | s->idle_insize = 0; |
686 | s->idle_outsize = 0; |
687 | s->sync_packet = -1; |
688 | s->inpacket_head = -1; |
689 | sk->iso_frame_balance = 0; |
690 | ++try; |
691 | for (u = 0; u < 2; u++) { |
692 | struct urb *inurb = sk->inurb[u]; |
693 | struct urb *outurb = sk->outurb[u]; |
694 | |
695 | playback_prep_freqn(sk, urb: outurb); |
696 | inurb->number_of_packets = outurb->number_of_packets; |
697 | inurb->transfer_buffer_length = |
698 | inurb->number_of_packets * |
699 | inurb->iso_frame_desc[0].length; |
700 | |
701 | if (u == 0) { |
702 | int now; |
703 | struct usb_device *dev = inurb->dev; |
704 | |
705 | frame = usb_get_current_frame_number(usb_dev: dev); |
706 | do { |
707 | now = usb_get_current_frame_number(usb_dev: dev); |
708 | ++iters; |
709 | } while (now > -1 && now == frame); |
710 | } |
711 | err = usb_submit_urb(urb: inurb, GFP_ATOMIC); |
712 | if (err < 0) { |
713 | snd_printk(KERN_ERR |
714 | "usb_submit_urb(sk->inurb[%i]) returned %i\n" , |
715 | u, err); |
716 | return err; |
717 | } |
718 | err = usb_submit_urb(urb: outurb, GFP_ATOMIC); |
719 | if (err < 0) { |
720 | snd_printk(KERN_ERR |
721 | "usb_submit_urb(sk->outurb[%i]) returned %i\n" , |
722 | u, err); |
723 | return err; |
724 | } |
725 | |
726 | if (inurb->start_frame != outurb->start_frame) { |
727 | snd_printd(KERN_DEBUG |
728 | "u[%i] start_frames differ in:%u out:%u\n" , |
729 | u, inurb->start_frame, outurb->start_frame); |
730 | goto check_retry; |
731 | } |
732 | } |
733 | snd_printdd(KERN_DEBUG "%i %i\n" , frame, iters); |
734 | try = 0; |
735 | check_retry: |
736 | if (try) { |
737 | usb_stream_stop(sk); |
738 | if (try < 5) { |
739 | msleep(msecs: 1500); |
740 | snd_printd(KERN_DEBUG "goto dotry;\n" ); |
741 | goto dotry; |
742 | } |
743 | snd_printk(KERN_WARNING |
744 | "couldn't start all urbs on the same start_frame.\n" ); |
745 | return -EFAULT; |
746 | } |
747 | |
748 | sk->idle_inurb = sk->inurb[USB_STREAM_NURBS - 2]; |
749 | sk->idle_outurb = sk->outurb[USB_STREAM_NURBS - 2]; |
750 | sk->completed_inurb = sk->inurb[USB_STREAM_NURBS - 1]; |
751 | sk->completed_outurb = sk->outurb[USB_STREAM_NURBS - 1]; |
752 | |
753 | /* wait, check */ |
754 | { |
755 | int wait_ms = 3000; |
756 | |
757 | while (s->state != usb_stream_ready && wait_ms > 0) { |
758 | snd_printdd(KERN_DEBUG "%i\n" , s->state); |
759 | msleep(msecs: 200); |
760 | wait_ms -= 200; |
761 | } |
762 | } |
763 | |
764 | return s->state == usb_stream_ready ? 0 : -EFAULT; |
765 | } |
766 | |
767 | |
768 | /* stop */ |
769 | |
770 | void usb_stream_stop(struct usb_stream_kernel *sk) |
771 | { |
772 | int u; |
773 | |
774 | if (!sk->s) |
775 | return; |
776 | for (u = 0; u < USB_STREAM_NURBS; ++u) { |
777 | usb_kill_urb(urb: sk->inurb[u]); |
778 | usb_kill_urb(urb: sk->outurb[u]); |
779 | } |
780 | sk->s->state = usb_stream_stopped; |
781 | msleep(msecs: 400); |
782 | } |
783 | |