Thank you - this worked! Amazing how it was such a small thing...
Also, looked again and I don't see any documentation explaining what you just did. I know it's sort-of internal to the API/Descriptor Tool, but off the top of your head did I just miss looking at something?
Anyways, I'm going to clean this up and write some MIDI functions. Will post an update later.
Thanks for the replies! I've managed to sort out the descriptors. I've got the device showing up in the device manager as a Generic USB Audio device and I've checked the descriptors with USBlyzer and they seem okay. Device manager reports the device is working properly and I'm able to successfully view the device and it's input and output ports in various MIDI programs (tested with midi-ox and ableton live).
Now I'm trying to send a midi message to the PC but am stuck again. In my test code I'm trying to spam a note on command (cable 0, channel 1: 0x09905840) in a while loop. Being naive, I tried using the CDC functions from the API example with no success. The example used "USBCDC_sendDataInBackground", but there is also "USBCDC_sendDataAndWaitTillDone", "USBCDC_sendData", and "CdcToHostFromBuffer". All the functions in the API are overwhelming! Looking for some direction here on where to go... Clavier, you mentioned CDC data transfer is essentially the same as MIDI - should I be able to use these functions to send my data?
I'm also a little confused on how the MIDI endpoints are working... to send a note-on message to the host PC: am I sending data with the embedded MIDI IN Jack through the MIDIStreaming Bulk OUT endpoint? And does this have any relevance for how to actually send this data?
You're right - MIDI is not supported, trying to alter the files to make it work. What's Reach Logging? (sorry, i'm a noob!)
Thanks for the tips! Made some comments above.
Thanks again for all the support on this.
Edit: Added some of my code...
// Simplified main.c
uint8_t midiTest[4] = {
0x09, //cable 0, note-on
0x90, //note-on, channel 1
0x88, //middle C
0x40 //non-sensitive velocity
};
while (1)
{
if (USBCDC_sendDataAndWaitTillDone(midiTest, 4, 0, 1000))
{
_NOP();
} else {
success = 1; // by setting a watch, this does actually execute
// at some point, but usually the call errors instead.
}
}
}
/*-----------------------------------------------------------------------------+
| Device Descriptor
|-----------------------------------------------------------------------------*/
uint8_t const abromDeviceDescriptor[SIZEOF_DEVICE_DESCRIPTOR] = {
SIZEOF_DEVICE_DESCRIPTOR, // Length of this descriptor
DESC_TYPE_DEVICE, // Type code of this descriptor
0x10, 0x01, // Release of USB spec
0x00, // Device's base class code
0x00, // Device's sub class code
0x00, // Device's protocol type code
EP0_PACKET_SIZE, // End point 0's packet size
USB_VID&0xFF, USB_VID>>8, // Vendor ID for device, TI=0x0451
USB_PID&0xFF, USB_PID>>8, // Product ID for device
VER_FW_L, VER_FW_H, // Revision level of device
1, // Index of manufacturer name string desc
2, // Index of product name string desc
0x00, // Index of serial number string desc
1 // Number of configurations supported
};
/*-----------------------------------------------------------------------------+
| Configuration Descriptor |
|-----------------------------------------------------------------------------*/
const struct abromConfigurationDescriptorGroup abromConfigurationDescriptorGroup=
{
/* Generic part */
{
// CONFIGURATION DESCRIPTOR (9 bytes)
SIZEOF_CONFIG_DESCRIPTOR,
DESC_TYPE_CONFIG,
0x65, 0x00,
USB_NUM_INTERFACES,
USB_CONFIG_VALUE,
0x00,
USB_SUPPORT_SELF_POWERED | USB_SUPPORT_REM_WAKE,
USB_MAX_POWER
},
{
/* start MIDI[0] */
{
//INTERFACE DESCRIPTOR (9 bytes)
0x09,
0x04,
0x00,
0x00,
0x00,
0x01,
0x01,
0x00,
0x00,
//Class-specific AC Interface Descriptor (9)
0x09,
0x24,
0x01,
0x00,
0x01,
0x09, 0x00,
0x01,
0x01,
//MIDIStreaming Interface Descriptors
//Standard MS Interface Descriptor (9)
0x09,
0x04,
0x01,
0x00,
0x02,
0x01,
0x03,
0x00,
0x00,
//Class-specific MS Interface Descriptor (7)
0x07,
0x24,
0x01,
0x00, 0x01,
0x41, 0x00,
//MIDI IN Jack Descriptor (6)
0x06,
0x24,
0x02,
0x01,
0x01,
0x00,
//MIDI IN Jack Descriptor (6)
0x06,
0x24,
0x02,
0x02,
0x02,
0x00,
//MIDI OUT Jack Descriptor (9)
0x09,
0x24,
0x03,
0x01,
0x03,
0x01,
0x02,
0x01,
0x00,
//MIDI OUT Jack Descriptor (9)
0x09,
0x24,
0x03,
0x02,
0x04,
0x01,
0x01,
0x01,
0x00,
// Standard Bulk OUT (9)
0x09,
0x05,
0x01,
0x02,
0x40, 0x00,
0x00,
0x00,
0x00,
// Class MS Bulk OUT (5)
0x05,
0x25,
0x01,
0x01,
0x01,
// Standard Bulk IN (9)
0x09,
0x05,
0x81,
0x02,
0x40, 0x00,
0x00,
0x00,
0x00,
// Class MS Bulk IN (5)
0x05,
0x25,
0x01,
0x01,
0x03
}
After a timeout error, the data is still in the buffer. As long as there still is data in the buffer, USBCDC_sendDataXxx will fail. You have to ensure that the host reads the data; and as long as that doesn't happen, there will be no interrupt.
The USB Audio specification requires that the device has two interfaces, an Audio Control interface (which doesn't do much for a MIDI device; it just lists the other interface), and a MIDI streaming interface. If you never see actual data being transferred to the host, this might be the problem (but then it shouldn't have enumerated any MIDI port).
The interface number you give to the CDC functions is used as an index into several arrays. So when you have a single "CDC" interfeace, you must use zero for these parameters; it is apparently not necessary for it to have the same value as the USB interface number.
Zero packets are not used with MIDI. However, they would be generated only when a USBCDC_sendXxx call happens to completely fill its last USB packet (64 bytes), which is not possible for shorter messages. In any case, the host should just ignore them.
TI's USB stack is designed for be used with the four supported device classes.
To implement another device class, you have to insert custom code at all the appropriate places. However, this is still easier than writing the entire USB stack from scratch.
USB MIDI is similar to CDC, which just transfers bytes over bulk pipes. In the case of USB MIDI, you have the four-byte event packets instead of bytes, but the overall management of the USB packets should be identical.
First, use the descriptor tool to generate a program for some other device class.
Then manually replace the descriptors in the USB_config/descriptors.* files.