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

« back to all changes in this revision

Viewing changes to kernel/drv/oss_usb/ossusb_midisport.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: Dedicated driver for M-Audio/Midiman MIDISPORT USB MIDI family
 
3
 */
 
4
 
 
5
/*
 
6
 *
 
7
 * This file is part of Open Sound System.
 
8
 *
 
9
 * Copyright (C) 4Front Technologies 1996-2008.
 
10
 *
 
11
 * This this source file is released under GPL v2 license (no other versions).
 
12
 * See the COPYING file included in the main directory of this source
 
13
 * distribution for the license terms and conditions.
 
14
 *
 
15
 */
 
16
 
 
17
#include "oss_config.h"
 
18
#include "midi_core.h"
 
19
#include "ossusb.h"
 
20
#include "midisport2x2_fw.h"
 
21
#include "midisport1x1_fw.h"
 
22
#include "oxygen8_fw.h"
 
23
 
 
24
/*
 
25
 * Audiosport Quattro also use the same packet protocol (no FW load).
 
26
 *                Out EP 2 is the output and in EP 1 is the input (check this).
 
27
 */
 
28
#define RECBUF_SIZE     (10*4)
 
29
#define DLBUF_SIZE      63
 
30
#define MAX_PACK        32
 
31
#define PLAYBUF_SIZE    (MAX_PACK*4)
 
32
#define QUEUE_ENTRIES   17
 
33
#define QUEUE_SIZE      (QUEUE_ENTRIES*PLAYBUF_SIZE)
 
34
#define MAX_PORTS       9
 
35
 
 
36
static int instance_num = 0;
 
37
 
 
38
typedef struct midisport_devc midisport_devc;
 
39
 
 
40
typedef unsigned char playbuf_t[PLAYBUF_SIZE];
 
41
 
 
42
typedef struct
 
43
{
 
44
  oss_mutex_t mutex;
 
45
  midisport_devc *devc;
 
46
  int open_count;
 
47
  int busy;
 
48
  int max_out_blocks;           /* Num of 4(3) byte blocks allowed in single message */
 
49
 
 
50
  playbuf_t *playbuf;           /* QUEUE_SIZE */
 
51
  oss_dma_handle_t playbuf_dma_handle;
 
52
  int playbuf_h, playbuf_t;
 
53
 
 
54
  unsigned char *out_ep_desc;
 
55
  udi_usb_request_t *output_pipe;
 
56
  udi_endpoint_handle_t *output_endpoint_handle;
 
57
} midisport_outqueue_t;
 
58
 
 
59
typedef struct
 
60
{
 
61
  midisport_devc *devc;
 
62
  oss_device_t *osdev;
 
63
  oss_mutex_t mutex;
 
64
 
 
65
  int portnum;
 
66
  int midi_dev;
 
67
  int open_mode;
 
68
  oss_midi_inputbyte_t midi_input_intr;
 
69
  playbuf_t output_buf;
 
70
  int outbuf_p;
 
71
 
 
72
  int outqueue_ix;              /* Output queue 0 or 1 */
 
73
  oss_midi_outputintr_t outputintr;
 
74
} midisport_midic;
 
75
 
 
76
static int alphabethic_numbering = 1;
 
77
 
 
78
struct midisport_devc
 
79
{
 
80
  special_unload_t unload_func;
 
81
  int is_dummy;
 
82
  oss_device_t *osdev;
 
83
  oss_mutex_t mutex;
 
84
  ossusb_devc *usb_devc;
 
85
  udi_usb_devc *usbdev;
 
86
 
 
87
  int instance_num;
 
88
 
 
89
  unsigned char *in_ep_desc;
 
90
 
 
91
  int num_inputs, num_outputs;
 
92
  int open_inputs;
 
93
  midisport_midic in_midic[MAX_PORTS];
 
94
  midisport_midic out_midic[MAX_PORTS];
 
95
 
 
96
  unsigned char *recbuf;
 
97
  oss_dma_handle_t recbuf_dma_handle;
 
98
  udi_usb_request_t *input_pipe;
 
99
  udi_endpoint_handle_t *input_endpoint_handle;
 
100
 
 
101
  int num_queues;
 
102
  midisport_outqueue_t out_queues[2];
 
103
};
 
104
 
 
105
static void
 
106
load_firmware (midisport_devc * devc, const struct setup_request *setup,
 
107
               char *name)
 
