/**
 * @brief Cancel an ongoing query for a list of available networks.
 *
 * JSON format:
 *  request:
 *    { }
 *  response:
 *    {
 *       "returnValue": <boolean>,
 *       "errorCode": <integer>,
 *       "errorString" <string>,
 *    }
 **/
bool _service_network_list_query_cancel_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->network_list_query_cancel) {
		g_warning("No implementation available for service networkListQueryCancel API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		return true;
	}

	if (!service->network_status_query_pending) {
		luna_service_message_reply_custom_error(handle, message, "No network list query pending");
		return true;
	}

	req_data = luna_service_req_data_new(handle, message);
	req_data->user_data = service;

	service->driver->network_list_query_cancel(service, _service_network_list_query_cancel_finish, req_data);

	return true;
}
Example #2
0
static bool play_feedback_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	struct play_feedback_data *pfd;
	const char *payload;
	jvalue_ref parsed_obj;
	char *name, *sink;
	bool play;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	name = luna_service_message_get_string(parsed_obj, "name", NULL);
	if (!name) {
		luna_service_message_reply_custom_error(handle, message, "Invalid parameters: name parameter is required");
		goto cleanup;
	}

	play = luna_service_message_get_boolean(parsed_obj, "play", true);

	sink = luna_service_message_get_string(parsed_obj, "sink", NULL);

	pfd = g_new0(struct play_feedback_data, 1);
	pfd->service = service;
	pfd->handle = handle;
	pfd->message = message;
	pfd->name = name;
	pfd->sink = sink;
	pfd->play = play;

	LSMessageRef(message);

	if (!preload_sample(service, pfd)) {
		luna_service_message_reply_custom_error(handle, message, "Could not preload sample");
		LSMessageUnref(message);
		g_free(pfd);
		g_free(name);
		g_free(sink);
		goto cleanup;
	}

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Example #3
0
static bool set_volume_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	const char *payload;
	jvalue_ref parsed_obj = NULL;
	jvalue_ref volume_obj = NULL;
	struct luna_service_req_data *req;
	int new_volume = 0;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("volume"), &volume_obj) ||
		!jis_number(volume_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	jnumber_get_i32(volume_obj, &new_volume);

	if (new_volume < 0 || new_volume > 100) {
		luna_service_message_reply_custom_error(handle, message, "Volume out of range. Must be in [0;100]");
		goto cleanup;
	}

	if (service->new_volume == service->volume) {
		luna_service_message_reply_custom_error(handle, message,
			"Provided volume doesn't differ from current one");
		goto cleanup;
	}

	req = luna_service_req_data_new(handle, message);
	req->user_data = service;

	set_volume(service, service->new_volume, req);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Example #4
0
static bool set_mic_mute_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	const char *payload;
	jvalue_ref parsed_obj = NULL;
	struct luna_service_req_data *req;
	pa_operation *op;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	service->mic_mute = luna_service_message_get_boolean(parsed_obj, "micMute", service->mic_mute);

	req = luna_service_req_data_new(handle, message);
	req->user_data = service;

	op = pa_context_get_source_info_list(service->context, mm_sourceinfo_cb, req);
	pa_operation_unref(op);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Example #5
0
static bool volume_down_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	struct luna_service_req_data *req;
	int normalized_volume;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	normalized_volume = (service->volume / 10) * 10;
	if (normalized_volume == 0)
		goto done;

	req = luna_service_req_data_new(handle, message);
	req->user_data = service;

	set_volume(service, normalized_volume - VOLUME_STEP, req);

	return true;

done:
	luna_service_message_reply_success(handle, message);

	return true;
}
Example #6
0
static bool get_status_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	jvalue_ref reply_obj = NULL;
	bool subscribed = false;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	subscribed = luna_service_check_for_subscription_and_process(handle, message);

	reply_obj = jobject_create();

	jobject_put(reply_obj, J_CSTR_TO_JVAL("volume"), jnumber_create_f64(service->volume));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("mute"), jboolean_create(service->mute));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("inCall"), jboolean_create(service->in_call));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("speakerMode"), jboolean_create(service->speaker_mode));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("micMute"), jboolean_create(service->mic_mute));
	if (subscribed)
		jobject_put(reply_obj, J_CSTR_TO_JVAL("subscribed"), jboolean_create(true));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("returnValue"), jboolean_create(true));

	if (!luna_service_message_validate_and_send(handle, message, reply_obj))
		goto cleanup;

