linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Bluez-devel] plugin tries
@ 2007-12-13 14:14 Frédéric Dalleau
  2007-12-13 14:16 ` Frédéric Dalleau
  2007-12-14  0:10 ` [Bluez-devel] [PATCH] HFP - Audio Gateway Features Alok
  0 siblings, 2 replies; 3+ messages in thread
From: Frédéric Dalleau @ 2007-12-13 14:14 UTC (permalink / raw)
  To: BlueZ development

[-- Attachment #1: Type: text/plain, Size: 425 bytes --]

alok,

This is my first try to implement a plugin that would handle hfp the ALP 
way.


Makefile.am is modified to build a library from hf_plugin_alp.*.

main.c reads a string containing the path of the library.
device.h is modified to keep a pointer to a plugin instance.
hf_plugin.c|h wraps plugin loading and calls (see the init func).
hf_plugin_alp.c|h are the plugin itself.


all this probably won't build...

Frederic

[-- Attachment #2: hf_plugin_alp.c --]
[-- Type: text/x-csrc, Size: 4743 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2007       Access Systems Inc. <http://www.access-company.com>
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <fcntl.h>
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

#include "device.h"
#include "manager.h"
#include "headset.h"
#include "hf_plugin.h"
#include "hf_plugin_alp.h"

/***********************************************************************
 *
 *	Methods implementation
 *
 ***********************************************************************/


/***********************************************************************
 *
 *	DBUS Method Handler
 *
 ***********************************************************************/

///////////////////////////////////////////////////////////////////////////////
static DBusHandlerResult dbus_handler_HSHF_func(DBusConnection * connection, DBusMessage * message, void *user_data)
///////////////////////////////////////////////////////////////////////////////
{
	UNUSED_PARAMETER(user_data);

	if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
		dbus_connection_unref(connection);
		connection = NULL;
	}
	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

int hf_plugin_alp_init(void** pag)
{
	int result;
	DBusError error;

	*pag = NULL;

	dbus_error_init(&error);

	g_message("%s [%s %s] starting ...", __FUNCTION__, __DATE__, __TIME__);
	connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
	if (connection == NULL)
	{
		g_critical("hshfgd: *** Failed to open connection to activating message bus: %s", error.message);
		goto failed;
	}

	g_message("hshfgd: Register object path");
	if (!dbus_connection_register_object_path(connection, hshfserver_object_path, &dbus_vtable_hshfserver, NULL))
	{
		g_critical("hshfgd: *** Failed to register object path");
		goto failed;
	}

	g_message("hshfgd: Acquire service: " HSHF_SERVICE_NAME);
	result = dbus_bus_request_name(connection, HSHF_SERVICE_NAME, 0, &error);
	if (dbus_error_is_set(&error))
	{
		g_critical("hshfgd: *** Failed to acquire service: %s", error.message);
		goto failed;
	}

	dbus_error_free(&error);

	return 0;

	failed:
		dbus_error_free(&error);

	return -ENOTCONN;
}

void hf_plugin_alp_exit(void* ag)
{
	g_message("%s [%s %s] exiting ...", __FUNCTION__, __DATE__, __TIME__);
}


void hf_plugin_alp_state_changed(int state, int type)
{
	gchar *stateP = NULL;
	gchar *profileP;

	g_message("%s", __FUNCTION__);

	switch (state)
	{
		case HEADSET_STATE_DISCONNECTED:
			stateP = HSHF_DISCONNECTED;
			break;
		case HEADSET_STATE_CONNECT_IN_PROGRESS:
			stateP = HSHF_CONNECTING;
			break;
		case HEADSET_STATE_CONNECTED:
			stateP = HSHF_CONNECTED;
			break;
		case HEADSET_STATE_PLAY_IN_PROGRESS:
			stateP = HSHF_AUDIO_CONNECTING;
			break;
		case HEADSET_STATE_PLAYING:
			stateP = HSHF_AUDIO_CONNECTED;
			break;
		default:
			stateP = HSHF_DISCONNECTED;
	}
	switch (type)
	{
		case SVC_HEADSET:
			profileP = HEADSET_PROFILE;
			break;
		case SVC_HANDSFREE:
			profileP = HANDSFREE_PROFILE;
			break;
		default:
			profileP = NO_PROFILE;
	}
	if(connection && hshfclient_name && hshfclient_object_path)
	{
		g_message("%s", __FUNCTION__);

		DBusMessage* msg = dbus_message_new_method_call(hshfclient_name, hshfclient_object_path, HSHFCLIENT_INTERFACE_NAME, "StateChange");
		if(msg) {
			if (dbus_message_append_args (msg,
						G_TYPE_STRING, stateP,
						G_TYPE_STRING, profileP,
						G_TYPE_UCHAR, 0,
						DBUS_TYPE_INVALID)) {
				// In case this gets fired off after we've disconnected.
				if (dbus_connection_get_is_connected (connection)) {
					dbus_connection_send (connection, msg, NULL);
				}
			}
			dbus_message_unref(msg);
		}

	}
}




[-- Attachment #3: hf_plugin_alp.h --]
[-- Type: text/x-chdr, Size: 991 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2007       Access Systems Inc. <http://www.access-company.com>
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

[-- Attachment #4: hf_plugin.c --]
[-- Type: text/x-csrc, Size: 3297 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2007       Access Systems Inc. <http://www.access-company.com>
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>

#include "hf_plugin.h"
#include "logging.h"

struct hf_service {
	int (*ag_state_changed_cb)(int state);
	int (*ag_indicate_call_cb)(int incoming);
	int (*ag_set_indicator_cb)(hf_indicator_t indicator, int value);
	int (*ag_cancel_call_cb)();
	int (*ag_event_cb)(int event, void *param);
};

struct hf_ag {
	struct hf_service service;
	void *handle;
	void *data;
	int (* init)(void **plg);
	void (* exit)(void *plg);
	void (* state_changed)(int state, int type);
};

void* hf_plugin_init(char* filename)
{
	struct hf_ag *plg;
	char funcname[512];
	char *basename, *dot;

	if(!filename || !*filename)
		return NULL;

	plg = malloc(sizeof(struct hf_ag));
	if(!plg)
		return NULL;

	memset(plg, 0, sizeof(struct hf_ag));

	info("%s(%s)", __FUNCTION__, filename);

	plg->handle = dlopen (filename, RTLD_NOW);
	if(!plg->handle)
		goto failed;

	basename = strrchr(filename, '/');
	if(basename)
		basename++;
	else
		basename = filename;

	if(strncmp(basename, "lib", 3)==0)
		basename += 3;

	dot = strrchr(basename, '.');
	if(dot)
		*dot = '\0';

	sprintf(funcname, "%s_exit", basename);
	debug("loading func %s", funcname);
	plg->exit = dlsym(plg->handle, funcname);
	if(!plg->exit)
		goto failed;

	sprintf(funcname, "%s_init", basename);
	debug("loading func %s", funcname);
	plg->init = dlsym(plg->handle, funcname);
	if(!plg->init)
		goto failed;

	sprintf(funcname, "%s_state_changed", basename);
	debug("loading func %s", funcname);
	plg->state_changed = dlsym(plg->handle, funcname);
	if(!plg->state_changed)
		goto failed;

	if(plg->init(&plg->data)<0)
		goto failed;

	debug("%s successful", funcname);

	return plg;

  failed:
	error("plugin load failed (error:%s, dlerror:%s)", strerror(errno), dlerror());
	hf_plugin_exit(plg);

	return NULL;
}

void hf_plugin_exit(void *plugin)
{
	struct hf_ag *plg = (struct hf_ag*)plugin;

	info("%s", __FUNCTION__);

	if(!plg)
		return;

	if(plg->exit)
		plg->exit(plg->data);

	if(plg->handle)
		dlclose (plg->handle); 

	free(plg);
}

void hf_plugin_state_changed(void *plugin, int state, int type)
{
	struct hf_ag *plg = (struct hf_ag*)plugin;

	info("%s(%d, %d)", __FUNCTION__, state, type);

	if(plg->state_changed)
		plg->state_changed(state, type);
}



[-- Attachment #5: hf_plugin.h --]
[-- Type: text/x-chdr, Size: 1103 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2007       Access Systems Inc. <http://www.access-company.com>
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdint.h>

void *hf_plugin_init(char *filename);
void hf_plugin_exit(void *plugin);
void hf_plugin_state_changed(void *plugin, int state, int type);


[-- Attachment #6: hfp_plugin.patch --]
[-- Type: text/x-patch, Size: 14380 bytes --]

Index: headset.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/headset.c,v
retrieving revision 1.143
diff -u -r1.143 headset.c
--- headset.c	23 Oct 2007 17:17:47 -0000	1.143
+++ headset.c	13 Dec 2007 11:14:47 -0000
@@ -56,6 +56,7 @@
 #include "manager.h"
 #include "error.h"
 #include "headset.h"
+#include "hf_plugin.h"
 
 #define RING_INTERVAL 3000
 
@@ -172,15 +173,23 @@
 static headset_event_t parse_headset_event(const char *buf, char *rsp,
 						int rsp_len)
 {
-	printf("Received: %s\n", buf);
+	debug("Received: %s", buf);
 
-	/* Return an error if this is not a proper AT command */
-	if (strncmp(buf, "AT", 2)) {
-		snprintf(rsp, rsp_len, "\r\nERROR\r\n");
-		return HEADSET_EVENT_INVALID;
+	if (!strncmp(buf, "+", 1)) {
+		buf += 1;
+		goto parse_at_event;
+	}
+	
+	if (!strncmp(buf, "AT", 2)) {
+		buf += 2;
+		goto parse_at_command;
 	}
 
-	buf += 2;
+	/* Return an error if this is not a proper AT command */
+	snprintf(rsp, rsp_len, "\r\nERROR\r\n");
+	return HEADSET_EVENT_INVALID;
+
+parse_at_command:
 
 	if (!strncmp(buf, "+CKPD", 5)) {
 		snprintf(rsp, rsp_len, "\r\nOK\r\n");
@@ -188,10 +197,52 @@
 	} else if (!strncmp(buf, "+VG", 3)) {
 		snprintf(rsp, rsp_len, "\r\nOK\r\n");
 		return HEADSET_EVENT_GAIN;
-	} else {
-		snprintf(rsp, rsp_len, "\r\nERROR\r\n");
-		return HEADSET_EVENT_UNKNOWN;
+	} else if (!strncmp(buf, "A", 1)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_CALL_ANSWERED;
+	} else if (!strncmp(buf, "D", 1)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_DIAL_NUMBER;
+	} else if (!strncmp(buf, "H", 1)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_CALL_HANGUP;
+	} else if (!strncmp(buf, "+BRSF=", 6)) {
+		snprintf(rsp, rsp_len, "\r\n+BRSF:127\r\n");
+		snprintf(rsp+strlen(rsp), rsp_len-strlen(rsp), "\r\nOK\r\n");
+		return HEADSET_EVENT_BRSF;
+	} else if (!strncmp(buf, "+CIND=?", 7)) {
+		snprintf(rsp, rsp_len, "\r\n+CIND:\r\n");
+		snprintf(rsp+strlen(rsp), rsp_len-strlen(rsp), "\r\nOK\r\n");
+		return HEADSET_EVENT_CIND_TEST;
+	} else if (!strncmp(buf, "+CIND", 5)) {
+		snprintf(rsp, rsp_len, "\r\n+CIND:\r\n");
+		snprintf(rsp+strlen(rsp), rsp_len-strlen(rsp), "\r\nOK\r\n");
+		return HEADSET_EVENT_CIND_READ;
+	} else if (!strncmp(buf, "+CMER=", 6)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_CMER;
+	} else if (!strncmp(buf, "+CHLD=?", 7)) {
+		snprintf(rsp, rsp_len, "\r\n+CHLD: 1,2,3,4,1x,2\r\n");
+		snprintf(rsp+strlen(rsp), rsp_len-strlen(rsp), "\r\nOK\r\n");
+		return HEADSET_EVENT_CHLD_TEST;
+	}
+
+	return HEADSET_EVENT_UNKNOWN;
+
+parse_at_event:
+
+	if (!strncmp(buf, "VGS", 3)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_SPEAKER_VOLUME;
 	}
+
+	if (!strncmp(buf, "VGM", 3)) {
+		snprintf(rsp, rsp_len, "\r\nOK\r\n");
+		return HEADSET_EVENT_MICROPHONE_VOLUME;
+	}
+
+	/* Just ignore, no error */
+	return HEADSET_EVENT_INVALID;
 }
 
 static void close_sco(struct device *device)
@@ -261,7 +312,6 @@
 	case HEADSET_EVENT_GAIN:
 		hs_signal_gain_setting(device, &hs->buf[hs->data_start] + 2);
 		break;
-
 	case HEADSET_EVENT_KEYPRESS:
 		if (hs->ring_timer) {
 			g_source_remove(hs->ring_timer);
@@ -274,6 +324,79 @@
 						DBUS_TYPE_INVALID);
 		break;
 
+	case HEADSET_EVENT_STATE_CHANGE:
+		debug("HEADSET_EVENT_STATE_CHANGE");
+		hf_plugin_state_changed(device->plugin, device->headset->state, device->headset->type);
+		break;
+	case HEADSET_EVENT_REMOTE_VOLUME:
+		debug("HEADSET_EVENT_REMOTE_VOLUME");
+		break;
+	case HEADSET_EVENT_SUPPORTED_FEATURES:
+		debug("HEADSET_EVENT_SUPPORTED_FEATURES");
+		break;
+	case HEADSET_EVENT_SPEAKER_VOLUME:
+		hs_signal_gain_setting(device, &hs->buf[hs->data_start] + 0);
+		break;
+	case HEADSET_EVENT_MICROPHONE_VOLUME:
+		hs_signal_gain_setting(device, &hs->buf[hs->data_start] + 0);
+		break;
+	case HEADSET_EVENT_CALL_ANSWERED:
+		debug("HEADSET_EVENT_CALL_ANSWERED");
+		break;
+	case HEADSET_EVENT_CALL_HANGUP:
+		debug("HEADSET_EVENT_CALL_HANGUP");
+		break;
+	case HEADSET_EVENT_DIAL_NUMBER:
+		debug("HEADSET_EVENT_DIAL_NUMBER");
+		break;
+	case HEADSET_EVENT_DIAL_MEMORY:
+		debug("HEADSET_EVENT_DIAL_MEMORY");
+		break;
+	case HEADSET_EVENT_CALL_HOLD:
+		debug("HEADSET_EVENT_CALL_HOLD");
+		break;
+	case HEADSET_EVENT_DTMF:
+		debug("HEADSET_EVENT_DTMF");
+		break;
+	case HEADSET_EVENT_GET_PHONE_NUMBER:
+		debug("HEADSET_EVENT_GET_PHONE_NUMBER");
+		break;
+	case HEADSET_EVENT_DIAL_LAST_NUMBER:
+		debug("HEADSET_EVENT_DIAL_LAST_NUMBER");
+		break;
+	case HEADSET_EVENT_VOICE_RECOGNITION:
+		debug("HEADSET_EVENT_VOICE_RECOGNITION");
+		break;
+	case HEADSET_EVENT_ECNR:
+		debug("HEADSET_EVENT_ECNR");
+		break;
+	case HEADSET_EVENT_RESPONSE_HOLD:
+		debug("HEADSET_EVENT_RESPONSE_HOLD");
+		break;
+	case HEADSET_EVENT_LIST_CURRENT_CALLS:
+		debug("HEADSET_EVENT_LIST_CURRENT_CALLS");
+		break;
+	case HEADSET_EVENT_COMMAND:
+		debug("HEADSET_EVENT_COMMAND");
+		break;
+	case HEADSET_EVENT_BRSF:
+		debug("HEADSET_EVENT_BRSF");
+		break;
+	case HEADSET_EVENT_CIND_TEST:
+		debug("HEADSET_EVENT_CIND_TEST");
+		break;
+	case HEADSET_EVENT_CIND_READ:
+		debug("HEADSET_EVENT_CIND_READ");
+		break;
+	case HEADSET_EVENT_CMER:
+		debug("HEADSET_EVENT_CMER");
+		if(device->headset->type == SVC_HEADSET)
+			headset_set_state(device, HEADSET_STATE_CONNECTED);
+		break;
+	case HEADSET_EVENT_CHLD_TEST:
+		debug("HEADSET_EVENT_CHLD_TEST");
+		break;
+
 	case HEADSET_EVENT_INVALID:
 	case HEADSET_EVENT_UNKNOWN:
 	default:
@@ -546,7 +669,8 @@
 	hs->rfcomm = chan;
 	c->io = NULL;
 
-	headset_set_state(device, HEADSET_STATE_CONNECTED);
+	if(device->headset->type == SVC_HEADSET)
+		headset_set_state(device, HEADSET_STATE_CONNECTED);
 
 	debug("%s: Connected to %s", device->path, hs_address);
 
@@ -571,9 +695,10 @@
 	g_slist_foreach(hs->pending, (GFunc) pending_connect_failed, device);
 	g_slist_free(hs->pending);
 	hs->pending = NULL;
-	if (hs->rfcomm)
-		headset_set_state(device, HEADSET_STATE_CONNECTED);
-	else
+	if (hs->rfcomm) {
+		if(device->headset->type == SVC_HEADSET)
+			headset_set_state(device, HEADSET_STATE_CONNECTED);
+	} else
 		headset_set_state(device, HEADSET_STATE_DISCONNECTED);
 
 	return FALSE;
@@ -1593,6 +1718,8 @@
 		break;
 	}
 
+	hf_plugin_state_changed(dev->plugin, dev->headset->state, dev->headset->type);
+
 	debug("State changed %s: %s -> %s", dev->path, str_state[hs->state],
 		str_state[state]);
 	hs->state = state;
Index: headset.h
===================================================================
RCS file: /cvsroot/bluez/utils/audio/headset.h,v
retrieving revision 1.31
diff -u -r1.31 headset.h
--- headset.h	23 Oct 2007 17:17:47 -0000	1.31
+++ headset.h	13 Dec 2007 11:14:47 -0000
@@ -31,7 +31,33 @@
 	HEADSET_EVENT_KEYPRESS,
 	HEADSET_EVENT_GAIN,
 	HEADSET_EVENT_UNKNOWN,
-	HEADSET_EVENT_INVALID
+	HEADSET_EVENT_INVALID,
+
+
+	HEADSET_EVENT_BRSF,
+	HEADSET_EVENT_CIND_READ,
+	HEADSET_EVENT_CIND_TEST,
+	HEADSET_EVENT_CMER,
+	HEADSET_EVENT_CHLD_TEST,
+	HEADSET_EVENT_CHLD,
+	HEADSET_EVENT_STATE_CHANGE,
+	HEADSET_EVENT_REMOTE_VOLUME,
+	HEADSET_EVENT_SUPPORTED_FEATURES,
+	HEADSET_EVENT_SPEAKER_VOLUME,
+	HEADSET_EVENT_MICROPHONE_VOLUME,
+	HEADSET_EVENT_CALL_ANSWERED,
+	HEADSET_EVENT_CALL_HANGUP,
+	HEADSET_EVENT_DIAL_NUMBER,
+	HEADSET_EVENT_DIAL_MEMORY,
+	HEADSET_EVENT_CALL_HOLD,
+	HEADSET_EVENT_DTMF,
+	HEADSET_EVENT_GET_PHONE_NUMBER,
+	HEADSET_EVENT_DIAL_LAST_NUMBER,
+	HEADSET_EVENT_VOICE_RECOGNITION,
+	HEADSET_EVENT_ECNR,
+	HEADSET_EVENT_RESPONSE_HOLD,
+	HEADSET_EVENT_LIST_CURRENT_CALLS,
+	HEADSET_EVENT_COMMAND,
 } headset_event_t;
 
 typedef enum {
Index: manager.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/manager.c,v
retrieving revision 1.80
diff -u -r1.80 manager.c
--- manager.c	24 Oct 2007 21:22:40 -0000	1.80
+++ manager.c	13 Dec 2007 11:14:47 -0000
@@ -62,6 +62,7 @@
 #include "sink.h"
 #include "control.h"
 #include "manager.h"
+#include "hf_plugin.h"
 
 typedef enum {
 	HEADSET	= 1 << 0,
@@ -94,6 +95,8 @@
 	void *cb_data;
 };
 
+static void* plugin = NULL;
+
 static DBusConnection *connection = NULL;
 
 static struct device *default_hs = NULL;
@@ -121,7 +124,7 @@
 	snprintf(path, sizeof(path) - 1,
 			"%s/device%d", AUDIO_MANAGER_PATH, device_id++);
 
-	return device_register(connection, path, bda);
+	return device_register(connection, path, bda, plugin);
 }
 
 static void destroy_device(struct device *device)
@@ -1531,10 +1534,13 @@
 	uint8_t chan = DEFAULT_HS_AG_CHANNEL;
 	sdp_buf_t buf;
 
+	info("Enabling headset server (hs=%d,hf=%d)", enabled->headset, enabled->gateway);
+
 	if (!(enabled->headset || enabled->gateway))
 		return 0;
 
 	hs_server = server_socket(&chan);
+
 	if (!hs_server)
 		return -1;
 
@@ -1558,6 +1564,8 @@
 	if (no_hfp)
 		return 0;
 
+	info("Enabling handsfree server");
+	
 	chan = DEFAULT_HF_AG_CHANNEL;
 
 	hf_server = server_socket(&chan);
@@ -1581,6 +1589,7 @@
 	g_io_add_watch(hf_server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 						(GIOFunc) ag_io_cb, NULL);
 
+	info("servers enabled");
 	return 0;
 }
 
@@ -1608,10 +1617,12 @@
 }
 
 int audio_init(DBusConnection *conn, struct enabled_interfaces *enable,
-		gboolean no_hfp, gboolean sco_hci, int source_count)
+		gboolean no_hfp, gboolean sco_hci, int source_count, char* plugin_path)
 {
 	int sinks, sources;
 
+	plugin = hf_plugin_init(plugin_path);
+
 	connection = dbus_connection_ref(conn);
 
 	enabled = enable;
@@ -1662,6 +1673,7 @@
 
 void audio_exit(void)
 {
+
 	server_exit();
 
 	dbus_connection_destroy_object_path(connection, AUDIO_MANAGER_PATH);
@@ -1669,6 +1681,8 @@
 	dbus_connection_unref(connection);
 
 	connection = NULL;
+
+	hf_plugin_exit(plugin);
 }
 
 struct device *manager_default_device(void)
Index: manager.h
===================================================================
RCS file: /cvsroot/bluez/utils/audio/manager.h,v
retrieving revision 1.30
diff -u -r1.30 manager.h
--- manager.h	23 Oct 2007 17:17:47 -0000	1.30
+++ manager.h	13 Dec 2007 11:14:47 -0000
@@ -38,7 +38,7 @@
 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);
+		gboolean no_hfp, gboolean sco_hci, int source_count, char* plugin_path);
 
 void audio_exit(void);
 
Index: main.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/main.c,v
retrieving revision 1.28
diff -u -r1.28 main.c
--- main.c	24 Oct 2007 20:02:53 -0000	1.28
+++ main.c	13 Dec 2007 11:14:47 -0000
@@ -45,15 +45,16 @@
 static gboolean disable_hfp = TRUE;
 static gboolean sco_hci = TRUE;
 static int source_count = 1;
+static char plugin_path[256] =  {0};
 
 static GMainLoop *main_loop = NULL;
 
 static struct enabled_interfaces enabled = {
-	.headset	= TRUE,
+	.headset	= FALSE,
 	.gateway	= FALSE,
 	.sink		= TRUE,
 	.source		= FALSE,
-	.control	= FALSE,
+	.control	= TRUE,
 	.target		= FALSE,
 };
 
@@ -144,6 +145,16 @@
 	} else
 		disable_hfp = no_hfp;
 
+	str = g_key_file_get_string(keyfile, "Headset", "HFPPluginPath", &err);
+	if (err) {
+		debug("%s: %s", file, err->message);
+		g_error_free(err);
+		err = NULL;
+	} else {
+		strncpy(plugin_path, str, sizeof(plugin_path)-1);
+		g_free(str);
+	}
+
 	str = g_key_file_get_string(keyfile, "A2DP", "SourceCount", &err);
 	if (err) {
 		debug("%s: %s", file, err->message);
@@ -154,8 +165,9 @@
 		g_free(str);
 	}
 
-	debug("Config options: DisableHFP=%s, SCORouting=%s, SourceCount=%d",
+	debug("Config options: DisableHFP=%s, HFPPluginPath=%s, SCORouting=%s, SourceCount=%d",
 			disable_hfp ? "true" : "false",
+			plugin_path,
 			sco_hci ? "HCI" : "PCM", source_count);
 
 	g_key_file_free(keyfile);
@@ -196,7 +208,7 @@
 	}
 
 	if (audio_init(conn, &enabled, disable_hfp, sco_hci,
-				source_count) < 0) {
+				source_count, plugin_path) < 0) {
 		error("Audio init failed!");
 		exit(1);
 	}
Index: Makefile.am
===================================================================
RCS file: /cvsroot/bluez/utils/audio/Makefile.am,v
retrieving revision 1.40
diff -u -r1.40 Makefile.am
--- Makefile.am	25 Oct 2007 10:33:03 -0000	1.40
+++ Makefile.am	13 Dec 2007 11:14:47 -0000
@@ -13,10 +13,18 @@
 bluetoothd_service_audio_SOURCES = main.c \
 	manager.h manager.c headset.h headset.c ipc.h unix.h unix.c \
 	error.h error.c device.h device.c gateway.h gateway.c \
+	hf_plugin.c \
 	sink.c sink.h avdtp.c avdtp.h a2dp.c a2dp.h control.c control.h
 
 bluetoothd_service_audio_LDADD = $(top_builddir)/common/libhelper.a \
-				@GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
+				@GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ -ldl
+
+hf_plugin_alpdir = $(libdir)
+hf_plugin_alp_LTLIBRARIES = libhf_plugin_alp.la 
+libhf_plugin_alp_la_SOURCES = hf_plugin_alp.c
+libhf_plugin_alp_la_LDFLAGS = -module -avoid-version -export-dynamic
+libhf_plugin_alp_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ @DBUS_GLIB_LIBS@
+libhf_plugin_alp_la_CFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@ @DBUS_GLIB_CFLAGS@
 
 if ALSA
 alsadir = $(libdir)/alsa-lib
Index: device.c
===================================================================
RCS file: /cvsroot/bluez/utils/audio/device.c,v
retrieving revision 1.24
diff -u -r1.24 device.c
--- device.c	25 Oct 2007 10:38:47 -0000	1.24
+++ device.c	13 Dec 2007 11:14:47 -0000
@@ -273,7 +273,7 @@
 }
 
 struct device *device_register(DBusConnection *conn,
-					const char *path, bdaddr_t *bda)
+					const char *path, bdaddr_t *bda, void* plugin)
 {
 	struct device *dev;
 	bdaddr_t src;
@@ -310,6 +310,7 @@
 		return NULL;
 	}
 
+	dev->plugin = plugin;
 	dev->name = get_dev_name(conn, dev->adapter_path, bda);
 	dev->path = g_strdup(path);
 	bacpy(&dev->dst, bda);
Index: device.h
===================================================================
RCS file: /cvsroot/bluez/utils/audio/device.h,v
retrieving revision 1.15
diff -u -r1.15 device.h
--- device.h	25 Oct 2007 10:38:47 -0000	1.15
+++ device.h	13 Dec 2007 11:14:47 -0000
@@ -60,6 +60,7 @@
 	bdaddr_t store;
 	bdaddr_t src;
 	bdaddr_t dst;
+	void* plugin;
 
 	struct headset *headset;
 	struct gateway *gateway;
@@ -70,7 +71,7 @@
 };
 
 struct device *device_register(DBusConnection *conn,
-					const char *path, bdaddr_t *bda);
+					const char *path, bdaddr_t *bda, void* plugin);
 
 int device_store(struct device *device, gboolean is_default);
 