108
{
 
109
  int err;
 
110
 
 
111
  if (setup == NULL)
 
112
    {
 
113
      cmn_err (CE_WARN, "midisport: No firmware available\n");
 
114
      return;
 
115
    }
 
116
 
 
117
  while (setup->pData != NULL)
 
118
    {
 
119
#if 0
 
120
      cmn_err (CE_CONT, "Load(%x, Rq=%x, Rqt=%x, Val=%x, Ix=%x, data=%x, len=%d\n", devc->usbdev, setup->bRequest,      /* Request */
 
121
               setup->bmRequestType,    /* Rqtype */
 
122
               setup->wValue,   /* Value */
 
123
               setup->wIndex,   /* Index */
 
124
               setup->pData,    /* Data */
 
125
               setup->wLength); /* Len */
 
126
#endif
 
127
 
 
128
      err = udi_usb_snd_control_msg (devc->usbdev, 0,   /* Endpoint */
 
129
                                     setup->bRequest,   /* Request */
 
130
                                     setup->bmRequestType,      /* Rqtype */
 
131
                                     setup->wValue,     /* Value */
 
132
                                     setup->wIndex,     /* Index */
 
133
                                     (void *) setup->pData,     /* Data */
 
134
                                     setup->wLength,    /* Len */
 
135
                                     OSS_HZ);
 
136
      if (err < 0)
 
137
        {
 
138
          cmn_err (CE_WARN, "%s: Firmware download failed (%d)\n", name, err);
 
139
          return;
 
140
        }
 
141
 
 
142
      setup++;
 
143
    }
 
144
}
 
145
 
 
146
static void
 
147
midisport_unload (void *d)
 
148
{
 
149
  midisport_devc *devc = d;
 
150
 
 
151
  if (devc->is_dummy)
 
152
    {
 
153
      return;
 
154
    }
 
155
 
 
156
  MUTEX_CLEANUP (devc->mutex);
 
157
}
 
158
 
 
159
void *
 
160
midisport_init (ossusb_devc * usb_devc)
 
161
{
 
162
  midisport_devc *devc;
 
163
  unsigned int devid;
 
164
  char *name = "Unknown device";
 
165
  const struct setup_request *setup = NULL;
 
166
 
 
167
  devid = (usb_devc->vendor << 16) | usb_devc->product;
 
168
 
 
169
  switch (devid)
 
170
    {
 
171
    case 0x07631001:
 
172
      name = "MIDISPORT 2x2";
 
173
      setup = midisport2x2_setupRequest;
 
174
      break;
 
175
    case 0x07631014:
 
176
      name = "Oxygen8";
 
177
      setup = oxygen8_setupRequest;
 
178
      break;
 
179
    case 0x07631010:
 
180
      name = "MIDISPORT 1x1";
 
181
      setup = midisport1x1_setupRequest;
 
182
      break;
 
183
    }
 
184
 
 
185
  cmn_err (CE_CONT, "%s firmware load started\n", name);
 
186
 
 
187
  if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL)
 
188
    {
 
189
      cmn_err (CE_WARN, "midisport: Out of memory\n");
 
190
      return NULL;
 
191
    }
 
192
 
 
193
  memset (devc, 0, sizeof (*devc));
 
194
 
 
195
  devc->unload_func = midisport_unload;
 
196
  devc->is_dummy = 1;
 
197
  devc->osdev = usb_devc->osdev;
 
198
  devc->usb_devc = usb_devc;
 
199
  devc->usbdev = usb_devc->last_usbdev;
 
200
 
 
201
  load_firmware (devc, setup, name);
 
202
 
 
203
  cmn_err (CE_CONT, "%s firmware load completed\n", name);
 
204
  return devc;
 
205
}
 
206
 
 
207
static int midisport_start_input (midisport_devc * devc);
 
208
 
 
209
static void
 
210
record_callback (udi_usb_request_t * request, void *arg)
 
211
{
 
212
  midisport_devc *devc = arg;
 
213
  int i, l, p;
 
214
  unsigned char *data;
 
215
  data = udi_usb_request_actdata (request);
 
216
 
 
217
  l = udi_usb_request_actlen (request);
 
218
  if (l == 0)
 
219
    goto restart;
 
220
 
 
221
  for (p = 0; p < l - 3; p += 4)
 
222
    {
 
223
      unsigned char *buf, cmd;
 
224
      int nbytes, src;
 
225
      midisport_midic *midic;
 
226
 
 
227
      buf = data + p;
 
228
      cmd = buf[3];
 
229
      nbytes = cmd & 0x0f;
 
230
      src = (cmd >> 4) & 0x0f;
 
231
 
 
232
      if (nbytes == 0)          /* End of data */
 
233
        break;
 
234
 
 
235
      if (nbytes > 3 || src >= devc->num_inputs)
 
236
        continue;               /* No data or error */
 
237
 
 
238
      midic = &devc->in_midic[src];
 
239
 
 
240
      if (!(midic->open_mode & OPEN_READ) || midic->midi_input_intr == NULL)
 
241
        continue;               /* This device is not recording */
 
242
 
 
243
      for (i = 0; i < nbytes; i++)
 
244
        {
 
245
          midic->midi_input_intr (midic->midi_dev, buf[i]);
 
246
        }
 
247
    }
 
248
 
 
249
restart:
 
250
  midisport_start_input (devc);
 
251
}
 