cleanup:
	if (!jis_null(reply_obj))
		j_release(&reply_obj);

	return true;
}
Example #7
0
static void play_feedback_sample(struct play_feedback_data *pfd)
{
	pa_operation *op;
	pa_proplist *proplist;
	char *sink = pfd->sink;

	if (!pfd->play) {
		luna_service_message_reply_success(pfd->handle, pfd->message);
		return;
	}

	if (!sink)
		sink = pfd->service->default_sink_name;

	if (!sink) {
		luna_service_message_reply_custom_error(pfd->handle, pfd->message, "No sink found to play sample on");
		return;
	}

	/* make sure we're running as event to enable ducking */
	proplist = pa_proplist_new();
	pa_proplist_setf(proplist, PA_PROP_MEDIA_ROLE, "event");

	op = pa_context_play_sample_with_proplist(pfd->service->context, pfd->name, sink, PA_VOLUME_NORM, proplist, NULL, NULL);
	if (op)
		pa_operation_unref(op);

	luna_service_message_reply_success(pfd->handle, pfd->message);
}
/**
 * @brief Set the network the modem should connect to.
 *
 * JSON format:
 *  request:
 *    {
 *        "automatic": <boolean>,
 *        "id": <string>,
 *    }
 *  response:
 *    {
 *       "returnValue": <boolean>,
 *       "errorCode": <integer>,
 *       "errorString": <string>,
 *    }
 **/
bool _service_network_set_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;
	jvalue_ref parsed_obj = NULL;
	jvalue_ref automatic_obj = NULL;
	jvalue_ref id_obj = NULL;
	const char *payload;
	raw_buffer id_buf;
	const char *id = NULL;
	bool automatic = false;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->network_set) {
		g_warning("No implementation available for service networkSet API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		goto cleanup;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("automatic"), &automatic_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	jboolean_get(automatic_obj, &automatic);

	if (!automatic) {
		if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("id"), &id_obj)) {
			luna_service_message_reply_error_bad_json(handle, message);
			goto cleanup;
		}

		id_buf = jstring_get(id_obj);
		id = id_buf.m_str;
	}

	req_data = luna_service_req_data_new(handle, message);

	service->driver->network_set(service, automatic, id, telephonyservice_common_finish, req_data);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
/**
 * @brief Set the radio access technology mode
 *
 * JSON format:
 *  request:
 *    {
 *        "mode": <string>,
 *    }
 *  response:
 *    {
 *       "returnValue": <boolean>,
 *       "errorCode": <integer>,
 *       "errorString": <string>,
 *    }
 **/
