Add missing HID Headers

This commit is contained in:
Roger Clark 2016-07-18 17:50:03 +10:00
parent d653a8a774
commit 1e88cf73f7
6 changed files with 1019 additions and 0 deletions

View File

@ -0,0 +1,155 @@
/*--------------------------------------------------------------------------MidiSpecs.h
*
* These defines are based on specs created by the USB and MMA standards organizations.
* There are not a lot of other ways to code them so liscensing this is rather ludicrous.
* However, in order to be able to embed this in client projects, and avoid the stupidity
* of enforced open everything I will declare the following about this file.
*
* Copyright (c) 2011 Donald Delmar Davis, Suspect Devices
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*
* USB midi commands from
* MIDI10.pdf "Universal Serial Bus Device Class Definition for MIDI Devices"
* REV 1. (1999)
* http://www.usb.org/developers/devclass_docs/midi10.pdf
*
*/
#ifdef USB_MIDI
#ifndef __LETS_MIDI_SPECS_H__
#define __LETS_MIDI_SPECS_H__
#include <stdint.h>
#include <stdbool.h>
// rework this for the different architectures....
#if defined(__GNUC__)
typedef struct
{
unsigned cin : 4; // this is the low nibble.
unsigned cable : 4;
// uint8_t cin;
uint8_t midi0;
uint8_t midi1;
uint8_t midi2;
} __attribute__ ((__packed__)) MIDI_EVENT_PACKET_t ;
#else
typedef struct // may need to be adjusted for other compilers and bitfield order...
{
unsigned cable : 4;
unsigned cin : 4;
uint8_t midi0;
uint8_t midi1;
uint8_t midi2;
} MIDI_EVENT_PACKET_t ;
#endif
#define CIN_MISC_FUNCTION 0x00 /* Reserved for future extension. */
#define CIN_CABLE_EVENT 0x01 /* Reserved for future extension. */
#define CIN_2BYTE_SYS_COMMON 0x02 /* 2Bytes -- MTC, SongSelect, etc. */
#define CIN_3BYTE_SYS_COMMON 0x03 /* 3Bytes -- SPP, etc. */
#define CIN_SYSEX 0x04 /* 3Bytes */
#define CIN_SYSEX_ENDS_IN_1 0x05 /* 1Bytes */
#define CIN_SYSEX_ENDS_IN_2 0x06 /* 2Bytes */
#define CIN_SYSEX_ENDS_IN_3 0x07 /* 3Bytes */
#define CIN_NOTE_OFF 0x08 /* 3Bytes */
#define CIN_NOTE_ON 0x09 /* 3Bytes */
#define CIN_AFTER_TOUCH 0x0A /* 3Bytes */
#define CIN_CONTROL_CHANGE 0x0B /* 3Bytes */
#define CIN_PROGRAM_CHANGE 0x0C /* 2Bytes */
#define CIN_CHANNEL_PRESSURE 0x0D /* 2Bytes */
#define CIN_PITCH_WHEEL 0x0E /* 3Bytes */
#define CIN_1BYTE 0x0F /* 1Bytes */
//#define CIN_IS_SYSEX(cin) ((cin == CIN_SYSEX)||(cin == CIN_SYSEX_ENDS_IN_1)||(cin == CIN_SYSEX_ENDS_IN_2)||(cin == CIN_SYSEX_ENDS_IN_3))
#define CIN_IS_SYSEX(cin) ( ((cin) & ~(0x08)) && ((cin) &0x04) )
/*
* MIDI V1 message definitions these are from the MMA document
* http://www.midi.org/techspecs/midimessages.php
*/
#define MIDIv1_BAUD_RATE 31250
/*
* parse midi (v1) message macros
*/
#define MIDIv1_IS_STATUS(b) ((b) & 0x80)
#define MIDIv1_IS_VOICE(b) ((b) <= 0xEF)
#define MIDIv1_VOICE_COMMAND(b) ((b) & 0xF0)
#define MIDIv1_VOICE_CHANNEL(b) ((b) & 0x0F)
#define MIDIv1_IS_SYSCOMMON(b) (((b) >= 0xF0) & ((b) < 0xF8))
#define MIDIv1_IS_REALTIME(b) ((b) >= 0xF8)
/*
* Voice category messages
*/
#define MIDIv1_NOTE_OFF 0x80 /* 2 bytes data -- CIN_NOTE_OFF */
#define MIDIv1_NOTE_ON 0x90 /* 2 bytes data -- CIN_NOTE_ON */
#define MIDIv1_AFTER_TOUCH 0xA0 /* 2 bytes data -- CIN_AFTER_TOUCH */
#define MIDIv1_CONTROL_CHANGE 0xB0 /* 2 bytes data -- CIN_CONTROL_CHANGE */
#define MIDIv1_PROGRAM_CHANGE 0xC0 /* 1 byte data -- CIN_PROGRAM_CHANGE */
#define MIDIv1_CHANNEL_PRESSURE 0xD0 /* 1 byte data -- CIN_CHANNEL_PRESSURE */
#define MIDIv1_PITCH_WHEEL 0xE0 /* 2 bytes data -- CIN_PITCH_WHEEL */
/*
* System common category messages
*/
#define MIDIv1_SYSEX_START 0xF0
#define MIDIv1_SYSEX_END 0xF7
#define MIDIv1_MTC_QUARTER_FRAME 0xF1 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
#define MIDIv1_SONG_POSITION_PTR 0xF2 /* 2 bytes data -- CIN_3BYTE_SYS_COMMON */
#define MIDIv1_SONG_SELECT 0xF3 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
#define MIDIv1_TUNE_REQUEST 0xF6 /* no data -- CIN_1BYTE */
/*
* Realtime category messages, can be sent anytime
*/
#define MIDIv1_CLOCK 0xF8 /* no data -- CIN_1BYTE */
#define MIDIv1_TICK 0xF9 /* no data -- CIN_1BYTE */
#define MIDIv1_START 0xFA /* no data -- CIN_1BYTE */
#define MIDIv1_CONTINUE 0xFB /* no data -- CIN_1BYTE */
#define MIDIv1_STOP 0xFC /* no data -- CIN_1BYTE */
#define MIDIv1_ACTIVE_SENSE 0xFE /* no data -- CIN_1BYTE */
#define MIDIv1_RESET 0xFF /* no data -- CIN_1BYTE */
/*
* sysex universal id's
*/
#define MIDIv1_UNIVERSAL_REALTIME_ID 0x7F
#define MIDIv1_UNIVERSAL_NON_REALTIME_ID 0x7E
#define MIDIv1_UNIVERSAL_ALL_CHANNELS 0x7F
/*
* Susbset of universal sysex (general info request)
* As described http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec.htm
*/
#define USYSEX_NON_REAL_TIME 0x7E
#define USYSEX_REAL_TIME 0x7F
#define USYSEX_ALL_CHANNELS 0x7F
#define USYSEX_GENERAL_INFO 0x06
#define USYSEX_GI_ID_REQUEST 0x01
#define USYSEX_GI_ID_RESPONSE 0x02
#endif
#endif