252
 
 
253
static int
 
254
midisport_start_input (midisport_devc * devc)
 
255
{
 
256
  oss_native_word flags;
 
257
  int err = 0;
 
258
 
 
259
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
260
 
 
261
  if ((err =
 
262
       udi_usb_submit_request (devc->input_pipe, record_callback, devc,
 
263
                               devc->input_endpoint_handle,
 
264
                               UDI_USBXFER_INTR_READ, devc->recbuf,
 
265
                               RECBUF_SIZE)) < 0)
 
266
    {
 
267
      cmn_err (CE_WARN, "udi_usb_submit_request failed, err=%d\n", err);
 
268
    }
 
269
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
270
 
 
271
  return err;
 
272
}
 
273
 
 
274
static void submit_output (midisport_devc * devc, midisport_outqueue_t * q);
 
275
 
 
276
 /*ARGSUSED*/ static void
 
277
play_callback (udi_usb_request_t * request, void *arg)
 
278
{
 
279
  midisport_outqueue_t *q = arg;
 
280
  midisport_devc *devc = q->devc;
 
281
  oss_native_word flags;
 
282
 
 
283
  MUTEX_ENTER_IRQDISABLE (q->mutex, flags);
 
284
  q->busy = 0;
 
285
  submit_output (devc, q);
 
286
  MUTEX_EXIT_IRQRESTORE (q->mutex, flags);
 
287
}
 
288
 
 
289
 /*ARGSUSED*/ static void
 
290
submit_output (midisport_devc * devc, midisport_outqueue_t * q)
 
291
{
 
292
  int err;
 
293
  int max_bytes;
 
294
  unsigned char *qbuf;
 
295
 
 
296
  if (q->busy)
 
297
    return;
 
298
 
 
299
  if (q->playbuf_h == q->playbuf_t)     /* Queue empty */
 
300
    return;
 
301
 
 
302
  qbuf = q->playbuf[q->playbuf_h];
 
303
  max_bytes = q->max_out_blocks * 4;
 
304
 
 
305
  q->playbuf_h = (q->playbuf_h + 1) % QUEUE_ENTRIES;
 
306
  q->busy = 1;
 
307
 
 
308
  if ((err =
 
309
       udi_usb_submit_request (q->output_pipe, play_callback, q,
 
310
                               q->output_endpoint_handle,
 
311
                               UDI_USBXFER_BULK_WRITE, qbuf, max_bytes)) < 0)
 
312
    {
 
313
      cmn_err (CE_WARN, "udi_usb_submit_request (play) failed, err=%d\n",
 
314
               err);
 
315
    }
 
316
}
 
317
 
 
318
 /*ARGSUSED*/ static void
 
319
midisport_close_input (int dev, int mode)
 
320
{
 
321
  oss_native_word flags;
 
322
  midisport_midic *midic;
 
323
  midisport_devc *devc;
 
324
  int do_stop = 0;
 
325
 
 
326
  midic = midi_devs[dev]->devc;
 
327
  devc = midic->devc;
 
328
 
 
329
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
330
  devc->open_inputs--;
 
331
  if (devc->open_inputs == 0)
 
332
    do_stop = 1;
 
333
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
334
 
 
335
  if (do_stop)
 
336
    {
 
337
      udi_usb_free_request (devc->input_pipe);
 
338
      udi_close_endpoint (devc->input_endpoint_handle);
 
339
      if (devc->recbuf != NULL)
 
340
        CONTIG_FREE (midic->osdev, devc->recbuf, RECBUF_SIZE, devc->recbuf_dma_handle);
 
341
    }
 
342
 
 
343
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
344
  midic->open_mode = 0;
 
345
  midic->midi_input_intr = NULL;
 
346
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
347
}
 
348
 
 
349
 /*ARGSUSED*/ static int
 
350
midisport_open_input (int dev, int mode, oss_midi_inputbyte_t inputbyte,
 
351
                      oss_midi_inputbuf_t inputbuf,
 
352
                      oss_midi_outputintr_t outputintr)
 
