static uint8_t ccc_write_cb(struct pending_op *op, void *user_data)
{
	struct external_chrc *chrc = user_data;
	DBusMessageIter iter;
	uint16_t value;

	value = op ? PTR_TO_UINT(op->data.iov_base) : 0;

	DBG("External CCC write received with value: 0x%04x", value);

	/* Notifications/indications disabled */
	if (!value) {
		if (!chrc->ntfy_cnt)
			goto done;

		if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
			goto done;

		if (chrc->notify_io) {
			io_destroy(chrc->notify_io);
			chrc->notify_io = NULL;
			goto done;
		}

		/*
		 * Send request to stop notifying. This is best-effort
		 * operation, so simply ignore the return the value.
		 */
		g_dbus_proxy_method_call(chrc->proxy, "StopNotify", NULL,
							NULL, NULL, NULL);
		goto done;
	}

	if (chrc->ntfy_cnt == UINT_MAX)
		/* Maximum number of per-device CCC descriptors configured */
		return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;

	/* Don't support undefined CCC values yet */
	if (value > 2 ||
		(value == 1 && !(chrc->props & BT_GATT_CHRC_PROP_NOTIFY)) ||
		(value == 2 && !(chrc->props & BT_GATT_CHRC_PROP_INDICATE)))
		return BT_ERROR_CCC_IMPROPERLY_CONFIGURED;

	if (chrc->notify_io) {
		__sync_fetch_and_add(&chrc->ntfy_cnt, 1);
		goto done;
	}

	/* Make use of AcquireNotify if supported */
	if (g_dbus_proxy_get_property(chrc->proxy, "NotifyAcquired", &iter)) {
		op->data.iov_base = (void *) chrc;
		op->data.iov_len = sizeof(chrc);
		op->owner_queue = chrc->pending_writes;
		if (g_dbus_proxy_method_call(chrc->proxy, "AcquireNotify",
						acquire_notify_setup,
						acquire_notify_reply,
						op, pending_op_free))
			return 0;
	}

	/*
	 * Always call StartNotify for an incoming enable and ignore the return
	 * value for now.
	 */
	if (g_dbus_proxy_method_call(chrc->proxy, "StartNotify", NULL, NULL,
						NULL, NULL) == FALSE)
		return BT_ATT_ERROR_UNLIKELY;

	__sync_fetch_and_add(&chrc->ntfy_cnt, 1);

done:
	if (op)
		pending_op_free(op);

	return 0;
}
static uint8_t ccc_write_cb(struct pending_op *op, void *user_data)
{
	struct external_chrc *chrc = user_data;
	DBusMessageIter iter;
	uint16_t value;

	value = op ? PTR_TO_UINT(op->data.iov_base) : 0;

	DBG("External CCC write received with value: 0x%04x", value);

	 
	if (!value) {
		if (!chrc->ntfy_cnt)
			goto done;

		if (__sync_sub_and_fetch(&chrc->ntfy_cnt, 1))
			goto done;

		if (chrc->notify_io) {
			io_destroy(chrc->notify_io);
			chrc->notify_io = NULL;
			goto done;
		}

		 
		g_dbus_proxy_method_call(chrc->proxy, "StopNotify", NULL,
							NULL, NULL, NULL);
		goto done;
	}

	if (chrc->ntfy_cnt == UINT_MAX)
		 
		return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;

	 
	if (value > 2 ||
		(value == 1 && !(chrc->props & BT_GATT_CHRC_PROP_NOTIFY)) ||
		(value == 2 && !(chrc->props & BT_GATT_CHRC_PROP_INDICATE)))
		return BT_ERROR_CCC_IMPROPERLY_CONFIGURED;

	if (chrc->notify_io) {
		__sync_fetch_and_add(&chrc->ntfy_cnt, 1);
		goto done;
	}

	 
	if (g_dbus_proxy_get_property(chrc->proxy, "NotifyAcquired", &iter)) {
		op->data.iov_base = (void *) chrc;
		op->data.iov_len = sizeof(chrc);
		op->owner_queue = chrc->pending_writes;
		if (g_dbus_proxy_method_call(chrc->proxy, "AcquireNotify",
						acquire_notify_setup,
						acquire_notify_reply,
						op, pending_op_free))
			return 0;
	}

	 
	if (g_dbus_proxy_method_call(chrc->proxy, "StartNotify", NULL, NULL,
						NULL, NULL) == FALSE)
		return BT_ATT_ERROR_UNLIKELY;

	__sync_fetch_and_add(&chrc->ntfy_cnt, 1);

done:
	if (op)
		pending_op_free(op);

	return 0;
}