|
24 | 24 | * THE SOFTWARE.
|
25 | 25 | */
|
26 | 26 |
|
| 27 | +#include <string.h> |
| 28 | +#include <stdio.h> |
| 29 | + |
27 | 30 | #include "ble_drv.h"
|
| 31 | +#include "ble_gatts.h" |
| 32 | +#include "nrf_soc.h" |
| 33 | +#include "py/nlr.h" |
28 | 34 | #include "shared-module/bleio/Characteristic.h"
|
29 |
| -#include "shared-module/bleio/Device.h" |
| 35 | + |
| 36 | +static volatile bleio_characteristic_obj_t *m_read_characteristic; |
| 37 | +static volatile uint8_t m_tx_in_progress; |
| 38 | +static nrf_mutex_t *m_write_mutex; |
| 39 | +//static volatile bool m_write_done; |
| 40 | + |
| 41 | +STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { |
| 42 | + bleio_device_obj_t *device = characteristic->service->device; |
| 43 | + const uint16_t conn_handle = device->conn_handle; |
| 44 | + |
| 45 | + ble_gatts_value_t gatts_value = { |
| 46 | + .p_value = bufinfo->buf, |
| 47 | + .len = bufinfo->len, |
| 48 | + }; |
| 49 | + |
| 50 | + const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value); |
| 51 | + if (err_code != NRF_SUCCESS) { |
| 52 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 53 | + "Failed to write gatts value, status: 0x%08lX", err_code)); |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +STATIC void gatts_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { |
| 58 | + bleio_device_obj_t *device = characteristic->service->device; |
| 59 | + uint16_t hvx_len = bufinfo->len; |
| 60 | + |
| 61 | + ble_gatts_hvx_params_t hvx_params = { |
| 62 | + .handle = characteristic->handle, |
| 63 | + .type = BLE_GATT_HVX_NOTIFICATION, |
| 64 | + .p_len = &hvx_len, |
| 65 | + .p_data = bufinfo->buf, |
| 66 | + }; |
| 67 | + |
| 68 | + while (m_tx_in_progress > MAX_TX_IN_PROGRESS) { |
| 69 | +#ifdef MICROPY_VM_HOOK_LOOP |
| 70 | + MICROPY_VM_HOOK_LOOP |
| 71 | +#endif |
| 72 | + } |
| 73 | + |
| 74 | + const uint32_t err_code = sd_ble_gatts_hvx(device->conn_handle, &hvx_params); |
| 75 | + if (err_code != NRF_SUCCESS) { |
| 76 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 77 | + "Failed to notify attribute value, status: 0x%08lX", err_code)); |
| 78 | + } |
| 79 | + |
| 80 | + m_tx_in_progress += 1; |
| 81 | +} |
| 82 | + |
| 83 | +STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { |
| 84 | + bleio_service_obj_t *service = characteristic->service; |
| 85 | + bleio_device_obj_t *device = service->device; |
| 86 | + |
| 87 | + m_read_characteristic = characteristic; |
| 88 | + |
| 89 | + const uint32_t err_code = sd_ble_gattc_read(device->conn_handle, characteristic->handle, 0); |
| 90 | + if (err_code != NRF_SUCCESS) { |
| 91 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 92 | + "Failed to read attribute value, status: 0x%08lX", err_code)); |
| 93 | + } |
| 94 | + |
| 95 | + while (m_read_characteristic != NULL) { |
| 96 | +#ifdef MICROPY_VM_HOOK_LOOP |
| 97 | + MICROPY_VM_HOOK_LOOP |
| 98 | +#endif |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { |
| 103 | + bleio_device_obj_t *device = characteristic->service->device; |
| 104 | + uint16_t conn_handle = device->conn_handle; |
| 105 | + uint32_t err_code; |
| 106 | + |
| 107 | + ble_gattc_write_params_t write_params; |
| 108 | + write_params.write_op = BLE_GATT_OP_WRITE_REQ; |
| 109 | + |
| 110 | + if (characteristic->props.write_wo_resp) { |
| 111 | + write_params.write_op = BLE_GATT_OP_WRITE_CMD; |
| 112 | + } |
| 113 | + |
| 114 | + write_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL; |
| 115 | + write_params.handle = characteristic->handle; |
| 116 | + write_params.offset = 0; |
| 117 | + write_params.len = bufinfo->len; |
| 118 | + write_params.p_value = bufinfo->buf; |
| 119 | + |
| 120 | + if (write_params.write_op == BLE_GATT_OP_WRITE_CMD) { |
| 121 | + err_code = sd_mutex_acquire(m_write_mutex); |
| 122 | + if (err_code != NRF_SUCCESS) { |
| 123 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 124 | + "Failed to acquire mutex, status: 0x%08lX", err_code)); |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + err_code = sd_ble_gattc_write(conn_handle, &write_params); |
| 129 | + if (err_code != 0) { |
| 130 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 131 | + "Failed to write attribute value, status: 0x%08lX", err_code)); |
| 132 | + } |
| 133 | + |
| 134 | + while (sd_mutex_acquire(m_write_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { |
| 135 | +#ifdef MICROPY_VM_HOOK_LOOP |
| 136 | + MICROPY_VM_HOOK_LOOP |
| 137 | +#endif |
| 138 | + } |
| 139 | + |
| 140 | + err_code = sd_mutex_release(m_write_mutex); |
| 141 | + if (err_code != NRF_SUCCESS) { |
| 142 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, |
| 143 | + "Failed to release mutex, status: 0x%08lX", err_code)); |
| 144 | + } |
| 145 | +} |
| 146 | + |
| 147 | +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *param) { |
| 148 | + switch (ble_evt->header.evt_id) { |
| 149 | +#if (BLE_API_VERSION == 4) |
| 150 | + case BLE_GATTS_EVT_HVN_TX_COMPLETE: |
| 151 | + m_tx_in_progress -= ble_evt->evt.gatts_evt.params.hvn_tx_complete.count; |
| 152 | + break; |
| 153 | +#else |
| 154 | + case BLE_EVT_TX_COMPLETE: |
| 155 | + m_tx_in_progress -= ble_evt->evt.common_evt.params.tx_complete.count; |
| 156 | + break; |
| 157 | +#endif |
| 158 | + |
| 159 | + case BLE_GATTC_EVT_READ_RSP: |
| 160 | + { |
| 161 | + ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; |
| 162 | + m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data); |
| 163 | + m_read_characteristic = NULL; |
| 164 | + break; |
| 165 | + } |
| 166 | + |
| 167 | + case BLE_GATTC_EVT_WRITE_RSP: |
| 168 | + sd_mutex_release(m_write_mutex); |
| 169 | +// m_write_done = true; |
| 170 | + break; |
| 171 | + } |
| 172 | +} |
| 173 | + |
| 174 | +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self) { |
| 175 | + ble_drv_add_event_handler(on_ble_evt, NULL); |
| 176 | +} |
30 | 177 |
|
31 | 178 | void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self) {
|
32 |
| - ble_drv_attr_c_read(self); |
| 179 | + gattc_read(self); |
33 | 180 | }
|
34 | 181 |
|
35 | 182 | void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
36 |
| - const bleio_device_obj_t *device = MP_OBJ_TO_PTR(self->service->device); |
| 183 | + const bleio_device_obj_t *device = self->service->device; |
37 | 184 |
|
38 | 185 | if (device->is_peripheral) {
|
39 | 186 | // TODO: Add indications
|
40 | 187 | if (self->props.notify) {
|
41 |
| - ble_drv_attr_s_notify(self, bufinfo); |
| 188 | + gatts_notify(self, bufinfo); |
42 | 189 | } else {
|
43 |
| - ble_drv_attr_s_write(self, bufinfo); |
| 190 | + gatts_write(self, bufinfo); |
44 | 191 | }
|
45 | 192 | } else {
|
46 |
| - ble_drv_attr_c_write(self, bufinfo); |
| 193 | + gattc_write(self, bufinfo); |
47 | 194 | }
|
48 | 195 |
|
49 | 196 | }
|
0 commit comments