Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de>
0004  */
0005 
0006 #include <linux/usb.h>
0007 #include <linux/gfp.h>
0008 
0009 #include "usb_stream.h"
0010 
0011 /*                             setup                                  */
0012 
0013 static unsigned int usb_stream_next_packet_size(struct usb_stream_kernel *sk)
0014 {
0015     struct usb_stream *s = sk->s;
0016 
0017     sk->out_phase_peeked = (sk->out_phase & 0xffff) + sk->freqn;
0018     return (sk->out_phase_peeked >> 16) * s->cfg.frame_size;
0019 }
0020 
0021 static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb)
0022 {
0023     struct usb_stream *s = sk->s;
0024     int pack, lb = 0;
0025 
0026     for (pack = 0; pack < sk->n_o_ps; pack++) {
0027         int l = usb_stream_next_packet_size(sk);
0028 
0029         if (s->idle_outsize + lb + l > s->period_size)
0030             goto check;
0031 
0032         sk->out_phase = sk->out_phase_peeked;
0033         urb->iso_frame_desc[pack].offset = lb;
0034         urb->iso_frame_desc[pack].length = l;
0035         lb += l;
0036     }
0037     snd_printdd(KERN_DEBUG "%i\n", lb);
0038 
0039 check:
0040     urb->number_of_packets = pack;
0041     urb->transfer_buffer_length = lb;
0042     s->idle_outsize += lb - s->period_size;
0043     snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize,
0044             lb, s->period_size);
0045 }
0046 
0047 static int init_pipe_urbs(struct usb_stream_kernel *sk,
0048               unsigned int use_packsize,
0049               struct urb **urbs, char *transfer,
0050               struct usb_device *dev, int pipe)
0051 {
0052     int u, p;
0053     int maxpacket = use_packsize ?
0054         use_packsize : usb_maxpacket(dev, pipe);
0055     int transfer_length = maxpacket * sk->n_o_ps;
0056 
0057     for (u = 0; u < USB_STREAM_NURBS;
0058          ++u, transfer += transfer_length) {
0059         struct urb *urb = urbs[u];
0060         struct usb_iso_packet_descriptor *desc;
0061 
0062         urb->transfer_buffer = transfer;
0063         urb->dev = dev;
0064         urb->pipe = pipe;
0065         urb->number_of_packets = sk->n_o_ps;
0066         urb->context = sk;
0067         urb->interval = 1;
0068         if (usb_pipeout(pipe))
0069             continue;
0070         if (usb_urb_ep_type_check(urb))
0071             return -EINVAL;
0072 
0073         urb->transfer_buffer_length = transfer_length;
0074         desc = urb->iso_frame_desc;
0075         desc->offset = 0;
0076         desc->length = maxpacket;
0077         for (p = 1; p < sk->n_o_ps; ++p) {
0078             desc[p].offset = desc[p - 1].offset + maxpacket;
0079             desc[p].length = maxpacket;
0080         }
0081     }
0082 
0083     return 0;
0084 }
0085 
0086 static int init_urbs(struct usb_stream_kernel *sk, unsigned int use_packsize,
0087              struct usb_device *dev, int in_pipe, int out_pipe)
0088 {
0089     struct usb_stream   *s = sk->s;
0090     char            *indata =
0091         (char *)s + sizeof(*s) + sizeof(struct usb_stream_packet) * s->inpackets;
0092     int         u;
0093 
0094     for (u = 0; u < USB_STREAM_NURBS; ++u) {
0095         sk->inurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
0096         if (!sk->inurb[u])
0097             return -ENOMEM;
0098 
0099         sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
0100         if (!sk->outurb[u])
0101             return -ENOMEM;
0102     }
0103 
0104     if (init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe) ||
0105         init_pipe_urbs(sk, use_packsize, sk->outurb, sk->write_page, dev,
0106                out_pipe))
0107         return -EINVAL;
0108 
0109     return 0;
0110 }
0111 
0112 /*
0113  * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
0114  * this will overflow at approx 524 kHz
0115  */
0116 static inline unsigned int get_usb_full_speed_rate(unsigned int rate)
0117 {
0118     return ((rate << 13) + 62) / 125;
0119 }
0120 
0121 /*
0122  * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
0123  * this will overflow at approx 4 MHz
0124  */
0125 static inline unsigned int get_usb_high_speed_rate(unsigned int rate)
0126 {
0127     return ((rate << 10) + 62) / 125;
0128 }
0129 
0130 void usb_stream_free(struct usb_stream_kernel *sk)
0131 {
0132     struct usb_stream *s;
0133     unsigned int u;
0134 
0135     for (u = 0; u < USB_STREAM_NURBS; ++u) {
0136         usb_free_urb(sk->inurb[u]);
0137         sk->inurb[u] = NULL;
0138         usb_free_urb(sk->outurb[u]);
0139         sk->outurb[u] = NULL;
0140     }
0141 
0142     s = sk->s;
0143     if (!s)
0144         return;
0145 
0146     if (sk->write_page) {
0147         free_pages_exact(sk->write_page, s->write_size);
0148         sk->write_page = NULL;
0149     }
0150 
0151     free_pages_exact(s, s->read_size);
0152     sk->s = NULL;
0153 }
0154 
0155 struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk,
0156                   struct usb_device *dev,
0157                   unsigned int in_endpoint,
0158                   unsigned int out_endpoint,
0159                   unsigned int sample_rate,
0160                   unsigned int use_packsize,
0161                   unsigned int period_frames,
0162                   unsigned int frame_size)
0163 {
0164     int packets, max_packsize;
0165     int in_pipe, out_pipe;
0166     int read_size = sizeof(struct usb_stream);
0167     int write_size;
0168     int usb_frames = dev->speed == USB_SPEED_HIGH ? 8000 : 1000;
0169 
0170     in_pipe = usb_rcvisocpipe(dev, in_endpoint);
0171     out_pipe = usb_sndisocpipe(dev, out_endpoint);
0172 
0173     max_packsize = use_packsize ?
0174         use_packsize : usb_maxpacket(dev, in_pipe);
0175 
0176     /*
0177         t_period = period_frames / sample_rate
0178         iso_packs = t_period / t_iso_frame
0179             = (period_frames / sample_rate) * (1 / t_iso_frame)
0180     */
0181 
0182     packets = period_frames * usb_frames / sample_rate + 1;
0183 
0184     if (dev->speed == USB_SPEED_HIGH)
0185         packets = (packets + 7) & ~7;
0186 
0187     read_size += packets * USB_STREAM_URBDEPTH *
0188         (max_packsize + sizeof(struct usb_stream_packet));
0189 
0190     max_packsize = usb_maxpacket(dev, out_pipe);
0191     write_size = max_packsize * packets * USB_STREAM_URBDEPTH;
0192 
0193     if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) {
0194         snd_printk(KERN_WARNING "a size exceeds 128*PAGE_SIZE\n");
0195         goto out;
0196     }
0197 
0198     sk->s = alloc_pages_exact(read_size,
0199                   GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
0200     if (!sk->s) {
0201         pr_warn("us122l: couldn't allocate read buffer\n");
0202         goto out;
0203     }
0204     sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION;
0205 
0206     sk->s->read_size = read_size;
0207 
0208     sk->s->cfg.sample_rate = sample_rate;
0209     sk->s->cfg.frame_size = frame_size;
0210     sk->n_o_ps = packets;
0211     sk->s->inpackets = packets * USB_STREAM_URBDEPTH;
0212     sk->s->cfg.period_frames = period_frames;
0213     sk->s->period_size = frame_size * period_frames;
0214 
0215     sk->s->write_size = write_size;
0216 
0217     sk->write_page = alloc_pages_exact(write_size,
0218                        GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
0219     if (!sk->write_page) {
0220         pr_warn("us122l: couldn't allocate write buffer\n");
0221         usb_stream_free(sk);
0222         return NULL;
0223     }
0224 
0225     /* calculate the frequency in 16.16 format */
0226     if (dev->speed == USB_SPEED_FULL)
0227         sk->freqn = get_usb_full_speed_rate(sample_rate);
0228     else
0229         sk->freqn = get_usb_high_speed_rate(sample_rate);
0230 
0231     if (init_urbs(sk, use_packsize, dev, in_pipe, out_pipe) < 0) {
0232         usb_stream_free(sk);
0233         return NULL;
0234     }
0235 
0236     sk->s->state = usb_stream_stopped;
0237 out:
0238     return sk->s;
0239 }
0240 
0241 /*                             start                                  */
0242 
0243 static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb)
0244 {
0245     bool r;
0246 
0247     if (unlikely(urb->status)) {
0248         if (urb->status != -ESHUTDOWN && urb->status != -ENOENT)
0249             snd_printk(KERN_WARNING "status=%i\n", urb->status);
0250         sk->iso_frame_balance = 0x7FFFFFFF;
0251         return false;
0252     }
0253     r = sk->iso_frame_balance == 0;
0254     if (!r)
0255         sk->i_urb = urb;
0256     return r;
0257 }
0258 
0259 static bool balance_playback(struct usb_stream_kernel *sk, struct urb *urb)
0260 {
0261     sk->iso_frame_balance += urb->number_of_packets;
0262     return balance_check(sk, urb);
0263 }
0264 
0265 static bool balance_capture(struct usb_stream_kernel *sk, struct urb *urb)
0266 {
0267     sk->iso_frame_balance -= urb->number_of_packets;
0268     return balance_check(sk, urb);
0269 }
0270 
0271 static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *))
0272 {
0273     int u;
0274 
0275     for (u = 0; u < USB_STREAM_NURBS; u++) {
0276         struct urb *urb = urbs[u];
0277 
0278         urb->complete = complete;
0279     }
0280 }
0281 
0282 static int usb_stream_prepare_playback(struct usb_stream_kernel *sk,
0283         struct urb *inurb)
0284 {
0285     struct usb_stream *s = sk->s;
0286     struct urb *io;
0287     struct usb_iso_packet_descriptor *id, *od;
0288     int p = 0, lb = 0, l = 0;
0289 
0290     io = sk->idle_outurb;
0291     od = io->iso_frame_desc;
0292 
0293     for (; s->sync_packet < 0; ++p, ++s->sync_packet) {
0294         struct urb *ii = sk->completed_inurb;
0295 
0296         id = ii->iso_frame_desc +
0297             ii->number_of_packets + s->sync_packet;
0298         l = id->actual_length;
0299 
0300         od[p].length = l;
0301         od[p].offset = lb;
0302         lb += l;
0303     }
0304 
0305     for (;
0306          s->sync_packet < inurb->number_of_packets && p < sk->n_o_ps;
0307          ++p, ++s->sync_packet) {
0308         l = inurb->iso_frame_desc[s->sync_packet].actual_length;
0309 
0310         if (s->idle_outsize + lb + l > s->period_size)
0311             goto check_ok;
0312 
0313         od[p].length = l;
0314         od[p].offset = lb;
0315         lb += l;
0316     }
0317 
0318 check_ok:
0319     s->sync_packet -= inurb->number_of_packets;
0320     if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) {
0321         snd_printk(KERN_WARNING "invalid sync_packet = %i;"
0322                " p=%i nop=%i %i %x %x %x > %x\n",
0323                s->sync_packet, p, inurb->number_of_packets,
0324                s->idle_outsize + lb + l,
0325                s->idle_outsize, lb,  l,
0326                s->period_size);
0327         return -1;
0328     }
0329     if (unlikely(lb % s->cfg.frame_size)) {
0330         snd_printk(KERN_WARNING"invalid outsize = %i\n",
0331                lb);
0332         return -1;
0333     }
0334     s->idle_outsize += lb - s->period_size;
0335     io->number_of_packets = p;
0336     io->transfer_buffer_length = lb;
0337     if (s->idle_outsize <= 0)
0338         return 0;
0339 
0340     snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize);
0341     return -1;
0342 }
0343 
0344 static void prepare_inurb(int number_of_packets, struct urb *iu)
0345 {
0346     struct usb_iso_packet_descriptor *id;
0347     int p;
0348 
0349     iu->number_of_packets = number_of_packets;
0350     id = iu->iso_frame_desc;
0351     id->offset = 0;
0352     for (p = 0; p < iu->number_of_packets - 1; ++p)
0353         id[p + 1].offset = id[p].offset + id[p].length;
0354 
0355     iu->transfer_buffer_length =
0356         id[0].length * iu->number_of_packets;
0357 }
0358 
0359 static int submit_urbs(struct usb_stream_kernel *sk,
0360                struct urb *inurb, struct urb *outurb)
0361 {
0362     int err;
0363 
0364     prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb);
0365     err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC);
0366     if (err < 0)
0367         goto report_failure;
0368 
0369     sk->idle_inurb = sk->completed_inurb;
0370     sk->completed_inurb = inurb;
0371     err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC);
0372     if (err < 0)
0373         goto report_failure;
0374 
0375     sk->idle_outurb = sk->completed_outurb;
0376     sk->completed_outurb = outurb;
0377     return 0;
0378 
0379 report_failure:
0380     snd_printk(KERN_ERR "%i\n", err);
0381     return err;
0382 }
0383 
0384 #ifdef DEBUG_LOOP_BACK
0385 /*
0386   This loop_back() shows how to read/write the period data.
0387  */
0388 static void loop_back(struct usb_stream *s)
0389 {
0390     char *i, *o;
0391     int il, ol, l, p;
0392     struct urb *iu;
0393     struct usb_iso_packet_descriptor *id;
0394 
0395     o = s->playback1st_to;
0396     ol = s->playback1st_size;
0397     l = 0;
0398 
0399     if (s->insplit_pack >= 0) {
0400         iu = sk->idle_inurb;
0401         id = iu->iso_frame_desc;
0402         p = s->insplit_pack;
0403     } else
0404         goto second;
0405 loop:
0406     for (; p < iu->number_of_packets && l < s->period_size; ++p) {
0407         i = iu->transfer_buffer + id[p].offset;
0408         il = id[p].actual_length;
0409         if (l + il > s->period_size)
0410             il = s->period_size - l;
0411         if (il <= ol) {
0412             memcpy(o, i, il);
0413             o += il;
0414             ol -= il;
0415         } else {
0416             memcpy(o, i, ol);
0417             singen_6pack(o, ol);
0418             o = s->playback_to;
0419             memcpy(o, i + ol, il - ol);
0420             o += il - ol;
0421             ol = s->period_size - s->playback1st_size;
0422         }
0423         l += il;
0424     }
0425     if (iu == sk->completed_inurb) {
0426         if (l != s->period_size)
0427             printk(KERN_DEBUG"%s:%i %i\n", __func__, __LINE__,
0428                    l/(int)s->cfg.frame_size);
0429 
0430         return;
0431     }
0432 second:
0433     iu = sk->completed_inurb;
0434     id = iu->iso_frame_desc;
0435     p = 0;
0436     goto loop;
0437 
0438 }
0439 #else
0440 static void loop_back(struct usb_stream *s)
0441 {
0442 }
0443 #endif
0444 
0445 static void stream_idle(struct usb_stream_kernel *sk,
0446             struct urb *inurb, struct urb *outurb)
0447 {
0448     struct usb_stream *s = sk->s;
0449     int l, p;
0450     int insize = s->idle_insize;
0451     int urb_size = 0;
0452 
0453     s->inpacket_split = s->next_inpacket_split;
0454     s->inpacket_split_at = s->next_inpacket_split_at;
0455     s->next_inpacket_split = -1;
0456     s->next_inpacket_split_at = 0;
0457 
0458     for (p = 0; p < inurb->number_of_packets; ++p) {
0459         struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc;
0460 
0461         l = id[p].actual_length;
0462         if (unlikely(l == 0 || id[p].status)) {
0463             snd_printk(KERN_WARNING "underrun, status=%u\n",
0464                    id[p].status);
0465             goto err_out;
0466         }
0467         s->inpacket_head++;
0468         s->inpacket_head %= s->inpackets;
0469         if (s->inpacket_split == -1)
0470             s->inpacket_split = s->inpacket_head;
0471 
0472         s->inpacket[s->inpacket_head].offset =
0473             id[p].offset + (inurb->transfer_buffer - (void *)s);
0474         s->inpacket[s->inpacket_head].length = l;
0475         if (insize + l > s->period_size &&
0476             s->next_inpacket_split == -1) {
0477             s->next_inpacket_split = s->inpacket_head;
0478             s->next_inpacket_split_at = s->period_size - insize;
0479         }
0480         insize += l;
0481         urb_size += l;
0482     }
0483     s->idle_insize += urb_size - s->period_size;
0484     if (s->idle_insize < 0) {
0485         snd_printk(KERN_WARNING "%i\n",
0486                (s->idle_insize)/(int)s->cfg.frame_size);
0487         goto err_out;
0488     }
0489     s->insize_done += urb_size;
0490 
0491     l = s->idle_outsize;
0492     s->outpacket[0].offset = (sk->idle_outurb->transfer_buffer -
0493                   sk->write_page) - l;
0494 
0495     if (usb_stream_prepare_playback(sk, inurb) < 0)
0496         goto err_out;
0497 
0498     s->outpacket[0].length = sk->idle_outurb->transfer_buffer_length + l;
0499     s->outpacket[1].offset = sk->completed_outurb->transfer_buffer -
0500         sk->write_page;
0501 
0502     if (submit_urbs(sk, inurb, outurb) < 0)
0503         goto err_out;
0504 
0505     loop_back(s);
0506     s->periods_done++;
0507     wake_up_all(&sk->sleep);
0508     return;
0509 err_out:
0510     s->state = usb_stream_xrun;
0511     wake_up_all(&sk->sleep);
0512 }
0513 
0514 static void i_capture_idle(struct urb *urb)
0515 {
0516     struct usb_stream_kernel *sk = urb->context;
0517 
0518     if (balance_capture(sk, urb))
0519         stream_idle(sk, urb, sk->i_urb);
0520 }
0521 
0522 static void i_playback_idle(struct urb *urb)
0523 {
0524     struct usb_stream_kernel *sk = urb->context;
0525 
0526     if (balance_playback(sk, urb))
0527         stream_idle(sk, sk->i_urb, urb);
0528 }
0529 
0530 static void stream_start(struct usb_stream_kernel *sk,
0531              struct urb *inurb, struct urb *outurb)
0532 {
0533     struct usb_stream *s = sk->s;
0534 
0535     if (s->state >= usb_stream_sync1) {
0536         int l, p, max_diff, max_diff_0;
0537         int urb_size = 0;
0538         unsigned int frames_per_packet, min_frames = 0;
0539 
0540         frames_per_packet = (s->period_size - s->idle_insize);
0541         frames_per_packet <<= 8;
0542         frames_per_packet /=
0543             s->cfg.frame_size * inurb->number_of_packets;
0544         frames_per_packet++;
0545 
0546         max_diff_0 = s->cfg.frame_size;
0547         if (s->cfg.period_frames >= 256)
0548             max_diff_0 <<= 1;
0549         if (s->cfg.period_frames >= 1024)
0550             max_diff_0 <<= 1;
0551         max_diff = max_diff_0;
0552         for (p = 0; p < inurb->number_of_packets; ++p) {
0553             int diff;
0554 
0555             l = inurb->iso_frame_desc[p].actual_length;
0556             urb_size += l;
0557 
0558             min_frames += frames_per_packet;
0559             diff = urb_size -
0560                 (min_frames >> 8) * s->cfg.frame_size;
0561             if (diff < max_diff) {
0562                 snd_printdd(KERN_DEBUG "%i %i %i %i\n",
0563                         s->insize_done,
0564                         urb_size / (int)s->cfg.frame_size,
0565                         inurb->number_of_packets, diff);
0566                 max_diff = diff;
0567             }
0568         }
0569         s->idle_insize -= max_diff - max_diff_0;
0570         s->idle_insize += urb_size - s->period_size;
0571         if (s->idle_insize < 0) {
0572             snd_printk(KERN_WARNING "%i %i %i\n",
0573                    s->idle_insize, urb_size, s->period_size);
0574             return;
0575         } else if (s->idle_insize == 0) {
0576             s->next_inpacket_split =
0577                 (s->inpacket_head + 1) % s->inpackets;
0578             s->next_inpacket_split_at = 0;
0579         } else {
0580             unsigned int split = s->inpacket_head;
0581 
0582             l = s->idle_insize;
0583             while (l > s->inpacket[split].length) {
0584                 l -= s->inpacket[split].length;
0585                 if (split == 0)
0586                     split = s->inpackets - 1;
0587                 else
0588                     split--;
0589             }
0590             s->next_inpacket_split = split;
0591             s->next_inpacket_split_at =
0592                 s->inpacket[split].length - l;
0593         }
0594 
0595         s->insize_done += urb_size;
0596 
0597         if (usb_stream_prepare_playback(sk, inurb) < 0)
0598             return;
0599 
0600     } else
0601         playback_prep_freqn(sk, sk->idle_outurb);
0602 
0603     if (submit_urbs(sk, inurb, outurb) < 0)
0604         return;
0605 
0606     if (s->state == usb_stream_sync1 && s->insize_done > 360000) {
0607         /* just guesswork                            ^^^^^^ */
0608         s->state = usb_stream_ready;
0609         subs_set_complete(sk->inurb, i_capture_idle);
0610         subs_set_complete(sk->outurb, i_playback_idle);
0611     }
0612 }
0613 
0614 static void i_capture_start(struct urb *urb)
0615 {
0616     struct usb_iso_packet_descriptor *id = urb->iso_frame_desc;
0617     struct usb_stream_kernel *sk = urb->context;
0618     struct usb_stream *s = sk->s;
0619     int p;
0620     int empty = 0;
0621 
0622     if (urb->status) {
0623         snd_printk(KERN_WARNING "status=%i\n", urb->status);
0624         return;
0625     }
0626 
0627     for (p = 0; p < urb->number_of_packets; ++p) {
0628         int l = id[p].actual_length;
0629 
0630         if (l < s->cfg.frame_size) {
0631             ++empty;
0632             if (s->state >= usb_stream_sync0) {
0633                 snd_printk(KERN_WARNING "%i\n", l);
0634                 return;
0635             }
0636         }
0637         s->inpacket_head++;
0638         s->inpacket_head %= s->inpackets;
0639         s->inpacket[s->inpacket_head].offset =
0640             id[p].offset + (urb->transfer_buffer - (void *)s);
0641         s->inpacket[s->inpacket_head].length = l;
0642     }
0643 #ifdef SHOW_EMPTY
0644     if (empty) {
0645         printk(KERN_DEBUG"%s:%i: %i", __func__, __LINE__,
0646                urb->iso_frame_desc[0].actual_length);
0647         for (pack = 1; pack < urb->number_of_packets; ++pack) {
0648             int l = urb->iso_frame_desc[pack].actual_length;
0649 
0650             printk(KERN_CONT " %i", l);
0651         }
0652         printk(KERN_CONT "\n");
0653     }
0654 #endif
0655     if (!empty && s->state < usb_stream_sync1)
0656         ++s->state;
0657 
0658     if (balance_capture(sk, urb))
0659         stream_start(sk, urb, sk->i_urb);
0660 }
0661 
0662 static void i_playback_start(struct urb *urb)
0663 {
0664     struct usb_stream_kernel *sk = urb->context;
0665 
0666     if (balance_playback(sk, urb))
0667         stream_start(sk, sk->i_urb, urb);
0668 }
0669 
0670 int usb_stream_start(struct usb_stream_kernel *sk)
0671 {
0672     struct usb_stream *s = sk->s;
0673     int frame = 0, iters = 0;
0674     int u, err;
0675     int try = 0;
0676 
0677     if (s->state != usb_stream_stopped)
0678         return -EAGAIN;
0679 
0680     subs_set_complete(sk->inurb, i_capture_start);
0681     subs_set_complete(sk->outurb, i_playback_start);
0682     memset(sk->write_page, 0, s->write_size);
0683 dotry:
0684     s->insize_done = 0;
0685     s->idle_insize = 0;
0686     s->idle_outsize = 0;
0687     s->sync_packet = -1;
0688     s->inpacket_head = -1;
0689     sk->iso_frame_balance = 0;
0690     ++try;
0691     for (u = 0; u < 2; u++) {
0692         struct urb *inurb = sk->inurb[u];
0693         struct urb *outurb = sk->outurb[u];
0694 
0695         playback_prep_freqn(sk, outurb);
0696         inurb->number_of_packets = outurb->number_of_packets;
0697         inurb->transfer_buffer_length =
0698             inurb->number_of_packets *
0699             inurb->iso_frame_desc[0].length;
0700 
0701         if (u == 0) {
0702             int now;
0703             struct usb_device *dev = inurb->dev;
0704 
0705             frame = usb_get_current_frame_number(dev);
0706             do {
0707                 now = usb_get_current_frame_number(dev);
0708                 ++iters;
0709             } while (now > -1 && now == frame);
0710         }
0711         err = usb_submit_urb(inurb, GFP_ATOMIC);
0712         if (err < 0) {
0713             snd_printk(KERN_ERR
0714                    "usb_submit_urb(sk->inurb[%i]) returned %i\n",
0715                    u, err);
0716             return err;
0717         }
0718         err = usb_submit_urb(outurb, GFP_ATOMIC);
0719         if (err < 0) {
0720             snd_printk(KERN_ERR
0721                    "usb_submit_urb(sk->outurb[%i]) returned %i\n",
0722                    u, err);
0723             return err;
0724         }
0725 
0726         if (inurb->start_frame != outurb->start_frame) {
0727             snd_printd(KERN_DEBUG
0728                    "u[%i] start_frames differ in:%u out:%u\n",
0729                    u, inurb->start_frame, outurb->start_frame);
0730             goto check_retry;
0731         }
0732     }
0733     snd_printdd(KERN_DEBUG "%i %i\n", frame, iters);
0734     try = 0;
0735 check_retry:
0736     if (try) {
0737         usb_stream_stop(sk);
0738         if (try < 5) {
0739             msleep(1500);
0740             snd_printd(KERN_DEBUG "goto dotry;\n");
0741             goto dotry;
0742         }
0743         snd_printk(KERN_WARNING
0744                "couldn't start all urbs on the same start_frame.\n");
0745         return -EFAULT;
0746     }
0747 
0748     sk->idle_inurb = sk->inurb[USB_STREAM_NURBS - 2];
0749     sk->idle_outurb = sk->outurb[USB_STREAM_NURBS - 2];
0750     sk->completed_inurb = sk->inurb[USB_STREAM_NURBS - 1];
0751     sk->completed_outurb = sk->outurb[USB_STREAM_NURBS - 1];
0752 
0753 /* wait, check */
0754     {
0755         int wait_ms = 3000;
0756 
0757         while (s->state != usb_stream_ready && wait_ms > 0) {
0758             snd_printdd(KERN_DEBUG "%i\n", s->state);
0759             msleep(200);
0760             wait_ms -= 200;
0761         }
0762     }
0763 
0764     return s->state == usb_stream_ready ? 0 : -EFAULT;
0765 }
0766 
0767 
0768 /*                             stop                                   */
0769 
0770 void usb_stream_stop(struct usb_stream_kernel *sk)
0771 {
0772     int u;
0773 
0774     if (!sk->s)
0775         return;
0776     for (u = 0; u < USB_STREAM_NURBS; ++u) {
0777         usb_kill_urb(sk->inurb[u]);
0778         usb_kill_urb(sk->outurb[u]);
0779     }
0780     sk->s->state = usb_stream_stopped;
0781     msleep(400);
0782 }