View File

@ -0,0 +1,304 @@
//
// MinSysex.c
// LibMaple4Midi
//
// Created by Donald D Davis on 4/11/13.
// Copyright (c) 2013 Suspect Devices. All rights reserved.
// Modified BSD Liscense
/*
0xF0 SysEx
0x7E Non-Realtime
0x7F The SysEx channel. Could be from 0x00 to 0x7F.
Here we set it to "disregard channel".
0x06 Sub-ID -- General Information
0x01 Sub-ID2 -- Identity Request
0xF7 End of SysEx
---- response
0xF0 SysEx
0x7E Non-Realtime
0x7F The SysEx channel. Could be from 0x00 to 0x7F.
Here we set it to "disregard channel".
0x06 Sub-ID -- General Information
0x02 Sub-ID2 -- Identity Reply
0xID Manufacturer's ID
0xf1 The f1 and f2 bytes make up the family code. Each
0xf2 manufacturer assigns different family codes to his products.
0xp1 The p1 and p2 bytes make up the model number. Each
0xp2 manufacturer assigns different model numbers to his products.
0xv1 The v1, v2, v3 and v4 bytes make up the version number.
0xv2
0xv3
0xv4
0xF7 End of SysEx
*/
#ifdef USB_MIDI
// change this to packets
#define STANDARD_ID_RESPONSE_LENGTH 7
#include <libmaple/usb_midi_device.h>
#include <libmaple/nvic.h>
#include <libmaple/delay.h>
#include <MinSysex.h>
//#include <wirish/wirish.h>
#define MAX_SYSEX_SIZE 256
/********************************* ACHTUNG! ignores usbmidi cable ********************************/
/*const MIDI_EVENT_PACKET_t standardIDResponse[]={
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX,
MIDIv1_SYSEX_START,
USYSEX_NON_REAL_TIME,
USYSEX_ALL_CHANNELS},
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX,
USYSEX_GENERAL_INFO,
USYSEX_GI_ID_RESPONSE,
LEAFLABS_MMA_VENDOR_1},
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX,
LEAFLABS_MMA_VENDOR_2, // extended ID
LEAFLABS_MMA_VENDOR_3, // extended ID
1}, // family #1
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX,
2, // family #2
1, // part #1
2}, // part #2
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX,
0, // version 1
0, // version 2
1}, // version 3
{ DEFAULT_MIDI_CABLE,
CIN_SYSEX_ENDS_IN_2,
'!', // lgl compatible
MIDIv1_SYSEX_END,
0}
};
*/
const uint8 standardIDResponse[]={
CIN_SYSEX,
MIDIv1_SYSEX_START,
USYSEX_NON_REAL_TIME,
USYSEX_ALL_CHANNELS,
CIN_SYSEX,
USYSEX_GENERAL_INFO,
USYSEX_GI_ID_RESPONSE,
LEAFLABS_MMA_VENDOR_1,
CIN_SYSEX,
LEAFLABS_MMA_VENDOR_2, // extended ID
LEAFLABS_MMA_VENDOR_3, // extended ID
1, // family #1
CIN_SYSEX,
2, // family #2
1, // part #1
2, // part #2
CIN_SYSEX,
0, // version 1
0, // version 2
1, // version 3
CIN_SYSEX_ENDS_IN_2,
'!', // lgl compatible
MIDIv1_SYSEX_END,
0
};
//#define STANDARD_ID_RESPONSE_LENGTH (sizeof(standardIDResponse))
typedef enum {NOT_IN_SYSEX=0,COULD_BE_MY_SYSEX,YUP_ITS_MY_SYSEX,ITS_NOT_MY_SYSEX} sysexStates;
volatile uint8 sysexBuffer[MAX_SYSEX_SIZE];
volatile sysexStates sysexState;
volatile int sysexFinger=0;
/*
0xF0 SysEx
0x?? LEAFLABS_MMA_VENDOR_1
0x?? LEAFLABS_MMA_VENDOR_2
0x?? LEAFLABS_MMA_VENDOR_3
0x10 LGL_DEVICE_NUMBER
0xLE CMD: REBOOT
0xf7 EOSysEx
*/
#define STACK_TOP 0x20000800
#define EXC_RETURN 0xFFFFFFF9
#define DEFAULT_CPSR 0x61000000
#define RESET_DELAY 100000
static void wait_reset(void) {
delay_us(RESET_DELAY);
nvic_sys_reset();
}
/* -----------------------------------------------------------------------------dealWithItQuickly()
* Note: at this point we have established that the sysex belongs to us.
* So we need to respond to any generic requests like information requests.
* We also need to handle requests which are meant for us. At the moment this is just the
* reset request.
*
*/
void dealWithItQuickly(){
switch (sysexBuffer[1]) {
case USYSEX_NON_REAL_TIME:
switch (sysexBuffer[3]) {
case USYSEX_GENERAL_INFO:
if (sysexBuffer[4]==USYSEX_GI_ID_REQUEST) {
usb_midi_tx((uint32 *) standardIDResponse, STANDARD_ID_RESPONSE_LENGTH);
}
}
case USYSEX_REAL_TIME:
break;
case LEAFLABS_MMA_VENDOR_1:
if (sysexBuffer[5]==LGL_RESET_CMD) {
uintptr_t target = (uintptr_t)wait_reset | 0x1;
asm volatile("mov r0, %[stack_top] \n\t" // Reset stack
"mov sp, r0 \n\t"
"mov r0, #1 \n\t"
"mov r1, %[target_addr] \n\t"
"mov r2, %[cpsr] \n\t"
"push {r2} \n\t" // Fake xPSR
"push {r1} \n\t" // PC target addr
"push {r0} \n\t" // Fake LR
"push {r0} \n\t" // Fake R12
"push {r0} \n\t" // Fake R3
"push {r0} \n\t" // Fake R2
"push {r0} \n\t" // Fake R1
"push {r0} \n\t" // Fake R0
"mov lr, %[exc_return] \n\t"
"bx lr"
:
: [stack_top] "r" (STACK_TOP),
[target_addr] "r" (target),
[exc_return] "r" (EXC_RETURN),
[cpsr] "r" (DEFAULT_CPSR)
: "r0", "r1", "r2");
/* Can't happen. */
ASSERT_FAULT(0);
}
default:
break;
}
;//turn the led on?
}
/* -----------------------------------------------------------------------------LglSysexHandler()
* The idea here is to identify which Sysex's belong to us and deal with them.
*/
void LglSysexHandler(uint32 *midiBufferRx, uint32 *rx_offset, uint32 *n_unread_packets) {
MIDI_EVENT_PACKET_t * midiPackets = (MIDI_EVENT_PACKET_t *) (midiBufferRx+(*rx_offset));
uint8 nPackets=((*n_unread_packets)-(*rx_offset));
int cPacket;
uint8 soPackets=0;
/********************************* ACHTUNG! ignores usbmidi cable ********************************/
MIDI_EVENT_PACKET_t *packet;
for (cPacket=0;cPacket<nPackets;cPacket++){
packet=midiPackets+cPacket;
if (!CIN_IS_SYSEX(packet->cin)) {
continue;
} // else {
if (!soPackets) {
soPackets=cPacket*4;
}
if ((sysexState==YUP_ITS_MY_SYSEX) && ((sysexFinger+3)>=MAX_SYSEX_SIZE)){
sysexState=ITS_NOT_MY_SYSEX; //eisenhower policy. Even if its mine I cant deal with it.
}
switch (packet->cin) {
case CIN_SYSEX:
switch (sysexState) {
case NOT_IN_SYSEX : // new sysex.
sysexFinger=0;
if (packet->midi0 == MIDIv1_SYSEX_START) {
if (packet->midi1==USYSEX_REAL_TIME
||packet->midi1==USYSEX_NON_REAL_TIME) {
if ((packet->midi2==myMidiChannel)
||(packet->midi2==USYSEX_ALL_CHANNELS)
) {
sysexState=YUP_ITS_MY_SYSEX;
sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START;
sysexBuffer[sysexFinger++]=packet->midi1;
sysexBuffer[sysexFinger++]=packet->midi2;
break;
}
} else if ((packet->midi1==myMidiID[0])
&& (packet->midi2==myMidiID[1])
){
sysexState=COULD_BE_MY_SYSEX;
sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START;
sysexBuffer[sysexFinger++]=packet->midi1;
sysexBuffer[sysexFinger++]=packet->midi2;
break;
}
}
break;
case COULD_BE_MY_SYSEX:
if (packet->midi0==myMidiID[2]) {
sysexState=YUP_ITS_MY_SYSEX;
sysexBuffer[sysexFinger++]=packet->midi0;
sysexBuffer[sysexFinger++]=packet->midi1;
sysexBuffer[sysexFinger++]=packet->midi2;
} else {
sysexState=ITS_NOT_MY_SYSEX;
sysexFinger=0;
}
break;
default:
break;
}
break;
case CIN_SYSEX_ENDS_IN_1:
case CIN_SYSEX_ENDS_IN_2:
case CIN_SYSEX_ENDS_IN_3:
sysexBuffer[sysexFinger++]=packet->midi0;
sysexBuffer[sysexFinger++]=packet->midi1;
sysexBuffer[sysexFinger++]=packet->midi2;
if (sysexState==YUP_ITS_MY_SYSEX) {
if(cPacket>=(*n_unread_packets)){
*n_unread_packets = soPackets;
*rx_offset = soPackets;
} else {
uint8 c = cPacket;
uint32 *s;
uint32 *d = midiBufferRx + soPackets;
for (s = midiBufferRx+c;
((*n_unread_packets) && (s <= midiBufferRx+(USB_MIDI_RX_EPSIZE/4)));
d++,s++
) {
(*d)=(*s);
(*n_unread_packets)--;
(*rx_offset)++;
}
// we need to reset the for loop variables to re process remaining data.
nPackets=((*n_unread_packets)-(*rx_offset));
cPacket=(*rx_offset);
}
dealWithItQuickly();
}
sysexFinger=0;
sysexState=NOT_IN_SYSEX;
break;
default:
return;
}
//}
}
// its our sysex and we will cry if we want to
return;
}
#endif

