Cleaned a bit, lights stopped working

This commit is contained in:
Neale Pickett 2014-12-14 20:29:21 -07:00
parent fe5f5ff21b
commit 879aa06038
3 changed files with 99 additions and 46 deletions

98
alsa.c
View File

@ -4,11 +4,15 @@
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include "alsa.h" #include "alsa.h"
#include "usb.h" #include "usb.h"
#include "log.h"
#include "dump.h" #include "dump.h"
static snd_seq_t *snd_handle; static snd_seq_t *snd_handle;
static int seq_port; static int seq_port;
static snd_seq_event_t *ev; static snd_midi_event_t *midi_event_parser;
#define ALSA_BUFSIZE 4096
int int
alsa_setup(const char *name) alsa_setup(const char *name)
@ -24,9 +28,21 @@ alsa_setup(const char *name)
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_READ |
SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC); SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
// Allocate parser object for converting to and from MIDI
if (snd_midi_event_new(ALSA_BUFSIZE, &midi_event_parser) < 0) {
fatal("ALSA cannot allocate MIDI event parser");
}
return 0; return 0;
} }
void
alsa_close()
{
snd_midi_event_free(midi_event_parser);
}
#define MAX_PFDS 20 #define MAX_PFDS 20
int npfd; int npfd;
struct pollfd pfd[MAX_PFDS]; struct pollfd pfd[MAX_PFDS];
@ -38,8 +54,7 @@ alsa_fd_setup(int *nfds, fd_set *rfds, fd_set *wfds)
int i; int i;
if (npfd > MAX_PFDS) { if (npfd > MAX_PFDS) {
fprintf(stderr, "ALSA wants too many file descriptors\n"); fatal("ALSA wants too many file descriptors");
abort();
} }
snd_seq_poll_descriptors(snd_handle, pfd, npfd, POLLIN); snd_seq_poll_descriptors(snd_handle, pfd, npfd, POLLIN);
@ -55,34 +70,33 @@ alsa_fd_setup(int *nfds, fd_set *rfds, fd_set *wfds)
} }
#define ALSA_BUFSIZE 4096
void void
alsa_read_ready() alsa_read_ready()
{ {
static snd_midi_event_t *midi_event_parser; static snd_seq_event_t *ev;
if (snd_midi_event_new(ALSA_BUFSIZE, &midi_event_parser) < 0) {
fprintf(stderr, "ALSA cannot allocate MIDI event parser\n");
abort();
}
for (;;) { for (;;) {
unsigned char buf[ALSA_BUFSIZE]; unsigned char buf[ALSA_BUFSIZE];
long converted; long converted;
int r;
if (snd_seq_event_input(snd_handle, &ev) < 0) { r = snd_seq_event_input(snd_handle, &ev);
if (r == -EAGAIN) {
break; break;
} }
if (r == -ENOSPC) {
warn("Out of space on input queue");
}
converted = snd_midi_event_decode(midi_event_parser, buf, ALSA_BUFSIZE, ev); converted = snd_midi_event_decode(midi_event_parser, buf, ALSA_BUFSIZE, ev);
if (converted < 0) { if (converted < 0) {
fprintf(stderr, "Can't decode MIDI event type %d\n", ev->type); warn("Can't decode MIDI event type %d", ev->type);
} else { } else {
DUMP_d(converted);
usb_write(buf, converted); usb_write(buf, converted);
} }
} }
snd_midi_event_free(midi_event_parser);
} }
void void
@ -103,28 +117,40 @@ alsa_check_fds(fd_set *rfds, fd_set *wfds)
void void
alsa_write(uint8_t *data, size_t datalen) alsa_write(uint8_t *data, size_t datalen)
{ {
static snd_midi_event_t *midi_event_parser; size_t offset = 0;
snd_seq_event_t ev;
long r;
if (snd_midi_event_new(ALSA_BUFSIZE, &midi_event_parser) < 0) { for (; datalen > offset;) {
fprintf(stderr, "ALSA cannot allocate MIDI event parser\n"); snd_seq_event_t ev;
abort(); long encoded;
int r;
encoded = snd_midi_event_encode(midi_event_parser, data + offset, datalen - offset, &ev);
if (encoded <= 1) {
int i;
warn("Unable to encode MIDI message (%ld < %ld)", encoded, datalen);
fprintf(stderr, " ");
for (i = offset; i < datalen; i += 1) {
fprintf(stderr, "%02x ", data[i]);
}
fprintf(stderr, "\n");
return;
}
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_source(&ev, seq_port);
snd_seq_ev_set_subs(&ev);
r = snd_seq_event_output(snd_handle, &ev);
if (r < 0) {
warn("Couldn't write an output event");
}
if (r > 200) {
warn("Output buffer size %d", r);
}
offset += encoded;
} }
snd_seq_drain_output(snd_handle);
r = snd_midi_event_encode(midi_event_parser, data, datalen, &ev);
if (r < datalen) {
fprintf(stderr, "ALSA didn't parse that message\n");
abort();
}
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_source(&ev, seq_port);
snd_seq_ev_set_subs(&ev);
if ((r = snd_seq_event_output_direct(snd_handle, &ev)) < 0) {
fprintf(stderr, "ALSA couldn't write an event: %ld\n", r);
abort();
}
snd_midi_event_free(midi_event_parser);
} }