bool _service_rat_set_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;
	jvalue_ref parsed_obj = NULL;
	jvalue_ref mode_obj = NULL;
	const char *payload;
	raw_buffer mode_buf;
	enum telephony_radio_access_mode mode;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->rat_set) {
		g_warning("No implementation available for service ratSet API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		goto cleanup;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("mode"), &mode_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	mode_buf = jstring_get(mode_obj);
	mode = telephony_radio_access_mode_from_string(mode_buf.m_str);

	if (mode < 0) {
		luna_service_message_reply_error_invalid_params(handle, message);
		goto cleanup;
	}

	req_data = luna_service_req_data_new(handle, message);

	service->driver->rat_set(service, mode, telephonyservice_common_finish, req_data);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Example #10
0
static void set_mute_success_cb(pa_context *context, int success, void *user_data)
{
	struct luna_service_req_data *req = user_data;
	struct audio_service *service = req->user_data;

	if (!success) {
		luna_service_message_reply_custom_error(req->handle, req->message, "Could not mute/unmute default sink");
		goto cleanup;
	}

	service->mute = service->new_mute;

	notify_status_subscribers(service);

	luna_service_message_reply_success(req->handle, req->message);

cleanup:
	luna_service_req_data_free(req);
}
/**
 * @brief Query the current radio access technology mode
 *
 * JSON format:
 *  request:
 *    { }
 *  response:
 *    {
 *       "returnValue": <boolean>,
 *       "errorCode": <integer>,
 *       "errorString": <string>,
 *       "extended": {
 *          "mode": <string>,
 *       }
 *    }
 **/
bool _service_rat_query_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->rat_query) {
		g_warning("No implementation available for service ratQuery API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		return true;
	}

	req_data = luna_service_req_data_new(handle, message);

	service->driver->rat_query(service, _service_rat_query_finish, req_data);

	return true;
}
Example #12
0
static void preload_stream_state_cb(pa_stream *stream, void *user_data)
{
	struct play_feedback_data *pfd = user_data;

	switch (pa_stream_get_state(stream)) {
	case PA_STREAM_CREATING:
	case PA_STREAM_READY:
		return;
	case PA_STREAM_TERMINATED:
		g_message("Successfully uploaded sample %s to pulseaudio", pfd->name);
		sample_list = g_slist_append(sample_list, g_strdup(pfd->name));
		play_feedback_sample(pfd);
		play_feedback_data_free(pfd);
		break;
	case PA_STREAM_FAILED:
	default:
		g_warning("Failed to upload sample %s", pfd->name);
		luna_service_message_reply_custom_error(pfd->handle, pfd->message,
												"Failed to upload sample to pulseaudio");
		play_feedback_data_free(pfd);
		break;
	}
}
/**
 * @brief Query the id of the network we're connected.
 *
 * JSON format:
 *  request:
 *    { }
 *  response:
 *    {
 *       "returnValue": <boolean>,
 *       "errorCode": <integer>,
 *       "errorString": <string>,
 *       "subscribed": <boolean>,
 *       "extended": {
 *            "mccmnc": <string>,
 *       },
 *    }
 **/
bool _service_network_id_query_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->network_id_query) {
		g_warning("No implementation available for service networkIdQuery API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		return true;
	}

	req_data = luna_service_req_data_new(handle, message);
	req_data->subscribed = luna_service_check_for_subscription_and_process(req_data->handle, req_data->message);

	service->driver->network_id_query(service, _service_network_id_query_finish, req_data);

	return true;
}
bool service_check_for_update_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	int err = 0;
	struct package_list_info plistinfo;
	GSList *iter;
	jvalue_ref reply_obj = NULL;

	if (opkg_new()) {
		luna_service_message_reply_error_internal(handle, message);
		return true;
	}

	err = opkg_update_package_lists(NULL, NULL);
	if (err != 0) {
		luna_service_message_reply_custom_error(handle, message, "Failed to update package list from configured feeds");
		return true;
	}

	plistinfo.pkgs = g_slist_alloc();
	opkg_list_upgradable_packages(upgradable_package_list_cb, &plistinfo);

	reply_obj = jobject_create();
	jobject_put(reply_obj, J_CSTR_TO_JVAL("returnValue"), jboolean_create(true));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("updatesAvailable"),
				jboolean_create(g_slist_length(plistinfo.pkgs) > 0));

	if(!luna_service_message_validate_and_send(handle, message, reply_obj))
		luna_service_message_reply_error_internal(handle, message);

	j_release(&reply_obj);
	g_slist_free_full(plistinfo.pkgs, g_free);

	opkg_free();

	return true;
}
bool _service_power_set_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct telephony_service *service = user_data;
	struct luna_service_req_data *req_data = NULL;
	bool power = false;
	jvalue_ref parsed_obj = NULL;
	jvalue_ref state_obj = NULL;
	jvalue_ref save_obj = NULL;
	const char *payload;
	bool should_save = false;

	if (!service->initialized) {
		luna_service_message_reply_custom_error(handle, message, "Backend not initialized");
		return true;
	}

	if (!service->driver || !service->driver->power_set) {
		g_warning("No implementation available for service powerSet API method");
		luna_service_message_reply_error_not_implemented(handle, message);
		goto cleanup;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("state"), &state_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (jstring_equal2(state_obj, J_CSTR_TO_BUF("on")))
		power = true;
	else if (jstring_equal2(state_obj, J_CSTR_TO_BUF("off")))
		power = false;
	else if (jstring_equal2(state_obj, J_CSTR_TO_BUF("default"))) {
		power = true;
	}
	else {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	if (jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("save"), &save_obj)) {
		jboolean_get(save_obj, &should_save);
		if (should_save)
			telephony_settings_store(TELEPHONY_SETTINGS_TYPE_POWER_STATE,
									 power ? "{\"state\":true}" : "{\"state\":false}");
	}

	service->power_off_pending = !power;

	req_data = luna_service_req_data_new(handle, message);
	req_data->user_data = service;

	service->driver->power_set(service, power, _service_power_set_finish, req_data);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Example #16
0
void luna_service_message_reply_error_internal(LSHandle *handle, LSMessage *message)
{
	luna_service_message_reply_custom_error(handle, message, "Internal error.");
}
Example #17
0
void luna_service_message_reply_error_not_implemented(LSHandle *handle, LSMessage *message)
{
	luna_service_message_reply_custom_error(handle, message, "Not implemented.");
}
Example #18
0
void luna_service_message_reply_error_invalid_params(LSHandle *handle, LSMessage *message)
{
	luna_service_message_reply_custom_error(handle, message, "Invalid parameters.");
}
Example #19
0
void luna_service_message_reply_error_bad_json(LSHandle *handle, LSMessage *message)
{
	luna_service_message_reply_custom_error(handle, message, "Malformed json.");
}
Example #20
0
void luna_service_message_reply_error_unknown(LSHandle *handle, LSMessage *message)
{
	luna_service_message_reply_custom_error(handle, message, "Unknown Error.");
}
bool service_retrieve_package_info_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	jvalue_ref reply_obj;
	jvalue_ref parsed_obj;
	jvalue_ref name_obj;
	jvalue_ref depends_obj;
	jvalue_ref recommends_obj;
	jvalue_ref conflicts_obj;
	pkg_t *package = NULL;
	const char *payload = NULL;
	const char *pkgname = NULL;
	raw_buffer name_buf;
	int n;

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		return true;
	}

	if (!jobject_get_exists(parsed_obj, J_CSTR_TO_BUF("name"), &name_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		return true;
	}

	if (opkg_new()) {
		luna_service_message_reply_error_internal(handle, message);
		return true;
	}

	name_buf = jstring_get(name_obj);
	package = opkg_find_package(name_buf.m_str, NULL, NULL, NULL);

	if (!package) {
		luna_service_message_reply_custom_error(handle, message, "Package does not exist");
		goto cleanup;
	}

	set_flags_from_control(package);

	reply_obj = jobject_create();
	jobject_put(reply_obj, J_CSTR_TO_JVAL("returnValue"), jboolean_create(true));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("version"), jstring_create(package->version ? package->version : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("revision"), jstring_create(package->revision ? package->revision : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("architecture"), jstring_create(package->architecture ? package->architecture : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("section"), jstring_create(package->section ? package->section : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("maintainer"), jstring_create(package->maintainer ? package->maintainer : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("description"), jstring_create(package->description ? package->description : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("tags"), jstring_create(package->tags ? package->tags : ""));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("size"), jnumber_create_i32(package->size));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("installed_size"), jnumber_create_i32(package->installed_size));
	jobject_put(reply_obj, J_CSTR_TO_JVAL("auto_installed"), jboolean_create(package->auto_installed > 0 ? true : false));

	if (!luna_service_message_validate_and_send(handle, message, reply_obj)) {
		luna_service_message_reply_error_internal(handle, message);
		goto cleanup;
	}

cleanup:
	opkg_free();

	return true;
}