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