[-- Attachment #7: Type: text/plain, Size: 308 bytes --]

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

[-- Attachment #8: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Bluez-devel] plugin tries
  2007-12-13 14:14 [Bluez-devel] plugin tries Frédéric Dalleau
@ 2007-12-13 14:16 ` Frédéric Dalleau
  2007-12-14  0:10 ` [Bluez-devel] [PATCH] HFP - Audio Gateway Features Alok
  1 sibling, 0 replies; 3+ messages in thread
From: Frédéric Dalleau @ 2007-12-13 14:16 UTC (permalink / raw)
  To: BlueZ development

Well,

This wasn't meant for the list,
anyway, let me know if anything is interesting ;D

Frederic



-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bluez-devel] [PATCH] HFP - Audio Gateway Features
  2007-12-13 14:14 [Bluez-devel] plugin tries Frédéric Dalleau
  2007-12-13 14:16 ` Frédéric Dalleau
@ 2007-12-14  0:10 ` Alok
  1 sibling, 0 replies; 3+ messages in thread
From: Alok @ 2007-12-14  0:10 UTC (permalink / raw)
  To: BlueZ development

[-- Attachment #1: Type: text/plain, Size: 212 bytes --]

Hello, 

Sending a patch for the following : 

1. Added AG's Feature definitions + BRSF response. 

2. Modified headset_send() for variable args. 


Let me know if anything needs to be fixed. 



-Alok Barsode.


[-- Attachment #2: patch --]
[-- Type: text/x-patch, Size: 5192 bytes --]

diff --git a/audio/headset.c b/audio/headset.c
index e7425d5..ee9a57f 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <signal.h>
 #include <string.h>
 #include <getopt.h>
@@ -64,6 +65,17 @@
 #define HEADSET_GAIN_SPEAKER 'S'
 #define HEADSET_GAIN_MICROPHONE 'M'
 
+#define AG_FEATURE_THREE_WAY_CALLING             0x0001
+#define AG_FEATURE_EC_ANDOR_NR                   0x0002
+#define AG_FEATURE_VOICE_RECOGNITION             0x0004
+#define AG_FEATURE_INBAND_RINGTONE               0x0008
+#define AG_FEATURE_ATTACH_NUMBER_TO_VOICETAG     0x0010
+#define AG_FEATURE_REJECT_A_CALL                 0x0020
+#define AG_FEATURE_ENHANCES_CALL_STATUS          0x0040
+#define AG_FEATURE_ENHANCES_CALL_CONTROL         0x0080
+/*Audio Gateway features.Default is In-band Ringtone*/
+static unsigned int ag_features = AG_FEATURE_INBAND_RINGTONE;
+
 static char *str_state[] = {
 	"HEADSET_STATE_DISCONNECTED",
 	"HEADSET_STATE_CONNECT_IN_PROGRESS",
@@ -120,21 +132,31 @@ struct event {
 static int rfcomm_connect(struct device *device, struct pending_connect *c);
 static int get_handles(struct device *device, struct pending_connect *c);
 
-static int headset_send(struct headset *hs, const char *str)
+static int headset_send(struct headset *hs, char *format, ...)
 {
+	char rsp[BUF_SIZE];
+	va_list ap;
 	GIOError err;
 	gsize total_written, written, count;
+	int er;
+
+	va_start(ap, hs);
+	er = vsnprintf(rsp, sizeof(rsp), format, ap);
+	va_end(ap);
+
+	if (er < 0)
+		return -EINVAL;
 
 	if (hs->state < HEADSET_STATE_CONNECTED || !hs->rfcomm) {
 		error("headset_send: the headset is not connected");
 		return -EIO;
 	}
 
-	count = strlen(str);
+	count = strlen(rsp);
 	written = total_written = 0;
 
 	while (total_written < count) {
-		err = g_io_channel_write(hs->rfcomm, str + total_written,
+		err = g_io_channel_write(hs->rfcomm, rsp + total_written,
 					count - total_written, &written);
 		if (err != G_IO_ERROR_NONE)
 			return -errno;
@@ -150,8 +172,7 @@ static int supported_features(struct device *device, const char *buf)
 	int err;
 
 	hs->hfp_features = strtoul(&buf[8], NULL, 10);
-
-	err = headset_send(hs, "\r\n+BRSF:0\r\n");
+	err = headset_send(hs, "\r\n+BRSF=%u\r\n", ag_features);
 	if (err < 0)
 		return err;
 
@@ -355,7 +376,7 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
 	err = handle_event(device, &hs->buf[hs->data_start]);
 	if (err < 0)
 		error("Error handling command %s: %s (%d)", &hs->buf[hs->data_start],
-				strerror(-err), -err);
+		      strerror(-err), -err);
 
 	hs->data_start += cmd_len;
 	hs->data_length -= cmd_len;
@@ -1103,8 +1124,11 @@ error:
 static gboolean ring_timer_cb(gpointer data)
 {
 	struct device *device = data;
+	int err;
+
+	err = headset_send(device->headset, "\r\nRING\r\n");
 
-	if (headset_send(device->headset, "\r\nRING\r\n") != G_IO_ERROR_NONE)
+	if (err)
 		error("Sending RING failed");
 
 	return TRUE;
@@ -1116,6 +1140,7 @@ static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg,
 	struct device *device = data;
 	struct headset *hs = device->headset;
 	DBusMessage *reply = NULL;
+	int err;
 
 	if (hs->state < HEADSET_STATE_CONNECTED)
 		return error_not_connected(conn, msg);
@@ -1129,7 +1154,8 @@ static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg,
 		goto done;
 	}
 
-	if (headset_send(device->headset, "\r\nRING\r\n") != G_IO_ERROR_NONE) {
+	err = headset_send(device->headset, "\r\nRING\r\n");
+	if (err) {
 		dbus_message_unref(reply);
 		return error_failed(conn, msg, "Failed");
 	}
@@ -1261,7 +1287,7 @@ static DBusHandlerResult hs_set_gain(DBusConnection *conn,
 	DBusMessage *reply;
 	DBusError derr;
 	dbus_uint16_t gain;
-	char str[13];
+	int err;
 
 	if (hs->state < HEADSET_STATE_CONNECTED)
 		return error_not_connected(conn, msg);
@@ -1286,10 +1312,8 @@ static DBusHandlerResult hs_set_gain(DBusConnection *conn,
 
 	if (hs->state != HEADSET_STATE_PLAYING)
 		goto done;
-
-	snprintf(str, sizeof(str) - 1, "\r\n+VG%c=%u\r\n", type, gain);
-
-	if (headset_send(device->headset, str) != G_IO_ERROR_NONE) {
+	err = headset_send(device->headset, "\r\n+VG%c=%u\r\n", type, gain);
+	if (err) {
 		dbus_message_unref(reply);
 		return error_failed(conn, msg, "Unable to send to headset");
 	}
@@ -1584,7 +1608,6 @@ int headset_close_rfcomm(struct device *dev)
 void headset_set_state(struct device *dev, headset_state_t state)
 {
 	struct headset *hs = dev->headset;
-	char str[13];
 
 	if (hs->state == state)
 		return;
@@ -1629,17 +1652,11 @@ void headset_set_state(struct device *dev, headset_state_t state)
 						AUDIO_HEADSET_INTERFACE,
 						"Playing", DBUS_TYPE_INVALID);
 
-		if (hs->sp_gain >= 0) {
-			snprintf(str, sizeof(str) - 1, "\r\n+VGS=%u\r\n",
-				hs->sp_gain);
-			headset_send(hs, str);
-		}
+		if (hs->sp_gain >= 0)
+			headset_send(hs, "\r\n+VGS=%u\r\n", hs->sp_gain);
 
-		if (hs->mic_gain >= 0) {
-			snprintf(str, sizeof(str) - 1, "\r\n+VGM=%u\r\n",
-				hs->sp_gain);
-			headset_send(hs, str);
-		}
+		if (hs->mic_gain >= 0)
+			headset_send(hs, "\r\n+VGM=%u\r\n", hs->mic_gain);
 		break;
 	}
 

[-- Attachment #3: Type: text/plain, Size: 308 bytes --]

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-12-14  0:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-13 14:14 [Bluez-devel] plugin tries Frédéric Dalleau
2007-12-13 14:16 ` Frédéric Dalleau
2007-12-14  0:10 ` [Bluez-devel] [PATCH] HFP - Audio Gateway Features Alok

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).