353
{
 
354
  oss_native_word flags;
 
355
  midisport_midic *midic;
 
356
  midisport_devc *devc;
 
357
  oss_native_word phaddr;
 
358
  int do_start = 0;
 
359
 
 
360
  midic = midi_devs[dev]->devc;
 
361
  devc = midic->devc;
 
362
 
 
363
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
364
  if (midic->open_mode)
 
365
    {
 
366
      MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
367
      return OSS_EBUSY;
 
368
    }
 
369
 
 
370
  midic->open_mode = mode;
 
371
  midic->midi_input_intr = inputbyte;
 
372
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
373
 
 
374
 
 
375
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
376
  devc->open_inputs++;
 
377
  if (devc->open_inputs == 1)
 
378
    do_start = 1;
 
379
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
380
 
 
381
  if (do_start)
 
382
    {
 
383
      int err;
 
384
 
 
385
      devc->recbuf =
 
386
        CONTIG_MALLOC (devc->osdev, RECBUF_SIZE, MEMLIMIT_32BITS, &phaddr, devc->recbuf_dma_handle);
 
387
      if (devc->recbuf == NULL)
 
388
        {
 
389
          cmn_err (CE_CONT, "Failed to allocate the recording buffer\n");
 
390
          return OSS_ENOMEM;
 
391
        }
 
392
 
 
393
      if ((devc->input_endpoint_handle =
 
394
           udi_open_endpoint (devc->usbdev, devc->in_ep_desc)) == NULL)
 
395
        {
 
396
          midic->open_mode = 0;
 
397
          midic->midi_input_intr = NULL;
 
398
          cmn_err (CE_WARN, "Cannot open audio pipe\n");
 
399
          return OSS_ENOMEM;
 
400
        }
 
401
      if ((devc->input_pipe =
 
402
           udi_usb_alloc_request (devc->usbdev, devc->input_endpoint_handle,
 
403
                                  1, UDI_USBXFER_INTR_READ)) == NULL)
 
404
        {
 
405
          return OSS_EIO;
 
406
        }
 
407
 
 
408
      if ((err = midisport_start_input (devc)) < 0)
 
409
        {
 
410
          cmn_err (CE_WARN, "midisport: Input error %d\n", err);
 
411
          midisport_close_input (dev, mode);
 
412
          return OSS_EIO;
 
413
        }
 
414
    }
 
415
 
 
416
  return 0;
 
417
}
 
418
 
 
419
static int
 
420
open_output_queue (midisport_devc * devc, int queue_ix)
 
421
{
 
422
  oss_native_word flags;
 
423
  midisport_outqueue_t *q;
 
424
  int open_count;
 
425
  oss_native_word phaddr;
 
426
 
 
427
  if (queue_ix < 0 || queue_ix >= devc->num_queues)
 
428
    {
 
429
      cmn_err (CE_WARN, "Bad output queue index %d\n", queue_ix);
 
430
      return OSS_EIO;
 
431
    }
 
432
 
 
433
  q = &devc->out_queues[queue_ix];
 
434
 
 
435
  MUTEX_ENTER_IRQDISABLE (q->mutex, flags);
 
436
  open_count = q->open_count++;
 
437
 
 
438
  if (open_count == 0)          /* First open */
 
439
    {
 
440
      q->playbuf_h = q->playbuf_t = 0;
 
441
      q->busy = 0;
 
442
    }
 
443
  MUTEX_EXIT_IRQRESTORE (q->mutex, flags);
 
444
 
 
445
  if (open_count == 0)          /* First open */
 
446
    {
 
447
      if ((q->playbuf =
 
448
           CONTIG_MALLOC (devc->osdev, QUEUE_SIZE, MEMLIMIT_32BITS,
 
449
                          &phaddr, q->playbuf_dma_handle)) == NULL)
 
450
        {
 
451
          cmn_err (CE_WARN, "Failed to allocate output buffer (%d bytes)\n",
 
452
                   QUEUE_SIZE);
 
453
          q->open_count--;
 
454
          return OSS_ENOMEM;
 
455
        }
 
456
 
 
457
      if ((q->output_endpoint_handle =
 
458
           udi_open_endpoint (devc->usbdev, q->out_ep_desc)) == NULL)
 
459
        {
 
460
          cmn_err (CE_WARN, "Failed to open output endpoint\n");
 
461
          q->open_count--;
 
462
          return OSS_EIO;
 
463
        }
 
464
 
 
465
      if ((q->output_pipe =
 
466
           udi_usb_alloc_request (devc->usbdev, q->output_endpoint_handle, 1,
 
467
                                  UDI_USBXFER_BULK_WRITE)) == NULL)
 
468
        {
 
469
          cmn_err (CE_WARN, "Failed to allocate output request\n");
 
470
          q->open_count--;
 
471
          return OSS_EIO;
 
472
        }
 
473
 
 
474
    }
 
475
  return 0;
 
476
}
 
477
 
 
478
static void
 
