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