View File

@ -0,0 +1,41 @@
//
// lgl_min_sysex.h
// LibMaple4Midi
//
// Created by Donald D Davis on 4/11/13.
// Copyright (c) 2013 Suspect Devices. All rights reserved.
//
#ifdef USB_MIDI
#ifndef __LGL_MIN_SYSEX_H__
#define __LGL_MIN_SYSEX_H__ 1
#include "MidiSpecs.h"
//#include "LGL.h"
#define LEAFLABS_MMA_VENDOR_1 0x7D
#define LEAFLABS_MMA_VENDOR_2 0x1E
#define LEAFLABS_MMA_VENDOR_3 0x4F
// move to LGL.h
#define LGL_RESET_CMD 0x1e
#define DEFAULT_MIDI_CHANNEL 0x0A
#define DEFAULT_MIDI_DEVICE 0x0A
#define DEFAULT_MIDI_CABLE 0x00
// eventually all of this should be in a place for settings which can be written to flash.
extern volatile uint8 myMidiChannel;
extern volatile uint8 myMidiDevice;
extern volatile uint8 myMidiCable;
extern volatile uint8 myMidiID[];
void LglSysexHandler(uint32 *midiBufferRx,uint32 *rx_offset,uint32 *n_unread_bytes);
#endif
#endif