479
close_output_queue (midisport_devc * devc, int queue_ix)
 
480
{
 
481
  oss_native_word flags;
 
482
  midisport_outqueue_t *q;
 
483
  int open_count;
 
484
 
 
485
  if (queue_ix < 0 || queue_ix >= devc->num_queues)
 
486
    {
 
487
      cmn_err (CE_WARN, "Bad output queue index %d\n", queue_ix);
 
488
      return;
 
489
    }
 
490
 
 
491
  q = &devc->out_queues[queue_ix];
 
492
 
 
493
  if (q->open_count <= 0)       /* Was not opened at all */
 
494
    return;
 
495
 
 
496
  MUTEX_ENTER_IRQDISABLE (q->mutex, flags);
 
497
  open_count = q->open_count--;
 
498
  MUTEX_EXIT_IRQRESTORE (q->mutex, flags);
 
499
 
 
500
  if (open_count <= 1)          /* Queue not needed any more */
 
501
    {
 
502
      udi_usb_free_request (q->output_pipe);
 
503
      udi_close_endpoint (q->output_endpoint_handle);
 
504
      if (q->playbuf != NULL)
 
505
        CONTIG_FREE (devc->osdev, q->playbuf, QUEUE_SIZE, q->playbuf_dma_handle);
 
506
    }
 
507
}
 
508
 
 
509
 /*ARGSUSED*/ static void
 
510
midisport_close_output (int dev, int mode)
 
511
{
 
512
  oss_native_word flags;
 
513
  midisport_midic *midic;
 
514
  midisport_devc *devc;
 
515
 
 
516
  midic = midi_devs[dev]->devc;
 
517
  devc = midic->devc;
 
518
 
 
519
  close_output_queue (devc, midic->outqueue_ix);
 
520
 
 
521
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
522
  midic->open_mode = 0;
 
523
  midic->outputintr = NULL;
 
524
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
525
}
 
526
 
 
527
 /*ARGSUSED*/ static int
 
528
midisport_open_output (int dev, int mode, oss_midi_inputbyte_t inputbyte,
 
529
                       oss_midi_inputbuf_t inputbuf,
 
530
                       oss_midi_outputintr_t outputintr)
 
531
{
 
532
  oss_native_word flags;
 
533
  midisport_midic *midic;
 
534
  midisport_devc *devc;
 
535
  int err;
 
536
 
 
537
  midic = midi_devs[dev]->devc;
 
538
  devc = midic->devc;
 
539
 
 
540
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
541
  if (midic->open_mode)
 
542
    {
 
543
      MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
544
      return OSS_EBUSY;
 
545
    }
 
546
 
 
547
  midic->open_mode = mode;
 
548
  midic->midi_input_intr = NULL, midic->outputintr = outputintr;
 
549
  midic->outbuf_p = 0;
 
550
  memset (midic->output_buf, 0, sizeof (midic->output_buf));
 
551
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
552
 
 
553
  if ((err = open_output_queue (devc, midic->outqueue_ix)) < 0)
 
554
    {
 
555
      cmn_err (CE_WARN, "Failed to open the output queue (%d)\n", err);
 
556
      midisport_close_output (dev, mode);
 
557
      return err;
 
558
    }
 
559
 
 
560
  return 0;
 
561
}
 
562
 
 
563
static int
 
564
do_flush (midisport_devc * devc, midisport_midic * midic,
 
565
          midisport_outqueue_t * q)
 
566
{
 
567
  int next;
 
568
  unsigned char *qbuf;
 
569
  int max_bytes;
 
570
 
 
571
  /*
 
572
   * Move stuff from the intermediate buffer to the EP queue
 
573
   */
 
574
  max_bytes = q->max_out_blocks * 4;
 
575
  next = (q->playbuf_t + 1) % QUEUE_ENTRIES;
 
576
  if (next == q->playbuf_h)     /* No more space in any of the buffers */
 
577
    {
 
578
      return 0;
 
579
    }
 
580
 
 
581
  qbuf = q->playbuf[q->playbuf_t];
 
582
  memcpy (qbuf, midic->output_buf, max_bytes);
 
583
  memset (midic->output_buf, 0, max_bytes);
 
584
  midic->outbuf_p = 0;
 
585
  q->playbuf_t = next;
 
586
 
 
587
  submit_output (devc, q);
 
588
 
 
589
  return 1;
 
590
}
 
591
 
 
592
#if 0
 
593
static void
 
594
midisport_flush_output (int dev)
 
