takawata / FreeBSD-BLE

15 stars 9 forks source link

BLE MIDI client for FreeBSD #11

Open hselasky opened 1 year ago

hselasky commented 1 year ago

Hi,

I want to implement support for BLE MIDI interfaces under FreeBSD.

Probably it makes most sense to create an ALSA client using the alsa-seq-server daemon, for Bluetooth only.

I want that pairing using default keys like 0000 or 1234 is done behind the scenes automagically.

I see there is a midi.c example at https://github.com/takawata/FreeBSD-BLE/blob/master/lehid/midi.c , but what is the state of this code and how shall it be used? Do all BLE MIDI device traffic have to go through the same daemon?

--HPS

takawata commented 1 year ago

First, the "midi.c" is part of "lehid" tool and it will work if you invoke it with the BT address of BLE MIDI device. And BLE MIDI device requires encrypted path per the specification. To pairing, you may want to use "lepair" tool. "lepair ${BTPUBADDR}" or "lepair -r ${BTRNDADDR}" will do pairing. If pin is required, pin input will prompted. Then add the "hcsecd.conf" entry in "lesecd" directory. I updated the "lepair" tool to genarete "hcsecd.conf" entry some hours ago. Then startup "lesecd" with background and invoke "lehid" with -s option to wait for encryption setup done before start operation. i.e. "lehid -s ${BTPUBADDR} or "lehid -s -r ${BTRNDADDR}"

hselasky commented 1 year ago

I would like to extract some device description. Do you have any advice?

hselasky commented 1 year ago

Also see: https://github.com/takawata/FreeBSD-BLE/pull/12

takawata commented 1 year ago

I wrote a fix for MIDI notify buffer interpretation in blemidi-parsefix branch.

https://www.midi.org/specifications-old/item/bluetooth-le-midi

To implement, I wrote a state machine.

  1. Notify has always header. this is initial state.
  2. If it is in SysEx processing, go SYSEX mode from initial state.
  3. Other go TIMESTAMP from initial state.
  4. In TIMESTAMP , if MSB of successive byte, go GETSTS else DATA (treat as running status).
  5. In GETSTS, read status and status is not system message go DATA.
  6. In GETSTS, if system message, if not system exclusive command or sytem exclusive end command, send commands to midi parser and check next byte and if its MSB is set, go TIMESTAMP mode, else DATA mode.
  7. In GETSTS if the message is SYSEX, mark SysEx processing and go SYSEX mode.
  8. In GETSTS, if the message is SysEX-ENd , unmark SysEx processing and go TIMESTAMP mode.
  9. In DATA , send current message status and parameters. then peek next byte and if its MSB is set, goto TIMESTAMP , else go DATA mode.
  10. In SYSEX, read bytes and if its MSB is set, go TIMESTAMP mode. Else send bytes to midi parser.
hselasky commented 1 year ago

I put some comments there.

hselasky commented 1 year ago

I based my parsing on this code: https://github.com/sparkfun/MIDI-BLE-Adapter/blob/master/ble-to-din/ble-to-din.ino

Which also claims to follow the MIDI BLE specification, but is much simpler? Am I wrong?

takawata commented 1 year ago

This drops timestamp completely. And do not handle SysEx message in multiple packet case, and do not handle running status with timestamp, it seems. Though there may be much simpler way.

hselasky commented 1 year ago

I see. Timestamps are not used for anything at the moment, but that doesn't mean we shouldn't parse them. As time permits I'll have a look at your code and pull it into my patchset and test it.