View File

@ -0,0 +1,151 @@
/*--------------------------------------------------------------------------MidiSpecs.h
*
* These defines are based on specs created by the USB and MMA standards organizations.
* There are not a lot of other ways to code them so liscensing this is rather ludicrous.
* However, in order to be able to embed this in client projects, and avoid the stupidity
* of enforced open everything I will declare the following about this file.
*
* Copyright (c) 2011 Donald Delmar Davis, Suspect Devices
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*
* USB midi commands from
* MIDI10.pdf "Universal Serial Bus Device Class Definition for MIDI Devices"
* REV 1. (1999)
* http://www.usb.org/developers/devclass_docs/midi10.pdf
*
*/
#ifndef __LETS_MIDI_SPECS_H__
#define __LETS_MIDI_SPECS_H__
#include <stdint.h>
#include <stdbool.h>
// rework this for the different architectures....
#if defined(__GNUC__)
typedef struct
{
unsigned cin : 4; // this is the low nibble.
unsigned cable : 4;
// uint8_t cin;
uint8_t midi0;
uint8_t midi1;
uint8_t midi2;
} __attribute__ ((__packed__)) MIDI_EVENT_PACKET_t ;
#else
typedef struct // may need to be adjusted for other compilers and bitfield order...
{
unsigned cable : 4;
unsigned cin : 4;
uint8_t midi0;
uint8_t midi1;
uint8_t midi2;
} MIDI_EVENT_PACKET_t ;
#endif
#define CIN_MISC_FUNCTION 0x00 /* Reserved for future extension. */
#define CIN_CABLE_EVENT 0x01 /* Reserved for future extension. */
#define CIN_2BYTE_SYS_COMMON 0x02 /* 2Bytes -- MTC, SongSelect, etc. */
#define CIN_3BYTE_SYS_COMMON 0x03 /* 3Bytes -- SPP, etc. */
#define CIN_SYSEX 0x04 /* 3Bytes */
#define CIN_SYSEX_ENDS_IN_1 0x05 /* 1Bytes */
#define CIN_SYSEX_ENDS_IN_2 0x06 /* 2Bytes */
#define CIN_SYSEX_ENDS_IN_3 0x07 /* 3Bytes */
#define CIN_NOTE_OFF 0x08 /* 3Bytes */
#define CIN_NOTE_ON 0x09 /* 3Bytes */
#define CIN_AFTER_TOUCH 0x0A /* 3Bytes */
#define CIN_CONTROL_CHANGE 0x0B /* 3Bytes */
#define CIN_PROGRAM_CHANGE 0x0C /* 2Bytes */
#define CIN_CHANNEL_PRESSURE 0x0D /* 2Bytes */
#define CIN_PITCH_WHEEL 0x0E /* 3Bytes */
#define CIN_1BYTE 0x0F /* 1Bytes */
//#define CIN_IS_SYSEX(cin) ((cin == CIN_SYSEX)||(cin == CIN_SYSEX_ENDS_IN_1)||(cin == CIN_SYSEX_ENDS_IN_2)||(cin == CIN_SYSEX_ENDS_IN_3))
#define CIN_IS_SYSEX(cin) ( ((cin) & ~(0x08)) && ((cin) &0x04) )
/*
* MIDI V1 message definitions these are from the MMA document
* http://www.midi.org/techspecs/midimessages.php
*/
#define MIDIv1_BAUD_RATE 31250
/*
* parse midi (v1) message macros
*/
#define MIDIv1_IS_STATUS(b) ((b) & 0x80)
#define MIDIv1_IS_VOICE(b) ((b) <= 0xEF)
#define MIDIv1_VOICE_COMMAND(b) ((b) & 0xF0)
#define MIDIv1_VOICE_CHANNEL(b) ((b) & 0x0F)
#define MIDIv1_IS_SYSCOMMON(b) (((b) >= 0xF0) & ((b) < 0xF8))
#define MIDIv1_IS_REALTIME(b) ((b) >= 0xF8)
/*
* Voice category messages
*/
#define MIDIv1_NOTE_OFF 0x80 /* 2 bytes data -- CIN_NOTE_OFF */
#define MIDIv1_NOTE_ON 0x90 /* 2 bytes data -- CIN_NOTE_ON */
#define MIDIv1_AFTER_TOUCH 0xA0 /* 2 bytes data -- CIN_AFTER_TOUCH */
#define MIDIv1_CONTROL_CHANGE 0xB0 /* 2 bytes data -- CIN_CONTROL_CHANGE */
#define MIDIv1_PROGRAM_CHANGE 0xC0 /* 1 byte data -- CIN_PROGRAM_CHANGE */
#define MIDIv1_CHANNEL_PRESSURE 0xD0 /* 1 byte data -- CIN_CHANNEL_PRESSURE */
#define MIDIv1_PITCH_WHEEL 0xE0 /* 2 bytes data -- CIN_PITCH_WHEEL */
/*
* System common category messages
*/
#define MIDIv1_SYSEX_START 0xF0
#define MIDIv1_SYSEX_END 0xF7
#define MIDIv1_MTC_QUARTER_FRAME 0xF1 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
#define MIDIv1_SONG_POSITION_PTR 0xF2 /* 2 bytes data -- CIN_3BYTE_SYS_COMMON */
#define MIDIv1_SONG_SELECT 0xF3 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
#define MIDIv1_TUNE_REQUEST 0xF6 /* no data -- CIN_1BYTE */
/*
* Realtime category messages, can be sent anytime
*/
#define MIDIv1_CLOCK 0xF8 /* no data -- CIN_1BYTE */
#define MIDIv1_TICK 0xF9 /* no data -- CIN_1BYTE */
#define MIDIv1_START 0xFA /* no data -- CIN_1BYTE */
#define MIDIv1_CONTINUE 0xFB /* no data -- CIN_1BYTE */
#define MIDIv1_STOP 0xFC /* no data -- CIN_1BYTE */
#define MIDIv1_ACTIVE_SENSE 0xFE /* no data -- CIN_1BYTE */
#define MIDIv1_RESET 0xFF /* no data -- CIN_1BYTE */
/*
* sysex universal id's
*/
#define MIDIv1_UNIVERSAL_REALTIME_ID 0x7F
#define MIDIv1_UNIVERSAL_NON_REALTIME_ID 0x7E
#define MIDIv1_UNIVERSAL_ALL_CHANNELS 0x7F
/*
* Susbset of universal sysex (general info request)
* As described http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec.htm
*/
#define USYSEX_NON_REAL_TIME 0x7E
#define USYSEX_REAL_TIME 0x7F
#define USYSEX_ALL_CHANNELS 0x7F
#define USYSEX_GENERAL_INFO 0x06
#define USYSEX_GI_ID_REQUEST 0x01
#define USYSEX_GI_ID_RESPONSE 0x02
#endif

