Greetings,
I have two nRF52840's where one is modeled as a peripheral and the other as a central. I have created a custom service and characteristics on the peripheral and can connect and read and write. However, I can perform one write and not more. In the example beneath, I am trying to write to the same characteristic twice in consequtive order, as can be seen in the discover_all_completed function.
struct bt_write_client {
/** Connection object. */
struct bt_conn *conn;
/** Internal state. */
atomic_t state;
/** GATT write parameters write request. */
struct bt_gatt_write_params write_params;
/** Characteristic handle. */
uint16_t val_handle;
/** Handle of the CCCD. */
uint16_t ccc_handle;
/** Characteristic properties. */
uint8_t properties;
/** Characteristic value?. */
uint8_t char_value;
/** Application write callbacks. */
bt_write_cb_t write_cb;
};
struct bt_write_client write_client;
int bt_write_to_characteristic(struct bt_write_client *write_client,
const uint8_t *data, uint16_t len) {
int err;
if (!write_client->conn) {
return -ENOTCONN;
}
if (atomic_test_and_set_bit(&write_client->state, WRITE_CLIENT_PENDING)) {
return -EALREADY;
}
write_client->write_params.func = on_sent;
write_client->write_params.handle = write_client->val_handle;
write_client->write_params.offset = 0;
write_client->write_params.data = data;
write_client->write_params.length = len;
err = bt_gatt_write(write_client->conn, &write_client->write_params);
if (err) {
atomic_clear_bit(&write_client->state, WRITE_CLIENT_PENDING);
}
return err;
}
static void on_sent(struct bt_conn *conn, uint8_t err,
struct bt_gatt_write_params *params) {
struct bt_write_client *write_client;
LOG_INF("LOL IM A CALLBACK\n");
write_client = CONTAINER_OF(params, struct bt_write_client, write_params);
atomic_clear_bit(&write_client->state, WRITE_CLIENT_PENDING);
}
static void discover_all_completed(struct bt_gatt_dm *dm, void *ctx) {
char uuid_str[37];
char periph_uuid[37];
const struct bt_gatt_dm_attr *gatt_service_attr = bt_gatt_dm_service_get(dm);
const struct bt_gatt_service_val *gatt_service =
bt_gatt_dm_attr_service_val(gatt_service_attr);
size_t attr_count = bt_gatt_dm_attr_cnt(dm);
bt_uuid_to_str(gatt_service->uuid, uuid_str, sizeof(uuid_str));
printk("Found service %s\n", uuid_str);
printk("Attribute count: %d\n", attr_count);
bt_uuid_to_str(&bt_uuid_periph_service.uuid, periph_uuid,
sizeof(periph_uuid));
int err;
if (!(strcmp(uuid_str, periph_uuid))) {
struct bt_conn *periph_conn = bt_gatt_dm_conn_get(dm);
const bt_addr_le_t *periph_addr = bt_conn_get_dst(periph_conn);
uint8_t periph_str_adr[13];
string_from_bt_addr(periph_addr, periph_str_adr);
LOG_INF("ID IS: %s", log_strdup(periph_str_adr));
err = bt_assign_write_handles(dm, &write_client,
&bt_uuid_periph_service.uuid,
&bt_uuid_characteristic.uuid);
if (err) {
printk("bt_assign_write_handles failed, error: %d\n", err);
}
uint8_t write_test_data[4] = {0x05, 0x05, 0x05, 0x05};
uint16_t sizeof_write_test_data = (uint16_t)sizeof(write_test_data);
err = bt_write_to_characteristic(&write_client, write_test_data,
sizeof_write_test_data);
if (err) {
printk("writing to characteristic failed: %d\n", err);
}
write_test_data[0] = 0x01;
write_test_data[1] = 0x02;
write_test_data[2] = 0x03;
write_test_data[3] = 0x04;
err = bt_write_to_characteristic(&write_client, write_test_data,
sizeof_write_test_data);
if (err) {
printk("writing to characteristic failed: %d\n", err);
}
}
bt_gatt_dm_data_release(dm);
bt_gatt_dm_continue(dm, NULL);
}
However, on the peripheral side, I just receive the write of characteristic to be 5:5:5:5, and not 0:1:2:3 afterwards, and I get one error message of "writing to characteristic failed: -120", which looking at errno.h is #define EALREADY 120 /**< Operation already in progress */. I tried putting a k_mutex_lock in bt_write_to_characteristic and k_mutex_unlock in on_sent, but that didn't help either.
This code is largely based on the nRF Uart Service sample / nus_client.c. Could you see what might be the problem?
Best regards,
Jonas