YuuichiAkagawa / USBH_MIDI

USB MIDI 1.0 class driver for Arduino USB Host Shield 2.0 Library
GNU General Public License v2.0
152 stars 32 forks source link

Behringer BControl BCF2000 #28

Closed RussCoty closed 3 years ago

RussCoty commented 8 years ago

Great work, you have put in a lot of hard work thanks.

I have tested with the BCF2000 and it seems to behave fine when tested with Hairless MIDI. In BControl mode at least.

I'm trying to get a Vox (made by Korg) Tonelab ST to work with the Hostshield (robotale.com.cn model which looks like a sparkfun), but that doesn't seem to want to be recognised so the intended sysex data is not being sent to it.

I would guess it is based on a similar system to the other Korg audio+midi devices. Any advice in adding support for that would be great. Do I need to find the midi endpoints?

Thanks for any help :-)

YuuichiAkagawa commented 8 years ago

Which device? BCF2000? TonelabST? You can check with "USB Host Shield Library 2.0 -> USB_Desc" example. If these device have MIDI Streaming descriptor, it can connect.

In Interface descriptor

Like this. Interface descriptor: Intf.number: xx Alt.: 00 Endpoints: 02 Intf. Class: 01 Intf. Subclass: 03 Intf. Protocol: 00

RussCoty commented 8 years ago

Yes the BCF2000 connects great. The Tonelab doesn't. I'll try to get the descriptor info and see if that works.

I'll keep you posted. :-)

RussCoty commented 8 years ago

So this is the descriptor for the VOX TonelabST (made by Korg) it has Korg VID

It is a combined device with Audio interface and MIDI over USB. It is a little beyond my limited knowledge and brainpower. But from what you are saying perhaps the Intf. Subclass is not correct. It looks to me like the MIDI has been set by KORG as Intf. Class: FF , Intf. Subclass: FF (vendor specific). Do you think that I could make a change to the USBH_MIDI library code to trick it into recognising this as a class compliant USB MIDI device?

Any help is most appreciated.

VOX TONELAB ST (MADE BY KORG)

Device descriptor: Descriptor Length: 12 Descriptor type: 01 USB version: 0110 Device class: 00 Device Subclass: 00 Device Protocol: 00 Max.packet size: 08 Vendor ID: 0944 Product ID: 0201 Revision ID: 0100 Mfg.string index: 01 Prod.string index: 02 Serial number index: 00 Number of conf.: 01

Configuration descriptor: Total length: 00F8 Num.intf: 04 Conf.value: 01 Conf.string: 00 Attr.: 40 Max.pwr: 00

Interface descriptor: Intf.number: 00 Alt.: 00 Endpoints: 00 Intf. Class: 01 Intf. Subclass: 01 Intf. Protocol: 00 Intf.string: 00 Unknown descriptor: Length: 0A Type: 24 Contents: 01000134000201020C24 Unknown descriptor: Length: 0C Type: 24 Contents: 020101010002030000000924 Unknown descriptor: Length: 09 Type: 24 Contents: 030202030001000C24 Unknown descriptor: Length: 0C Type: 24 Contents: 020301020002030000000924 Unknown descriptor: Length: 09 Type: 24 Contents: 030401010003000904

Interface descriptor: Intf.number: 01 Alt.: 00 Endpoints: 00 Intf. Class: 01 Intf. Subclass: 02 Intf. Protocol: 00 Intf.string: 00

Interface descriptor: Intf.number: 01 Alt.: 01 Endpoints: 01 Intf. Class: 01 Intf. Subclass: 02 Intf. Protocol: 00 Intf.string: 00 Unknown descriptor: Length: 07 Type: 24 Contents: 01010101000B24 Unknown descriptor: Length: 0B Type: 24 Contents: 02010202100144AC000905

Endpoint descriptor: Endpoint address: 01 Attr.: 09 Max.pkt size: 00C0 Polling interval: 01 Unknown descriptor: Length: 07 Type: 25 Contents: 01000101000904

Interface descriptor: Intf.number: 02 Alt.: 00 Endpoints: 00 Intf. Class: 01 Intf. Subclass: 02 Intf. Protocol: 00 Intf.string: 00

Interface descriptor: Intf.number: 02 Alt.: 01 Endpoints: 01 Intf. Class: 01 Intf. Subclass: 02 Intf. Protocol: 00 Intf.string: 00 Unknown descriptor: Length: 07 Type: 24 Contents: 01040101000B24 Unknown descriptor: Length: 0B Type: 24 Contents: 02010202100144AC000905