View File

@ -0,0 +1,161 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file libmaple/include/libmaple/usb_hid.h
* @brief USB HID (human interface device) support
*
* IMPORTANT: this API is unstable, and may change without notice.
*/
#if defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J)
#ifndef _LIBMAPLE_USB_HID_H_
#define _LIBMAPLE_USB_HID_H_
#include <libmaple/libmaple_types.h>
#include <libmaple/gpio.h>
#include <libmaple/usb.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Descriptors, etc.
*/
//extern const uint8_t hid_report_descriptor[];
typedef enum _HID_REQUESTS
{
GET_REPORT = 1,
GET_IDLE,
GET_PROTOCOL,
SET_REPORT = 9,
SET_IDLE,
SET_PROTOCOL
} HID_REQUESTS;
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define HID_ENDPOINT_INT 1
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define HID_DESCRIPTOR_TYPE 0x21
#define REPORT_DESCRIPTOR 0x22
typedef struct
{
uint8_t len; // 9
uint8_t dtype; // 0x21
uint8_t versionL; // 0x101
uint8_t versionH; // 0x101
uint8_t country;
uint8_t numDesc;
uint8_t desctype; // 0x22 report
uint8_t descLenL;
uint8_t descLenH;
} HIDDescriptor;
#define USB_DEVICE_CLASS_HID 0x00
#define USB_DEVICE_SUBCLASS_HID 0x00
#define USB_INTERFACE_CLASS_HID 0x03
#define USB_INTERFACE_SUBCLASS_HID 0x00
#define USB_INTERFACE_CLASS_DIC 0x0A
/*
* Endpoint configuration
*/
#define USB_HID_CTRL_ENDP 0
#define USB_HID_CTRL_RX_ADDR 0x40
#define USB_HID_CTRL_TX_ADDR 0x80
#define USB_HID_CTRL_EPSIZE 0x40
#define USB_HID_TX_ENDP 1
#define USB_HID_TX_ADDR 0xC0
#define USB_HID_TX_EPSIZE 0x40
#define USB_HID_RX_ENDP 2
#define USB_HID_RX_ADDR 0x100
#define USB_HID_RX_EPSIZE 0x40
#ifndef __cplusplus
#define USB_HID_DECLARE_DEV_DESC(vid, pid) \
{ \
.bLength = sizeof(usb_descriptor_device), \
.bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, \
.bcdUSB = 0x0200, \
.bDeviceClass = USB_DEVICE_CLASS_HID, \
.bDeviceSubClass = USB_DEVICE_SUBCLASS_HID, \
.bDeviceProtocol = 0x00, \
.bMaxPacketSize0 = 0x40, \
.idVendor = vid, \
.idProduct = pid, \
.bcdDevice = 0x0200, \
.iManufacturer = 0x01, \
.iProduct = 0x02, \
.iSerialNumber = 0x00, \
.bNumConfigurations = 0x01, \
}
#endif
/*
* HID interface
*/
void usb_hid_enable(gpio_dev*, uint8);
void usb_hid_disable(gpio_dev*, uint8);
void usb_hid_putc(char ch);
uint32 usb_hid_tx(const uint8* buf, uint32 len);
uint32 usb_hid_tx_mod(const uint8* buf, uint32 len);
uint32 usb_hid_rx(uint8* buf, uint32 len);
uint32 usb_hid_data_available(void); /* in RX buffer */
uint16 usb_hid_get_pending(void);
uint8 usb_hid_is_transmitting(void);
void HID_SendReport(uint8_t id, const void* data, uint32_t len);
//static RESULT HID_SetProtocol(void);
static uint8 *HID_GetProtocolValue(uint16 Length);
static uint8 *HID_GetReportDescriptor(uint16 Length);
static uint8 *HID_GetHIDDescriptor(uint16 Length);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,207 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs LLC.
* Copyright (c) 2013 Magnus Lundin.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file libmaple/include/libmaple/usb_midi.h
* @brief USB MIDI support
*
* IMPORTANT: this API is unstable, and may change without notice.
*/
#ifdef USB_MIDI
#ifndef _LIBMAPLE_USB_MIDI_H_
#define _LIBMAPLE_USB_MIDI_H_
#include <libmaple/libmaple_types.h>
#include <libmaple/gpio.h>
#include <libmaple/usb.h>
#include <MinSysex.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef union {
uint8 byte[4];
uint32 data;
} USB_MIDI_Event_Packet;
/*
* USB MIDI Requests
*/
/*
* Descriptors, etc.
*/
#define USB_DESCRIPTOR_TYPE_CS_INTERFACE 0x24
#define USB_DESCRIPTOR_TYPE_CS_ENDPOINT 0x25
#define USB_DEVICE_CLASS_UNDEFINED 0x00
#define USB_DEVICE_CLASS_CDC 0x02
#define USB_DEVICE_SUBCLASS_UNDEFINED 0x00
#define USB_INTERFACE_CLASS_AUDIO 0x01
#define USB_INTERFACE_SUBCLASS_UNDEFINED 0x00
#define USB_INTERFACE_AUDIOCONTROL 0x01
#define USB_INTERFACE_AUDIOSTREAMING 0x02
#define USB_INTERFACE_MIDISTREAMING 0x03
/* MIDI Streaming class specific interfaces */
#define MIDI_IN_JACK 0x02
#define MIDI_OUT_JACK 0x03
#define MIDI_JACK_EMBEDDED 0x01
#define MIDI_JACK_EXTERNAL 0x02
#define AC_CS_INTERFACE_DESCRIPTOR_SIZE(DataSize) (8 + DataSize)
#define AC_CS_INTERFACE_DESCRIPTOR(DataSize) \
struct { \
uint8 bLength; \
uint8 bDescriptorType; \
uint8 SubType; \
uint16 bcdADC; \
uint16 wTotalLength; \
uint8 bInCollection; \
uint8 baInterfaceNr[DataSize]; \
} __packed
typedef struct {
uint8 bLength;
uint8 bDescriptorType;
uint8 SubType;
uint16 bcdADC;
uint16 wTotalLength;
} __packed MS_CS_INTERFACE_DESCRIPTOR;
typedef struct {
uint8 bLength;
uint8 bDescriptorType;
uint8 SubType;
uint8 bJackType;
uint8 bJackId;
uint8 iJack;
} __packed MIDI_IN_JACK_DESCRIPTOR;
#define MIDI_OUT_JACK_DESCRIPTOR_SIZE(DataSize) (7 + 2*DataSize)
#define MIDI_OUT_JACK_DESCRIPTOR(DataSize) \
struct { \
uint8 bLength; \
uint8 bDescriptorType; \
uint8 SubType; \
uint8 bJackType; \
uint8 bJackId; \
uint8 bNrInputPins; \
uint8 baSourceId[DataSize]; \
uint8 baSourcePin[DataSize]; \
uint8 iJack; \
} __packed
#define MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(DataSize) (4 + DataSize)
#define MS_CS_BULK_ENDPOINT_DESCRIPTOR(DataSize) \
struct { \
uint8 bLength; \
uint8 bDescriptorType; \
uint8 SubType; \
uint8 bNumEmbMIDIJack; \
uint8 baAssocJackID[DataSize]; \
} __packed
/*
* Endpoint configuration
*/
#define USB_MIDI_CTRL_ENDP 0
#define USB_MIDI_CTRL_RX_ADDR 0x40
#define USB_MIDI_CTRL_TX_ADDR 0x80
#define USB_MIDI_CTRL_EPSIZE 0x40
#define USB_MIDI_TX_ENDP 1
#define USB_MIDI_TX_ADDR 0xC0
#define USB_MIDI_TX_EPSIZE 0x40
#define USB_MIDI_RX_ENDP 2
#define USB_MIDI_RX_ADDR 0x100
#define USB_MIDI_RX_EPSIZE 0x40
#ifndef __cplusplus
#define USB_MIDI_DECLARE_DEV_DESC(vid, pid) \
{ \
.bLength = sizeof(usb_descriptor_device), \
.bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, \
.bcdUSB = 0x0110, \
.bDeviceClass = USB_DEVICE_CLASS_UNDEFINED, \
.bDeviceSubClass = USB_DEVICE_SUBCLASS_UNDEFINED, \
.bDeviceProtocol = 0x00, \
.bMaxPacketSize0 = 0x40, \
.idVendor = vid, \
.idProduct = pid, \
.bcdDevice = 0x0200, \
.iManufacturer = 0x01, \
.iProduct = 0x02, \
.iSerialNumber = 0x00, \
.bNumConfigurations = 0x01, \
}
#endif
/*
* Sysex Stuff.
*/
#define SYSEX_BUFFER_LENGTH 256
/*
* MIDI interface
*/
void usb_midi_enable(gpio_dev*, uint8);
void usb_midi_disable(gpio_dev*, uint8);
void usb_midi_putc(char ch);
uint32 usb_midi_tx(const uint32* buf, uint32 len);
uint32 usb_midi_rx(uint32* buf, uint32 len);
uint32 usb_midi_peek(uint32* buf, uint32 len);
uint32 usb_midi_data_available(void); /* in RX buffer */
uint16 usb_midi_get_pending(void);
uint8 usb_midi_is_transmitting(void);
void sendThroughSysex(char *printbuffer, int bufferlength);
#ifdef __cplusplus
}
#endif
#endif
#endif