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