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

BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED

Hi. I have two codebases here:

  1. A peripheral application on an nRF51822 using SDK 12.2.0, SD 130. It has a vendor-specific service with a characteristic that is write only (actually, write or write without response only).
  2. A central application on an nRF51 dongle using the pc-ble-driver and running on Windows, written in C.

The central is already scanning, connecting, discovering the service and getting handles for everything it needs. It can enable notifications on another characteristic. When it tries to write to the write only characteristic though, the call to sd_ble_gattc_write() works but the BLE event handler gets BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED with the BLE_GATTC_EVT_WRITE_RSP event.

Here's the characteristic in the peripheral:

static void test_mode_char_add(ble_bts_t * p_bts)
{
	uint32_t err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t attr_char_value;
    ble_uuid_t ble_uuid;
    ble_gatts_attr_md_t attr_md;

    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.write = 1;
    char_md.char_props.write_wo_resp = 1;
    char_md.p_char_user_desc = NULL;
    char_md.p_char_pf = NULL;
    char_md.p_user_desc_md = NULL;
    char_md.p_cccd_md = NULL;
    char_md.p_sccd_md = NULL;

    // Vendor-specific characteristic UUID
    ble_uuid.type = p_bts->uuid_type;
    ble_uuid.uuid = BTS_UUID_TEST_STATE_CHAR;

    memset(&attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);

    attr_md.vloc = BLE_GATTS_VLOC_STACK;

    attr_md.wr_auth = 0;
    attr_md.vlen = 0;

    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len = sizeof(uint8_t);
    attr_char_value.init_offs = 0;
    attr_char_value.max_len = sizeof(uint8_t);
    attr_char_value.p_value = 0;

    err_code = sd_ble_gatts_characteristic_add(p_bts->service_handle, &char_md, &attr_char_value, &p_bts->test_state_handles);
    APP_ERROR_CHECK(err_code);
}

Here's the function in the central code that write to this characteristic:

uint32_t start_test(char * p_test_state_name)
{
	ble_gattc_write_params_t write_params;
	write_params.handle = m_bts_test_state_char_handle; // This is decimal 22 at this point.
	write_params.len = 2;
	write_params.write_op = BLE_GATT_OP_WRITE_REQ;
	write_params.offset = 0;

	// First enable notifications on the log characteristic.
	m_write_is_in_progress = true;
	log_cccd_set(BLE_CCCD_NOTIFY);

	// Wait for that to complete before we write the next one, or we'll just get an NRF_ERROR_BUSY.
	while (m_write_is_in_progress)
	{
		// Wait. We don't have the SD WFE function here, since we're on Windows using pc-ble-driver.
	}

	if (strcmp("pcba", p_test_state_name) == 0 || strcmp("PCBA", p_test_state_name) == 0)
	{
		m_test_state = STATE_TEST_PCBA;
	}
	else if (strcmp("system", p_test_state_name) == 0 || strcmp("SYSTEM", p_test_state_name) == 0)
	{
		m_test_state = STATE_TEST_SYSTEM;
	}
	else
	{
		printf("Error: No such test state: %s.\n", p_test_state_name);
		return 4003;
	}

	write_params.p_value = (uint8_t *)&m_test_state;

	printf("Writing to test state characterisitc to start test %s.\n", p_test_state_name);
	fflush(stdout);

	// Calls back to on_write_response().
	uint32_t error_code = sd_ble_gattc_write(m_adapter, m_connection_handle, &write_params);

	if (error_code == NRF_ERROR_BUSY)
	{
		printf("Error: Busy. Slow down.\n");
		fflush(stdout);
	}

	return error_code;
}

I also tried writing to this characteristic from the nRF Connect app and got a completely different error. I can't tell from this log whether the write succeeded or not. Maybe the error 133 afterwards is unrelated.

image description

Parents Reply Children
No Data
Related