summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2004-06-27 19:44:49 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2004-06-27 19:44:49 +0000
commitaf9cf440474893bc7dab5537c61e8bebcbc81807 (patch)
treeadcdf8143d4db11402ff24fedfaf1d5bd6362ef7 /sys/dev/usb
parent739008766bfd25d4eb6ba3069aa0b9562d33c322 (diff)
better midi stuff from alex@caoua.org
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/umidi.c489
-rw-r--r--sys/dev/usb/umidi_quirks.c193
-rw-r--r--sys/dev/usb/umidireg.h5
-rw-r--r--sys/dev/usb/umidivar.h27
4 files changed, 435 insertions, 279 deletions
diff --git a/sys/dev/usb/umidi.c b/sys/dev/usb/umidi.c
index 266b719820d..9188f8fb55d 100644
--- a/sys/dev/usb/umidi.c
+++ b/sys/dev/usb/umidi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umidi.c,v 1.9 2003/05/19 00:36:33 nate Exp $ */
+/* $OpenBSD: umidi.c,v 1.10 2004/06/27 19:44:48 deraadt Exp $ */
/* $NetBSD: umidi.c,v 1.16 2002/07/11 21:14:32 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -123,7 +123,7 @@ static usbd_status start_output_transfer(struct umidi_endpoint *);
static int out_jack_output(struct umidi_jack *, int);
static void in_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
static void out_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
-static void out_build_packet(int, struct umidi_packet *, uByte);
+static int out_build_packet(int, struct umidi_packet *, uByte);
struct midi_hw_if umidi_hw_if = {
@@ -163,6 +163,7 @@ USB_ATTACH(umidi)
usbd_status err;
USB_ATTACH_START(umidi, sc, uaa);
char devinfo[1024];
+ int i;
DPRINTFN(1,("umidi_attach\n"));
@@ -180,15 +181,11 @@ USB_ATTACH(umidi)
err = alloc_all_endpoints(sc);
if (err!=USBD_NORMAL_COMPLETION) {
- printf("%s: alloc_all_endpoints failed. (err=%d)\n",
- USBDEVNAME(sc->sc_dev), err);
goto error;
}
err = alloc_all_jacks(sc);
if (err!=USBD_NORMAL_COMPLETION) {
free_all_endpoints(sc);
- printf("%s: alloc_all_jacks failed. (err=%d)\n",
- USBDEVNAME(sc->sc_dev), err);
goto error;
}
printf("%s: out=%d, in=%d\n",
@@ -200,22 +197,22 @@ USB_ATTACH(umidi)
unbind_all_jacks(sc);
free_all_jacks(sc);
free_all_endpoints(sc);
- printf("%s: assign_all_jacks_automatically failed. (err=%d)\n",
- USBDEVNAME(sc->sc_dev), err);
goto error;
}
err = attach_all_mididevs(sc);
if (err!=USBD_NORMAL_COMPLETION) {
free_all_jacks(sc);
free_all_endpoints(sc);
- printf("%s: attach_all_mididevs failed. (err=%d)\n",
- USBDEVNAME(sc->sc_dev), err);
}
#ifdef UMIDI_DEBUG
dump_sc(sc);
#endif
+ for (i = 0; i < sc->sc_in_num_endpoints; i++) {
+ (void)start_input_transfer(&sc->sc_in_ep[i]);
+ }
+
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH,
sc->sc_udev, USBDEV(sc->sc_dev));
@@ -328,7 +325,6 @@ void
umidi_getinfo(void *addr, struct midi_info *mi)
{
struct umidi_mididev *mididev = addr;
-/* struct umidi_softc *sc = mididev->sc; */
mi->name = "USB MIDI I/F"; /* XXX: model name */
mi->props = MIDI_PROP_OUT_INTR;
@@ -349,23 +345,22 @@ alloc_pipe(struct umidi_endpoint *ep)
usbd_status err;
DPRINTF(("%s: alloc_pipe %p\n", USBDEVNAME(sc->sc_dev), ep));
- LIST_INIT(&ep->queue_head);
+ TAILQ_INIT(&ep->queue_head);
ep->xfer = usbd_alloc_xfer(sc->sc_udev);
if (ep->xfer == NULL) {
- err = USBD_NOMEM;
- goto quit;
+ return USBD_NOMEM;
}
- ep->buffer = usbd_alloc_buffer(ep->xfer, UMIDI_PACKET_SIZE);
+ ep->buffer = usbd_alloc_buffer(ep->xfer, ep->packetsize);
if (ep->buffer == NULL) {
- usbd_free_xfer(ep->xfer);
- err = USBD_NOMEM;
- goto quit;
+ usbd_free_xfer(ep->xfer);
+ return USBD_NOMEM;
}
err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe);
- if (err)
- usbd_free_xfer(ep->xfer);
-quit:
- return err;
+ if (err != USBD_NORMAL_COMPLETION) {
+ usbd_free_xfer(ep->xfer);
+ return err;
+ }
+ return USBD_NORMAL_COMPLETION;
}
static void
@@ -403,14 +398,17 @@ alloc_all_endpoints(struct umidi_softc *sc)
ep = sc->sc_endpoints;
for (i=sc->sc_out_num_endpoints+sc->sc_in_num_endpoints; i>0; i--) {
- err = alloc_pipe(ep++);
+ err = alloc_pipe(ep);
if (err!=USBD_NORMAL_COMPLETION) {
- for (; ep!=sc->sc_endpoints; ep--)
- free_pipe(ep-1);
+ while(ep != sc->sc_endpoints) {
+ ep--;
+ free_pipe(ep);
+ }
free(sc->sc_endpoints, M_USBDEV);
sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL;
break;
}
+ ep++;
}
return err;
}
@@ -459,8 +457,8 @@ alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
sc->sc_iface,
fp->out_ep[i].ep);
if (!epd) {
- printf("%s: cannot get endpoint descriptor(out:%d)\n",
- USBDEVNAME(sc->sc_dev), fp->out_ep[i].ep);
+ DPRINTF(("%s: cannot get endpoint descriptor(out:%d)\n",
+ USBDEVNAME(sc->sc_dev), fp->out_ep[i].ep));
err = USBD_INVAL;
goto error;
}
@@ -472,12 +470,13 @@ alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
goto error;
}
ep->sc = sc;
+ ep->packetsize = UGETW(epd->wMaxPacketSize);
ep->addr = epd->bEndpointAddress;
ep->num_jacks = fp->out_ep[i].num_jacks;
sc->sc_out_num_jacks += fp->out_ep[i].num_jacks;
ep->num_open = 0;
memset(ep->jacks, 0, sizeof(ep->jacks));
- LIST_INIT(&ep->queue_head);
+ TAILQ_INIT(&ep->queue_head);
ep++;
}
ep = &sc->sc_in_ep[0];
@@ -486,8 +485,8 @@ alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
sc->sc_iface,
fp->in_ep[i].ep);
if (!epd) {
- printf("%s: cannot get endpoint descriptor(in:%d)\n",
- USBDEVNAME(sc->sc_dev), fp->in_ep[i].ep);
+ DPRINTF(("%s: cannot get endpoint descriptor(in:%d)\n",
+ USBDEVNAME(sc->sc_dev), fp->in_ep[i].ep));
err = USBD_INVAL;
goto error;
}
@@ -500,6 +499,7 @@ alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
}
ep->sc = sc;
ep->addr = epd->bEndpointAddress;
+ ep->packetsize = UGETW(epd->wMaxPacketSize);
ep->num_jacks = fp->in_ep[i].num_jacks;
sc->sc_in_num_jacks += fp->in_ep[i].num_jacks;
ep->num_open = 0;
@@ -520,7 +520,7 @@ alloc_all_endpoints_yamaha(struct umidi_softc *sc)
/* This driver currently supports max 1in/1out bulk endpoints */
usb_descriptor_t *desc;
usb_endpoint_descriptor_t *epd;
- int out_addr, in_addr, i;
+ int out_addr, in_addr, in_packetsize, i;
int dir;
size_t remain, descsize;
@@ -535,8 +535,10 @@ alloc_all_endpoints_yamaha(struct umidi_softc *sc)
dir = UE_GET_DIR(epd->bEndpointAddress);
if (dir==UE_DIR_OUT && !out_addr)
out_addr = epd->bEndpointAddress;
- else if (dir==UE_DIR_IN && !in_addr)
+ else if (dir==UE_DIR_IN && !in_addr) {
in_addr = epd->bEndpointAddress;
+ in_packetsize = UGETW(epd->wMaxPacketSize);
+ }
}
}
desc = NEXT_D(desc);
@@ -591,6 +593,7 @@ alloc_all_endpoints_yamaha(struct umidi_softc *sc)
sc->sc_out_ep = sc->sc_endpoints;
sc->sc_out_ep->sc = sc;
sc->sc_out_ep->addr = out_addr;
+ sc->sc_out_ep->packetsize = UMIDI_PACKET_SIZE;
sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks;
sc->sc_out_ep->num_open = 0;
memset(sc->sc_out_ep->jacks, 0, sizeof(sc->sc_out_ep->jacks));
@@ -601,6 +604,7 @@ alloc_all_endpoints_yamaha(struct umidi_softc *sc)
sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints;
sc->sc_in_ep->sc = sc;
sc->sc_in_ep->addr = in_addr;
+ sc->sc_in_ep->packetsize = in_packetsize;
sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks;
sc->sc_in_ep->num_open = 0;
memset(sc->sc_in_ep->jacks, 0, sizeof(sc->sc_in_ep->jacks));
@@ -613,20 +617,17 @@ alloc_all_endpoints_yamaha(struct umidi_softc *sc)
static usbd_status
alloc_all_endpoints_genuine(struct umidi_softc *sc)
{
+ usb_interface_descriptor_t *interface_desc;
+ usb_config_descriptor_t *config_desc;
usb_descriptor_t *desc;
int num_ep;
size_t remain, descsize;
struct umidi_endpoint *p, *q, *lowest, *endep, tmpep;
- int epaddr;
+ int epaddr, eppacketsize;
- desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface));
- num_ep = TO_IFD(desc)->bNumEndpoints;
- desc = NEXT_D(desc); /* ifd -> csifd */
- remain = ((size_t)UGETW(TO_CSIFD(desc)->wTotalLength) -
- (size_t)desc->bLength);
- desc = NEXT_D(desc);
-
- sc->sc_endpoints = p = malloc(sizeof(struct umidi_endpoint)*num_ep,
+ interface_desc = usbd_get_interface_descriptor(sc->sc_iface);
+ num_ep = interface_desc->bNumEndpoints;
+ sc->sc_endpoints = p = malloc(sizeof(struct umidi_endpoint) * num_ep,
M_USBDEV, M_WAITOK);
if (!p)
return USBD_NOMEM;
@@ -636,6 +637,9 @@ alloc_all_endpoints_genuine(struct umidi_softc *sc)
epaddr = -1;
/* get the list of endpoints for midi stream */
+ config_desc = usbd_get_config_descriptor(sc->sc_udev);
+ desc = (usb_descriptor_t *) config_desc;
+ remain = (size_t)UGETW(config_desc->wTotalLength);
while (remain>=sizeof(usb_descriptor_t)) {
descsize = desc->bLength;
if (descsize>remain || descsize==0)
@@ -644,6 +648,7 @@ alloc_all_endpoints_genuine(struct umidi_softc *sc)
remain>=USB_ENDPOINT_DESCRIPTOR_SIZE &&
UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes) == UE_BULK) {
epaddr = TO_EPD(desc)->bEndpointAddress;
+ eppacketsize = UGETW(TO_EPD(desc)->wMaxPacketSize);
} else if (desc->bDescriptorType==UDESC_CS_ENDPOINT &&
remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE &&
epaddr!=-1) {
@@ -651,6 +656,7 @@ alloc_all_endpoints_genuine(struct umidi_softc *sc)
num_ep--;
p->sc = sc;
p->addr = epaddr;
+ p->packetsize = eppacketsize;
p->num_jacks = TO_CSEPD(desc)->bNumEmbMIDIJack;
if (UE_GET_DIR(epaddr)==UE_DIR_OUT) {
sc->sc_out_num_endpoints++;
@@ -860,8 +866,6 @@ assign_all_jacks_automatically(struct umidi_softc *sc)
static usbd_status
open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *))
{
- struct umidi_endpoint *ep = jack->endpoint;
-
if (jack->opened)
return USBD_IN_USE;
@@ -869,59 +873,34 @@ open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *))
jack->u.out.intr = intr;
init_packet(&jack->packet);
jack->opened = 1;
- ep->num_open++;
-
+ jack->endpoint->num_open++;
+
return USBD_NORMAL_COMPLETION;
}
static usbd_status
open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int))
{
- usbd_status err = USBD_NORMAL_COMPLETION;
- struct umidi_endpoint *ep = jack->endpoint;
-
if (jack->opened)
return USBD_IN_USE;
jack->arg = arg;
jack->u.in.intr = intr;
jack->opened = 1;
- if (ep->num_open++==0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) {
- err = start_input_transfer(ep);
- if (err!=USBD_NORMAL_COMPLETION) {
- ep->num_open--;
- }
- }
-
- return err;
+ jack->endpoint->num_open++;
+
+ return USBD_NORMAL_COMPLETION;
}
static void
close_out_jack(struct umidi_jack *jack)
{
- struct umidi_jack *tail;
- int s;
-
if (jack->opened) {
- s = splusb();
- LIST_FOREACH(tail,
- &jack->endpoint->queue_head,
- u.out.queue_entry)
- if (tail == jack) {
- LIST_REMOVE(jack, u.out.queue_entry);
- break;
- }
- if (jack == jack->endpoint->queue_tail) {
- /* find tail */
- LIST_FOREACH(tail,
- &jack->endpoint->queue_head,
- u.out.queue_entry) {
- if (!LIST_NEXT(tail, u.out.queue_entry)) {
- jack->endpoint->queue_tail = tail;
- }
- }
+#ifdef UMIDI_DEBUG
+ if (!TAILQ_EMPTY(&jack->endpoint->queue_head)) {
+ printf("close_out_jack: queue_head still not empty\n");
}
- splx(s);
+#endif
jack->opened = 0;
jack->endpoint->num_open--;
}
@@ -932,7 +911,7 @@ close_in_jack(struct umidi_jack *jack)
{
if (jack->opened) {
jack->opened = 0;
- jack->endpoint->num_open--;
+ jack->endpoint->num_open--;
}
}
@@ -1109,28 +1088,6 @@ static const int packet_length[16] = {
/*F*/ 1,
};
-static const struct {
- int cin;
- packet_state_t next;
-} packet_0xFX[16] = {
- /*F0: SysEx */ { 0x04, PS_EXCL_1 },
- /*F1: MTC */ { 0x02, PS_NORMAL_1OF2 },
- /*F2: S.POS */ { 0x03, PS_NORMAL_1OF3 },
- /*F3: S.SEL */ { 0x02, PS_NORMAL_1OF2 },
- /*F4: UNDEF */ { 0x00, PS_INITIAL },
- /*F5: UNDEF */ { 0x00, PS_INITIAL },
- /*F6: Tune */ { 0x0F, PS_END },
- /*F7: EofEx */ { 0x00, PS_INITIAL },
- /*F8: Timing */ { 0x0F, PS_END },
- /*F9: UNDEF */ { 0x00, PS_INITIAL },
- /*FA: Start */ { 0x0F, PS_END },
- /*FB: Cont */ { 0x0F, PS_END },
- /*FC: Stop */ { 0x0F, PS_END },
- /*FD: UNDEF */ { 0x00, PS_INITIAL },
- /*FE: ActS */ { 0x0F, PS_END },
- /*FF: Reset */ { 0x0F, PS_END },
-};
-
#define GET_CN(p) (((unsigned char)(p)>>4)&0x0F)
#define GET_CIN(p) ((unsigned char)(p)&0x0F)
#define MIX_CN_CIN(cn, cin) \
@@ -1140,33 +1097,46 @@ static const struct {
static void
init_packet(struct umidi_packet *packet)
{
- memset(packet->buffer, 0, UMIDI_PACKET_SIZE);
- packet->state = PS_INITIAL;
+ packet->status = 0;
+ packet->index = 0;
}
static usbd_status
start_input_transfer(struct umidi_endpoint *ep)
{
+ usbd_status err;
usbd_setup_xfer(ep->xfer, ep->pipe,
(usbd_private_handle)ep,
- ep->buffer, UMIDI_PACKET_SIZE,
- USBD_NO_COPY, USBD_NO_TIMEOUT, in_intr);
- return usbd_transfer(ep->xfer);
+ ep->buffer, ep->packetsize,
+ USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, in_intr);
+ err = usbd_transfer(ep->xfer);
+ if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
+ DPRINTF(("%s: start_input_transfer: usbd_transfer() failed err=%s\n",
+ USBDEVNAME(ep->sc->sc_dev), usbd_errstr(err)));
+ return err;
+ }
+ return USBD_NORMAL_COMPLETION;
}
static usbd_status
start_output_transfer(struct umidi_endpoint *ep)
{
+ usbd_status err;
usbd_setup_xfer(ep->xfer, ep->pipe,
(usbd_private_handle)ep,
ep->buffer, UMIDI_PACKET_SIZE,
USBD_NO_COPY, USBD_NO_TIMEOUT, out_intr);
- return usbd_transfer(ep->xfer);
+ err = usbd_transfer(ep->xfer);
+ if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
+ DPRINTF(("%s: start_output_transfer: usbd_transfer() failed err=%s\n",
+ USBDEVNAME(ep->sc->sc_dev), usbd_errstr(err)));
+ return err;
+ }
+ return USBD_NORMAL_COMPLETION;
}
#ifdef UMIDI_DEBUG
#define DPR_PACKET(dir, sc, p) \
-if ((unsigned char)(p)->buffer[1]!=0xFE) \
DPRINTFN(500, \
("%s: umidi packet(" #dir "): %02X %02X %02X %02X\n", \
USBDEVNAME(sc->sc_dev), \
@@ -1183,76 +1153,74 @@ out_jack_output(struct umidi_jack *out_jack, int d)
{
struct umidi_endpoint *ep = out_jack->endpoint;
struct umidi_softc *sc = ep->sc;
- int error;
int s;
if (sc->sc_dying)
return EIO;
- error = 0;
- if (out_jack->opened) {
- DPRINTFN(1000, ("umidi_output: ep=%p 0x%02x\n", ep, d));
- out_build_packet(out_jack->cable_number, &out_jack->packet, d);
- switch (out_jack->packet.state) {
- case PS_EXCL_0:
- case PS_END:
- DPR_PACKET(out, sc, &out_jack->packet);
- s = splusb();
- if (LIST_EMPTY(&ep->queue_head)) {
- memcpy(ep->buffer,
- out_jack->packet.buffer,
- UMIDI_PACKET_SIZE);
- start_output_transfer(ep);
- }
- if (LIST_EMPTY(&ep->queue_head))
- LIST_INSERT_HEAD(&ep->queue_head,
- out_jack, u.out.queue_entry);
- else
- LIST_INSERT_AFTER(ep->queue_tail,
- out_jack, u.out.queue_entry);
- ep->queue_tail = out_jack;
- splx(s);
- break;
- default:
- error = EINPROGRESS;
+ if (!out_jack->opened) {
+ return ENODEV;
+ }
+
+ if (out_build_packet(out_jack->cable_number, &out_jack->packet, d)) {
+ DPR_PACKET(out, sc, &out_jack->packet);
+ s = splusb();
+ if (TAILQ_EMPTY(&ep->queue_head)) {
+ memcpy(ep->buffer,
+ out_jack->packet.buffer,
+ UMIDI_PACKET_SIZE);
+ TAILQ_INSERT_TAIL(&ep->queue_head,
+ out_jack, u.out.queue_entry);
+ start_output_transfer(ep);
+ } else {
+ DPRINTF(("%s: out_jack_output: packet ignored\n", USBDEVNAME(sc->sc_dev)));
}
- } else
- error = ENODEV;
-
- return error;
+ splx(s);
+ return 0;
+ }
+
+ return EINPROGRESS;
}
static void
in_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
- int cn, len, i;
+ int cn, evlen, remain, i;
+ unsigned char *buf;
struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
struct umidi_jack *jack;
- if (ep->sc->sc_dying || !ep->num_open)
+ if (ep->sc->sc_dying)
return;
- cn = GET_CN(ep->buffer[0]);
- len = packet_length[GET_CIN(ep->buffer[0])];
- jack = ep->jacks[cn];
- if (cn>=ep->num_jacks || !jack) {
- DPRINTF(("%s: stray umidi packet (in): %02X %02X %02X %02X\n",
- USBDEVNAME(ep->sc->sc_dev),
- (unsigned)ep->buffer[0],
- (unsigned)ep->buffer[1],
- (unsigned)ep->buffer[2],
- (unsigned)ep->buffer[3]));
- return;
- }
- if (!jack->binded || !jack->opened)
- return;
- DPR_PACKET(in, ep->sc, &jack->packet);
- if (jack->u.in.intr) {
- for (i=0; i<len; i++) {
- (*jack->u.in.intr)(jack->arg, ep->buffer[i+1]);
- }
+ usbd_get_xfer_status(xfer, NULL, NULL, &remain, NULL);
+ if (status != USBD_NORMAL_COMPLETION) {
+ DPRINTF(("umidi: in_intr: abnormal status: %s\n", usbd_errstr(status)));
+ goto quit;
+ }
+ buf = ep->buffer;
+ while (remain >= UMIDI_PACKET_SIZE) {
+ cn = GET_CN(buf[0]);
+ if (cn < ep->num_jacks && (jack = ep->jacks[cn]) &&
+ jack->binded && jack->opened && jack->u.in.intr) {
+ evlen = packet_length[GET_CIN(buf[0])];
+ for (i=0; i<evlen; i++)
+ (*jack->u.in.intr)(jack->arg, buf[i+1]);
+ } else
+ DPRINTFN(10, ("in_intr: unused packet %02x %02x %02x %02x\n",
+ buf[0], buf[1], buf[2], buf[3]));
+
+ buf += UMIDI_PACKET_SIZE;
+ remain -= UMIDI_PACKET_SIZE;
}
+#ifdef UMIDI_DEBUG
+ if (remain != 0) {
+ DPRINTF(("umidi: in_intr: remain != 0\n"));
+ }
+#endif
+
+quit:
(void)start_input_transfer(ep);
}
@@ -1262,120 +1230,129 @@ out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
struct umidi_softc *sc = ep->sc;
struct umidi_jack *jack;
-
- if (sc->sc_dying || !ep->num_open)
+ int s;
+
+ if (sc->sc_dying)
return;
- jack = LIST_FIRST(&ep->queue_head);
- if (jack && jack->opened) {
- LIST_REMOVE(jack, u.out.queue_entry);
- if (!LIST_EMPTY(&ep->queue_head)) {
+ s = splusb();
+ jack = TAILQ_FIRST(&ep->queue_head);
+ if (jack) {
+ TAILQ_REMOVE(&ep->queue_head, jack, u.out.queue_entry);
+ if (!TAILQ_EMPTY(&ep->queue_head)) {
memcpy(ep->buffer,
- LIST_FIRST(&ep->queue_head)->packet.buffer,
+ TAILQ_FIRST(&ep->queue_head)->packet.buffer,
UMIDI_PACKET_SIZE);
(void)start_output_transfer(ep);
}
- if (jack->u.out.intr) {
+ if (jack->opened && jack->u.out.intr)
(*jack->u.out.intr)(jack->arg);
- }
}
+ splx(s);
}
-static void
-out_build_packet(int cable_number, struct umidi_packet *packet, uByte in)
+#define UMIDI_VOICELEN(status) (umidi_evlen[((status) >> 4) & 7])
+unsigned umidi_evlen[] = { 4, 4, 4, 4, 3, 3, 4 };
+
+#define EV_SYSEX 0xf0
+#define EV_MTC 0xf1
+#define EV_SPP 0xf2
+#define EV_SONGSEL 0xf3
+#define EV_TUNE_REQ 0xf6
+#define EV_SYSEX_STOP 0xf7
+
+static int
+out_build_packet(int cable_number, struct umidi_packet *packet, uByte data)
{
- int cin;
- uByte prev;
-
-retry:
- switch (packet->state) {
- case PS_END:
- case PS_INITIAL:
- prev = packet->buffer[1];
- memset(packet->buffer, 0, UMIDI_PACKET_SIZE);
- if (in<0x80) {
- if (prev>=0x80 && prev<0xf0) {
- /* running status */
- out_build_packet(cable_number, packet, prev);
- goto retry;
- }
- /* ??? */
+ if (data >= 0xf8) { /* is it a realtime message ? */
+ packet->buffer[0] = data >> 4 | cable_number << 4;
+ packet->buffer[1] = data;
+ packet->buffer[2] = 0;
+ packet->buffer[3] = 0;
+ return 1;
+ }
+ if (data >= 0xf0) { /* is it a common message ? */
+ switch(data) {
+ case EV_SYSEX:
+ packet->buffer[1] = packet->status = data;
+ packet->index = 2;
+ break;
+ case EV_SYSEX_STOP:
+ if (packet->status != EV_SYSEX) break;
+ packet->status = data;
+ packet->buffer[packet->index++] = data;
+ packet->buffer[0] = (0x4 - 1 + packet->index) | cable_number << 4;
+ goto packetready;
+ case EV_TUNE_REQ:
+ packet->status = data;
+ packet->buffer[0] = 0x5 | cable_number << 4;
+ packet->index = 1;
+ goto packetready;
+ default:
+ packet->status = data;
break;
}
- if (in>=0xf0) {
- cin=packet_0xFX[in&0x0F].cin;
- packet->state=packet_0xFX[in&0x0F].next;
- } else {
- cin=(unsigned char)in>>4;
- switch (packet_length[cin]) {
- case 2:
- packet->state = PS_NORMAL_1OF2;
- break;
- case 3:
- packet->state = PS_NORMAL_1OF3;
- break;
- default:
- /* ??? */
- packet->state = PS_INITIAL;
+ return 0;
+ }
+ if (data >= 0x80) { /* is it a voice message ? */
+ packet->status = data;
+ packet->index = 0;
+ return 0;
+ }
+
+ /* else it is a data byte */
+ if (packet->status >= 0xf0) {
+ switch(packet->status) {
+ case EV_SYSEX: /* sysex starts or continues */
+ if (packet->index == 0)
+ packet->index = 1;
+
+ packet->buffer[packet->index++] = data;
+ if (packet->index >= UMIDI_PACKET_SIZE) {
+ packet->buffer[0] = 0x4 | cable_number << 4;
+ goto packetready;
}
- }
- packet->buffer[0] = MIX_CN_CIN(cable_number, cin);
- packet->buffer[1] = in;
- break;
- case PS_NORMAL_1OF3:
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[2] = in;
- packet->state = PS_NORMAL_2OF3;
- break;
- case PS_NORMAL_2OF3:
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[3] = in;
- packet->state = PS_END;
- break;
- case PS_NORMAL_1OF2:
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[2] = in;
- packet->state = PS_END;
- break;
- case PS_EXCL_0:
- memset(packet->buffer, 0, UMIDI_PACKET_SIZE);
- if (in==0xF7) {
- packet->buffer[0] = MIX_CN_CIN(cable_number, 0x05);
- packet->buffer[1] = 0xF7;
- packet->state = PS_END;
break;
- }
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[1] = in;
- packet->state = PS_EXCL_1;
- break;
- case PS_EXCL_1:
- if (in==0xF7) {
- packet->buffer[0] = MIX_CN_CIN(cable_number, 0x06);
- packet->buffer[2] = 0xF7;
- packet->state = PS_END;
+ case EV_MTC: /* messages with 1 data byte */
+ case EV_SONGSEL:
+ packet->buffer[0] = 0x2 | cable_number << 4;
+ packet->buffer[1] = packet->status;
+ packet->buffer[2] = data;
+ packet->index = 3;
+ goto packetready;
+ case EV_SPP: /* messages with 2 data bytes */
+ if (packet->index == 0) {
+ packet->buffer[0] = 0x3 | cable_number << 4;
+ packet->index = 1;
+ }
+ packet->buffer[packet->index++] = data;
+ if (packet->index >= UMIDI_PACKET_SIZE) {
+ packet->buffer[1] = packet->status;
+ goto packetready;
+ }
break;
- }
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[2] = in;
- packet->state = PS_EXCL_2;
- break;
- case PS_EXCL_2:
- if (in==0xF7) {
- packet->buffer[0] = MIX_CN_CIN(cable_number, 0x07);
- packet->buffer[3] = 0xF7;
- packet->state = PS_END;
+ default: /* ignore data with unknown status */
break;
}
- if (in>=0x80) { /* ??? */ packet->state = PS_END; break; }
- packet->buffer[0] = MIX_CN_CIN(cable_number, 0x04);
- packet->buffer[3] = in;
- packet->state = PS_EXCL_0;
- break;
- default:
- printf("umidi: ambiguous state.\n");
- packet->state = PS_INITIAL;
- goto retry;
+ return 0;
+ }
+ if (packet->status >= 0x80) { /* is it a voice message ? */
+ if (packet->index == 0) {
+ packet->buffer[0] = packet->status >> 4 | cable_number << 4;
+ packet->buffer[1] = packet->status;
+ packet->index = 2;
+ }
+ packet->buffer[packet->index++] = data;
+ if (packet->index >= UMIDI_VOICELEN(packet->status))
+ goto packetready;
}
+ /* ignore data with unknown status */
+ return 0;
+
+packetready:
+ while (packet->index < UMIDI_PACKET_SIZE)
+ packet->buffer[packet->index++] = 0;
+
+ packet->index = 0;
+ return 1;
}
-
diff --git a/sys/dev/usb/umidi_quirks.c b/sys/dev/usb/umidi_quirks.c
index 37c9c826549..d1cfe011191 100644
--- a/sys/dev/usb/umidi_quirks.c
+++ b/sys/dev/usb/umidi_quirks.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umidi_quirks.c,v 1.5 2003/05/19 00:36:52 nate Exp $ */
+/* $OpenBSD: umidi_quirks.c,v 1.6 2004/06/27 19:44:48 deraadt Exp $ */
/* $NetBSD: umidi_quirks.c,v 1.4 2002/06/19 13:55:30 tshiozak Exp $ */
/*
@@ -166,6 +166,185 @@ UMQ_DEF(ROLAND, ROLAND_UM880N, 0) = {
UMQ_TERMINATOR
};
+/*
+ * ROLAND UA-100
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA100, 2, 1, 1) = {
+ /* out */
+ { 0, 3 },
+ /* in */
+ { 1, 3 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_UA100, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA100, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND UM-4
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM4, 2, 1, 1) = {
+ /* out */
+ { 0, 4 },
+ /* in */
+ { 1, 4 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_UM4, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM4, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND U-8
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_U8, 2, 1, 1) = {
+ /* out */
+ { 0, 2 },
+ /* in */
+ { 1, 2 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_U8, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_U8, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND UM-2
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM2, 2, 1, 1) = {
+ /* out */
+ { 0, 2 },
+ /* in */
+ { 1, 2 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_UM2, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM2, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND SC-8820
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SC8820, 2, 1, 1) = {
+ /* out */
+ { 0, 5 }, /* cables 0, 1, 4 only */
+ /* in */
+ { 1, 5 } /* do. */
+};
+
+UMQ_DEF(ROLAND, ROLAND_SC8820, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_SC8820, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND PC-300
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_PC300, 2, 1, 1) = {
+ /* out */
+ { 0, 1 },
+ /* in */
+ { 1, 1 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_PC300, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_PC300, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND SK-500
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SK500, 2, 1, 1) = {
+ /* out */
+ { 0, 5 }, /* cables 0, 1, 4 only */
+ /* in */
+ { 1, 5 } /* do. */
+};
+
+UMQ_DEF(ROLAND, ROLAND_SK500, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_SK500, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND SC-D70
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SCD70, 2, 1, 1) = {
+ /* out */
+ { 0, 3 },
+ /* in */
+ { 1, 3 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_SCD70, 2) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_SCD70, 2),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND UM-550
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM550, 0, 1, 1) = {
+ /* out */
+ { 0, 6 },
+ /* in */
+ { 1, 6 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_UM550, 0) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM550, 0),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND SD-20
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD20, 0, 1, 1) = {
+ /* out */
+ { 0, 2 },
+ /* in */
+ { 1, 3 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_SD20, 0) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD20, 0),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND SD-80
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_SD80, 0, 1, 1) = {
+ /* out */
+ { 0, 4 },
+ /* in */
+ { 1, 4 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_SD80, 0) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_SD80, 0),
+ UMQ_TERMINATOR
+};
+
+/*
+ * ROLAND UA-700
+ */
+UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UA700, 3, 1, 1) = {
+ /* out */
+ { 0, 2 },
+ /* in */
+ { 1, 2 }
+};
+
+UMQ_DEF(ROLAND, ROLAND_UA700, 3) = {
+ UMQ_FIXED_EP_REG(ROLAND, ROLAND_UA700, 3),
+ UMQ_TERMINATOR
+};
/*
@@ -178,6 +357,18 @@ struct umidi_quirk umidi_quirklist[] = {
UMQ_REG(ROLAND, ROLAND_SC8850, 2),
UMQ_REG(ROLAND, ROLAND_SD90, 2),
UMQ_REG(ROLAND, ROLAND_UM880N, 0),
+ UMQ_REG(ROLAND, ROLAND_UA100, 2),
+ UMQ_REG(ROLAND, ROLAND_UM4, 2),
+ UMQ_REG(ROLAND, ROLAND_U8, 2),
+ UMQ_REG(ROLAND, ROLAND_UM2, 2),
+ UMQ_REG(ROLAND, ROLAND_SC8820, 2),
+ UMQ_REG(ROLAND, ROLAND_PC300, 2),
+ UMQ_REG(ROLAND, ROLAND_SK500, 2),
+ UMQ_REG(ROLAND, ROLAND_SCD70, 2),
+ UMQ_REG(ROLAND, ROLAND_UM550, 0),
+ UMQ_REG(ROLAND, ROLAND_SD20, 0),
+ UMQ_REG(ROLAND, ROLAND_SD80, 0),
+ UMQ_REG(ROLAND, ROLAND_UA700, 3),
UMQ_TERMINATOR
};
diff --git a/sys/dev/usb/umidireg.h b/sys/dev/usb/umidireg.h
index 77bc91ad544..e2a51b40f4a 100644
--- a/sys/dev/usb/umidireg.h
+++ b/sys/dev/usb/umidireg.h
@@ -1,11 +1,10 @@
-/* $OpenBSD: umidireg.h,v 1.3 2002/06/11 07:49:57 nate Exp $ */
-/* $NetBSD: umidireg.h,v 1.2 2001/05/28 20:52:06 tshiozak Exp $ */
+/* $NetBSD: umidireg.h,v 1.3 2003/12/04 13:57:31 keihan Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Takuya SHIOZAKI (tshiozak@netbsd.org).
+ * by Takuya SHIOZAKI (tshiozak@NetBSD.org).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/sys/dev/usb/umidivar.h b/sys/dev/usb/umidivar.h
index 4b6d34a1d45..46c38d2cc25 100644
--- a/sys/dev/usb/umidivar.h
+++ b/sys/dev/usb/umidivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: umidivar.h,v 1.7 2002/11/11 02:32:32 nate Exp $ */
+/* $OpenBSD: umidivar.h,v 1.8 2004/06/27 19:44:48 deraadt Exp $ */
/* $NetBSD: umidivar.h,v 1.5 2002/09/12 21:00:42 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -36,22 +36,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* pending MUX-MIDI packet */
-typedef enum {
- PS_EXCL_0=-2, /* put, and next state is PS_EXCL_0 */
- PS_END=-1, /* put, and next state is PS_INITIAL */
- PS_INITIAL=0, /* 0>= : not put, and state is keeped */
- PS_NORMAL_1OF3=1,
- PS_NORMAL_2OF3=2,
- PS_NORMAL_1OF2=3,
- PS_EXCL_1=4,
- PS_EXCL_2=5
-} packet_state_t;
-
#define UMIDI_PACKET_SIZE 4
struct umidi_packet {
- char buffer[UMIDI_PACKET_SIZE];
- packet_state_t state;
+ unsigned status;
+ unsigned index;
+ unsigned char buffer[UMIDI_PACKET_SIZE];
};
/*
@@ -88,7 +77,7 @@ struct umidi_jack {
union {
struct {
void (*intr)(void *);
- LIST_ENTRY(umidi_jack) queue_entry;
+ TAILQ_ENTRY(umidi_jack) queue_entry;
} out;
struct {
void (*intr)(void *, int);
@@ -104,12 +93,12 @@ struct umidi_endpoint {
int addr;
usbd_pipe_handle pipe;
usbd_xfer_handle xfer;
- char *buffer;
+ unsigned char *buffer;
+ unsigned packetsize;
int num_open;
int num_jacks;
struct umidi_jack *jacks[UMIDI_MAX_EPJACKS];
- LIST_HEAD(, umidi_jack) queue_head;
- struct umidi_jack *queue_tail;
+ TAILQ_HEAD(, umidi_jack) queue_head;
};
/* software context */