⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a2dpd_dbus.c

📁 linux蓝牙剖面实现
💻 C
字号:
/***  A2DPD - Bluetooth A2DP daemon for Linux**  Copyright (C) 2006  Frédéric DALLEAU <frederic.dalleau@palmsource.com>**  This program is free software; you can redistribute it and/or modify*  it under the terms of the GNU General Public License as published by*  the Free Software Foundation; either version 2 of the License, or*  (at your option) any later version.**  This program is distributed in the hope that it will be useful,*  but WITHOUT ANY WARRANTY; without even the implied warranty of*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the*  GNU General Public License for more details.**  You should have received a copy of the GNU General Public License*  along with this program; if not, write to the Free Software*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <pthread.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include "a2dpd_dbus.h"#include "a2dpd_protocol.h"#define DBUS_API_SUBJECT_TO_CHANGE#include <dbus/dbus-glib.h>#include <dbus/dbus-glib-lowlevel.h>// D-Bus constants#define A2DPD_SERVICE_NAME			"com.access.a2dpd"#define A2DPD_SERVICE_PATH			"/com/access/a2dpd"#define A2DPD_SERVER_INTERFACE_NAME		A2DPD_SERVICE_NAME ".server"#define A2DPD_SERVER_FAILED_ERROR		"com.access.Error.Failed"#define A2DPD_SERVER_PARAM_ERROR		"com.access.Error.ParamError"#define A2DPD_SERVER_BUSY_ERROR			"com.access.Error.Busy"#define A2DPD_SERVER_NOT_SUPPORTED_ERROR	"com.access.Error.NotSupported"#define A2DPD_SERVER_ALREADY_EXISTS_ERROR	"com.access.Error.AlreadyExists"#define A2DPD_SERVER_NOT_EXIST_ERROR		"com.access.Error.DoesNotExist"static DBusGConnection *gconnection = NULL;static pthread_t a2dpd_dbus_thread;static GMainLoop *loop = NULL;static int ctl_socket = 0;int write_config_string(char *filename, char *section, char *key, char *value){	GError *error = NULL;	GKeyFile *key_file = g_key_file_new();	gchar *key_file_data = NULL;	unsigned int key_file_len = 0;	int result = EINVAL;	if (key_file)	{		g_key_file_load_from_file(key_file, filename, G_KEY_FILE_KEEP_COMMENTS, &error);		if (error)		{			DBG("Failed to load key file %s: %s", filename, error->message);			g_error_free(error);			error = NULL;		}		g_key_file_set_value(key_file, section, key, value);		key_file_data = g_key_file_to_data(key_file, &key_file_len, &error);		if (error)		{			DBG("Failed to convert keyfile %s to data: %s", filename, error->message);			g_error_free(error);			error = NULL;		}		g_key_file_free(key_file);		if (key_file_data)		{			/* Why do this fail on UML??			   Is it because we use busybox and not a real unix with all compatible commands...			   result = g_file_set_contents(filename, key_file_data, key_file_len, &error);			   if(error) {			   g_print("3) %d bytes: %s", key_file_len, error->message);			   g_error_free(error);			   error = NULL; */			FILE *hFile = fopen(filename, "wt");			if (hFile)			{				if ((int) (fwrite((void *) key_file_data, key_file_len, 1, hFile)) != 1)				{					DBG("Write failed (errno=%d:%s)", errno, strerror(errno));					result = errno;				}				else				{					DBG("Write %s successful", filename);					result = 0;				}				fclose(hFile);			}			else			{				DBG("fopen %s failed", filename);				result = errno;			}		}	}	return result;}static DBusHandlerResult a2dpd_dbus_Connect(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char c = 'c';	DBG("Begin");	write(ctl_socket, &c, sizeof(c));	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_Disconnect(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char c = 'd';	DBG("Begin");	write(ctl_socket, &c, sizeof(c));	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_StreamStart(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char c = 's';	DBG("Begin");	write(ctl_socket, &c, sizeof(c));	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_StreamSuspend(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char c = 'p';	DBG("Begin");	write(ctl_socket, &c, sizeof(c));	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_Startup(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	// This dummy method is intended to be used with activation	// Calling startup should startup the daemon thanks to dbus activation	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_Exit(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	kill(getpid(), SIGTERM);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_Save(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char c = 'w';	DBG("Begin");	write(ctl_socket, &c, sizeof(c));	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_SetAddress(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char addr[32];	char* lpszParam = NULL;	char c = 't';	DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		memset(addr, 0, sizeof(addr));		strncpy(addr, lpszParam, sizeof(addr));		write(ctl_socket, &c, sizeof(c));		write(ctl_socket, &addr, sizeof(addr));	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_AutoConnect(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char* lpszParam = NULL;	char c0 = 'a';	char c1 = 'a';	DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		DBG("Param %s", lpszParam);		write(ctl_socket, &c0, sizeof(c0));		if(!strcasecmp(lpszParam, "swap")) {			c1 = 'a';		} else if(!strcasecmp(lpszParam, "0")) {			c1 = '0';		} else {			c1 = '1';		}		write(ctl_socket, &c1, sizeof(c1));	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_SetDebug(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char* lpszParam = NULL;	DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		DBG("Param %s", lpszParam);		if(!strcasecmp(lpszParam, "0")) {			g_bdebug = 0;		} else {			g_bdebug = 1;		}	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_SetVolume(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char* lpszParam = NULL;	char c = 'v';	int param = 0;		DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		param = atoi(lpszParam);		DBG("Param %s => %d", lpszParam, param);		write(ctl_socket, &c, sizeof(c));		write(ctl_socket, &param, sizeof(param));	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_SetFlags(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char* lpszParam = NULL;	char c = 'f';	int param = 0;	DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		param = atoi(lpszParam);		DBG("Param %s => %d", lpszParam, param);		write(ctl_socket, &c, sizeof(c));		write(ctl_socket, &param, sizeof(param));	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult a2dpd_dbus_SetReReadConfig(DBusMessage * message, DBusMessage * reply, DBusError* error, void *user_data){	char* lpszParam = NULL;	char c = 'r';	int param = 0;	DBG("Begin");	if(dbus_message_get_args(message, error, DBUS_TYPE_STRING, &lpszParam, DBUS_TYPE_INVALID)) {		param = atoi(lpszParam);		DBG("Param %s => %d", lpszParam, param);		write(ctl_socket, &c, sizeof(c));		write(ctl_socket, &param, sizeof(param));	}	DBG("OK");	return DBUS_HANDLER_RESULT_HANDLED;}void a2dpd_signal_command(char* dir, char* cmd){	// Print a trace	DBG("%s", cmd);	// Send signal if connected	if (gconnection != NULL) {		DBusMessage *signal = dbus_message_new_signal (A2DPD_SERVICE_PATH, A2DPD_SERVER_INTERFACE_NAME, "A2Command");		if(signal) {			if (dbus_message_append_args (signal,						DBUS_TYPE_STRING, &dir,						DBUS_TYPE_STRING, &cmd,						DBUS_TYPE_INVALID)) {				// In case this gets fired off after we've disconnected.				if (dbus_connection_get_is_connected (dbus_g_connection_get_connection(gconnection))) {					dbus_connection_send (dbus_g_connection_get_connection(gconnection), signal, NULL);				}			}			dbus_message_unref(signal);		}	}}void a2dpd_signal_state(int state, char* bdaddr){	static int s_state = -1;	if(state != s_state) {		char* signal_name = (state==DISCONNECTED)?"Disconnected":(state==CONNECTING)?"Connecting":"Connected";		DBG("%s %s", signal_name, bdaddr);		// Send signal if connected		if (gconnection != NULL) {			DBusMessage *signal = dbus_message_new_signal (A2DPD_SERVICE_PATH, A2DPD_SERVER_INTERFACE_NAME, "A2StateChange");			if(signal) {				if (dbus_message_append_args (signal,							DBUS_TYPE_STRING, &signal_name,							DBUS_TYPE_STRING, &bdaddr,							DBUS_TYPE_INVALID)) {					// In case this gets fired off after we've disconnected.					if (dbus_connection_get_is_connected (dbus_g_connection_get_connection(gconnection))) {						dbus_connection_send (dbus_g_connection_get_connection(gconnection), signal, NULL);					}				}				dbus_message_unref(signal);			}		}		// Print a trace		s_state = state;	}}static DBusHandlerResult a2dpd_handler_func(DBusConnection * connection, DBusMessage * message, void *user_data){	DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	DBusError dbusError;	DBusMessage *reply = dbus_message_new_method_return(message);	if (reply) {		dbus_error_init(&dbusError);		DBG("");		// Methods		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "Connect"))			result = a2dpd_dbus_Connect(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "Disconnect"))			result = a2dpd_dbus_Disconnect(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "StreamStart"))			result = a2dpd_dbus_StreamStart(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "StreamSuspend"))			result = a2dpd_dbus_StreamSuspend(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "SetAddress"))			result = a2dpd_dbus_SetAddress(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "AutoConnect"))			result = a2dpd_dbus_AutoConnect(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "SetDebug"))			result = a2dpd_dbus_SetDebug(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "SetVolume"))			result = a2dpd_dbus_SetVolume(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "SetFlags"))			result = a2dpd_dbus_SetFlags(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "SetReReadConfig"))			result = a2dpd_dbus_SetReReadConfig(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "Startup"))			result = a2dpd_dbus_Startup(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "Exit"))			result = a2dpd_dbus_Exit(message, reply, &dbusError, user_data);		if (dbus_message_is_method_call(message, A2DPD_SERVER_INTERFACE_NAME, "Save"))			result = a2dpd_dbus_Save(message, reply, &dbusError, user_data);		// Signals		if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))		{			DBG("Disconnected from BUS");			//result = a2dpd_dbus_Exit(message, reply, &dbusError, user_data);			result = DBUS_HANDLER_RESULT_HANDLED;		}		// Send answers		if(!dbus_connection_send(connection, reply, NULL)) {			DBG("Failed to send reply");			result = DBUS_HANDLER_RESULT_NEED_MEMORY;		}		dbus_message_unref(reply);		dbus_error_free(&dbusError);	} else {		DBG("Failed to allocate reply");		result = DBUS_HANDLER_RESULT_NEED_MEMORY;	}	return result;}void *a2dpd_thread_handler(void *param){	DBusError dbusError;	static DBusObjectPathVTable dbus_vtable_a2dpd_server = { NULL, a2dpd_handler_func, NULL, NULL, NULL, NULL };	dbus_error_init(&dbusError);	if (gconnection != NULL) {		DBG("Registering object path: "A2DPD_SERVICE_PATH);		if (dbus_connection_register_object_path(dbus_g_connection_get_connection(gconnection), A2DPD_SERVICE_PATH, &dbus_vtable_a2dpd_server, NULL)) {			DBG("Acquiring service: " A2DPD_SERVICE_NAME);			if(dbus_bus_request_name(dbus_g_connection_get_connection(gconnection), A2DPD_SERVICE_NAME, 0, &dbusError)) {				if (!dbus_error_is_set(&dbusError)) {					// Run main loop					DBG("Running ...");					g_main_loop_run(loop);					DBG("Closing ...");				} else {					DBG("Failed to acquire service[2]: %s", dbusError.message);				}			} else {				DBG("Failed to acquire service: %s", dbusError.message);			}		} else {			DBG("Failed to register object path");		}	}	dbus_error_free(&dbusError);	return NULL;}void a2dpd_signal_init(int session_bus){	GError *gError = NULL;	pthread_attr_t tattr;	size_t size = PTHREAD_STACK_MIN;	DBG("");	if (!g_thread_supported ())		g_thread_init (NULL);	g_type_init();	loop = g_main_loop_new(NULL, FALSE);	DBG("Getting on DBUS");	gconnection = dbus_g_bus_get((session_bus)?DBUS_BUS_SESSION:DBUS_BUS_SYSTEM, &gError);	if(gconnection != NULL) {		// Start thread		pthread_attr_init(&tattr);		pthread_attr_setstacksize(&tattr, size);		pthread_create(&a2dpd_dbus_thread, &tattr, a2dpd_thread_handler, NULL);		pthread_attr_destroy(&tattr);	} else {		DBG("Failed to get on DBUS: %s", gError->message);	}	if(gError)		g_error_free(gError);	DBG("OK");}void a2dpd_signal_set_socket(int a2dpd_ctl_socket){	DBG("Signal socket set to %d", a2dpd_ctl_socket);	ctl_socket = a2dpd_ctl_socket;}void a2dpd_signal_kill(){	DBG("");	if (loop)	{		g_main_quit(loop);	}	DBG("joining");	pthread_join(a2dpd_dbus_thread, NULL);	DBG("OK");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -