This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Cannot write to more than one characteristic

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

Parents Reply Children
No Data
Related