linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree
@ 2007-12-06 11:27 Frédéric Dalleau
  2007-12-06 11:30 ` Frédéric Dalleau
  2007-12-06 11:40 ` Marcel Holtmann
  0 siblings, 2 replies; 6+ messages in thread
From: Frédéric Dalleau @ 2007-12-06 11:27 UTC (permalink / raw)
  To: BlueZ development

Hello,

As of today, when calling org.bluez.audio.headset.Connect(), the hfp 
profile is searched only if the headset->hfp_handle is initialized.
This member variable is initialized upon CreateDevice the first time the 
device is created (during resolve_services).
The variable is not initialized when the audio service is restarted, so 
after restarting audio service, it is no longer possible to connect to hfp.

The attached patch fix the problem as follow : first search the hfp 
profile handle, then search an hsp profile handle, by getting rfcomm 
channel to connect to.

It is based against latest git tree.

Frederic.


-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

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

* Re: [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree
  2007-12-06 11:27 [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree Frédéric Dalleau
@ 2007-12-06 11:30 ` Frédéric Dalleau
  2007-12-06 11:40 ` Marcel Holtmann
  1 sibling, 0 replies; 6+ messages in thread
From: Frédéric Dalleau @ 2007-12-06 11:30 UTC (permalink / raw)
  To: BlueZ development

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

Here is the patch. :/

Frederic

Frédéric Dalleau wrote:
> Hello,
>
> As of today, when calling org.bluez.audio.headset.Connect(), the hfp 
> profile is searched only if the headset->hfp_handle is initialized.
> This member variable is initialized upon CreateDevice the first time the 
> device is created (during resolve_services).
> The variable is not initialized when the audio service is restarted, so 
> after restarting audio service, it is no longer possible to connect to hfp.
>
> The attached patch fix the problem as follow : first search the hfp 
> profile handle, then search an hsp profile handle, by getting rfcomm 
> channel to connect to.
>
> It is based against latest git tree.
>
> Frederic.
>
>
> -------------------------------------------------------------------------
> SF.Net email is sponsored by: The Future of Linux Business White Paper
> from Novell.  From the desktop to the data center, Linux is going
> mainstream.  Let it simplify your IT future.
> http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel
>   


[-- Attachment #2: handsfreeconnect.patch --]
[-- Type: text/x-patch, Size: 2347 bytes --]

diff --git a/audio/headset.c b/audio/headset.c
index 6cb5406..b32b61b 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -111,6 +111,7 @@ struct headset {
 };
 
 static int rfcomm_connect(struct device *device, struct pending_connect *c);
+static int get_handles(struct device *device, struct pending_connect *c);
 
 static void pending_connect_free(struct pending_connect *c)
 {
@@ -640,11 +641,21 @@ static void get_record_reply(DBusPendingCall *call, void *data)
 		goto failed_not_supported;
 	}
 
-	if ((uuid.type == SDP_UUID32 &&
+	if (hs->type == SVC_HEADSET &&
+			((uuid.type == SDP_UUID32 &&
 			uuid.value.uuid32 != HEADSET_SVCLASS_ID) ||
 			(uuid.type == SDP_UUID16 &&
-			 uuid.value.uuid16 != HEADSET_SVCLASS_ID)) {
-		error("Service classes did not contain the expected UUID");
+			 uuid.value.uuid16 != HEADSET_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID for hsp");
+		goto failed_not_supported;
+	}
+
+	if (hs->type == SVC_HANDSFREE &&
+			((uuid.type == SDP_UUID32 &&
+			uuid.value.uuid32 != HANDSFREE_SVCLASS_ID) ||
+			(uuid.type == SDP_UUID16 &&
+			 uuid.value.uuid16 != HANDSFREE_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID for hfp");
 		goto failed_not_supported;
 	}
 
@@ -750,7 +761,17 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
 	}
 
 	if (array_len < 1) {
-		debug("No record handles found");
+
+		if(hs->type == SVC_HANDSFREE) {
+			debug("No record handles found for hfp");
+			hs->type = SVC_HEADSET;
+			get_handles(device, c);
+			dbus_message_unref(reply);
+			return;
+		}
+
+		debug("No record handles found for hsp");
+
 		if (c->msg)
 			error_not_supported(device->conn, c->msg);
 		goto failed;
@@ -785,6 +806,7 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
 	}
 
 	dbus_pending_call_set_notify(pending, get_record_reply, device, NULL);
+
 	dbus_pending_call_unref(pending);
 	dbus_message_unref(msg);
 	dbus_message_unref(reply);
@@ -862,7 +884,7 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c)
 		if (!g_slist_find(hs->pending, c))
 			hs->pending = g_slist_append(hs->pending, c);
 
-		hs->type = hs->hfp_handle ? SVC_HANDSFREE : SVC_HEADSET;
+		hs->type = SVC_HANDSFREE;
 
 		if (hs->state == HEADSET_STATE_DISCONNECTED)
 			return get_handles(device, c);

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

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

[-- 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] 6+ messages in thread

* Re: [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree
  2007-12-06 11:27 [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree Frédéric Dalleau
  2007-12-06 11:30 ` Frédéric Dalleau
@ 2007-12-06 11:40 ` Marcel Holtmann
  2007-12-06 15:16   ` Frédéric Dalleau
  1 sibling, 1 reply; 6+ messages in thread
From: Marcel Holtmann @ 2007-12-06 11:40 UTC (permalink / raw)
  To: BlueZ development

Hi Frederic,

> As of today, when calling org.bluez.audio.headset.Connect(), the hfp 
> profile is searched only if the headset->hfp_handle is initialized.
> This member variable is initialized upon CreateDevice the first time the 
> device is created (during resolve_services).
> The variable is not initialized when the audio service is restarted, so 
> after restarting audio service, it is no longer possible to connect to hfp.

we had to disable HFP with a config setting since we are not fully
supporting it at the moment. So this must depend on the config setting
if we search for HFP and if we consider it for the connect. By default
we only support HSP.

Regards

Marcel




-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

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

* Re: [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree
  2007-12-06 11:40 ` Marcel Holtmann
@ 2007-12-06 15:16   ` Frédéric Dalleau
  2007-12-07 14:02     ` Frédéric Dalleau
  0 siblings, 1 reply; 6+ messages in thread
From: Frédéric Dalleau @ 2007-12-06 15:16 UTC (permalink / raw)
  To: BlueZ development


[-- Attachment #1.1: Type: text/plain, Size: 1408 bytes --]

Right!

Here is an updated patch. It adds a parameter to headset_init() to know 
whether hfp is enabled or not.

Let me know what you think,
Regards,

Frederic


Marcel Holtmann wrote:
> Hi Frederic,
>
>   
>> As of today, when calling org.bluez.audio.headset.Connect(), the hfp 
>> profile is searched only if the headset->hfp_handle is initialized.
>> This member variable is initialized upon CreateDevice the first time the 
>> device is created (during resolve_services).
>> The variable is not initialized when the audio service is restarted, so 
>> after restarting audio service, it is no longer possible to connect to hfp.
>>     
>
> we had to disable HFP with a config setting since we are not fully
> supporting it at the moment. So this must depend on the config setting
> if we search for HFP and if we consider it for the connect. By default
> we only support HSP.
>
> Regards
>
> Marcel
>
>
>
>
> -------------------------------------------------------------------------
> SF.Net email is sponsored by: The Future of Linux Business White Paper
> from Novell.  From the desktop to the data center, Linux is going
> mainstream.  Let it simplify your IT future.
> http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel
>   


[-- Attachment #1.2: Type: text/html, Size: 2090 bytes --]

[-- Attachment #2: handsfreeconnect.patch --]
[-- Type: text/x-patch, Size: 5394 bytes --]

diff --git a/audio/headset.c b/audio/headset.c
index 6cb5406..98d2836 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -99,6 +99,7 @@ struct headset {
 	int data_start;
 	int data_length;
 
+	int enable_hfp;
 	headset_type_t type;
 
 	headset_state_t state;
@@ -111,6 +112,7 @@ struct headset {
 };
 
 static int rfcomm_connect(struct device *device, struct pending_connect *c);
+static int get_handles(struct device *device, struct pending_connect *c);
 
 static void pending_connect_free(struct pending_connect *c)
 {
@@ -640,11 +642,21 @@ static void get_record_reply(DBusPendingCall *call, void *data)
 		goto failed_not_supported;
 	}
 
-	if ((uuid.type == SDP_UUID32 &&
+	if (hs->type == SVC_HEADSET &&
+			((uuid.type == SDP_UUID32 &&
 			uuid.value.uuid32 != HEADSET_SVCLASS_ID) ||
 			(uuid.type == SDP_UUID16 &&
-			 uuid.value.uuid16 != HEADSET_SVCLASS_ID)) {
-		error("Service classes did not contain the expected UUID");
+			 uuid.value.uuid16 != HEADSET_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID hsp");
+		goto failed_not_supported;
+	}
+
+	if (hs->type == SVC_HANDSFREE &&
+			((uuid.type == SDP_UUID32 &&
+			uuid.value.uuid32 != HANDSFREE_SVCLASS_ID) ||
+			(uuid.type == SDP_UUID16 &&
+			 uuid.value.uuid16 != HANDSFREE_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID hfp");
 		goto failed_not_supported;
 	}
 
@@ -750,7 +762,17 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
 	}
 
 	if (array_len < 1) {
-		debug("No record handles found");
+
+		if(hs->type == SVC_HANDSFREE) {
+			debug("No record handles found for hfp");
+			hs->type = SVC_HEADSET;
+			get_handles(device, c);
+			dbus_message_unref(reply);
+			return;
+		}
+
+		debug("No record handles found for hsp");
+
 		if (c->msg)
 			error_not_supported(device->conn, c->msg);
 		goto failed;
@@ -862,7 +884,7 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c)
 		if (!g_slist_find(hs->pending, c))
 			hs->pending = g_slist_append(hs->pending, c);
 
-		hs->type = hs->hfp_handle ? SVC_HANDSFREE : SVC_HEADSET;
+		hs->type = hs->enable_hfp ? SVC_HANDSFREE : SVC_HEADSET;
 
 		if (hs->state == HEADSET_STATE_DISCONNECTED)
 			return get_handles(device, c);
@@ -1368,8 +1390,8 @@ void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc)
 	headset_set_channel(headset, record);
 }
 
-struct headset *headset_init(struct device *dev, sdp_record_t *record,
-				uint16_t svc)
+struct headset *headset_init(struct device *dev, int enable_hfp,
+				sdp_record_t *record, uint16_t svc)
 {
 	struct headset *hs;
 
@@ -1377,6 +1399,7 @@ struct headset *headset_init(struct device *dev, sdp_record_t *record,
 	hs->rfcomm_ch = -1;
 	hs->sp_gain = -1;
 	hs->mic_gain = -1;
+	hs->enable_hfp = enable_hfp;
 
 	if (!record)
 		goto register_iface;
diff --git a/audio/headset.h b/audio/headset.h
index 5e19cd9..b151dbd 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -54,8 +54,8 @@ typedef enum {
 
 typedef void (*headset_stream_cb_t) (struct device *dev, void *user_data);
 
-struct headset *headset_init(struct device *dev, sdp_record_t *record,
-				uint16_t svc);
+struct headset *headset_init(struct device *dev, int enable_hfp,
+				sdp_record_t *record, uint16_t svc);
 
 void headset_free(struct device *dev);
 
diff --git a/audio/manager.c b/audio/manager.c
index 507f60a..6f690f9 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -108,6 +108,7 @@ static GIOChannel *hs_server = NULL;
 static GIOChannel *hf_server = NULL;
 
 static const struct enabled_interfaces *enabled;
+static gboolean enable_hfp = FALSE;
 
 static void get_next_record(struct audio_sdp_data *data);
 static DBusHandlerResult get_handles(const char *uuid,
@@ -213,7 +214,7 @@ done:
 	return uuid16;
 }
 
-static gboolean server_is_enabled(uint16_t svc)
+gboolean server_is_enabled(uint16_t svc)
 {
 	gboolean ret;
 
@@ -254,6 +255,7 @@ static void handle_record(sdp_record_t *record, struct device *device)
 			headset_update(device, record, uuid16);
 		else
 			device->headset = headset_init(device,
+							enable_hfp,
 							record, uuid16);
 		break;
 	case HEADSET_AGW_SVCLASS_ID:
@@ -265,6 +267,7 @@ static void handle_record(sdp_record_t *record, struct device *device)
 			headset_update(device, record, uuid16);
 		else
 			device->headset = headset_init(device,
+							enable_hfp,
 							record, uuid16);
 		break;
 	case HANDSFREE_AGW_SVCLASS_ID:
@@ -645,7 +648,7 @@ struct device *manager_device_connected(bdaddr_t *bda, const char *uuid)
 		if (device->headset)
 			return device;
 
-		device->headset = headset_init(device, NULL, 0);
+		device->headset = headset_init(device, enable_hfp, NULL, 0);
 
 		if (!device->headset)
 			return NULL;
@@ -1070,7 +1073,7 @@ static void parse_stored_devices(char *key, char *value, void *data)
 	bacpy(&device->store, src);
 
 	if (enabled->headset && strstr(value, "headset"))
-		device->headset = headset_init(device, NULL, 0);
+		device->headset = headset_init(device, enable_hfp, NULL, 0);
 	if (enabled->sink && strstr(value, "sink"))
 		device->sink = sink_init(device);
 	if (enabled->control && strstr(value, "control"))
@@ -1561,6 +1564,8 @@ static int headset_server_init(DBusConnection *conn, gboolean no_hfp)
 	if (no_hfp)
 		return 0;
 
+	enable_hfp = TRUE;
+
 	chan = DEFAULT_HF_AG_CHANNEL;
 
 	hf_server = server_socket(&chan);

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

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

[-- 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] 6+ messages in thread

* Re: [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree
  2007-12-06 15:16   ` Frédéric Dalleau
@ 2007-12-07 14:02     ` Frédéric Dalleau
  2007-12-11 15:44       ` [Bluez-devel] [Patch] Service Level Connection for HFP Alok
  0 siblings, 1 reply; 6+ messages in thread
From: Frédéric Dalleau @ 2007-12-07 14:02 UTC (permalink / raw)
  To: BlueZ development

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


> Here is an updated patch. It adds a parameter to headset_init() to 
> know whether hfp is enabled or not.
>
> Marcel Holtmann wrote:
>> Hi Frederic,
>>
>>   
>>> As of today, when calling org.bluez.audio.headset.Connect(), the hfp 
>> So this must depend on the config setting
Updated again, do not remove the static attribute in front of 
server_is_enabled().

Frederic


[-- Attachment #2: handsfreeconnect.patch --]
[-- Type: text/x-patch, Size: 5234 bytes --]

diff --git a/audio/headset.c b/audio/headset.c
index 97419a6..7bb1746 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -99,6 +99,7 @@ struct headset {
 	int data_start;
 	int data_length;
 
+	int enable_hfp;
 	headset_type_t type;
 
 	headset_state_t state;
@@ -111,6 +112,7 @@ struct headset {
 };
 
 static int rfcomm_connect(struct device *device, struct pending_connect *c);
+static int get_handles(struct device *device, struct pending_connect *c);
 
 static void pending_connect_free(struct pending_connect *c)
 {
@@ -640,11 +642,21 @@ static void get_record_reply(DBusPendingCall *call, void *data)
 		goto failed_not_supported;
 	}
 
-	if ((uuid.type == SDP_UUID32 &&
+	if (hs->type == SVC_HEADSET &&
+			((uuid.type == SDP_UUID32 &&
 			uuid.value.uuid32 != HEADSET_SVCLASS_ID) ||
 			(uuid.type == SDP_UUID16 &&
-			 uuid.value.uuid16 != HEADSET_SVCLASS_ID)) {
-		error("Service classes did not contain the expected UUID");
+			 uuid.value.uuid16 != HEADSET_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID hsp");
+		goto failed_not_supported;
+	}
+
+	if (hs->type == SVC_HANDSFREE &&
+			((uuid.type == SDP_UUID32 &&
+			uuid.value.uuid32 != HANDSFREE_SVCLASS_ID) ||
+			(uuid.type == SDP_UUID16 &&
+			 uuid.value.uuid16 != HANDSFREE_SVCLASS_ID))) {
+		error("Service classes did not contain the expected UUID hfp");
 		goto failed_not_supported;
 	}
 
@@ -750,7 +762,17 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
 	}
 
 	if (array_len < 1) {
-		debug("No record handles found");
+
+		if(hs->type == SVC_HANDSFREE) {
+			debug("No record handles found for hfp");
+			hs->type = SVC_HEADSET;
+			get_handles(device, c);
+			dbus_message_unref(reply);
+			return;
+		}
+
+		debug("No record handles found for hsp");
+
 		if (c->msg)
 			error_not_supported(device->conn, c->msg);
 		goto failed;
@@ -862,7 +884,7 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c)
 		if (!g_slist_find(hs->pending, c))
 			hs->pending = g_slist_append(hs->pending, c);
 
-		hs->type = hs->hfp_handle ? SVC_HANDSFREE : SVC_HEADSET;
+		hs->type = hs->enable_hfp ? SVC_HANDSFREE : SVC_HEADSET;
 
 		if (hs->state == HEADSET_STATE_DISCONNECTED)
 			return get_handles(device, c);
@@ -1368,8 +1390,8 @@ void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc)
 	headset_set_channel(headset, record);
 }
 
-struct headset *headset_init(struct device *dev, sdp_record_t *record,
-				uint16_t svc)
+struct headset *headset_init(struct device *dev, int enable_hfp,
+				sdp_record_t *record, uint16_t svc)
 {
 	struct headset *hs;
 
@@ -1377,6 +1399,7 @@ struct headset *headset_init(struct device *dev, sdp_record_t *record,
 	hs->rfcomm_ch = -1;
 	hs->sp_gain = -1;
 	hs->mic_gain = -1;
+	hs->enable_hfp = enable_hfp;
 
 	if (!record)
 		goto register_iface;
diff --git a/audio/headset.h b/audio/headset.h
index 5e19cd9..b151dbd 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -54,8 +54,8 @@ typedef enum {
 
 typedef void (*headset_stream_cb_t) (struct device *dev, void *user_data);
 
-struct headset *headset_init(struct device *dev, sdp_record_t *record,
-				uint16_t svc);
+struct headset *headset_init(struct device *dev, int enable_hfp,
+				sdp_record_t *record, uint16_t svc);
 
 void headset_free(struct device *dev);
 
diff --git a/audio/manager.c b/audio/manager.c
index 507f60a..cfadec4 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -108,6 +108,7 @@ static GIOChannel *hs_server = NULL;
 static GIOChannel *hf_server = NULL;
 
 static const struct enabled_interfaces *enabled;
+static gboolean enable_hfp = FALSE;
 
 static void get_next_record(struct audio_sdp_data *data);
 static DBusHandlerResult get_handles(const char *uuid,
@@ -254,6 +255,7 @@ static void handle_record(sdp_record_t *record, struct device *device)
 			headset_update(device, record, uuid16);
 		else
 			device->headset = headset_init(device,
+							enable_hfp,
 							record, uuid16);
 		break;
 	case HEADSET_AGW_SVCLASS_ID:
@@ -265,6 +267,7 @@ static void handle_record(sdp_record_t *record, struct device *device)
 			headset_update(device, record, uuid16);
 		else
 			device->headset = headset_init(device,
+							enable_hfp,
 							record, uuid16);
 		break;
 	case HANDSFREE_AGW_SVCLASS_ID:
@@ -645,7 +648,7 @@ struct device *manager_device_connected(bdaddr_t *bda, const char *uuid)
 		if (device->headset)
 			return device;
 
-		device->headset = headset_init(device, NULL, 0);
+		device->headset = headset_init(device, enable_hfp, NULL, 0);
 
 		if (!device->headset)
 			return NULL;
@@ -1070,7 +1073,7 @@ static void parse_stored_devices(char *key, char *value, void *data)
 	bacpy(&device->store, src);
 
 	if (enabled->headset && strstr(value, "headset"))
-		device->headset = headset_init(device, NULL, 0);
+		device->headset = headset_init(device, enable_hfp, NULL, 0);
 	if (enabled->sink && strstr(value, "sink"))
 		device->sink = sink_init(device);
 	if (enabled->control && strstr(value, "control"))
@@ -1561,6 +1564,8 @@ static int headset_server_init(DBusConnection *conn, gboolean no_hfp)
 	if (no_hfp)
 		return 0;
 
+	enable_hfp = TRUE;
+
 	chan = DEFAULT_HF_AG_CHANNEL;
 
 	hf_server = server_socket(&chan);

[-- Attachment #3: Type: text/plain, Size: 277 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://sourceforge.net/services/buy/index.php

[-- 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] 6+ messages in thread

* [Bluez-devel] [Patch] Service Level Connection for HFP.
  2007-12-07 14:02     ` Frédéric Dalleau
@ 2007-12-11 15:44       ` Alok
  0 siblings, 0 replies; 6+ messages in thread
From: Alok @ 2007-12-11 15:44 UTC (permalink / raw)
  To: BlueZ development

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

Hello, 

I am sending a patch for Service Level Connection(SLC) Establishment for
the HandsFree Profile. This patch includes: 

1. String table mechanism for headset/handsfree events. 

2. Callbacks in form of function pointers for the events. 

3. Basic event handling for SLC and complete event handling for
   Headset. 

4. Modification in get_record_reply for HFP.

Currently there are no extra signals/methods, for the sake of
simplicity.   

This patch requires Fredric's 1st patch(dated:07 Dec 2007) to be applied
first. 

Please let me know if any changes are required. 

Thanks, 
Alok.

[-- Attachment #2: SLC.patch --]
[-- Type: text/x-patch, Size: 8905 bytes --]

diff --git a/audio/headset.c b/audio/headset.c
index 7bb1746..98c4d4c 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -108,9 +108,27 @@ struct headset {
 	int sp_gain;
 	int mic_gain;
 
+	unsigned int hfp_features;
 	headset_lock_t lock;
 };
 
+struct event {
+	const char *cmd;
+	 int(*callback) (struct device *device, const char *buf);
+};
+
+static struct event event_callbacks[] = {
+	{"ATA", hf_answer_call},
+	{"AT+VG", hs_signal_gain_setting},
+	{"AT+BRSF", hf_supported_features},
+	{"AT+CIND", hf_report_indicators},
+	{"AT+CMER", hf_event_reporting},
+	{"AT+CHLD", hf_call_hold},
+	{"AT+CHUP", hf_terminate_call},
+	{"AT+CKPD", hf_answer_call},
+	{0}
+};
+
 static int rfcomm_connect(struct device *device, struct pending_connect *c);
 static int get_handles(struct device *device, struct pending_connect *c);
 
@@ -130,70 +148,114 @@ static void pending_connect_free(struct pending_connect *c)
 	g_free(c);
 }
 
-static void hs_signal_gain_setting(struct device *device, const char *buf)
+int handle_event(struct device *device, const char *buf)
+{
+	struct event *pt;
+	debug("Received %s", buf);
+	for (pt = event_callbacks; pt->cmd; pt++) {
+		if (!strncmp(buf, pt->cmd, strlen(pt->cmd)))
+			return pt->callback(device, buf);
+	}
+	debug("Invalid Event");
+	return -1;
+}
+
+int hf_supported_features(struct device *device, const char *buf)
+{
+	struct headset *hs = device->headset;
+
+	hs->hfp_features = strtoul(&buf[8], NULL, 10);
+	headset_send(hs, "\r\n+BRSF:0\r\n");
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
+}
+
+int hf_report_indicators(struct device *device, const char *buf)
+{
+	struct headset *hs = device->headset;
+
+	if (buf[7] == '=')
+		headset_send(hs, "\r\n+CIND:(\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0-3))\r\n");
+	else
+		headset_send(hs, "\r\n+CIND:1, 0, 0\r\n");
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
+}
+
+int hf_event_reporting(struct device *device, const char *buf)
+{
+	struct headset *hs = device->headset;
+
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;	
+}
+
+int hf_call_hold(struct device *device, const char *buf)
+{
+	struct headset *hs = device->headset;
+
+	headset_send(hs, "\r\n+CHLD:(0,1,1x,2,2x,3,4)\r\n");
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
+}
+
+int hf_answer_call(struct device *device, const char *buf)
+{
+	struct headset *hs = device->headset;
+
+	dbus_connection_emit_signal(device->conn,
+				    device->path, AUDIO_HEADSET_INTERFACE, "AnswerRequested", DBUS_TYPE_INVALID);
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
+}
+
+int hf_terminate_call(struct device *device, const char *buf)
+{
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
+}
+
+
+int hs_signal_gain_setting(struct device *device, const char *buf)
 {
 	const char *name;
 	dbus_uint16_t gain;
 
-	if (strlen(buf) < 6) {
+	if (strlen(buf) < 8) {
 		error("Too short string for Gain setting");
-		return;
+		return -1;
 	}
 
-	gain = (dbus_uint16_t) strtol(&buf[5], NULL, 10);
+	gain = (dbus_uint16_t) strtol(&buf[7], NULL, 10);
 
 	if (gain > 15) {
 		error("Invalid gain value received: %u", gain);
-		return;
+		return -1;
 	}
 
-	switch (buf[3]) {
+	switch (buf[5]) {
 	case HEADSET_GAIN_SPEAKER:
 		if (device->headset->sp_gain == gain)
-			return;
+			break;
 		name = "SpeakerGainChanged";
 		device->headset->sp_gain = gain;
 		break;
 	case HEADSET_GAIN_MICROPHONE:
 		if (device->headset->mic_gain == gain)
-			return;
+			break;
 		name = "MicrophoneGainChanged";
 		device->headset->mic_gain = gain;
 		break;
 	default:
 		error("Unknown gain setting");
-		return;
-	}
-
-	dbus_connection_emit_signal(device->conn, device->path,
-					AUDIO_HEADSET_INTERFACE, name,
-					DBUS_TYPE_UINT16, &gain,
-					DBUS_TYPE_INVALID);
-}
-
-static headset_event_t parse_headset_event(const char *buf, char *rsp,
-						int rsp_len)
-{
-	printf("Received: %s\n", 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;
+		return -1;
 	}
 
-	buf += 2;
-
-	if (!strncmp(buf, "+CKPD", 5)) {
-		snprintf(rsp, rsp_len, "\r\nOK\r\n");
-		return HEADSET_EVENT_KEYPRESS;
-	} 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;
-	}
+	dbus_connection_emit_signal(device->conn,
+				    device->path,
+				    AUDIO_HEADSET_INTERFACE, name, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID);
+	headset_send(device->headset, "\r\nOK\r\n");
+	return 0;
 }
 
 static void close_sco(struct device *device)
@@ -214,9 +276,9 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
 {
 	struct headset *hs;
 	unsigned char buf[BUF_SIZE];
-	char *cr, rsp[BUF_SIZE];
+	char *cr;
 	gsize bytes_read = 0;
-	gsize free_space, count, bytes_written, total_bytes_written;
+	gsize free_space;
 	GIOError err;
 	off_t cmd_len;
 
@@ -256,46 +318,8 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
 	cmd_len	= 1 + (off_t) cr - (off_t) &hs->buf[hs->data_start];
 	*cr = '\0';
 
-	memset(rsp, 0, sizeof(rsp));
-
-	switch (parse_headset_event(&hs->buf[hs->data_start], rsp,
-					sizeof(rsp))) {
-	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);
-			hs->ring_timer = 0;
-		}
-
-		dbus_connection_emit_signal(device->conn, device->path,
-						AUDIO_HEADSET_INTERFACE,
-						"AnswerRequested",
-						DBUS_TYPE_INVALID);
-		break;
-
-	case HEADSET_EVENT_INVALID:
-	case HEADSET_EVENT_UNKNOWN:
-	default:
-		debug("Unknown headset event");
-		break;
-	}
-
-	count = strlen(rsp);
-	total_bytes_written = bytes_written = 0;
-	err = G_IO_ERROR_NONE;
-
-	while (err == G_IO_ERROR_NONE && total_bytes_written < count) {
-		err = g_io_channel_write(hs->rfcomm,
-						rsp + total_bytes_written, 
-						count - total_bytes_written,
-						&bytes_written);
-		if (err != G_IO_ERROR_NONE)
-			error("Error while writting to the audio output channel");
-		total_bytes_written += bytes_written;
-	};
+	if(handle_event(device, &hs->buf[hs->data_start]) == -1)
+		error("Error in event");
 
 	hs->data_start += cmd_len;
 	hs->data_length -= cmd_len;
@@ -593,6 +617,7 @@ static void get_record_reply(DBusPendingCall *call, void *data)
 	struct device *device = data;
 	struct headset *hs = device->headset;
 	struct pending_connect *c;
+	unsigned int SVCLASS_ID;
 
 	c = hs->pending->data;
 
@@ -642,21 +667,11 @@ static void get_record_reply(DBusPendingCall *call, void *data)
 		goto failed_not_supported;
 	}
 
-	if (hs->type == SVC_HEADSET &&
-			((uuid.type == SDP_UUID32 &&
-			uuid.value.uuid32 != HEADSET_SVCLASS_ID) ||
-			(uuid.type == SDP_UUID16 &&
-			 uuid.value.uuid16 != HEADSET_SVCLASS_ID))) {
-		error("Service classes did not contain the expected UUID hsp");
-		goto failed_not_supported;
-	}
+	SVCLASS_ID = hs->enable_hfp ? HANDSFREE_SVCLASS_ID : HEADSET_SVCLASS_ID;
 
-	if (hs->type == SVC_HANDSFREE &&
-			((uuid.type == SDP_UUID32 &&
-			uuid.value.uuid32 != HANDSFREE_SVCLASS_ID) ||
-			(uuid.type == SDP_UUID16 &&
-			 uuid.value.uuid16 != HANDSFREE_SVCLASS_ID))) {
-		error("Service classes did not contain the expected UUID hfp");
+	if ((uuid.type == SDP_UUID32 && uuid.value.uuid32 != SVCLASS_ID)
+	    || (uuid.type == SDP_UUID16 && uuid.value.uuid16 != SVCLASS_ID)) {
+		error("Service classes did not contain the expected UUID");
 		goto failed_not_supported;
 	}
 
diff --git a/audio/headset.h b/audio/headset.h
index b151dbd..86be42e 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -28,13 +28,6 @@
 #define DEFAULT_HF_AG_CHANNEL 13
 
 typedef enum {
-	HEADSET_EVENT_KEYPRESS,
-	HEADSET_EVENT_GAIN,
-	HEADSET_EVENT_UNKNOWN,
-	HEADSET_EVENT_INVALID
-} headset_event_t;
-
-typedef enum {
 	HEADSET_STATE_DISCONNECTED,
 	HEADSET_STATE_CONNECT_IN_PROGRESS,
 	HEADSET_STATE_CONNECTED,
@@ -84,3 +77,12 @@ gboolean headset_lock(struct device *dev, headset_lock_t lock);
 gboolean headset_unlock(struct device *dev, headset_lock_t lock);
 gboolean headset_suspend(struct device *dev, void *data);
 gboolean headset_play(struct device *dev, void *data);
+static GIOError headset_send(struct headset *hs, const char *str);
+int hs_signal_gain_setting(struct device *device, const char *buf);
+int hf_supported_features(struct device *device, const char *buf);
+int hf_report_indicators(struct device *device, const char *buf);
+int hf_event_reporting(struct device *device, const char *buf);
+int hf_answer_call(struct device *device, const char *buf);
+int hf_call_hold(struct device *device, const char *buf);
+int hf_terminate_call(struct device *device, const char *buf);
+int hf_answer_call(struct device *device, const char *buf);

[-- Attachment #3: Type: text/plain, Size: 277 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://sourceforge.net/services/buy/index.php

[-- 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] 6+ messages in thread

end of thread, other threads:[~2007-12-11 15:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-06 11:27 [Bluez-devel] [Patch] org.bluez.audio.headset.Connect() to handsfree Frédéric Dalleau
2007-12-06 11:30 ` Frédéric Dalleau
2007-12-06 11:40 ` Marcel Holtmann
2007-12-06 15:16   ` Frédéric Dalleau
2007-12-07 14:02     ` Frédéric Dalleau
2007-12-11 15:44       ` [Bluez-devel] [Patch] Service Level Connection for HFP 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).