595
{
 
596
  midisport_midic *midic = midi_devs[dev]->devc;
 
597
  midisport_devc *devc = midic->devc;
 
598
  midisport_outqueue_t *q;
 
599
  oss_native_word flags;
 
600
  oss_native_word qflags;
 
601
 
 
602
  q = &devc->out_queues[midic->outqueue_ix];
 
603
 
 
604
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
605
  MUTEX_ENTER_IRQDISABLE (q->mutex, qflags);
 
606
  do_flush (devc, midic, q);
 
607
  MUTEX_EXIT_IRQRESTORE (q->mutex, qflags);
 
608
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
609
}
 
610
#endif
 
611
 
 
612
static int
 
613
midisport_bulk_write (int dev, unsigned char *buf, int len)
 
614
{
 
615
  midisport_midic *midic = midi_devs[dev]->devc;
 
616
  midisport_devc *devc = midic->devc;
 
617
  oss_native_word flags;
 
618
  oss_native_word qflags;
 
619
  int i, l = 0, n = 0, p;
 
620
  //int max_bytes;
 
621
  midisport_outqueue_t *q;
 
622
  unsigned char *outbuf;
 
623
 
 
624
  if (midic->outqueue_ix < 0 || midic->outqueue_ix >= devc->num_queues)
 
625
    {
 
626
      cmn_err (CE_WARN, "Bad output queue index %d\n", midic->outqueue_ix);
 
627
      return OSS_EIO;
 
628
    }
 
629
 
 
630
  q = &devc->out_queues[midic->outqueue_ix];
 
631
 
 
632
  MUTEX_ENTER_IRQDISABLE (midic->mutex, flags);
 
633
 
 
634
  //max_bytes = q->max_out_blocks * 4;
 
635
 
 
636
  for (i = 0; i < len; i += 3)
 
637
    {
 
638
      l = len - i;
 
639
      if (l > 3)
 
640
        l = 3;
 
641
      p = midic->outbuf_p;
 
642
 
 
643
      if ((p + 4) >= q->max_out_blocks)
 
644
        {
 
645
          int next;
 
646
          MUTEX_ENTER_IRQDISABLE (q->mutex, qflags);
 
647
 
 
648
          next = (q->playbuf_t + 1) % QUEUE_ENTRIES;
 
649
          if (next == q->playbuf_h)     /* No more space in any of the buffers */
 
650
            {
 
651
              MUTEX_EXIT_IRQRESTORE (q->mutex, qflags);
 
652
              MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
653
              return n;
 
654
            }
 
655
 
 
656
          if (!do_flush (devc, midic, q))       /* Output FIFO full */
 
657
            {
 
658
              MUTEX_EXIT_IRQRESTORE (q->mutex, qflags);
 
659
              return n;
 
660
            }
 
661
          p = midic->outbuf_p;
 
662
          MUTEX_EXIT_IRQRESTORE (q->mutex, qflags);
 
663
        }
 
664
 
 
665
      outbuf = midic->output_buf + p;
 
666
      memcpy (outbuf, buf, l);
 
667
      outbuf[3] = (midic->portnum << 4) | l;
 
668
      midic->outbuf_p += 4;
 
669
      if (midic->outbuf_p >= q->max_out_blocks)
 
670
        do_flush (devc, midic, q);
 
671
      n += l;
 
672
    }
 
673
 
 
674
  MUTEX_EXIT_IRQRESTORE (midic->mutex, flags);
 
675
 
 
676
  return n;
 
677
}
 
678
 
 
679
 /*ARGSUSED*/ static int
 
680
midisport_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 
681
{
 
682
  return OSS_EINVAL;
 
683
}
 
684
 
 
685
static midi_driver_t midisport_midi_input_driver = {
 
686
  midisport_open_input,
 
687
  midisport_close_input,
 
688
  midisport_ioctl
 
689
};
 
690
 
 
691
static midi_driver_t midisport_midi_output_driver = {
 
692
  midisport_open_output,
 
693
  midisport_close_output,
 
694
  midisport_ioctl,
 
695
  NULL,
 
696
  midisport_bulk_write,
 
697
  8 * 3                         /* 8 packets of 3 bytes */
 
698
};
 
699
 
 
700
static void
 
701
create_inputs (midisport_devc * devc, char *name, int ep, int ninputs)
 
