/* get_sysex_dump.c * cc -Wall -Wformat -g -o get_sysex_dump get_sysex_dump.c */ #include #include #include #include #include #include #define SYSEX_START 0xf0 #define SYSEX_END 0xf7 struct sysex { unsigned int length; unsigned char *data; }; static struct sysex *sysex_new(void); static void sysex_delete(struct sysex *); static void sysex_set_length(struct sysex *, unsigned int); static void sysex_read(int, struct sysex *, int); static void sysex_write(int, struct sysex *); static int sysex_checksum(struct sysex *, int, int); int main(int argc, char *argv[]) { int fd, i; struct sysex *se; fd = open("/dev/rmidi2", O_RDWR|O_SYNC); if (fd == -1) { fprintf(stderr, "open() failed: %s\n", strerror(errno)); return 1; } se = sysex_new(); sysex_set_length(se, 11); se->data[0] = 0x41; /* Roland's ID */ se->data[1] = 0x10; /* Device Number - default appears to be 0x10 */ se->data[2] = 0x16; /* Model ID */ se->data[3] = 0x11; /* Command ID - "Request Data" */ se->data[4] = 0x04; /* Address MSB */ se->data[5] = 0x01; /* Address */ se->data[6] = 0x76; /* Address LSB */ se->data[7] = 0x00; /* Size MSB */ se->data[8] = 0x01; /* Size */ se->data[9] = 0x76; /* Size LSB */ se->data[10] = 0x0e; /* Checksum */ sysex_write(fd, se); sysex_set_length(se, 252); /* 8 bytes to wrap data, and 246 bytes of data */ sysex_read(fd, se, 1); printf("Read %d bytes\n", se->length); for (i = 0; i < se->length; i++) printf("0x%0x\n", se->data[i]); sysex_delete(se); if (close(fd) == -1) { fprintf(stderr, "close() failed: %s\n", strerror(errno)); return 1; } return 0; } /* Receives a MIDI System Exclusive message */ void sysex_read(int fd, struct sysex *se, int autostop) { int n, length = 0; unsigned char c; if (fd == -1) { fprintf(stderr, "sysex_read() failed: invalid fd\n"); return; } if (se == NULL) { fprintf(stderr, "sysex_read() failed: null sysex argument\n"); return; } while ((n = read(fd, &c, 1)) == 1 && c != SYSEX_START) usleep(40); if (n != 1) return; while (length < se->length) { n = read(fd, &c, 1); if (n == 1) { se->data[length++] = c; if (autostop && se->data[length - 1] == SYSEX_END) break; } } if (length < se->length) { se->length = length; se->data = realloc(se->data, se->length); } } /* Sends a MIDI System Exclusive message */ void sysex_write(int fd, struct sysex *se) { unsigned char *data; if (fd == -1) { fprintf(stderr, "sysex_write() failed: invalid fd\n"); return; } if (se == NULL) { fprintf(stderr, "sysex_write() failed: null sysex argument\n"); return; } data = calloc(se->length + 2, sizeof(unsigned char)); data[0] = SYSEX_START; memcpy(data + 1, se->data, se->length); data[se->length + 1] = SYSEX_END; write(fd, data, se->length + 2); free(data); } static struct sysex *sysex_new(void) { struct sysex *se; se = calloc(1, sizeof(struct sysex)); return se; } static void sysex_delete(struct sysex *se) { if (se->length != 0) free(se->data); free(se); } /* Sets the length of a MIDI System Exclusive message */ void sysex_set_length(struct sysex *se, unsigned int length) { if (se == NULL) { fprintf(stderr, "sysex_set_length() failed: null sysex argument\n"); return; } se->length = length; se->data = realloc(se->data, se->length); } /* Determine a Roland System Exclusive checksum */ int sysex_checksum(struct sysex *se, int start, int length) { int checksum, i; if (se == NULL) { fprintf(stderr, "sysex_checksum() failed: null sysex argument\n"); return 0; } checksum = 0; for (i = start; i < start + length; i++) { checksum += se->data[i]; if (checksum > 127) checksum -= 128; } checksum = 128 - checksum; return checksum; }