Control Surface stm32
MIDI Control Surface library for Arduino
midi-write.c
Go to the documentation of this file.
1#ifdef ESP32
2
14#include "logging.h"
15#include "midi-private.h"
16
17#include <esp_gatt_common_api.h>
18
19#include <stddef.h>
20#include <stdlib.h> // malloc
21#include <string.h> // memcpy
22
23typedef struct {
24 uint8_t *prepare_buf;
25 int prepare_len;
26} prepare_type_env_t;
27static prepare_type_env_t MIDI_prepare_write_env;
28const static size_t PREPARE_BUF_MAX_SIZE = ESP_GATT_MAX_MTU_SIZE;
29
30static midi_write_callback_t midi_callback = NULL;
31
32void midi_set_write_callback(midi_write_callback_t cb) { midi_callback = cb; }
33
34void midi_handle_write_event(esp_gatt_if_t gatts_if,
35 esp_ble_gatts_cb_param_t *param) {
36 if (param->write.need_rsp)
37 return; // MIDI never needs response, return without acknowledgement
38
39 // If this is a long write across multiple packets
40 if (param->write.is_prep) {
41 esp_gatt_status_t status = ESP_GATT_OK;
42 // Allocate a buffer to receive the write data
43 if (MIDI_prepare_write_env.prepare_buf == NULL) {
44 MIDI_prepare_write_env.prepare_buf =
45 (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
46 MIDI_prepare_write_env.prepare_len = 0;
47 if (MIDI_prepare_write_env.prepare_buf == NULL) {
48 ESP_LOGE("MIDIBLE", "Gatt_server prep no mem\n");
49 status = ESP_GATT_NO_RESOURCES;
50 }
51 }
52 // Make sure that the data fits in the buffer
53 if (param->write.offset > PREPARE_BUF_MAX_SIZE) {
54 status = ESP_GATT_INVALID_OFFSET;
55 }
56 if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
57 status = ESP_GATT_INVALID_ATTR_LEN;
58 }
59
60 // If we're either out of buffer space or out of memory, don't store the
61 // data
62 if (status != ESP_GATT_OK) {
63 // We don't need to send a response for MIDI
64 return;
65 }
66
67 // Copy the write data to the buffer
68 memcpy(MIDI_prepare_write_env.prepare_buf + param->write.offset,
69 param->write.value, param->write.len);
70 MIDI_prepare_write_env.prepare_len += param->write.len;
71 } else {
72 // Not a prepare event, handle the data immediately
73 if (midi_callback)
74 midi_callback(param->write.value, param->write.len);
75 }
76}
77
78// Logs prepared written data and frees the buffer
79void midi_handle_write_exec_event(esp_gatt_if_t gatts_if,
80 esp_ble_gatts_cb_param_t *param) {
81 if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_CANCEL) {
82 ESP_LOGI("MIDIBLE", "ESP_GATT_PREP_WRITE_CANCEL");
83 }
84
85 if (midi_callback && MIDI_prepare_write_env.prepare_buf &&
86 MIDI_prepare_write_env.prepare_len)
87 midi_callback(MIDI_prepare_write_env.prepare_buf,
88 MIDI_prepare_write_env.prepare_len);
89
90 // if (*MIDI_char_handle == param->exec_write.handle) {
91 // TODO: how do we know the write was for this characteristic?
92 // Check transfer ID? Connection ID?
93 if (MIDI_prepare_write_env.prepare_buf) {
94 free(MIDI_prepare_write_env.prepare_buf);
95 MIDI_prepare_write_env.prepare_buf = NULL;
96 }
97 MIDI_prepare_write_env.prepare_len = 0;
98
99 esp_ble_gatts_send_response(gatts_if, param->exec_write.conn_id,
100 param->exec_write.trans_id, ESP_GATT_OK, NULL);
101}
102
103#endif
Declarations of internal functions for the MIDI over BLE system, used in the midi-*....
void midi_handle_write_event(esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
void midi_handle_write_exec_event(esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
void midi_set_write_callback(midi_write_callback_t cb)
Set the callback that is to be called when the client writes (sends) a MIDI packet.
void(* midi_write_callback_t)(const uint8_t *, size_t)
Type for the BLE MIDI write callback.
Definition: midi.h:31