Endpoint descriptor: Endpoint address: 82 Attr.: 05 Max.pkt size: 00C0 Polling interval: 01 Unknown descriptor: Length: 07 Type: 25 Contents: 01000000000904

Interface descriptor: Intf.number: 03 Alt.: 00 Endpoints: 02 Intf. Class: FF Intf. Subclass: FF Intf. Protocol: 00 Intf.string: 00 Unknown descriptor: Length: 07 Type: 24 Contents: 01000125000624 Unknown descriptor: Length: 06 Type: 24 Contents: 020110030924 Unknown descriptor: Length: 09 Type: 24 Contents: 030240011001000924 Unknown descriptor: Length: 09 Type: 24 Contents: 030130012001040624 Unknown descriptor: Length: 06 Type: 24 Contents: 020220000905

Endpoint descriptor: Endpoint address: 04 Attr.: 02 Max.pkt size: 0040 Polling interval: 00 Unknown descriptor: Length: 05 Type: 25 Contents: 0101100905

Endpoint descriptor: Endpoint address: 85 Attr.: 02 Max.pkt size: 0040 Polling interval: 00 Unknown descriptor: Length: 05 Type: 25 Contents: 0101300002

Addr:1(0.0.1)

YuuichiAkagawa commented 8 years ago

Yes. USBH_MIDI has been using a little trick.

Few devices work with this technique. (e.g. Roland UM-ONE)

RussCoty commented 8 years ago

Cool I'll try and figure out how to apply that.

I suppose I could assign MIDISTREAMING as 255 to match the subclass ?

YuuichiAkagawa commented 8 years ago

This is more debug information version. Please replace and execute USBH_MIDI_dump example.

usbh_midi-debug.zip

RussCoty commented 8 years ago

Brilliant thanks. I'll have a go and see if I can get it running.

RussCoty commented 8 years ago

Interestingly I am now getting sporadic responses from the Tonelab:

MIDI Init Addr:01 VID:0944 PID:0201 #Conf:01

NumEP:01

So it looks like there is some MIDI device initialisation. Still no sysex being passed through with bidirectional_convertor sketch. However I seem to be making some progress...slow but progress.

RussCoty commented 8 years ago

It's all a bit beyond my knowlege (newbie) at the moment so any help anyone can give would be appreciated greatly.

1) It looks like I should be able to change this line to recognise the Tonelab's USB class (0xff) and subclass (0xff) as a midi device. In the file usbh_midi.cpp

                    if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) {  //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)

So I tried:

if( buf_ptr[5] == 0xff) { //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming) isMidiFound = true; //MIDI device found. isMidi = true;

This just causes the sketch to hang up at the point where it outputs 'MIDI Init' on the serial monitor.

2) I also have some USB packets and a more indepth debug info from ardiuno. From USBH_MIDI_dump example:

Conf:01 Int:03 Alt:00 EPs:02 IntCl:FF IntSubCl:FF IntSubCl:FF No MIDI Device -EPAddr:04 bmAttr:02 MacPktSz:40 Endpoint descriptor: Length: 09 Type: 05 Address: 04 Attributes: 02 MaxPktSize: 0040 Poll Intrv: 00 -EPAddr:85 bmAttr:02 MacPktSz:40 Endpoint descriptor: Length: 09 Type: 05 Address: 85 Attributes: 02 MaxPktSize: 0040 Poll Intrv: 00

3) Using a USB sniffer I get the following when I send program change info that works when sent from the computer directly to the Tonelab. I'm wondering whether I could just replicate the packets directly to the USBhost. The sysex data seems to be in the Leftover Capture Data starting with F0: 04f0423004000108044e000905f70000

Frame 1: 43 bytes on wire (344 bits), 43 bytes captured (344 bits) Encapsulation type: USB packets with USBPcap header (153) Arrival Time: Apr 8, 2016 11:25:24.828125000 BST [Time shift for this packet: 0.000000000 seconds] Epoch Time: 1460111124.828125000 seconds [Time delta from previous captured frame: 0.000000000 seconds] [Time delta from previous displayed frame: 0.000000000 seconds] [Time since reference or first frame: 0.000000000 seconds] Frame Number: 1 Frame Length: 43 bytes (344 bits) Capture Length: 43 bytes (344 bits) [Frame is marked: False] [Frame is ignored: False] [Protocols in frame: usb] USB URB [Source: host] [Destination: 1.1.4] USBPcap pseudoheader length: 27 IRP ID: 0xffffffff82bb5008 IRP USBD_STATUS: Unknown (0x00000048) URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER (0x0009) IRP information: 0x00, Direction: FDO -> PDO 0000 000. = Reserved: 0x00 .... ...0 = Direction: FDO -> PDO (0x00) URB bus id: 1 Device address: 1 Endpoint: 0x04, Direction: OUT 0... .... = Direction: OUT (0) .000 0100 = Endpoint value: 4 URB transfer type: URB_BULK (0x03) Packet Data Length: 16 [bInterfaceClass: Unknown (0xffff)] Leftover Capture Data: 04f0423004000108044e000905f70000

