~ubuntu-branches/ubuntu/vivid/oss4/vivid

« back to all changes in this revision

Viewing changes to kernel/drv/oss_usb/ossusb_audio.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis, Samuel Thibault, Romain Beauxis, Sebastien NOEL
  • Date: 2011-06-14 10:06:56 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110614100656-cx4oc7u426zn812z
Tags: 4.2-build2004-1
[ Samuel Thibault ]
* debian/control: Add liboss4-salsa2, liboss4-salsa-dev and
  liboss4-salsa-asound2 packages, equivalent to (and will replace) those from
  the oss-libsalsa package (Closes: #589127).
* debian/patches/liboss4-salsa.patch: New patch to rename libsalsa into
  liboss4-salsa to avoid conflicts in the archive for no good reason.
* debian/rules: Make in libOSSlib and libsalsa.
* debian/liboss4-salsa-dev.install, debian/liboss4-salsa2.install,
  debian/liboss4-salsa-asound2.links, debian/liboss4-salsa-dev.links:
  Install liboss4-salsa libraries like was done in the oss-libsalsa package.
* include-alsa: Add a copy of ALSA 1.0.5 headers: Cf ALSA_1.0.* symbols in
  libsalsa, this is the roughly supported version.
* debian/copyright: Update for new include-alsa files.
* alsa.pc: New file for compatibility with libasound-dev.
* debian/control:
  - Add Vcs-Browser and Vcs-Svn fields.
  - Use linux-any instead of the list of Linux archs (Closes: #604679).
  - Make dkms dependency linux-any only.
* debian/patches/hurd_iot.patch: New patch to fix soundcard.h usage in
  libsalsa on hurd-i386.
* debian/patches/libsalsa_fixes.patch: New patch to fix some printf usages
  and ioctl declaration in libsalsa.
* debian/patches/no_EBADE.patch: New patch to cope with hurd-i386 not having
  EBADE.
* debian/patches/CFLAGS.patch: New patch to make oss4 take debian/rules
  CFLAGS into account.
* debian/patches/snd_asoundlib_version.patch: New patch to add
  snd_asoundlib_version().
* debian/patches/generic_srccconf.patch: New patch to fix source
  configuration on unknown archs.

[ Romain Beauxis ]
* Fixed README.Debian to only mention dkms' modules.
* Switch to dpkg-source 3.0 (quilt) format
* Added DM-Upload-Allowed: yes

[ Sebastien NOEL ]
* New upstream release (Closes: #595298, #619272).
* Fix typo in initscript (Closes: #627149).
* debian/control: adjust linux-headers dependencies (Closes: #628879).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: USB audio streaming interface support
 
3
 */
 
4
/*
 
5
 *
 
6
 * This file is part of Open Sound System.
 
7
 *
 
8
 * Copyright (C) 4Front Technologies 1996-2008.
 
9
 *
 
10
 * This this source file is released under GPL v2 license (no other versions).
 
11
 * See the COPYING file included in the main directory of this source
 
12
 * distribution for the license terms and conditions.
 
13
 *
 
14
 */
 
15
 
 
16
#include "oss_config.h"
 
17
#include "ossusb.h"
 
18
 
 
19
#define SAMPLING_FREQ_CONTROL      0x01
 
20
#define PITCH_CONTROL              0x02
 
21
 
 
22
#define FORMAT_II_UNDEFINED             0x1000
 
23
#define FORMAT_II_MPEG                  0x1001
 
24
#define FORMAT_II_AC3                   0x1002
 
25
 
 
26
#define TMPBUF_SIZE     4096
 
27
 
 
28
#if 0
 
29
static int
 
30
read_control_value (ossusb_devc * devc, int endpoint, int ctl, int l)
 
31
{
 
32
  unsigned char buf[4];
 
33
  int len, i, v;
 
34
 
 
35
  memset (buf, 0, sizeof (buf));
 
36
 
 
37
  len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint
 
38
                                 GET_CUR, USB_RECIP_ENDPOINT | USB_TYPE_CLASS,  // rqtype
 
39
                                 ctl << 8,      // value
 
40
                                 endpoint,      // index
 
41
                                 buf,   // buffer
 
42
                                 l,     // buflen
 
43
                                 OSS_HZ);
 
44
  if (len < 0)
 
45
    {
 
46
      cmn_err (CE_WARN, "Endpoint read error %d\n", len);
 
47
      return 0;
 
48
    }
 
49
 
 
50
  cmn_err (CE_CONT, "Read len %d (%d): ", len, l);
 
51
  for (i = 0; i < len; i++)
 
52
    cmn_err (CE_CONT, "%02x ", buf[i]);
 
53
 
 
54
  switch (len)
 
55
    {
 
56
    case 3:
 
57
      v = buf[0] | (buf[1] << 8) | (buf[2] << 16);
 
58
      break;
 
59
 
 
60
    default:
 
61
      cmn_err (CE_CONT, "oss usbaudio: Bad control read (%d)\n", l);
 
62
    }
 
63
 
 
64
  cmn_err (CE_CONT, "= %d\n", v);
 
65
 
 
66
  return v;
 
67
}
 
68
#endif
 
69
 
 
70
static int
 
71
write_control_value (ossusb_devc * devc, udi_endpoint_handle_t * endpoint,
 
72
                     int ctl, int l, unsigned int v)
 
73
{
 
74
  unsigned char buf[4];
 
75
  int len;
 
76
 
 
77
  memset (buf, 0, sizeof (buf));
 
78
 
 
79
  switch (l)
 
80
    {
 
81
    case 3:
 
82
      buf[0] = (v) & 0xff;
 
83
      buf[1] = (v >> 8) & 0xff;
 
84
      buf[2] = (v >> 16) & 0xff;
 
85
      break;
 
86
 
 
87
    default:
 
88
      cmn_err (CE_CONT, "oss usbaudio: Bad control size %d\n", l);
 
89
      return OSS_EIO;
 
90
    }
 
91
 
 
92
  len = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint
 
93
                                 SET_CUR, USB_RECIP_ENDPOINT | USB_TYPE_CLASS,  // rqtype
 
94
                                 ctl << 8,      // value
 
95
                                 udi_endpoint_get_num (endpoint),       // index
 
96
                                 buf,   // buffer
 
97
                                 l,     // buflen
 
98
                                 OSS_HZ);
 
99
  if (len < 0)
 
100
    {
 
101
      cmn_err (CE_WARN, "Endpoint control write error %d\n", len);
 
102
      return OSS_EIO;
 
103
    }
 
104
 
 
105
  return len;
 
106
}
 
107
 
 
108
static void
 
109
set_fraglimits (adev_t * adev, ossusb_portc * portc)
 
110
{
 
111
  int l, m;
 
112
 
 
113
  if (portc->bytes_per_sample < 1)
 
114
    portc->bytes_per_sample = 1;
 
115
 
 
116
  l = portc->bytes_per_sample * adev->min_channels * portc->speed / 1000;
 
117
  l = (l / portc->bytes_per_sample) * portc->bytes_per_sample;
 
118
 
 
119
  m = 2;
 
120
 
 
121
  while (m < l)
 
122
    m *= 2;
 
123
 
 
124
  adev->min_block = m;
 
125
  adev->max_block = TMPBUF_SIZE / 2;
 
126
  portc->fragment_size = l;
 
127
}
 
128
 
 
129
static int
 
130
usbaudio_set_rate (int dev, int arg)
 
131
{
 
132
  adev_p adev = audio_engines[dev];
 
133
  ossusb_portc *portc = adev->portc;
 
134
  ossusb_devc *devc = adev->devc;
 
135
 
 
136
  int i, x, diff, bestdiff;
 
137
 
 
138
  if (devc->disabled)
 
139
    return OSS_EPIPE;
 
140
 
 
141
  if (arg == 0)
 
142
    return portc->speed;
 
143
 
 
144
  if (arg < adev->min_rate)
 
145
    arg = adev->min_rate;
 
146
  if (arg > adev->max_rate)
 
147
    arg = adev->max_rate;
 
148
 
 
149
  if (!(adev->caps & PCM_CAP_FREERATE))
 
150
    {
 
151
      /* Search for the nearest supported rate */
 
152
      bestdiff = 0x7fffffff;
 
153
      x = -1;
 
154
 
 
155
      for (i = 0; i < adev->nrates; i++)
 
156
        {
 
157
          diff = arg - adev->rates[i];
 
158
 
 
159
          if (diff < 0)
 
160
            diff = -diff;       /* ABS */
 
161
          if (diff < bestdiff)
 
162
            {
 
163
              x = i;
 
164
              bestdiff = diff;
 
165
            }
 
166
        }
 
167
 
 
168
      if (x > -1)
 
169
        arg = adev->rates[x];
 
170
    }
 
171
 
 
172
  portc->speed = arg;
 
173
  set_fraglimits (adev, portc);
 
174
 
 
175
  return portc->speed;
 
176
}
 
177
 
 
178
/*ARGSUSED*/
 
179
static short
 
180
usbaudio_set_channels (int dev, short arg)
 
181
{
 
182
  adev_p adev = audio_engines[dev];
 
183
  ossusb_devc *devc = adev->devc;
 
184
 
 
185
  if (devc->disabled)
 
186
    return OSS_EPIPE;
 
187
 
 
188
  return adev->min_channels;    /* max_channels should be the same too */
 
189
}
 
190
 
 
191
/*ARGSUSED*/
 
192
static unsigned int
 
193
usbaudio_set_format (int dev, unsigned int arg)
 
194
{
 
195
  adev_p adev = audio_engines[dev];
 
196
  ossusb_devc *devc = adev->devc;
 
197
 
 
198
  if (devc->disabled)
 
199
    return adev->oformat_mask;
 
200
 
 
201
  return adev->oformat_mask;    /* iformat_mask should be the same  too */
 
202
}
 
203
 
 
204
/*ARGSUSED*/
 
205
static int
 
206
usbaudio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 
207
{
 
208
  ossusb_devc *devc = audio_engines[dev]->devc;
 
209
  if (devc->disabled)
 
210
    return OSS_EPIPE;
 
211
 
 
212
  return OSS_EINVAL;
 
213
}
 
214
 
 
215
/*ARGSUSED*/
 
216
static int
 
217
setup_format_I (ossusb_devc * devc, ossusb_portc * portc, adev_p adev,
 
218
                unsigned char *d, int l)
 
219
{
 
220
  int min_rate = 0, max_rate = 0;
 
221
  int i, n;
 
222
  int frame_size, bits, channels;
 
223
  unsigned int fmt = 0;
 
224
 
 
225
  if (usb_trace > 1)
 
226
    {
 
227
      cmn_err (CE_CONT,
 
228
               "AS_FORMAT_TYPE: FORMAT_TYPE_I, #ch %d, framesize %d, bits %d, freq_type %02x, freq=",
 
229
               d[4], d[5], d[6], d[7]);
 
230
      if (d[7] == 0)
 
231
        cmn_err (CE_CONT, "%d-%d ", ossusb_get_int (&d[8], 3),
 
232
                 ossusb_get_int (&d[11], 3));
 
233
      {
 
234
        for (i = 0; i < d[7]; i++)
 
235
          cmn_err (CE_CONT, "%d ", ossusb_get_int (&d[8 + i * 3], 3));
 
236
        cmn_err (CE_CONT, " ");
 
237
      }
 
238
 
 
239
      switch (d[3])
 
240
        {
 
241
        case 0x00:
 
242
          cmn_err (CE_CONT, "Undefined ");
 
243
          break;
 
244
        case 0x01:
 
245
          cmn_err (CE_CONT, "PCM ");
 
246
          break;
 
247
        case 0x02:
 
248
          cmn_err (CE_CONT, "PCM8 ");
 
249
          break;
 
250
        case 0x03:
 
251
          cmn_err (CE_CONT, "float ");
 
252
          break;
 
253
        case 0x04:
 
254
          cmn_err (CE_CONT, "A-Law ");
 
255
          break;
 
256
        case 0x05:
 
257
          cmn_err (CE_CONT, "u-Law ");
 
258
          break;
 
259
        }
 
260
      cmn_err (CE_CONT, "\n");
 
261
    }
 
262
 
 
263
  channels = d[4];
 
264
  frame_size = d[5];
 
265
  bits = d[6];
 
266
  UDB (cmn_err (CE_CONT, "Channels %d, bits %d (%d bytes)\n", channels, bits,
 
267
                frame_size));
 
268
 
 
269
  adev->min_channels = adev->max_channels = channels;
 
270
  portc->convert_3byte = 0;
 
271
 
 
272
  switch (d[3])
 
273
    {
 
274
    case 0x01:
 
275
      fmt = AFMT_S16_LE;
 
276
      break;
 
277
    case 0x02:
 
278
      fmt = AFMT_U8;
 
279
      break;
 
280
    case 0x03:
 
281
      fmt = AFMT_FLOAT;
 
282
      break;
 
283
    case 0x04:
 
284
      fmt = AFMT_A_LAW;
 
285
      break;
 
286
    case 0x05:
 
287
      fmt = AFMT_MU_LAW;
 
288
      break;
 
289
    }
 
290
 
 
291
  if (fmt == AFMT_S16_LE)       /* Have to check the frame size too */
 
292
    {
 
293
      switch (frame_size)
 
294
        {
 
295
        case 1:
 
296
          fmt = AFMT_S8;
 
297
          break;
 
298
        case 2:
 
299
          fmt = AFMT_S16_LE;
 
300
          break;
 
301
        case 3:
 
302
          fmt = AFMT_S32_LE;
 
303
          frame_size = 4;
 
304
          portc->convert_3byte = 1;
 
305
          break;
 
306
        case 4:
 
307
          fmt = AFMT_S32_LE;
 
308
          break;
 
309
        }
 
310
    }
 
311
 
 
312
  portc->bytes_per_sample = frame_size;
 
313
  adev->oformat_mask = adev->iformat_mask = fmt;
 
314
  UDB (cmn_err (CE_CONT, "Format mask %08x\n", fmt));
 
315
 
 
316
  adev->caps &= ~PCM_CAP_FREERATE;
 
317
  n = d[7];
 
318
  if (n < 1)                    /* Free rate selection between min (0) and max (1) */
 
319
    {
 
320
      n = 2;
 
321
      adev->caps |= PCM_CAP_FREERATE;
 
322
    }
 
323
 
 
324
  min_rate = 0x7fffffff;
 
325
  max_rate = 0;
 
326
 
 
327
  if (n > 20)
 
328
    {
 
329
      cmn_err (CE_WARN, "The device supports too many sample rates\n");
 
330
      n = 20;
 
331
    }
 
332
 
 
333
  adev->nrates = 0;
 
334
 
 
335
  for (i = 0; i < n; i++)
 
336
    {
 
337
      int rate = ossusb_get_int (&d[8 + i * 3], 3);
 
338
 
 
339
#if 0
 
340
      /* Skip rates that are not multiples of 1000 Hz */
 
341
      if (rate % 1000)
 
342
        continue;
 
343
#endif
 
344
 
 
345
      if (rate < min_rate)
 
346
        min_rate = rate;
 
347
      if (rate > max_rate)
 
348
        max_rate = rate;
 
349
      adev->rates[adev->nrates++] = rate;
 
350
    }
 
351
 
 
352
  adev->min_rate = min_rate;
 
353
  adev->max_rate = max_rate;
 
354
  UDB (cmn_err (CE_CONT, "Min rate %d, max rate %d\n", min_rate, max_rate));
 
355
 
 
356
  adev->caps &= ~DSP_CH_MASK;
 
357
 
 
358
  switch (channels)
 
359
    {
 
360
    case 1:
 
361
      adev->caps |= DSP_CH_MONO;
 
362
      break;
 
363
    case 2:
 
364
      adev->caps |= DSP_CH_STEREO;
 
365
      break;
 
366
    default:
 
367
      adev->caps |= DSP_CH_MULTI;
 
368
      break;
 
369
    }
 
370
  return 0;
 
371
}
 
372
 
 
373
/*ARGSUSED*/
 
374
static int
 
375
setup_format_II (ossusb_devc * devc, ossusb_portc * portc, adev_p adev,
 
376
                 unsigned char *d, int l)
 
377
{
 
378
  int min_rate = 0, max_rate = 0;
 
379
  int i;
 
380
 
 
381
  if (usb_trace > 1)
 
382
    {
 
383
      cmn_err (CE_CONT, "MaxBitRate %d ", d[4]);
 
384
      cmn_err (CE_CONT, "SamplesPerFrame %d ", d[5]);
 
385
 
 
386
      if (d[8] == 0)
 
387
        cmn_err (CE_CONT, "Sample Rates %d-%d ", ossusb_get_int (&d[9], 3),
 
388
                 ossusb_get_int (&d[12], 3));
 
389
      else
 
390
        {
 
391
          int n;
 
392
          int min_rate = 0x7fffffff;
 
393
          int max_rate = 0;
 
394
 
 
395
          n = d[8];
 
396
 
 
397
          if (n > 20)
 
398
            {
 
399
              cmn_err (CE_CONT, "oss usbaudio: Too many sample rates (%d)\n",
 
400
                       n);
 
401
              n = 20;
 
402
            }
 
403
 
 
404
          adev->nrates = 0;
 
405
          cmn_err (CE_CONT, "Possible sample rates: ");
 
406
          for (i = 0; i < d[8]; i++)
 
407
            {
 
408
              int rate = ossusb_get_int (&d[9 + i * 3], 3);
 
409
 
 
410
#if 0
 
411
              /* Skip rates that are not multiples of 1000 Hz */
 
412
              if (rate % 1000)
 
413
                continue;
 
414
#endif
 
415
 
 
416
              if (rate < min_rate)
 
417
                min_rate = rate;
 
418
              if (rate > max_rate)
 
419
                max_rate = rate;
 
420
              cmn_err (CE_CONT, "%d ", rate);
 
421
              adev->rates[adev->nrates++] = rate;
 
422
            }
 
423
          adev->min_rate = min_rate;
 
424
          adev->max_rate = max_rate;
 
425
        }
 
426
 
 
427
      cmn_err (CE_CONT, "\n");
 
428
    }
 
429
 
 
430
  adev->caps &= ~PCM_CAP_FREERATE;
 
431
  if (d[8] == 0)
 
432
    {
 
433
      min_rate = ossusb_get_int (&d[9], 3);
 
434
      max_rate = ossusb_get_int (&d[12], 3);
 
435
      adev->caps |= PCM_CAP_FREERATE;
 
436
    }
 
437
  else
 
438
    {
 
439
      min_rate = 1 << 30;
 
440
      max_rate = 0;
 
441
 
 
442
      for (i = 0; i < d[8]; i++)
 
443
        {
 
444
          int r = ossusb_get_int (&d[9 + i * 3], 3);
 
445
 
 
446
          if (r < min_rate)
 
447
            min_rate = r;
 
448
          if (r > max_rate)
 
449
            max_rate = r;
 
450
        }
 
451
    }
 
452
 
 
453
  adev->min_channels = adev->max_channels = 2;
 
454
  adev->oformat_mask = adev->iformat_mask = AFMT_AC3;
 
455
  adev->min_rate = min_rate;
 
456
  adev->max_rate = max_rate;
 
457
 
 
458
  return 0;
 
459
}
 
460
 
 
461
/*ARGSUSED*/
 
462
static int
 
463
setup_format_specific (ossusb_devc * devc, ossusb_portc * portc, adev_p adev,
 
464
                       unsigned char *d, int l)
 
465
{
 
466
  int fmt;
 
467
 
 
468
  fmt = ossusb_get_int (&d[3], 2);
 
469
 
 
470
  if (usb_trace > 1)
 
471
    cmn_err (CE_CONT, "Format specific: fmt=%04x\n", fmt);
 
472
 
 
473
  switch (fmt)
 
474
    {
 
475
    case FORMAT_II_MPEG:
 
476
      if (usb_trace > 1)
 
477
        cmn_err (CE_CONT, "MPEG format\n");
 
478
      adev->oformat_mask = adev->iformat_mask = AFMT_MPEG;
 
479
      break;
 
480
 
 
481
    case FORMAT_II_AC3:
 
482
      if (usb_trace > 1)
 
483
        cmn_err (CE_CONT, "AC3 format\n");
 
484
      adev->oformat_mask = adev->iformat_mask = AFMT_AC3;
 
485
#if 0
 
486
      cmn_err (CE_CONT, "BSID=%08x\n", ossusb_get_int (&d[5], 4));
 
487
      cmn_err (CE_CONT, "AC3Features %02x\n", d[9]);
 
488
#endif
 
489
      break;
 
490
 
 
491
    default:
 
492
      cmn_err (CE_CONT, "oss usbaudio: Unsupported FORMAT II tag %04x\n",
 
493
               fmt);
 
494
      adev->enabled = 0;
 
495
      return OSS_ENXIO;
 
496
    }
 
497
  return 0;
 
498
}
 
499
 
 
500
static int
 
501
prepare_altsetting (ossusb_devc * devc, ossusb_portc * portc, int new_setting)
 
502
{
 
503
  int desc_len;
 
504
  unsigned char *desc, *d;
 
505
  int l, p;
 
506
  int err;
 
507
  adev_p adev;
 
508
 
 
509
  adev = audio_engines[portc->audio_dev];
 
510
  adev->enabled = 1;
 
511
  portc->disabled = 0;
 
512
 
 
513
  if (portc->act_setting == new_setting)        /* No need to change */
 
514
    return 0;
 
515
 
 
516
  if (new_setting < portc->num_settings)
 
517
    desc = udi_usbdev_get_altsetting (portc->usbdev, new_setting, &desc_len);
 
518
  else
 
519
    desc = NULL;
 
520
 
 
521
  if (desc == NULL || desc_len < 3)
 
522
    {
 
523
      cmn_err (CE_CONT,
 
524
               "Audio device %d not available when altsetting=%d\n",
 
525
               audio_engines[portc->audio_dev]->real_dev, new_setting);
 
526
      portc->disabled = 1;
 
527
      adev->enabled = 0;
 
528
      portc->act_setting = new_setting;
 
529
      return OSS_ENXIO;
 
530
    }
 
531
 
 
532
  UDB (cmn_err
 
533
       (CE_CONT, "Select active setting %d on interface %d (dsp%d)\n",
 
534
        new_setting, portc->if_number, adev->engine_num));
 
535
  portc->act_setting = new_setting;
 
536
 
 
537
  p = 0;
 
538
  while (p < desc_len)
 
539
    {
 
540
      int i;
 
541
 
 
542
      d = desc + p;
 
543
      l = *d;
 
544
 
 
545
      if (usb_trace > 1)
 
546
        {
 
547
          cmn_err (CE_CONT, "Streaming desc: ");
 
548
          for (i = 0; i < l; i++)
 
549
            cmn_err (CE_CONT, "%02x ", d[i]);
 
550
          cmn_err (CE_CONT, "\n");
 
551
 
 
552
        }
 
553
 
 
554
      if (d[1] != CS_INTERFACE)
 
555
        {
 
556
        UDB (cmn_err (CE_CONT, "Unknown descriptor type %02x\n", d[1]))}
 
557
      else
 
558
        switch (d[2])
 
559
          {
 
560
          case AS_GENERAL:
 
561
            portc->terminal_link = d[3];
 
562
            portc->pipeline_delay = d[4];
 
563
 
 
564
            if (usb_trace > 1)
 
565
              {
 
566
                cmn_err (CE_CONT, "AS_GENERAL ");
 
567
                cmn_err (CE_CONT, "Terminal link %d/%s ", d[3],
 
568
                         devc->units[d[3]].name);
 
569
                cmn_err (CE_CONT, "Delay %d ", d[4]);
 
570
                cmn_err (CE_CONT, "Format tag %02x%02x ", d[5], d[6]);
 
571
                cmn_err (CE_CONT, "\n");
 
572
              }
 
573
            break;
 
574
 
 
575
          case AS_FORMAT_TYPE:
 
576
            if (usb_trace > 1)
 
577
              {
 
578
                cmn_err (CE_CONT, "AS_FORMAT_TYPE: FORMAT_TYPE_%d: ", d[3]);
 
579
              }
 
580
 
 
581
            switch (d[3])
 
582
              {
 
583
              case 1:           /* FORMAT_TYPE_I */
 
584
                if ((err = setup_format_I (devc, portc, adev, d, l)) < 0)
 
585
                  return err;
 
586
                break;
 
587
 
 
588
              case 2:           /* FORMAT_TYPE_II */
 
589
                if ((err = setup_format_II (devc, portc, adev, d, l)) < 0)
 
590
                  return err;
 
591
                break;
 
592
 
 
593
              default:
 
594
                cmn_err (CE_CONT,
 
595
                         "\noss usbaudio: Unsupported format type %d\n",
 
596
                         d[3]);
 
597
                adev->enabled = 0;
 
598
                return OSS_ENXIO;
 
599
              }
 
600
            break;
 
601
 
 
602
          case AS_FORMAT_SPECIFIC:
 
603
            if ((err = setup_format_specific (devc, portc, adev, d, l)) < 0)
 
604
              return err;
 
605
            break;
 
606
 
 
607
          default:
 
608
            UDB (cmn_err
 
609
                 (CE_CONT, "Unknown descriptor subtype %02x\n", d[2]));
 
610
          }
 
611
 
 
612
      p += l;
 
613
    }
 
614
 
 
615
  desc = udi_usbdev_get_endpoint (portc->usbdev, portc->act_setting, 0, &l);
 
616
  if (desc == NULL)
 
617
    {
 
618
      cmn_err (CE_CONT, "oss usbaudio: Bad endpoint\n");
 
619
      return OSS_EIO;
 
620
    }
 
621
 
 
622
  portc->endpoint_desc = desc;
 
623
 
 
624
  desc = udi_usbdev_get_endpoint (portc->usbdev, portc->act_setting, 1, &l);
 
625
#if 0
 
626
  if (desc != NULL)
 
627
    {
 
628
      /* TODO: Handle sync endpoints */
 
629
      cmn_err (CE_CONT, "Sync Endpoint: ");
 
630
      ossusb_dump_desc (desc, l);
 
631
    }
 
632
#endif
 
633
 
 
634
  return 0;
 
635
}
 
636
 
 
637
static void usbaudio_close (int dev, int mode);
 
638
 
 
639
/*ARGSUSED*/
 
640
static int
 
641
usbaudio_open (int dev, int mode, int open_flags)
 
642
{
 
643
  ossusb_devc *devc = audio_engines[dev]->devc;
 
644
  ossusb_portc *portc = audio_engines[dev]->portc;
 
645
  oss_native_word flags, phaddr;
 
646
  int err;
 
647
  int i;
 
648
 
 
649
  if (devc->disabled)
 
650
    return OSS_EPIPE;
 
651
 
 
652
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
653
  if (portc->open_mode != 0)
 
654
    {
 
655
      MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
656
      return OSS_EBUSY;
 
657
    }
 
658
  portc->open_mode = mode;
 
659
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
660
 
 
661
  if ((err = prepare_altsetting (devc, portc, portc->act_setting)) < 0)
 
662
    {
 
663
      portc->open_mode = 0;
 
664
      return err;
 
665
    }
 
666
 
 
667
  {
 
668
    int i;
 
669
 
 
670
    for (i = 0; i < 2; i++)
 
671
      portc->tmp_buf[i] =
 
672
        CONTIG_MALLOC (devc->osdev, TMPBUF_SIZE, MEMLIMIT_32BITS, &phaddr, portc->tmpbuf_dma_handle[i]);
 
673
  }
 
674
 
 
675
  if ((err =
 
676
       udi_usbdev_set_interface (portc->usbdev, portc->if_number,
 
677
                                 portc->act_setting)) < 0)
 
678
    {
 
679
      cmn_err (CE_NOTE,
 
680
               "oss usbaudio: Failed to set interface mode, error %d - ignored\n",
 
681
               err);
 
682
      // portc->open_mode = 0;
 
683
      //return err;
 
684
    }
 
685
 
 
686
  portc->curr_datapipe = 0;
 
687
 
 
688
  if ((portc->endpoint_handle =
 
689
       udi_open_endpoint (portc->usbdev, portc->endpoint_desc)) == NULL)
 
690
    {
 
691
      usbaudio_close (dev, mode);
 
692
      cmn_err (CE_WARN, "Cannot open audio pipe\n");
 
693
      return OSS_ENOMEM;
 
694
    }
 
695
 
 
696
  for (i = 0; i < 2; i++)
 
697
    {
 
698
      if ((portc->datapipe[i] =
 
699
           udi_usb_alloc_request (portc->usbdev, portc->endpoint_handle, 1,
 
700
                                  UDI_USBXFER_ISO_WRITE)) == NULL)
 
701
        {
 
702
          usbaudio_close (dev, mode);
 
703
          cmn_err (CE_WARN, "Cannot alloc isoc request\n");
 
704
          return OSS_ENOMEM;
 
705
        }
 
706
    }
 
707
 
 
708
  set_fraglimits (audio_engines[dev], portc);
 
709
  return 0;
 
710
}
 
711
 
 
712
static void usbaudio_reset (int dev);
 
713
 
 
714
/*ARGSUSED*/
 
715
static void
 
716
usbaudio_close (int dev, int mode)
 
717
{
 
718
  ossusb_devc *devc = audio_engines[dev]->devc;
 
719
  ossusb_portc *portc = audio_engines[dev]->portc;
 
720
  int i;
 
721
 
 
722
  usbaudio_reset (dev);
 
723
 
 
724
  for (i = 0; i < 2; i++)
 
725
    {
 
726
      if (portc->datapipe[i] != NULL)
 
727
        {
 
728
          udi_usb_free_request (portc->datapipe[i]);
 
729
          portc->datapipe[i] = NULL;
 
730
        }
 
731
 
 
732
      if (portc->tmp_buf[i] != NULL)
 
733
        {
 
734
          CONTIG_FREE (devc->osdev, portc->tmp_buf[i], TMPBUF_SIZE, portc->tmpbuf_dma_handle[i]);
 
735
          portc->tmp_buf[i] = NULL;
 
736
        }
 
737
    }
 
738
 
 
739
  if (portc->endpoint_handle != NULL)
 
740
    udi_close_endpoint (portc->endpoint_handle);
 
741
 
 
742
  udi_usbdev_set_interface (portc->usbdev, portc->if_number, 0);
 
743
  portc->open_mode = 0;
 
744
}
 
745
 
 
746
/*ARGSUSED*/
 
747
static void
 
748
usbaudio_output_block (int dev, oss_native_word buf, int count,
 
749
                       int fragsize, int intrflag)
 
750
{
 
751
  ossusb_devc *devc = audio_engines[dev]->devc;
 
752
  if (devc->disabled)
 
753
    return;
 
754
}
 
755
 
 
756
/*ARGSUSED*/
 
757
static void
 
758
usbaudio_start_input (int dev, oss_native_word buf, int count, int fragsize,
 
759
                      int intrflag)
 
760
{
 
761
  ossusb_devc *devc = audio_engines[dev]->devc;
 
762
  if (devc->disabled)
 
763
    return;
 
764
}
 
765
 
 
766
static int feed_output (int dev, ossusb_devc * devc, ossusb_portc * portc);
 
767
static void start_input (int dev, ossusb_devc * devc, ossusb_portc * portc);
 
768
 
 
769
static int
 
770
copy_input (ossusb_portc * portc, dmap_t * dmap, unsigned char *buf, int len)
 
771
{
 
772
  int outlen = 0;
 
773
  int offs;
 
774
 
 
775
  offs = (int) (dmap->byte_counter % dmap->bytes_in_use);
 
776
 
 
777
  while (len > 0)
 
778
    {
 
779
      int l;
 
780
      l = len;
 
781
 
 
782
      if (portc->convert_3byte)
 
783
        {
 
784
          int i, n;
 
785
          int *dmabuf;
 
786
 
 
787
          l = (l * 4) / 3;
 
788
          /* Check for buffer wraparound */
 
789
          if (offs + l > dmap->bytes_in_use)
 
790
            l = dmap->bytes_in_use - offs;
 
791
 
 
792
          n = (l / 4);
 
793
 
 
794
          if (dmap == NULL || dmap->dmabuf == NULL)
 
795
            return outlen;
 
796
 
 
797
          dmabuf = (int *) (dmap->dmabuf + offs);
 
798
 
 
799
          for (i = 0; i < n; i++)
 
800
            {
 
801
              int v;
 
802
 
 
803
              v = buf[2] | (buf[1] << 8) | (buf[0] << 16);
 
804
              *dmabuf++ = v;
 
805
              buf += 3;
 
806
            }
 
807
 
 
808
          outlen += l;
 
809
        }
 
810
      else
 
811
        {
 
812
          unsigned char *dmabuf;
 
813
          dmabuf = dmap->dmabuf;
 
814
 
 
815
          if (dmap == NULL || dmap->dmabuf == NULL)
 
816
            return outlen;
 
817
 
 
818
          /* Check for buffer wraparound */
 
819
          if (offs + l > dmap->bytes_in_use)
 
820
            l = dmap->bytes_in_use - offs;
 
821
 
 
822
          memcpy (dmabuf + offs, buf, l);
 
823
          outlen += l;
 
824
          buf += l;
 
825
        }
 
826
 
 
827
      len -= l;
 
828
      offs = 0;
 
829
    }
 
830
 
 
831
  return outlen;
 
832
}
 
833
 
 
834
/*ARGSUSED*/
 
835
static void
 
836
play_callback (udi_usb_request_t * request, void *arg)
 
837
{
 
838
  ossusb_portc *portc = arg;
 
839
 
 
840
  feed_output (portc->audio_dev, portc->devc, portc);
 
841
  oss_audio_outputintr (portc->audio_dev,
 
842
                        AINTR_NO_POINTER_UPDATES | AINTR_LOCALQUEUE);
 
843
}
 
844
 
 
845
static void
 
846
rec_callback (udi_usb_request_t * request, void *arg)
 
847
{
 
848
  ossusb_portc *portc = arg;
 
849
  dmap_t *dmap;
 
850
  int len;
 
851
 
 
852
  if (portc == NULL || (unsigned long) arg < 4096)
 
853
    {
 
854
      cmn_err (CE_WARN, "Bad portc\n");
 
855
      return;
 
856
    }
 
857
 
 
858
  dmap = audio_engines[portc->audio_dev]->dmap_in;
 
859
  len = udi_usb_request_actlen (request);
 
860
 
 
861
  if (len == 0)
 
862
    return;                     /* No data so it looks like we are closing down */
 
863
 
 
864
  if ((len =
 
865
       copy_input (portc, dmap, udi_usb_request_actdata (request), len)) < 1)
 
866
    {
 
867
      cmn_err (CE_WARN, "Saving recorded data failed (%d)\n", len);
 
868
      return;
 
869
    }
 
870
 
 
871
  oss_audio_inc_byte_counter (dmap, len);
 
872
  oss_audio_inputintr (portc->audio_dev, AINTR_NO_POINTER_UPDATES);
 
873
#ifdef linux
 
874
  start_input (portc->audio_dev, portc->devc, portc);
 
875
#endif
 
876
}
 
877
 
 
878
#if 0
 
879
/*
 
880
 * Testing stuff only
 
881
 */
 
882
static int
 
883
sin_gen (void)
 
884
{
 
885
 
 
886
  static int phase = 0, v;
 
887
 
 
888
  static short sinebuf[48] = {
 
889
    0, 4276, 8480, 12539, 16383, 19947, 23169, 25995,
 
890
    28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272,
 
891
    28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276,
 
892
    0, -4276, -8480, -12539, -16383, -19947, -23169, -25995,
 
893
    -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272,
 
894
    -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276
 
895
  };
 
896
  v = sinebuf[phase] * 256;
 
897
  phase = (phase + 1) % 48;
 
898
 
 
899
  return v;
 
900
}
 
901
#endif
 
902
 
 
903
/*ARGSUSED*/
 
904
static int
 
905
output_convert (ossusb_devc * devc, ossusb_portc * portc, dmap_p dmap,
 
906
                unsigned char *dmabuf, int pos, int pn, int total_len)
 
907
{
 
908
  unsigned char *tmpbuf = portc->tmp_buf[pn], *b;
 
909
  int i, n, len, out_size = 0;
 
910
  int err;
 
911
 
 
912
  while (total_len > 0)
 
913
    {
 
914
      int l = total_len;
 
915
 
 
916
      /* Check for buffer wraparound */
 
917
      if (pos + l > dmap->bytes_in_use)
 
918
        l = dmap->bytes_in_use - pos;
 
919
 
 
920
      total_len -= l;
 
921
 
 
922
      b = dmabuf + pos;
 
923
 
 
924
      if (portc->convert_3byte)
 
925
        {
 
926
          int *buf;
 
927
 
 
928
          n = l / sizeof (*buf);
 
929
          buf = (int *) b;
 
930
 
 
931
          len = n * 3;
 
932
 
 
933
          for (i = 0; i < n; i++)
 
934
            {
 
935
              int val = (*buf++);
 
936
 
 
937
              val /= 256;
 
938
              // val=sin_gen();
 
939
              *tmpbuf++ = (val) & 0xff;
 
940
              *tmpbuf++ = (val >> 8) & 0xff;
 
941
              *tmpbuf++ = (val >> 16) & 0xff;
 
942
            }
 
943
        }
 
944
      else
 
945
        {
 
946
          len = l;
 
947
          memcpy (tmpbuf, b, l);
 
948
          tmpbuf += l;
 
949
        }
 
950
 
 
951
      pos = 0;
 
952
      out_size += len;
 
953
    }
 
954
 
 
955
  if ((err =
 
956
       udi_usb_submit_request (portc->datapipe[pn], play_callback, portc,
 
957
                               portc->endpoint_handle, UDI_USBXFER_ISO_WRITE,
 
958
                               portc->tmp_buf[pn], out_size)) < 0)
 
959
    {
 
960
      //cmn_err(CE_CONT, "oss usbaudio: Write transfer eror %d\n", err);
 
961
      return err;
 
962
    }
 
963
 
 
964
  return 0;
 
965
}
 
966
 
 
967
static int
 
968
feed_output (int dev, ossusb_devc * devc, ossusb_portc * portc)
 
969
{
 
970
  int pn, pos, len;
 
971
  oss_native_word flags;
 
972
  adev_p adev = audio_engines[dev];
 
973
  dmap_p dmap = adev->dmap_out;
 
974
 
 
975
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
976
 
 
977
  if (portc->stopping)
 
978
    {
 
979
      MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
980
      return 0;
 
981
    }
 
982
 
 
983
  pn = portc->curr_datapipe;
 
984
  portc->curr_datapipe = (portc->curr_datapipe + 1) % NR_DATAPIPES;
 
985
 
 
986
  pos = (int) (dmap->byte_counter % dmap->bytes_in_use);
 
987
  len = portc->fragment_size;
 
988
 
 
989
  portc->overflow_samples += portc->overflow_size;
 
990
  if (portc->overflow_samples > 1000)
 
991
    {
 
992
      len += dmap->frame_size * (portc->overflow_samples / 1000);
 
993
      portc->overflow_samples = portc->overflow_samples % 1000;
 
994
    }
 
995
 
 
996
  output_convert (devc, portc, dmap, dmap->dmabuf, pos, pn, len);
 
997
  oss_audio_inc_byte_counter (dmap, len);
 
998
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
999
  return 0;
 
1000
}
 
1001
 
 
1002
static void
 
1003
start_input (int dev, ossusb_devc * devc, ossusb_portc * portc)
 
1004
{
 
1005
  int frag, err;
 
1006
  oss_native_word flags;
 
1007
  adev_p adev = audio_engines[dev];
 
1008
  dmap_p dmap = adev->dmap_in;
 
1009
 
 
1010
  if (portc->stopping)
 
1011
    return;
 
1012
 
 
1013
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
1014
  frag = 0;
 
1015
 
 
1016
  if ((err =
 
1017
       udi_usb_submit_request (portc->datapipe[0], rec_callback, portc,
 
1018
                               portc->endpoint_handle, UDI_USBXFER_ISO_READ,
 
1019
                               dmap->dmabuf + frag * portc->fragment_size,
 
1020
                               portc->fragment_size)) < 0)
 
1021
    {
 
1022
      cmn_err (CE_WARN, "oss usbaudio: Read transfer error %d\n", err);
 
1023
      cmn_err (CE_CONT, "Endpoint %02x\n",
 
1024
               udi_endpoint_get_num (portc->endpoint_handle));
 
1025
    }
 
1026
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
1027
}
 
1028
 
 
1029
static void
 
1030
usbaudio_trigger (int dev, int state)
 
1031
{
 
1032
  ossusb_devc *devc = audio_engines[dev]->devc;
 
1033
  ossusb_portc *portc = audio_engines[dev]->portc;
 
1034
 
 
1035
  if (devc->disabled)
 
1036
    return;
 
1037
 
 
1038
  if (portc->open_mode & PCM_ENABLE_OUTPUT)
 
1039
    {
 
1040
      if ((portc->prepared_modes & PCM_ENABLE_OUTPUT)
 
1041
          && (state & PCM_ENABLE_OUTPUT))
 
1042
        {
 
1043
          portc->prepared_modes &= ~PCM_ENABLE_OUTPUT;
 
1044
          portc->curr_datapipe = 0;
 
1045
          portc->stopping = 0;
 
1046
 
 
1047
          feed_output (dev, devc, portc);
 
1048
          feed_output (dev, devc, portc);
 
1049
        }
 
1050
      else if (!(state & PCM_ENABLE_OUTPUT))
 
1051
        {
 
1052
          portc->stopping = 1;
 
1053
#if 1
 
1054
          udi_usb_cancel_request (portc->datapipe[0]);
 
1055
          udi_usb_cancel_request (portc->datapipe[1]);
 
1056
#endif
 
1057
          portc->curr_datapipe = 0;
 
1058
        }
 
1059
    }
 
1060
 
 
1061
  if (portc->open_mode & PCM_ENABLE_INPUT)
 
1062
    {
 
1063
      if ((portc->prepared_modes & PCM_ENABLE_INPUT)
 
1064
          && (state & PCM_ENABLE_INPUT))
 
1065
        {
 
1066
          portc->prepared_modes &= ~PCM_ENABLE_INPUT;
 
1067
          portc->stopping = 0;
 
1068
          start_input (dev, devc, portc);
 
1069
        }
 
1070
      else if (!(state & PCM_ENABLE_INPUT))
 
1071
        {
 
1072
          portc->stopping = 1;
 
1073
#if 0
 
1074
          udi_usb_cancel_request (portc->datapipe[0]);
 
1075
          udi_usb_cancel_request (portc->datapipe[1]);
 
1076
#endif
 
1077
          portc->curr_datapipe = 0;
 
1078
        }
 
1079
    }
 
1080
}
 
1081
 
 
1082
static void
 
1083
usbaudio_reset (int dev)
 
1084
{
 
1085
  usbaudio_trigger (dev, 0);
 
1086
}
 
1087
 
 
1088
/*ARGSUSED*/
 
1089
static int
 
1090
usbaudio_prepare_for_input (int dev, int bsize, int bcount)
 
1091
{
 
1092
  ossusb_devc *devc = audio_engines[dev]->devc;
 
1093
  ossusb_portc *portc = audio_engines[dev]->portc;
 
1094
  adev_p adev = audio_engines[dev];
 
1095
 
 
1096
  if (devc->disabled)
 
1097
    return OSS_EPIPE;
 
1098
 
 
1099
 
 
1100
  if (adev->flags & ADEV_NOINPUT)
 
1101
    return OSS_ENOTSUP;
 
1102
 
 
1103
  portc->stopping = 0;
 
1104
 
 
1105
  if (write_control_value
 
1106
      (devc, portc->endpoint_handle, SAMPLING_FREQ_CONTROL, 3,
 
1107
       portc->speed) < 0)
 
1108
    {
 
1109
      cmn_err (CE_CONT, "Failed to set %d Hz sampling rate\n", portc->speed);
 
1110
      return OSS_EIO;
 
1111
    }
 
1112
 
 
1113
  /*
 
1114
   * Handle fractional samples that don't fit in the 1ms period.
 
1115
   */
 
1116
  portc->overflow_size = portc->speed % 1000;
 
1117
  portc->overflow_samples = 0;
 
1118
 
 
1119
  portc->prepared_modes |= PCM_ENABLE_INPUT;
 
1120
  return 0;
 
1121
}
 
1122
 
 
1123
/*ARGSUSED*/
 
1124
static int
 
1125
usbaudio_prepare_for_output (int dev, int bsize, int bcount)
 
1126
{
 
1127
  ossusb_devc *devc = audio_engines[dev]->devc;
 
1128
  ossusb_portc *portc = audio_engines[dev]->portc;
 
1129
  adev_p adev = audio_engines[dev];
 
1130
 
 
1131
  if (devc->disabled)
 
1132
    return OSS_EPIPE;
 
1133
 
 
1134
  if (adev->flags & ADEV_NOOUTPUT)
 
1135
    return OSS_ENOTSUP;
 
1136
 
 
1137
  portc->stopping = 0;
 
1138
 
 
1139
  if (write_control_value
 
1140
      (devc, portc->endpoint_handle, SAMPLING_FREQ_CONTROL, 3,
 
1141
       portc->speed) < 0)
 
1142
    {
 
1143
      cmn_err (CE_CONT, "Failed to set %d Hz sampling rate\n", portc->speed);
 
1144
      return OSS_EIO;
 
1145
    }
 
1146
 
 
1147
  /*
 
1148
   * Handle fractional samples that don't fit in the 1ms period.
 
1149
   */
 
1150
  portc->overflow_size = portc->speed % 1000;
 
1151
  portc->overflow_samples = 0;
 
1152
 
 
1153
  portc->prepared_modes |= PCM_ENABLE_OUTPUT;
 
1154
  return 0;
 
1155
}
 
1156
 
 
1157
static int
 
1158
usbaudio_check_input (int dev)
 
1159
{
 
1160
  ossusb_devc *devc = audio_engines[dev]->devc;
 
1161
  if (devc->disabled)
 
1162
    {
 
1163
      cmn_err (CE_CONT,
 
1164
               "oss usbaudio: Audio device %d removed from the system.\n",
 
1165
               dev);
 
1166
      return OSS_EPIPE;
 
1167
    }
 
1168
 
 
1169
  cmn_err (CE_CONT, "oss usbaudio: Audio input timed out on device %d.\n",
 
1170
           dev);
 
1171
  return OSS_EIO;
 
1172
}
 
1173
 
 
1174
static int
 
1175
usbaudio_check_output (int dev)
 
1176
{
 
1177
  ossusb_devc *devc = audio_engines[dev]->devc;
 
1178
  if (devc->disabled)
 
1179
    {
 
1180
      cmn_err (CE_CONT,
 
1181
               "oss usbaudio: Audio device %d removed from the system.\n",
 
1182
               dev);
 
1183
      return OSS_EPIPE;
 
1184
    }
 
1185
 
 
1186
  cmn_err (CE_CONT, "oss usbaudio: Audio output timed out on device %d.\n",
 
1187
           dev);
 
1188
  return OSS_EIO;
 
1189
}
 
1190
 
 
1191
static int
 
1192
usbaudio_local_qlen (int dev)
 
1193
{
 
1194
  ossusb_portc *portc = audio_engines[dev]->portc;
 
1195
  dmap_p dmap = audio_engines[dev]->dmap_out;
 
1196
  int delay = portc->pipeline_delay + 1;        /* Pipeline delay in 1 msec ticks */
 
1197
 
 
1198
  delay = delay * dmap->data_rate / 1000;       /* Bytes/msec */
 
1199
 
 
1200
  return delay;
 
1201
}
 
1202
 
 
1203
static audiodrv_t usbaudio_driver = {
 
1204
  usbaudio_open,
 
1205
  usbaudio_close,
 
1206
  usbaudio_output_block,
 
1207
  usbaudio_start_input,
 
1208
  usbaudio_ioctl,
 
1209
  usbaudio_prepare_for_input,
 
1210
  usbaudio_prepare_for_output,
 
1211
  usbaudio_reset,
 
1212
  usbaudio_local_qlen,
 
1213
  NULL,
 
1214
  NULL,
 
1215
  NULL,
 
1216
  usbaudio_trigger,
 
1217
  usbaudio_set_rate,
 
1218
  usbaudio_set_format,
 
1219
  usbaudio_set_channels,
 
1220
  NULL,
 
1221
  NULL,
 
1222
  usbaudio_check_input,
 
1223
  usbaudio_check_output,
 
1224
  NULL,                         /* usbaudio_alloc_buffer */
 
1225
  NULL,                         /* usbaudio_free_buffer */
 
1226
  NULL,
 
1227
  NULL,
 
1228
  NULL                          /* usbaudio_get_buffer_pointer */
 
1229
};
 
1230
 
 
1231
ossusb_devc *
 
1232
ossusb_init_audiostream (ossusb_devc * devc, udi_usb_devc * usbdev, int inum,
 
1233
                         int reinit)
 
1234
{
 
1235
  int nsettings, actsetting = 0, desc_len;
 
1236
  unsigned char *desc, *d;
 
1237
  adev_p adev;
 
1238
  int i, p, l;
 
1239
  int portc_num;
 
1240
  void *endpoint_desc;
 
1241
 
 
1242
  char dev_name[128];
 
1243
 
 
1244
  int opts = ADEV_AUTOMODE;
 
1245
 
 
1246
  ossusb_portc *portc;
 
1247
 
 
1248
  if (devc->num_audio_engines >= MAX_PORTC)
 
1249
    {
 
1250
      cmn_err (CE_CONT, "usbaudio: Too many audio streaming interfaces\n");
 
1251
      return devc;
 
1252
    }
 
1253
 
 
1254
  if (usbdev == NULL)
 
1255
    {
 
1256
      cmn_err (CE_CONT, "usbaudio: usbdev==NULL\n");
 
1257
      return devc;
 
1258
    }
 
1259
 
 
1260
  nsettings = udi_usbdev_get_num_altsettings (usbdev);
 
1261
  desc = udi_usbdev_get_endpoint (usbdev, 1, 0, &l);
 
1262
  if (desc != NULL)
 
1263
    {
 
1264
      /* cmn_err(CE_CONT, "Endpoint: ");ossusb_dump_desc(desc, l); */
 
1265
      endpoint_desc = desc;
 
1266
    }
 
1267
  else
 
1268
    endpoint_desc = NULL;
 
1269
 
 
1270
  if (reinit)
 
1271
    for (i = 0; i < devc->num_audio_engines; i++)
 
1272
      if (devc->portc[i].orig_endpoint_desc == endpoint_desc)   /* Already registered this */
 
1273
        {
 
1274
          prepare_altsetting (devc, &devc->portc[i],
 
1275
                              devc->portc[i].act_setting);
 
1276
          return devc;
 
1277
        }
 
1278
 
 
1279
  portc = &devc->portc[devc->num_audio_engines];
 
1280
  portc_num = devc->num_audio_engines;
 
1281
  portc->if_number = inum;
 
1282
  portc->endpoint_desc = portc->orig_endpoint_desc = endpoint_desc;
 
1283
  portc->usbdev = usbdev;
 
1284
  portc->act_setting = -1;      /* Set to an impossible value */
 
1285
  devc->num_audio_engines++;
 
1286
 
 
1287
  memset (dev_name, 0, sizeof (dev_name));
 
1288
  strncpy (dev_name, devc->dev_name, sizeof (dev_name) - 1);
 
1289
  portc->num_settings = nsettings;
 
1290
 
 
1291
#if 1
 
1292
  if (usb_trace > 2)
 
1293
    for (i = 0; i < nsettings; i++)
 
1294
      {
 
1295
        desc = udi_usbdev_get_altsetting (usbdev, i, &desc_len);
 
1296
        cmn_err (CE_CONT, "\nDumping altsetting %d (l=%d)\n", i, desc_len);
 
1297
        if (usb_trace)
 
1298
          ossusb_dump_desc (desc, desc_len);
 
1299
      }
 
1300
#endif
 
1301
 
 
1302
  desc = udi_usbdev_get_altsetting (usbdev, actsetting, &desc_len);
 
1303
 
 
1304
  if (desc == NULL || desc_len < 1)
 
1305
    for (i = 0; i < nsettings && (desc == NULL || desc_len < 1); i++)
 
1306
      {
 
1307
        UDB (cmn_err (CE_CONT, "Trying to read altsetting %d\n", i));
 
1308
        desc = udi_usbdev_get_altsetting (usbdev, i, &desc_len);
 
1309
        if (desc != NULL)
 
1310
          actsetting = i;
 
1311
      }
 
1312
 
 
1313
  UDB (cmn_err (CE_CONT, "Altsetting %d, len %d\n", actsetting, desc_len));
 
1314
 
 
1315
  if (desc == NULL)
 
1316
    {
 
1317
      cmn_err (CE_WARN, "Can't read interface descriptors\n");
 
1318
      return NULL;
 
1319
    }
 
1320
 
 
1321
  if (usb_trace > 2)
 
1322
    ossusb_dump_desc (desc, desc_len);
 
1323
 
 
1324
  p = 0;
 
1325
  while (p < desc_len)
 
1326
    {
 
1327
      d = desc + p;
 
1328
      l = *d;
 
1329
 
 
1330
      if (d[1] != CS_INTERFACE)
 
1331
        {
 
1332
        UDB (cmn_err (CE_CONT, "Unknown descriptor type %02x\n", d[1]))}
 
1333
      else
 
1334
        switch (d[2])
 
1335
          {
 
1336
          case AS_GENERAL:
 
1337
            portc->terminal_link = d[3];
 
1338
            break;
 
1339
          }
 
1340
 
 
1341
      p += l;
 
1342
    }
 
1343
 
 
1344
  if (portc->terminal_link > 0 && portc->terminal_link <= devc->nunits)
 
1345
    {
 
1346
      char *s = dev_name + strlen (dev_name);
 
1347
 
 
1348
      sprintf (s, " %s", devc->units[portc->terminal_link].name);
 
1349
      s += strlen (s);
 
1350
 
 
1351
      if (devc->units[portc->terminal_link].typ == TY_OUTPUT)   /* USB terminal type */
 
1352
        {
 
1353
          opts |= ADEV_NOOUTPUT;
 
1354
        }
 
1355
      else
 
1356
        {
 
1357
          opts |= ADEV_NOINPUT;
 
1358
        }
 
1359
    }
 
1360
 
 
1361
  if ((portc->audio_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
 
1362
                                                devc->osdev,
 
1363
                                                devc->osdev,
 
1364
                                                dev_name,
 
1365
                                                &usbaudio_driver,
 
1366
                                                sizeof (audiodrv_t),
 
1367
                                                opts,
 
1368
                                                AFMT_S16_NE, devc, -1)) < 0)
 
1369
    {
 
1370
      return devc;
 
1371
    }
 
1372
 
 
1373
  portc->devc = devc;
 
1374
  adev = audio_engines[portc->audio_dev];
 
1375
  adev->portc = portc;
 
1376
  adev->mixer_dev = devc->mixer_dev;
 
1377
  adev->rate_source = devc->portc[0].audio_dev;
 
1378
  adev->max_block = 256;
 
1379
  adev->min_fragments = 4;      /* vmix needs this */
 
1380
 
 
1381
  prepare_altsetting (devc, portc, 1);
 
1382
 
 
1383
  if (portc->num_settings > 2)
 
1384
    {
 
1385
      char name[128];
 
1386
 
 
1387
      sprintf (name, "%s-altset", devc->units[portc->terminal_link].name);
 
1388
      ossusb_create_altset_control (devc->mixer_dev, portc_num,
 
1389
                                    portc->num_settings, name);
 
1390
    }
 
1391
 
 
1392
#if 0
 
1393
  // TODO: This needs to be checked before vmix is enabled
 
1394
#ifdef CONFIG_OSS_VMIX
 
1395
  if (devc->units[portc->terminal_link].typ != TY_OUTPUT)
 
1396
     vmix_attach_audiodev(devc->osdev, portc->audio_dev, -1, 0);
 
1397
#endif
 
1398
#endif
 
1399
  return devc;
 
1400
}
 
1401
 
 
1402
/*ARGSUSED*/
 
1403
int
 
1404
ossusb_change_altsetting (int dev, int ctrl, unsigned int cmd, int value)
 
1405
{
 
1406
  ossusb_devc *devc = mixer_devs[dev]->devc;
 
1407
  ossusb_portc *portc;
 
1408
 
 
1409
  if (ctrl < 0 || ctrl >= devc->num_audio_engines)
 
1410
    return OSS_ENXIO;
 
1411
 
 
1412
  portc = &devc->portc[ctrl];
 
1413
 
 
1414
  if (cmd == SNDCTL_MIX_READ)
 
1415
    return portc->act_setting;
 
1416
 
 
1417
  if (value >= portc->num_settings)
 
1418
    value = portc->num_settings - 1;
 
1419
 
 
1420
  if (portc->act_setting != value)
 
1421
    {
 
1422
      prepare_altsetting (devc, portc, value);
 
1423
    }
 
1424
  return value;
 
1425
}