midi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2015,2016 Felipe F. Tonello <eu@felipetonello.com>
  7. * Copyright (C) 2016 ROLI Ltd.
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <errno.h>
  14. #include <alsa/asoundlib.h>
  15. #include "lib/bluetooth.h"
  16. #include "lib/sdp.h"
  17. #include "lib/uuid.h"
  18. #include "src/plugin.h"
  19. #include "src/adapter.h"
  20. #include "src/device.h"
  21. #include "src/profile.h"
  22. #include "src/service.h"
  23. #include "src/shared/util.h"
  24. #include "src/shared/att.h"
  25. #include "src/shared/queue.h"
  26. #include "src/shared/gatt-db.h"
  27. #include "src/shared/gatt-client.h"
  28. #include "src/shared/io.h"
  29. #include "src/log.h"
  30. #include "attrib/att.h"
  31. #include "libmidi.h"
  32. struct midi {
  33. struct btd_device *dev;
  34. struct gatt_db *db;
  35. struct bt_gatt_client *client;
  36. unsigned int io_cb_id;
  37. struct io *io;
  38. uint16_t midi_io_handle;
  39. /* ALSA handlers */
  40. snd_seq_t *seq_handle;
  41. int seq_client_id;
  42. int seq_port_id;
  43. /* MIDI parser*/
  44. struct midi_read_parser midi_in;
  45. struct midi_write_parser midi_out;
  46. };
  47. static bool midi_write_cb(struct io *io, void *user_data)
  48. {
  49. struct midi *midi = user_data;
  50. int err;
  51. void foreach_cb(const struct midi_write_parser *parser, void *user_data) {
  52. struct midi *midi = user_data;
  53. bt_gatt_client_write_without_response(midi->client,
  54. midi->midi_io_handle,
  55. false,
  56. midi_write_data(parser),
  57. midi_write_data_size(parser));
  58. };
  59. do {
  60. snd_seq_event_t *event = NULL;
  61. err = snd_seq_event_input(midi->seq_handle, &event);
  62. if (err < 0 || !event)
  63. break;
  64. midi_read_ev(&midi->midi_out, event, foreach_cb, midi);
  65. } while (err > 0);
  66. if (midi_write_has_data(&midi->midi_out))
  67. bt_gatt_client_write_without_response(midi->client,
  68. midi->midi_io_handle,
  69. false,
  70. midi_write_data(&midi->midi_out),
  71. midi_write_data_size(&midi->midi_out));
  72. midi_write_reset(&midi->midi_out);
  73. return true;
  74. }
  75. static void midi_io_value_cb(uint16_t value_handle, const uint8_t *value,
  76. uint16_t length, void *user_data)
  77. {
  78. struct midi *midi = user_data;
  79. snd_seq_event_t ev;
  80. unsigned int i = 0;
  81. if (length < 3) {
  82. warn("MIDI I/O: Wrong packet format: length is %u bytes but it should "
  83. "be at least 3 bytes", length);
  84. return;
  85. }
  86. snd_seq_ev_clear(&ev);
  87. snd_seq_ev_set_source(&ev, midi->seq_port_id);
  88. snd_seq_ev_set_subs(&ev);
  89. snd_seq_ev_set_direct(&ev);
  90. midi_read_reset(&midi->midi_in);
  91. while (i < length) {
  92. size_t count = midi_read_raw(&midi->midi_in, value + i, length - i, &ev);
  93. if (count == 0)
  94. goto _err;
  95. if (ev.type != SND_SEQ_EVENT_NONE)
  96. snd_seq_event_output_direct(midi->seq_handle, &ev);
  97. i += count;
  98. }
  99. return;
  100. _err:
  101. error("Wrong BLE-MIDI message");
  102. }
  103. static void midi_io_ccc_written_cb(uint16_t att_ecode, void *user_data)
  104. {
  105. if (att_ecode != 0) {
  106. error("MIDI I/O: notifications not enabled %s",
  107. att_ecode2str(att_ecode));
  108. return;
  109. }
  110. DBG("MIDI I/O: notification enabled");
  111. }
  112. static void midi_io_initial_read_cb(bool success, uint8_t att_ecode,
  113. const uint8_t *value, uint16_t length,
  114. void *user_data)
  115. {
  116. struct midi *midi = user_data;
  117. if (!success) {
  118. error("MIDI I/O: Failed to read initial request");
  119. return;
  120. }
  121. /* request notify */
  122. midi->io_cb_id =
  123. bt_gatt_client_register_notify(midi->client,
  124. midi->midi_io_handle,
  125. midi_io_ccc_written_cb,
  126. midi_io_value_cb,
  127. midi,
  128. NULL);
  129. }
  130. static void handle_midi_io(struct midi *midi, uint16_t value_handle)
  131. {
  132. DBG("MIDI I/O handle: 0x%04x", value_handle);
  133. midi->midi_io_handle = value_handle;
  134. /*
  135. * The BLE-MIDI 1.0 spec specifies that The Central shall attempt to
  136. * read the MIDI I/O characteristic of the Peripheral right after
  137. * estrablhishing a connection with the accessory.
  138. */
  139. if (!bt_gatt_client_read_value(midi->client,
  140. value_handle,
  141. midi_io_initial_read_cb,
  142. midi,
  143. NULL))
  144. DBG("MIDI I/O: Failed to send request to read initial value");
  145. }
  146. static void handle_characteristic(struct gatt_db_attribute *attr,
  147. void *user_data)
  148. {
  149. struct midi *midi = user_data;
  150. uint16_t value_handle;
  151. bt_uuid_t uuid, midi_io_uuid;
  152. if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
  153. NULL, &uuid)) {
  154. error("Failed to obtain characteristic data");
  155. return;
  156. }
  157. bt_string_to_uuid(&midi_io_uuid, MIDI_IO_UUID);
  158. if (bt_uuid_cmp(&midi_io_uuid, &uuid) == 0)
  159. handle_midi_io(midi, value_handle);
  160. else {
  161. char uuid_str[MAX_LEN_UUID_STR];
  162. bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
  163. DBG("Unsupported characteristic: %s", uuid_str);
  164. }
  165. }
  166. static void foreach_midi_service(struct gatt_db_attribute *attr,
  167. void *user_data)
  168. {
  169. struct midi *midi = user_data;
  170. gatt_db_service_foreach_char(attr, handle_characteristic, midi);
  171. }
  172. static int midi_device_probe(struct btd_service *service)
  173. {
  174. struct btd_device *device = btd_service_get_device(service);
  175. struct midi *midi;
  176. char addr[18];
  177. ba2str(device_get_address(device), addr);
  178. DBG("MIDI GATT Driver profile probe (%s)", addr);
  179. /* Ignore, if we were probed for this device already */
  180. midi = btd_service_get_user_data(service);
  181. if (midi) {
  182. error("Profile probed twice for the same device!");
  183. return -EADDRINUSE;
  184. }
  185. midi = g_new0(struct midi, 1);
  186. if (!midi)
  187. return -ENOMEM;
  188. midi->dev = btd_device_ref(device);
  189. btd_service_set_user_data(service, midi);
  190. return 0;
  191. }
  192. static void midi_device_remove(struct btd_service *service)
  193. {
  194. struct btd_device *device = btd_service_get_device(service);
  195. struct midi *midi;
  196. char addr[18];
  197. ba2str(device_get_address(device), addr);
  198. DBG("MIDI GATT Driver profile remove (%s)", addr);
  199. midi = btd_service_get_user_data(service);
  200. if (!midi) {
  201. error("MIDI Service not handled by profile");
  202. return;
  203. }
  204. btd_device_unref(midi->dev);
  205. g_free(midi);
  206. }
  207. static int midi_accept(struct btd_service *service)
  208. {
  209. struct btd_device *device = btd_service_get_device(service);
  210. struct gatt_db *db = btd_device_get_gatt_db(device);
  211. struct bt_gatt_client *client = btd_device_get_gatt_client(device);
  212. bt_uuid_t midi_uuid;
  213. struct pollfd pfd;
  214. struct midi *midi;
  215. char addr[18];
  216. char device_name[MAX_NAME_LENGTH + 11]; /* 11 = " Bluetooth\0"*/
  217. int err;
  218. snd_seq_client_info_t *info;
  219. ba2str(device_get_address(device), addr);
  220. DBG("MIDI GATT Driver profile accept (%s)", addr);
  221. midi = btd_service_get_user_data(service);
  222. if (!midi) {
  223. error("MIDI Service not handled by profile");
  224. return -ENODEV;
  225. }
  226. /* Port Name */
  227. memset(device_name, 0, sizeof(device_name));
  228. if (device_name_known(device))
  229. device_get_name(device, device_name, sizeof(device_name));
  230. else
  231. strncpy(device_name, addr, sizeof(device_name));
  232. /* ALSA Sequencer Client and Port Setup */
  233. err = snd_seq_open(&midi->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, 0);
  234. if (err < 0) {
  235. error("Could not open ALSA Sequencer: %s (%d)", snd_strerror(err), err);
  236. return err;
  237. }
  238. err = snd_seq_nonblock(midi->seq_handle, SND_SEQ_NONBLOCK);
  239. if (err < 0) {
  240. error("Could not set nonblock mode: %s (%d)", snd_strerror(err), err);
  241. goto _err_handle;
  242. }
  243. err = snd_seq_set_client_name(midi->seq_handle, device_name);
  244. if (err < 0) {
  245. error("Could not configure ALSA client: %s (%d)", snd_strerror(err), err);
  246. goto _err_handle;
  247. }
  248. err = snd_seq_client_id(midi->seq_handle);
  249. if (err < 0) {
  250. error("Could retreive ALSA client: %s (%d)", snd_strerror(err), err);
  251. goto _err_handle;
  252. }
  253. midi->seq_client_id = err;
  254. err = snd_seq_create_simple_port(midi->seq_handle, strcat(device_name, " Bluetooth"),
  255. SND_SEQ_PORT_CAP_READ |
  256. SND_SEQ_PORT_CAP_WRITE |
  257. SND_SEQ_PORT_CAP_SUBS_READ |
  258. SND_SEQ_PORT_CAP_SUBS_WRITE,
  259. SND_SEQ_PORT_TYPE_MIDI_GENERIC |
  260. SND_SEQ_PORT_TYPE_HARDWARE);
  261. if (err < 0) {
  262. error("Could not create ALSA port: %s (%d)", snd_strerror(err), err);
  263. goto _err_handle;
  264. }
  265. midi->seq_port_id = err;
  266. snd_seq_client_info_alloca(&info);
  267. err = snd_seq_get_client_info(midi->seq_handle, info);
  268. if (err < 0)
  269. goto _err_port;
  270. /* list of relevant sequencer events */
  271. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_NOTEOFF);
  272. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_NOTEON);
  273. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_KEYPRESS);
  274. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_CONTROLLER);
  275. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_PGMCHANGE);
  276. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_CHANPRESS);
  277. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_PITCHBEND);
  278. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_SYSEX);
  279. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_QFRAME);
  280. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_SONGPOS);
  281. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_SONGSEL);
  282. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_TUNE_REQUEST);
  283. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_CLOCK);
  284. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_START);
  285. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_CONTINUE);
  286. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_STOP);
  287. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_SENSING);
  288. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_RESET);
  289. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_CONTROL14);
  290. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_NONREGPARAM);
  291. snd_seq_client_info_event_filter_add(info, SND_SEQ_EVENT_REGPARAM);
  292. err = snd_seq_set_client_info(midi->seq_handle, info);
  293. if (err < 0)
  294. goto _err_port;
  295. /* Input file descriptors */
  296. snd_seq_poll_descriptors(midi->seq_handle, &pfd, 1, POLLIN);
  297. midi->io = io_new(pfd.fd);
  298. if (!midi->io) {
  299. error("Could not allocate I/O eventloop");
  300. goto _err_port;
  301. }
  302. io_set_read_handler(midi->io, midi_write_cb, midi, NULL);
  303. midi->db = gatt_db_ref(db);
  304. midi->client = bt_gatt_client_ref(client);
  305. err = midi_read_init(&midi->midi_in);
  306. if (err < 0) {
  307. error("Could not initialise MIDI input parser");
  308. goto _err_port;
  309. }
  310. err = midi_write_init(&midi->midi_out, bt_gatt_client_get_mtu(midi->client) - 3);
  311. if (err < 0) {
  312. error("Could not initialise MIDI output parser");
  313. goto _err_midi;
  314. }
  315. bt_string_to_uuid(&midi_uuid, MIDI_UUID);
  316. gatt_db_foreach_service(db, &midi_uuid, foreach_midi_service, midi);
  317. btd_service_connecting_complete(service, 0);
  318. return 0;
  319. _err_midi:
  320. midi_read_free(&midi->midi_in);
  321. _err_port:
  322. snd_seq_delete_simple_port(midi->seq_handle, midi->seq_port_id);
  323. _err_handle:
  324. snd_seq_close(midi->seq_handle);
  325. midi->seq_handle = NULL;
  326. btd_service_connecting_complete(service, err);
  327. return err;
  328. }
  329. static int midi_disconnect(struct btd_service *service)
  330. {
  331. struct btd_device *device = btd_service_get_device(service);
  332. struct midi *midi;
  333. char addr[18];
  334. ba2str(device_get_address(device), addr);
  335. DBG("MIDI GATT Driver profile disconnect (%s)", addr);
  336. midi = btd_service_get_user_data(service);
  337. if (!midi) {
  338. error("MIDI Service not handled by profile");
  339. return -ENODEV;
  340. }
  341. midi_read_free(&midi->midi_in);
  342. midi_write_free(&midi->midi_out);
  343. io_destroy(midi->io);
  344. snd_seq_delete_simple_port(midi->seq_handle, midi->seq_port_id);
  345. midi->seq_port_id = 0;
  346. snd_seq_close(midi->seq_handle);
  347. midi->seq_handle = NULL;
  348. /* Clean-up any old client/db */
  349. bt_gatt_client_unregister_notify(midi->client, midi->io_cb_id);
  350. bt_gatt_client_unref(midi->client);
  351. gatt_db_unref(midi->db);
  352. btd_service_disconnecting_complete(service, 0);
  353. return 0;
  354. }
  355. static struct btd_profile midi_profile = {
  356. .name = "MIDI GATT Driver",
  357. .remote_uuid = MIDI_UUID,
  358. .priority = BTD_PROFILE_PRIORITY_HIGH,
  359. .auto_connect = true,
  360. .device_probe = midi_device_probe,
  361. .device_remove = midi_device_remove,
  362. .accept = midi_accept,
  363. .disconnect = midi_disconnect,
  364. };
  365. static int midi_init(void)
  366. {
  367. return btd_profile_register(&midi_profile);
  368. }
  369. static void midi_exit(void)
  370. {
  371. btd_profile_unregister(&midi_profile);
  372. }
  373. BLUETOOTH_PLUGIN_DEFINE(midi, VERSION, BLUETOOTH_PLUGIN_PRIORITY_HIGH,
  374. midi_init, midi_exit);