13
log.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __LOG_H__
#define __LOG_H__
#include <stdio.h>
#include <stdlib.h>
#define __log__(fmt, args...) fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##args)
#define warn(fmt, args...) __log__("Warning: %s:%d " fmt, __FILE__, __LINE__, ##args)
#define fatal(fmt, args...) do { __log__("Fatal: " fmt, ##args); abort(); } while (0)
#endif

30
usb.c
View File

@ -6,6 +6,7 @@
#include <sys/select.h> #include <sys/select.h>
#include "usb.h" #include "usb.h"
#include "alsa.h" #include "alsa.h"
#include "log.h"
#include "dump.h" #include "dump.h"
static struct libusb_device_handle *usb_dev; static struct libusb_device_handle *usb_dev;
@ -16,14 +17,15 @@ static int reads_pending = 0;
struct device { struct device {
uint16_t product_id; uint16_t product_id;
uint8_t interface_number;
uint8_t ep_in; uint8_t ep_in;
uint8_t ep_out; uint8_t ep_out;
}; };
const struct device devices[] = { const struct device devices[] = {
{ 0xb102, 0x83, 0x04 }, // Steel { 0xb102, 1, 0x83, 0x04 }, // Steel
{ 0xb105, 0x82, 0x03 }, // MP3e2 { 0xb105, 1, 0x82, 0x03 }, // MP3e2
{ 0, 0, 0 } { 0, 0, 0, 0 }
}; };
void usb_xfer_done(struct libusb_transfer *transfer); void usb_xfer_done(struct libusb_transfer *transfer);
@ -64,7 +66,7 @@ usb_setup(char *name, size_t namelen)
} }
if (libusb_pollfds_handle_timeouts(NULL) == 0) { if (libusb_pollfds_handle_timeouts(NULL) == 0) {
printf("I'm too dumb to handle events on such an old system.\n"); fatal("I'm too dumb to handle events on such an old system.");
return -1; return -1;
} }
@ -75,8 +77,7 @@ usb_setup(char *name, size_t namelen)
} }
} }
if (! usb_dev) { if (! usb_dev) {
printf("Couldn't find a controller.\n"); fatal("Couldn't find a controller.");
return -1;
} }
// Figure out what it's called // Figure out what it's called
@ -94,11 +95,16 @@ usb_setup(char *name, size_t namelen)
ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iProduct, (unsigned char *)p, namelen - ret - 1); ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iProduct, (unsigned char *)p, namelen - ret - 1);
} }
if (ret < 0) { if (ret < 0) {
printf("Warning: I can't figure out what to call this thing.\n"); warn("I can't figure out what to call this thing.");
} }
printf("Opened [%s]\n", name); printf("Opened [%s]\n", name);
} }
if (0 != libusb_claim_interface(usb_dev, d->interface_number)) {
fatal("Couldn't claim interface %d", d->interface_number);
}
usb_initiate_transfer(); usb_initiate_transfer();
return 0; return 0;
@ -125,7 +131,7 @@ usb_fd_setup(int *nfds, fd_set *rfds, fd_set *wfds)
} }
if (reads_pending + writes_pending > 10) { if (reads_pending + writes_pending > 10) {
fprintf(stderr, "Warning: %d+%d = %d outstanding USB transactions!\n", reads_pending, writes_pending, reads_pending + writes_pending); warn("%d(r)+%d(w) = %d outstanding USB transactions!", reads_pending, writes_pending, reads_pending + writes_pending);
} }
} }
@ -150,6 +156,7 @@ usb_check_fds(fd_set *rfds, fd_set *wfds)
void void
usb_write_done(struct libusb_transfer *xfer) usb_write_done(struct libusb_transfer *xfer)
{ {
DUMP_d(xfer->status);
writes_pending -= 1; writes_pending -= 1;
free(xfer->buffer); free(xfer->buffer);
libusb_free_transfer(xfer); libusb_free_transfer(xfer);
@ -160,6 +167,13 @@ usb_write(uint8_t *data, size_t datalen)
{ {
struct libusb_transfer *xfer; struct libusb_transfer *xfer;
unsigned char *buf; unsigned char *buf;
int i;
DUMP_d(datalen);
for (i = 0; i < datalen; i += 1) {
fprintf(stderr, " %02x", data[i]);
}
fprintf(stderr, "\n");
writes_pending += 1; writes_pending += 1;
xfer = libusb_alloc_transfer(0); xfer = libusb_alloc_transfer(0);