diff options
| -rw-r--r-- | audio/audio.conf | 12 | ||||
| -rw-r--r-- | audio/headset.c | 114 | ||||
| -rw-r--r-- | audio/headset.h | 2 | ||||
| -rw-r--r-- | audio/main.c | 111 | ||||
| -rw-r--r-- | audio/manager.c | 115 | ||||
| -rw-r--r-- | audio/manager.h | 5 | 
6 files changed, 232 insertions, 127 deletions
diff --git a/audio/audio.conf b/audio/audio.conf index 3fe8965f..ae9742b8 100644 --- a/audio/audio.conf +++ b/audio/audio.conf @@ -20,6 +20,18 @@  # Defaults to false  DisableHFP=true +# HFP Gateway features +# Defaults to false +3WayCalling=false +EchoCancelNoiseCancel=false +VoiceRecognition=false +InBandRingtone=false +VoiceTags=false +RejectingCalls=false +EnhancedCallStatus=false +EnhancedCallControl=false +ExtendedErrorResultCodes=false +  # Just an example of potential config options for the other interfaces  #[A2DP]  #SourceCount=2 diff --git a/audio/headset.c b/audio/headset.c index 73c832f2..0fc013d7 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -73,8 +73,10 @@  #define AG_FEATURE_REJECT_A_CALL                 0x0020  #define AG_FEATURE_ENHANCES_CALL_STATUS          0x0040  #define AG_FEATURE_ENHANCES_CALL_CONTROL         0x0080 +#define AG_FEATURE_EXTENDED_ERROR_RESULT_CODES   0x0100  /*Audio Gateway features.Default is In-band Ringtone*/ -static unsigned int ag_features = AG_FEATURE_INBAND_RINGTONE; +static unsigned int ag_features; +static gboolean sco_hci = TRUE;  static char *str_state[] = {  	"HEADSET_STATE_DISCONNECTED", @@ -1586,6 +1588,116 @@ register_iface:  	return hs;  } +int headset_config_init(GKeyFile *config) +{ +	GError *err = NULL; +	gboolean value; +	char *str; + +	/* Use the default values if there is no config file */ +	if (config == NULL) +		return 0; + +	str = g_key_file_get_string(config, "General", "SCORouting", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else { +		if (strcmp(str, "PCM") == 0) +			sco_hci = FALSE; +		else if (strcmp(str, "HCI") == 0) +			sco_hci = TRUE; +		else +			error("Invalid Headset Routing value: %s", str); +		g_free(str); +	} + +	value = g_key_file_get_boolean(config, "Headset", "3WayCalling", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_THREE_WAY_CALLING; + +	value = g_key_file_get_boolean(config, "Headset", "EchoCancelNoiseCancel", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_EC_ANDOR_NR; + +	value = g_key_file_get_boolean(config, "Headset", "VoiceRecognition", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_VOICE_RECOGNITION; + +	value = g_key_file_get_boolean(config, "Headset", "InBandRingtone", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_INBAND_RINGTONE; + +	value = g_key_file_get_boolean(config, "Headset", "VoiceTags", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_ATTACH_NUMBER_TO_VOICETAG; + +	value = g_key_file_get_boolean(config, "Headset", "RejectingCalls", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_REJECT_A_CALL; + +	value = g_key_file_get_boolean(config, "Headset", "EnhancedCallStatus", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_ENHANCES_CALL_STATUS; + +	value = g_key_file_get_boolean(config, "Headset", "EnhancedCallControl", +					&err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_ENHANCES_CALL_CONTROL; + +	value = g_key_file_get_boolean(config, "Headset", +					"ExtendedErrorResultCodes", &err); +	if (err) { +		debug("audio.conf: %s", err->message); +		g_error_free(err); +		err = NULL; +	} else if (value) +		ag_features |= AG_FEATURE_EXTENDED_ERROR_RESULT_CODES; + +	return 0; +} +  void headset_free(struct device *dev)  {  	struct headset *hs = dev->headset; diff --git a/audio/headset.h b/audio/headset.h index 4869bb36..a70ad973 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -47,6 +47,8 @@ struct headset *headset_init(struct device *dev, sdp_record_t *record,  void headset_free(struct device *dev); +int headset_config_init(GKeyFile *config); +  void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc);  unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb, diff --git a/audio/main.c b/audio/main.c index 52396beb..75cb67e6 100644 --- a/audio/main.c +++ b/audio/main.c @@ -42,32 +42,17 @@  #include "device.h"  #include "manager.h" -static gboolean disable_hfp = TRUE; -static gboolean sco_hci = TRUE; -static int source_count = 1; -  static GMainLoop *main_loop = NULL; -static struct enabled_interfaces enabled = { -	.headset	= TRUE, -	.gateway	= FALSE, -	.sink		= TRUE, -	.source		= FALSE, -	.control	= TRUE, -	.target		= FALSE, -}; -  static void sig_term(int sig)  {  	g_main_loop_quit(main_loop);  } -static void read_config(const char *file) +static GKeyFile *load_config_file(const char *file)  { -	GKeyFile *keyfile;  	GError *err = NULL; -	gboolean no_hfp; -	char *str; +	GKeyFile *keyfile;  	keyfile = g_key_file_new(); @@ -75,96 +60,17 @@ static void read_config(const char *file)  		error("Parsing %s failed: %s", file, err->message);  		g_error_free(err);  		g_key_file_free(keyfile); -		return; -	} - -	str = g_key_file_get_string(keyfile, "General", "SCORouting", &err); -	if (err) { -		debug("%s: %s", file, err->message); -		g_error_free(err); -		err = NULL; -	} else { -		if (strcmp(str, "PCM") == 0) -			sco_hci = FALSE; -		else if (strcmp(str, "HCI") == 0) -			sco_hci = TRUE; -		else -			error("Invalid Headset Routing value: %s", str); -		g_free(str); -	} - -	str = g_key_file_get_string(keyfile, "General", "Enable", &err); -	if (err) { -		debug("%s: %s", file, err->message); -		g_error_free(err); -		err = NULL; -	} else { -		if (strstr(str, "Headset")) -			enabled.headset = TRUE; -		if (strstr(str, "Gateway")) -			enabled.gateway = TRUE; -		if (strstr(str, "Sink")) -			enabled.sink = TRUE; -		if (strstr(str, "Source")) -			enabled.source = TRUE; -		if (strstr(str, "Control")) -			enabled.control = TRUE; -		if (strstr(str, "Target")) -			enabled.target = TRUE; -		g_free(str); +		return NULL;  	} -	str = g_key_file_get_string(keyfile, "General", "Disable", &err); -	if (err) { -		debug("%s: %s", file, err->message); -		g_error_free(err); -		err = NULL; -	} else { -		if (strstr(str, "Headset")) -			enabled.headset = FALSE; -		if (strstr(str, "Gateway")) -			enabled.gateway = FALSE; -		if (strstr(str, "Sink")) -			enabled.sink = FALSE; -		if (strstr(str, "Source")) -			enabled.source = FALSE; -		if (strstr(str, "Control")) -			enabled.control = FALSE; -		if (strstr(str, "Target")) -			enabled.target = FALSE; -		g_free(str); -	} - -	no_hfp = g_key_file_get_boolean(keyfile, "Headset", "DisableHFP", -					&err); -	if (err) { -		debug("%s: %s", file, err->message); -		g_error_free(err); -		err = NULL; -	} else -		disable_hfp = no_hfp; - -	str = g_key_file_get_string(keyfile, "A2DP", "SourceCount", &err); -	if (err) { -		debug("%s: %s", file, err->message); -		g_error_free(err); -		err = NULL; -	} else { -		source_count = atoi(str); -		g_free(str); -	} - -	debug("Config options: DisableHFP=%s, SCORouting=%s, SourceCount=%d", -			disable_hfp ? "true" : "false", -			sco_hci ? "HCI" : "PCM", source_count); - -	g_key_file_free(keyfile); +	return keyfile;  }  int main(int argc, char *argv[])  {  	DBusConnection *conn;  	struct sigaction sa; +	GKeyFile *config;  	start_logging("audio", "Bluetooth Audio daemon"); @@ -180,7 +86,7 @@ int main(int argc, char *argv[])  	enable_debug(); -	read_config(CONFIGDIR "/audio.conf"); +	config = load_config_file(CONFIGDIR "/audio.conf");  	main_loop = g_main_loop_new(NULL, FALSE); @@ -195,14 +101,15 @@ int main(int argc, char *argv[])  		exit(1);  	} -	if (audio_init(conn, &enabled, disable_hfp, sco_hci, -				source_count) < 0) { +	if (audio_init(conn, config) < 0) {  		error("Audio init failed!");  		exit(1);  	}  	if (argc > 1 && !strcmp(argv[1], "-s"))  		register_external_service(conn, "audio", "Audio service", ""); +	if (config) +		g_key_file_free(config);  	g_main_loop_run(main_loop); diff --git a/audio/manager.c b/audio/manager.c index cd4ba873..dd580f8c 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -107,7 +107,13 @@ static uint32_t hf_record_id = 0;  static GIOChannel *hs_server = NULL;  static GIOChannel *hf_server = NULL; -static const struct enabled_interfaces *enabled; +static struct enabled_interfaces enabled = { +	.headset	= TRUE, +	.gateway	= FALSE, +	.sink		= TRUE, +	.source		= FALSE, +	.control	= TRUE, +};  static void get_next_record(struct audio_sdp_data *data);  static DBusHandlerResult get_handles(const char *uuid, @@ -225,10 +231,10 @@ gboolean server_is_enabled(uint16_t svc)  		ret = (hf_server != NULL);  		break;  	case AUDIO_SINK_SVCLASS_ID: -		return enabled->sink; +		return enabled.sink;  	case AV_REMOTE_TARGET_SVCLASS_ID:  	case AV_REMOTE_SVCLASS_ID: -		return enabled->control; +		return enabled.control;  	default:  		ret = FALSE;  		break; @@ -1069,11 +1075,11 @@ static void parse_stored_devices(char *key, char *value, void *data)  	/* Change storage to source adapter */  	bacpy(&device->store, src); -	if (enabled->headset && strstr(value, "headset")) +	if (enabled.headset && strstr(value, "headset"))  		device->headset = headset_init(device, NULL, 0); -	if (enabled->sink && strstr(value, "sink")) +	if (enabled.sink && strstr(value, "sink"))  		device->sink = sink_init(device); -	if (enabled->control && strstr(value, "control")) +	if (enabled.control && strstr(value, "control"))  		device->control = control_init(device);  	add_device(device, FALSE);  } @@ -1529,12 +1535,14 @@ static GIOChannel *server_socket(uint8_t *channel)  	return io;  } -static int headset_server_init(DBusConnection *conn, gboolean no_hfp) +static int headset_server_init(DBusConnection *conn, GKeyFile *config)  {  	uint8_t chan = DEFAULT_HS_AG_CHANNEL;  	sdp_buf_t buf; +	gboolean no_hfp = FALSE; +	GError *err = NULL; -	if (!(enabled->headset || enabled->gateway)) +	if (!(enabled.headset || enabled.gateway))  		return 0;  	hs_server = server_socket(&chan); @@ -1556,7 +1564,17 @@ static int headset_server_init(DBusConnection *conn, gboolean no_hfp)  	}  	g_io_add_watch(hs_server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, -						(GIOFunc) ag_io_cb, NULL); +				(GIOFunc) ag_io_cb, NULL); + +	if (config) { +		no_hfp = g_key_file_get_boolean(config, "Headset", "DisableHFP", +						&err); +		if (err) { +			debug("audio.conf: %s", err->message); +			g_error_free(err); +			err = NULL; +		} +	}  	if (no_hfp)  		return 0; @@ -1582,7 +1600,7 @@ static int headset_server_init(DBusConnection *conn, gboolean no_hfp)  	}  	g_io_add_watch(hf_server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, -						(GIOFunc) ag_io_cb, NULL); +			(GIOFunc) ag_io_cb, NULL);  	return 0;  } @@ -1610,14 +1628,55 @@ static void server_exit(void)  	}  } -int audio_init(DBusConnection *conn, struct enabled_interfaces *enable, -		gboolean no_hfp, gboolean sco_hci, int source_count) +int audio_init(DBusConnection *conn, GKeyFile *config)  {  	int sinks, sources; +	char *str; +	GError *err = NULL;  	connection = dbus_connection_ref(conn); -	enabled = enable; +	if (config) { +		str = g_key_file_get_string(config, "General", "Enable", &err); + +		if (err) { +			debug("audio.conf: %s", err->message); +			g_error_free(err); +			err = NULL; +		} else { +			if (strstr(str, "Headset")) +				enabled.headset = TRUE; +			if (strstr(str, "Gateway")) +				enabled.gateway = TRUE; +			if (strstr(str, "Sink")) +				enabled.sink = TRUE; +			if (strstr(str, "Source")) +				enabled.source = TRUE; +			if (strstr(str, "Control")) +				enabled.control = TRUE; +			g_free(str); +		} + +		str = g_key_file_get_string(config, "General", "Disable", &err); + +		if (err) { +			debug("audio.conf: %s", err->message); +			g_error_free(err); +			err = NULL; +		} else { +			if (strstr(str, "Headset")) +				enabled.headset = FALSE; +			if (strstr(str, "Gateway")) +				enabled.gateway = FALSE; +			if (strstr(str, "Sink")) +				enabled.sink = FALSE; +			if (strstr(str, "Source")) +				enabled.source = FALSE; +			if (strstr(str, "Control")) +				enabled.control = FALSE; +			g_free(str); +		} +	}  	if (!dbus_connection_create_object_path(conn, AUDIO_MANAGER_PATH,  						NULL, manager_unregister)) { @@ -1625,15 +1684,31 @@ int audio_init(DBusConnection *conn, struct enabled_interfaces *enable,  		goto failed;  	} -	if (headset_server_init(conn, no_hfp) < 0) -		goto failed; +	if (enabled.headset) { +		if (headset_config_init(config) < 0) +			goto failed; -	if (enable->sink) -		sources = source_count; -	else +		if (headset_server_init(conn, config) < 0) +			goto failed; +	} + +	if (enabled.sink) { +		if (config) { +			str = g_key_file_get_string(config, "A2DP", +							"SourceCount", &err); +			if (err) { +				debug("audio.conf: %s", err->message); +				g_error_free(err); +				err = NULL; +			} else { +				sources = atoi(str); +				g_free(str); +			} +		} +	} else  		sources = 0; -	if (enable->source) +	if (enabled.source)  		sinks = 1;  	else  		sinks = 0; @@ -1641,7 +1716,7 @@ int audio_init(DBusConnection *conn, struct enabled_interfaces *enable,  	if (a2dp_init(conn, sources, sinks) < 0)  		goto failed; -	if (enable->control && avrcp_init(conn) < 0) +	if (enabled.control && avrcp_init(conn) < 0)  		goto failed;  	if (!dbus_connection_register_interface(conn, AUDIO_MANAGER_PATH, diff --git a/audio/manager.h b/audio/manager.h index 85fe4881..e740a524 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -32,14 +32,11 @@ struct enabled_interfaces {  	gboolean sink;  	gboolean source;  	gboolean control; -	gboolean target;  };  typedef void (*create_dev_cb_t) (struct device *dev, void *user_data); -int audio_init(DBusConnection *conn, struct enabled_interfaces *enabled, -		gboolean no_hfp, gboolean sco_hci, int source_count); - +int audio_init(DBusConnection *conn, GKeyFile *config);  void audio_exit(void);  uint32_t add_service_record(DBusConnection *conn, sdp_buf_t *buf);  | 