702
{
 
703
  int desc_len;
 
704
  int i, ix = ep;
 
705
  char portid = 'A';
 
706
  unsigned char *desc;
 
707
  int flags = MFLAG_INPUT;
 
708
 
 
709
  for (i = 0; i < 32; i++)
 
710
    if ((desc =
 
711
         udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL)
 
712
      {
 
713
        if (desc[2] == (ep | 0x80))
 
714
          ix = i;
 
715
      }
 
716
 
 
717
  if (!alphabethic_numbering)
 
718
    portid = '1';
 
719
 
 
720
  if (ninputs > MAX_PORTS)
 
721
    {
 
722
      cmn_err (CE_WARN, "Too many input ports %d\n", ninputs);
 
723
      return;
 
724
    }
 
725
 
 
726
  if ((devc->in_ep_desc =
 
727
       udi_usbdev_get_endpoint (devc->usbdev, 0, ix, &desc_len)) == NULL)
 
728
    {
 
729
      cmn_err (CE_WARN, "Bad endpoint %d\n", ep);
 
730
      return;
 
731
    }
 
732
 
 
733
  if (!(devc->in_ep_desc[2] & 0x80))
 
734
    {
 
735
      cmn_err (CE_WARN, "Bad endpoint %d - not input\n", ep);
 
736
    }
 
737
 
 
738
  for (i = 0; i < ninputs; i++)
 
739
    {
 
740
      midisport_midic *midic = midic = &devc->in_midic[i];
 
741
      char tmp[128];
 
742
 
 
743
      midic->devc = devc;
 
744
      midic->osdev = devc->osdev;
 
745
      MUTEX_INIT (devc->osdev, midic->mutex, MH_DRV + 1);
 
746
      midic->portnum = i;
 
747
      devc->num_inputs++;
 
748
 
 
749
      if (i == 8)
 
750
        {
 
751
          sprintf (tmp, "%s SMPTE status", name);
 
752
          flags = MFLAG_MTC;
 
753
        }
 
754
      else
 
755
        sprintf (tmp, "%s input %c", name, portid + i);
 
756
 
 
757
      midic->midi_dev =
 
758
        oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "MIDISPORT", tmp,
 
759
                             &midisport_midi_input_driver,
 
760
                             sizeof (midi_driver_t),
 
761
                             flags, midic, midic->osdev);
 
762
    }
 
763
}
 
764
 
 
765
static void
 
766
create_output (midisport_devc * devc, char *name, int queue_ix)
 
767
{
 
768
  int n;
 
769
  midisport_midic *midic = NULL;
 
770
  char tmp[128];
 
771
  char portid = 'A';
 
772
  int flags = MFLAG_OUTPUT;
 
773
 
 
774
  if (!alphabethic_numbering)
 
775
    portid = '1';
 
776
 
 
777
  n = devc->num_outputs++;
 
778
  midic = &devc->out_midic[n];
 
779
  midic->devc = devc;
 
780
  MUTEX_INIT (devc->osdev, midic->mutex, MH_DRV + 1);
 
781
  midic->osdev = devc->osdev;
 
782
  midic->portnum = n;
 
783
  midic->outqueue_ix = queue_ix;
 
784
 
 
785
  if (n == 8)
 
786
    {
 
787
      sprintf (tmp, "%s SMPTE control", name);
 
788
      flags = MFLAG_MTC;
 
789
    }
 
790
  else
 
791
    sprintf (tmp, "%s output %c", name, portid + n);
 
792
 
 
793
  midic->midi_dev =
 
794
    oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "MIDISPORT", tmp,
 
795
                         &midisport_midi_output_driver,
 
796
                         sizeof (midi_driver_t),
 
797
                         flags, midic, midic->osdev);
 
798
}
 
799
 
 
800
static void
 
801
init_outqueue (midisport_devc * devc, int ix, int ep, int max_blocks)
 
802
{
 
803
  int desc_len;
 
804
  midisport_outqueue_t *q;
 
805
  int i, epix = ep;
 
806
 
 
807
  unsigned char *desc;
 
808
 
 
809
  for (i = 0; i < 32; i++)
 
810
    if ((desc =
 
811
         udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL)
 
812
      {
 
813
        if (desc[2] == ep)
 
814
          epix = i;
 
815
      }
 
816
 
 
817
  if (ix < 0 || ix > devc->num_queues)
 
818
    {
 
819
      cmn_err (CE_WARN, "Endpoint index outside bounds\n");
 
820
      return;
 
821
    }
 
822
 
 
823
  q = &devc->out_queues[ix];
 
824
  MUTEX_INIT (devc->osdev, q->mutex, MH_DRV + 2);
 
825
  q->max_out_blocks = max_blocks;
 
826
  q->devc = devc;
 
827
 
 
828
  if ((q->out_ep_desc =
 
829
       udi_usbdev_get_endpoint (devc->usbdev, 0, epix, &desc_len)) == NULL)
 
830
    {
 
831
      cmn_err (CE_WARN, "Bad endpoint %d\n", ep);
 
832
      return;
 
833
    }
 
834
 
 
835
  if (q->out_ep_desc[2] & 0x80)
 
836
    {
 
837
      cmn_err (CE_WARN, "Bad endpoint %d - not output\n", ep);
 
838
    }
 
839
  cmn_err (CE_CONT, "Attaching output endpoint %d=%02x\n", ep,
 
840
           q->out_ep_desc[2]);
 
841
}
 
842
 
 
843
void *
 
844
midisport_driver (ossusb_devc * usb_devc)
 
845
{
 
846
  midisport_devc *devc;
 
847
  char *name;
 
848
  unsigned int devid;
 
849
  int i;
 
850
  unsigned char *desc;
 
851
  int desc_len;
 
852
 
 
853
  devid = (usb_devc->vendor << 16) | usb_devc->product;
 
854
 
 
855
  if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL)
 
856
    {
 
857
      cmn_err (CE_WARN, "midisport: Out of memory\n");
 
858
      return NULL;
 
859
    }
 
860
 
 
861
  memset (devc, 0, sizeof (*devc));
 
862
 
 
863
  devc->unload_func = midisport_unload;
 
864
  devc->osdev = usb_devc->osdev;
 
865
  MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
 
866
 
 
867
  devc->usb_devc = usb_devc;
 
868
  devc->usbdev = usb_devc->last_usbdev;
 
869
  devc->instance_num = instance_num++;
 
870
 
 
871
  for (i = 0; i < 32; i++)
 
872
    if ((desc =
 
873
         udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL)
 
874
      {
 
875
        if (desc[2] & 0x80)
 
876
          {
 
877
            cmn_err (CE_CONT, "Input endpoint %02x\n", desc[2]);
 
878
          }
 
879
        else
 
880
          {
 
881
            cmn_err (CE_CONT, "Output endpoint %02x\n", desc[2]);
 
882
          }
 
883
      }
 
884
 
 
885
  alphabethic_numbering = 1;
 
886
 
 
887
  devc->num_queues = 2;
 
888
 
 
889
  switch (devid)
 
890
    {
 
891
    case 0x07631002:
 
892
      name = "Midisport 2x2";
 
893
      create_inputs (devc, name, 1, 2);
 
894
      init_outqueue (devc, 0, 2, 8);
 
895
      init_outqueue (devc, 1, 4, 8);
 
896
      create_output (devc, name, 0);
 
897
      create_output (devc, name, 1);
 
898
      break;
 
899
 
 
900
    case 0x07631011:
 
901
      name = "Midisport 1x1";
 
902
      devc->num_queues = 1;
 
903
      init_outqueue (devc, 0, 2, 8);
 
904
      create_inputs (devc, name, 1, 1);
 
905
      create_output (devc, name, 0);
 
906
      break;
 
907
 
 
908
    case 0x07631015:
 
909
      name = "Oxygen8";
 
910
      devc->num_queues = 1;
 
911
      create_inputs (devc, name, 1, 1);
 
912
      init_outqueue (devc, 0, 2, 8);
 
913
      create_output (devc, name, 0);
 
914
      break;
 
915
 
 
916
    case 0x07632001:
 
917
      name = "Quattro";
 
918
      devc->num_queues = 1;
 
919
      create_inputs (devc, name, 1, 1);
 
920
      init_outqueue (devc, 0, 2, 8);
 
921
      create_output (devc, name, 0);
 
922
      break;
 
923
 
 
924
    case 0x07631031:
 
925
      name = "Midisport 8x8";
 
926
      alphabethic_numbering = 0;
 
927
      create_inputs (devc, name, 2, 9);
 
928
      init_outqueue (devc, 0, 2, 10);
 
929
      init_outqueue (devc, 1, 4, 8);
 
930
      create_output (devc, name, 0);
 
931
      create_output (devc, name, 1);
 
932
      create_output (devc, name, 0);
 
933
      create_output (devc, name, 1);
 
934
      create_output (devc, name, 0);
 
935
      create_output (devc, name, 1);
 
936
      create_output (devc, name, 0);
 
937
      create_output (devc, name, 1);
 
938
      create_output (devc, name, 0);    /* SMPTE control */
 
939
      break;
 
940
 
 
941
    case 0x07631021:
 
942
      name = "Midisport 4x4";
 
943
      create_inputs (devc, name, 2, 4);
 
944
      init_outqueue (devc, 0, 2, 16);
 
945
      init_outqueue (devc, 1, 4, 16);
 
946
      create_output (devc, name, 0);
 
947
      create_output (devc, name, 1);
 
948
      create_output (devc, name, 0);
 
949
      create_output (devc, name, 1);
 
950
      break;
 
951
 
 
952
    default:
 
953
      cmn_err (CE_WARN, "Unrecognized MIDI device %08x\n", devid);
 
954
    }
 
955
 
 
956
  return devc;
 
957
}