static DBusMessage *descriptor_write_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct descriptor *desc = user_data; struct bt_gatt_client *gatt = desc->chrc->service->client->gatt; uint8_t *value = NULL; size_t value_len = 0; if (!gatt) return btd_error_failed(msg, "Not connected"); if (desc->write_id) return btd_error_in_progress(msg); if (!parse_value_arg(msg, &value, &value_len)) return btd_error_invalid_args(msg); /* * Don't allow writing to Client Characteristic Configuration * descriptors. We achieve this through the StartNotify and StopNotify * methods on GattCharacteristic1. */ if (uuid_cmp(&desc->uuid, GATT_CLIENT_CHARAC_CFG_UUID)) return btd_error_not_permitted(msg, "Write not permitted"); /* * Based on the value length and the MTU, either use a write or a long * write. */ if (value_len <= (unsigned) bt_gatt_client_get_mtu(gatt) - 3) desc->write_id = start_write_request(msg, desc->handle, gatt, value, value_len, desc, desc_write_complete); else desc->write_id = start_long_write(msg, desc->handle, gatt, false, value, value_len, desc, desc_write_complete); if (!desc->write_id) return btd_error_failed(msg, "Failed to initiate write"); return NULL; }
static DBusMessage *characteristic_write_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct characteristic *chrc = user_data; struct bt_gatt_client *gatt = chrc->service->client->gatt; uint8_t *value = NULL; size_t value_len = 0; bool supported = false; if (chrc->write_id) return btd_error_in_progress(msg); if (!parse_value_arg(msg, &value, &value_len)) return btd_error_invalid_args(msg); /* * Decide which write to use based on characteristic properties. For now * we don't perform signed writes since gatt-client doesn't support them * and the user can always encrypt the through pairing. The procedure to * use is determined based on the following priority: * * * "reliable-write" property set -> reliable long-write. * * "write" property set -> write request. * - If value is larger than MTU - 3: long-write * * "write-without-response" property set -> write command. */ if ((chrc->ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE)) { supported = true; chrc->write_id = start_long_write(msg, chrc->value_handle, gatt, true, value, value_len, chrc, chrc_write_complete); if (chrc->write_id) return NULL; } if (chrc->props & BT_GATT_CHRC_PROP_WRITE) { uint16_t mtu; supported = true; mtu = bt_gatt_client_get_mtu(gatt); if (!mtu) return btd_error_failed(msg, "No ATT transport"); if (value_len <= (unsigned) mtu - 3) chrc->write_id = start_write_request(msg, chrc->value_handle, gatt, value, value_len, chrc, chrc_write_complete); else chrc->write_id = start_long_write(msg, chrc->value_handle, gatt, false, value, value_len, chrc, chrc_write_complete); if (chrc->write_id) return NULL; } if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)) goto fail; supported = true; chrc->write_id = bt_gatt_client_write_without_response(gatt, chrc->value_handle, false, value, value_len); if (chrc->write_id) return dbus_message_new_method_return(msg); fail: if (supported) return btd_error_failed(msg, "Failed to initiate write"); return btd_error_not_supported(msg); }