YuuichiAkagawa commented 8 years ago

Probably I think TonelabST requires a dedicated driver. Can you capture the communication between PC and TonelabST?

RussCoty commented 8 years ago

Yes they have their own MIDI driver. I have captured a chunk of data that changes the patches on the tonelab (basically what I want ardiuno to do). There are only 4 different packets I want to send so a direct data send might be the most viable option. This is what happens when I send the Sysex command 00 F0 42 30 00 01 08 4E 00 09 F7
(I'm sending it from the computer and snififng it on the way out with USBPcap then reading in Wireshark)

0000 1b 00 08 50 bb 82 ff ff ff ff 48 00 00 00 09 00 ...P......H..... 0010 00 01 00 01 00 04 03 10 00 00 00 04 f0 42 30 04 .............B0. 0020 00 01 08 04 4e 00 09 05 f7 00 00 ....N......

RussCoty commented 8 years ago

It looks like there are extra bytes that sit inbetween that sysex data 04 f0 42 30 04 0020 00 01 08 04 4e 00 09 _05 _f7 00 00 Being new to USB protocol I don't know if that is normal.

YuuichiAkagawa commented 8 years ago

"04 f0 42 30 04 00 01 08 04 4e 00 09 05 f7 00 00" is valid USB MIDI packets. SysEx packets is split by 3 bytes each.

first byte mean
x4 SysEx starts or continues
x5 SysEx ends with following single byte
x6 SysEx ends with following two bytes
x7 SysEx ends with following three bytes

But I do not know the meaning of the preceding data. Hmm... I have no solution.

RussCoty commented 8 years ago

Thanks that makes sense. I am waiting to hear back from Korg about the driver protocol. In the meantime I will have a look into sending that raw data. If I can replicate that I suspect I can get the thing working. Perhaps if I send the preceding bytes as raw data then I can send the Sysex as midi using your library.

Out of interest Wireshark lets me highlight the captured bytes and shows what they mean. It looks like the preceding data relates to this chunk of info.

USBPcap pseudoheader length: 27
IRP ID: 0xffffffff82bb5008 IRP USBD_STATUS: Unknown (0x00000048) URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER (0x0009) IRP information: 0x00, Direction: FDO -> PDO 0000 000. = Reserved: 0x00 .... ...0 = Direction: FDO -> PDO (0x00) URB bus id: 1 Device address: 1 Endpoint: 0x04, Direction: OUT 0... .... = Direction: OUT (0) .000 0100 = Endpoint value: 4 URB transfer type: URB_BULK (0x03) Packet Data Length: 16 [bInterfaceClass: Unknown (0xffff)]

YuuichiAkagawa commented 8 years ago

Oops. You're absolutely right.

This library is always send each 4 bytes packet. Probably this may be a cause. I will fix this limitation at week end.

RussCoty commented 8 years ago

Brilliant.

YuuichiAkagawa commented 8 years ago

I update library temporary. Please test. usbh_midi-022.zip

If you want debug info, you may uncomment following line. usbh_midi.h : L29 //#define DEBUG_USB_HOST

And I added new function. uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr) Send raw data. You can send any data to MIDI.

RussCoty commented 8 years ago

Wow, thanks you are a superstar. I'll have a look at that and keep you posted. Thanks again.

YuuichiAkagawa commented 8 years ago

Thank you for your report. :smile:

RussCoty commented 8 years ago

Some progress but still nothing functional. The new library seems great though. Thanks

RussCoty commented 8 years ago

When korg get back to me about the driver I'll send the protocol details over

YuuichiAkagawa commented 8 years ago

Sorry, I jumped to conclusions.

RussCoty commented 8 years ago

Ha ha no it's fine, I should have got it nailed by now...just bogged down in work. I'll keep you posted. ;-)

YuuichiAkagawa commented 3 years ago

Closing this issue due to lack of feedback. Feel free to reopen the issue again if needed.