Linux bluetooth development
 help / color / mirror / Atom feed
* Re: Proposed API for HDP
From: Marcel Holtmann @ 2010-07-08 17:39 UTC (permalink / raw)
  To: José Antonio Santos Cadenas; +Cc: linux-bluetooth
In-Reply-To: <201007081912.31407.santoscadenas@gmail.com>

Hi Jose,

> Health Device Profile hierarchy
> ===============================
> 
> Service		org.bluez
> Interface	org.bluez.HealthAdapter
> Object path	[variable prefix]/{hci0,hci1,...}

so I changed my mind here. Basing this on the local adapter is rather
pointless.

Lets just do org.bluez.HealthManager on /org/bluez object path. There is
no need that the calling application knows anything about the specific
adapters in our system. We properly separate them anyway during paring.

Only the application that does the initial pairing with a remote health
device needs to know which adapter to use. For the actual health
application it is pointless since it will be notified about the paired
health device initially.

> Methods:
> 
> 	path	CreateApplication(object path, dict config)
> 
> 		Returns the path of the new created application. The path
> 		parameter is the path of the object with the callbacks to
> 		notify events (see org.bluez.HealthAgent at the end of this
> 		document)
> 		This petition starts an mcap instance and also register a proper
> 		record in the SDP if is needed.
> 
> 		Dict is defined as bellow:
> 		{
> 		  "end_points" : [{ (optional)
> 			"role" : ("source" or "sink"), (mandatory)
> 			"specs" :[{ (mandatory)
> 				"data_type" : uint16, (mandatory)
> 				"description" : string, (optional)
> 			}]
> 		  }]
> 		}
> 
> 		Application will be closed by the call or implicitly when the
> 		programs leaves the bus.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 
> 	void	ReleaseApplication(path application)
> 
> 		Closes the HDP application identified by the object path. Also
> 		application will be closed if the process that started it leaves
> 		the bus. If there is a SDP record associated to this application
> 		it will be removed.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.NotFound

Since we now make this as part of a generic manager, the method class
RegisterApplication and UnregisterApplication are a lot better choice.

> 	array	GetRemoteApplications(path application)
> 
> 		This method will return an array with the paths of all the
> 		remote instances found in remote devices.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.NotFound

We don't wanna do that. When you register your application the first
callback via the agent should be telling what remote instances are
available.

This has the advantage that the code flow for the application is
simpler. It just has to listen to that update. And if you register your
application before pairing with a new device, it will still work. So no
extra work to listen for new devices and bootstrapping an existing list.

> --------------------------------------------------------------------------------
> 
> Service		org.bluez
> Interface	org.bluez.HealthDevice
> Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX

This is not really a health device. As mentioned yesterday, we can have
multiple health service per remote device. So we should be using here
are org.bluez.HealthService for every SDP record for HDP inside the
remote device.

So potential object paths are .../hci0/dev_xxxxxxxx/{hdp0,hdp1,...} and
so on. This way we clearly map health service and not bother with remote
device details that might implement multiple functions.

> Methods:
> 
> 	void Refresh()
> 
> 		This method searches for HDP applications in the remote device
> 		and notifies them to the appropriate agents.

I might have called this Update(), but that is a minor detail.

> --------------------------------------------------------------------------------
> 
> Service		org.bluez
> Interface	org.bluez.HealthDeviceApplication
> Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/hdp_YYYY
> 

That is more like the org.bluez.HealthService as mentioned above. So
lets combine them. I don't see a need for splitting these.

> Methods:
> 
> 	array GetProperties()
> 
> 		Gets the information of the remote application published on its
> 		SDP record. The returned data format is as follows:
> 
> 		{
> 			"end_points": [
> 				"mdepid": uint8,
> 				"role"  : "source" or "sink" ,
> 				"specs" : [{
> 					"dtype"       : uint16,
> 					"description" : string, (optional)
> 					}]
> 				]
> 		}
> 
> 	object Connect(path local_application_id)
> 
> 		Connects the local application with the remote application.
> 
> 		Only the bus client that created the local session will be able
> 		to create connections using it.
> 
> 		If the Device is already connected with an other application an
> 		org.bluez.Error.AlreadyConnected error will be received.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.AlreadyConnected
> 				org.bluez.Error.HealthError
> 
> 	void Disconnect()
> 
> 		Disconnect from the remote application the state will also be
> 		deleted. And no future reconnections will be possible. For
> 		keeping the state the method Pause of the health link should be
> 		used.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.NotFound
> 				org.bluez.Error.HealthError

Do we need Connect() and Disconnect() here. Can we just not create these
connections in the background based of a reference counting via the
channels?

> 	boolean Echo(array{byte})
> 
> 		Sends an echo petition to the remote intance. Returns True if
> 		response matches with the buffer sent. If some error is detected
> 		False value is returned and the associated MCL is closed.
> 
> 	path OpenDataChannel(byte mdepid, string conf)
> 
> 		Creates a new data channel with the indicated config to the
> 		remote MCAP Data End Point (MDEP).
> 		The configuration should indicate the channel quality of
> 		service using one of this values "reliable", "streaming", "any".
> 
> 		Returns the data channel path.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.HealthError
> 
> 	void ReconnectDataChannel(path data_channel)
> 
> 		Reconnects a previously created data channel indicated by its
> 		path.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.HealthError
> 				org.bluez.Error.NotFound
> 
> 	int GetDataChannelFileDescriptor(path data_channel)
> 
> 		Gets a file descriptor where data can be read or written.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.NotFound
> 				org.bluez.Error.HealthError
> 
> 	void DeleteDataChannel(path data_channel)
> 
> 		Deletes a data channel so it will not be available to use.
> 
> 		Possible errors: org.bluez.Error.InvalidArguments
> 				org.bluez.Error.NotFound
> 				org.bluez.Error.HealthError
> 
> 	void DeleteAllDataChannels()
> 
> 		Deletes all data channels so they will not be available for
> 		future use. Typically this function is called when the
> 		connection with the remote device will be closed permanently.
> 
> 		Possible errors: org.bluez.Error.HealthError

This actually means also Disconnect() to me. So clear the extra work of
connect and disconnect can be done in the background and invisible for
the user.

> 	dict GetDataChannelStatus()
> 
> 		Return a dictionary with all the data channels that can be used
> 		to send data right now. The dictionary is formed like follows:
> 
> 		{
> 			"reliable": [channel_path_r1, channel_path_r2, ...],
> 			"streaming" : [channel_path_s1, channel_path_s2, ...]
> 		}
> 
> 		The fist reliable data channel will always be the first data
> 		channel in reliable array.
> 
> HealthAgent hierarchy
> =====================
> 
> (this object is implemented by the HDP user in order to receive notifications)
> 
> Service		unique name
> Interface	org.bluez.HealthAgent
> Object path	freely definable
> 
> Methods:
> 
> 	void DeviceApplicationDiscovered(object path)
> 
> 		This method is called when a device containing an hdp
> 		application is connected. The object path is the application
> 		path. The method will be called one time for each
> 		application.

I think this should be ServiceDiscovered and map to a HealthService.

> 	void DeviceConnected(object path)
> 
> 		This method is called whenever a new connection has been
> 		established over the control channel of the current HDP
> 		application. The object path paremeter contains the object path
> 		of the connected HealthDevice.

Don't see a useful need for this. I don't want to expose HealthDevice
details anyway.

> 	void DevicePaused(object path)
> 
> 		This method is called when a MCL is closed. Future reconnections
> 		will be notified using the DeviceRestarted callback.
> 		All data channels associated to this device will be closed and
> 		a reconnection will be needed before using them again.
> 
> 	void DeviceResumed(object path)
> 
> 		This method is called whenever a MCL is reconnected. All data
> 		channels associated are still closed but they will be able to be
> 		reconnected skipping the configuration process.
> 
> 	void DeviceDisconnected(object path)
> 
> 		This method is called when a remote device is disconnected or
> 		removed from MCAP cache. Any future reconnections will fail.
> 		Also all data channels associated to this device will be closed.

Why bother with this. We can do this on channel level.

> 	void CreatedDataChannel(object path, path data_channel, string conf)
> 
> 		This method is called when a new data channel is created.
> 
> 		The path contains the object path of the HealthDeviceApplication
> 		where the new connection is created, the data_channel is the
> 		path for identify the data channel and conf is the quality of
> 		service of the data channel ("reliable" or "streaming").

DataChannelCreated please.

> 	void DataChannelReconnected(object path, path data_channel, string conf)
> 
> 		This method is called when a closed data channel is reconnected
> 		by the remote device.
> 
> 		Conf will be "reliable" or "streaming".
> 
> 		TThe path contains the object path of the
> 		HealthDeviceApplication where the new connection is reconnected,
> 		the data_channel is the path for identify the data channel and
> 		conf is the quality of service of the data channel ("reliable"
> 		or "streaming").
> 
> 	void DeletedDataChannel(object path, path data_channel)
> 
> 		This method is called when a data channel is deleted.
> 
> 		After this call the data channel path will not be valid and can
> 		be reused for future creation of data channels.

DataChannelRemoved. We always map create with remove.

> 	void DeletedAllDataChannels(object path)
> 
> 		This method is called when all data channels are deleted.
> 
> 		The path contains the object path of the HealthDeviceApplication
> 		where the data channels are deleted.

That is pointless. You will get separate callbacks for each channel
anyway.

And the agent is missing a Release method for unforseen terminations.
See other agents for that detail.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 3/3] Extended support for generating dictionary value of service UUIDs
From: Marcel Holtmann @ 2010-07-08 17:23 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, johan.hedberg, rshaffer
In-Reply-To: <1278540518-18620-4-git-send-email-ingas@codeaurora.org>

Hi Inga,

>  src/adapter.c  |  103 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  src/adapter.h  |    4 +-
>  src/dbus-hci.c |    7 ++--
>  src/sdpd.h     |    2 +
>  4 files changed, 107 insertions(+), 9 deletions(-)

as requested please split these properly into multiple patches.

> diff --git a/src/sdpd.h b/src/sdpd.h
> index 8fd8bbe..38677d3 100644
> --- a/src/sdpd.h
> +++ b/src/sdpd.h
> @@ -39,6 +39,8 @@
>  
>  #define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
>  #define EIR_UUID16_ALL              0x03  /* 16-bit UUID, all listed */
> +#define EIR_UUID32_SOME             0x04  /* 32-bit UUID, more available */
> +#define EIR_UUID32_ALL              0x05  /* 32-bit UUID, all listed */
>  #define EIR_UUID128_SOME            0x06  /* 128-bit UUID, more available */
>  #define EIR_UUID128_ALL             0x07  /* 128-bit UUID, all listed */
>  #define EIR_NAME_SHORT              0x08  /* shortened local name */

And this should go into the initial patch listing all of these.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 2/3] Update EIR whenever record is added or removed
From: Marcel Holtmann @ 2010-07-08 17:21 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, johan.hedberg, rshaffer
In-Reply-To: <1278540518-18620-3-git-send-email-ingas@codeaurora.org>

Hi Inga,

> index 96280bd..8ec4df4 100644
> --- a/plugins/service.c
> +++ b/plugins/service.c
> @@ -4,6 +4,7 @@
>   *
>   *  Copyright (C) 2006-2010  Nokia Corporation
>   *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
> + *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.

see my comment from the other email.

>   *
>   *
>   *  This program is free software; you can redistribute it and/or modify
> @@ -445,6 +446,8 @@ static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
>  				strerror(EIO));
>  	}
>  
> +	adapter_update_ext_inquiry_response(&src);
> +
>  	return dbus_message_new_method_return(msg);
>  }
>  
> @@ -516,6 +519,7 @@ static DBusMessage *add_service_record(DBusConnection *conn,
>  	const char *sender, *record;
>  	dbus_uint32_t handle;
>  	int err;
> +	bdaddr_t addr;

Use bdaddr as variable name. In general the addr name is used for the
string version of the address.
 
>  	if (dbus_message_get_args(msg, NULL,
>  			DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)
> @@ -526,6 +530,13 @@ static DBusMessage *add_service_record(DBusConnection *conn,
>  	if (err < 0)
>  		return failed_strerror(msg, err);
>  
> +	if (serv_adapter->adapter)
> +		adapter_get_address(serv_adapter->adapter, &addr);
> +	else
> +		bacpy(&addr, BDADDR_ANY);
> +
> +	adapter_update_ext_inquiry_response(&addr);
> +
>  	reply = dbus_message_new_method_return(msg);
>  	if (!reply)
>  		return NULL;
> @@ -550,6 +561,7 @@ static DBusMessage *remove_service_record(DBusConnection *conn,
>  	struct service_adapter *serv_adapter = data;
>  	dbus_uint32_t handle;
>  	const char *sender;
> +	bdaddr_t addr;

See above.

>  
>  	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
>  						DBUS_TYPE_INVALID) == FALSE)
> @@ -560,6 +572,13 @@ static DBusMessage *remove_service_record(DBusConnection *conn,
>  	if (remove_record(conn, sender, serv_adapter, handle) < 0)
>  		return not_available(msg);
>  
> +	if (serv_adapter->adapter)
> +		adapter_get_address(serv_adapter->adapter, &addr);
> +	else
> +		bacpy(&addr, BDADDR_ANY);
> +
> +	adapter_update_ext_inquiry_response(&addr);
> +
>  	return dbus_message_new_method_return(msg);
>  }
>  
> diff --git a/src/adapter.c b/src/adapter.c
> index 2a6ac18..8a05356 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -4,6 +4,7 @@
>   *
>   *  Copyright (C) 2006-2010  Nokia Corporation
>   *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
> + *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
>   *
>   *
>   *  This program is free software; you can redistribute it and/or modify
> @@ -820,7 +821,7 @@ static DBusMessage *set_pairable_timeout(DBusConnection *conn,
>  
>  static void update_ext_inquiry_response(struct btd_adapter *adapter)
>  {
> -	uint8_t fec = 0, data[240];
> +	uint8_t fec = 0, data[EIR_DATA_LENGTH];
>  	struct hci_dev *dev = &adapter->dev;
>  	int dd;
>  
> @@ -846,6 +847,27 @@ static void update_ext_inquiry_response(struct btd_adapter *adapter)
>  	hci_close_dev(dd);
>  }
>  
> +void adapter_update_ext_inquiry_response(const bdaddr_t *src)

Call this adapter_update_eir_data().

Feel free to fix the update_ext_... into update_eir_data() if you want
in a separate patch.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 1/3] Support for adding UUID128 to extended inquiry response
From: Marcel Holtmann @ 2010-07-08 17:17 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, johan.hedberg, rshaffer
In-Reply-To: <1278540518-18620-2-git-send-email-ingas@codeaurora.org>

Hi Inga,

>  void register_public_browse_group(void)
> diff --git a/src/sdpd.h b/src/sdpd.h
> index e93b0b6..8fd8bbe 100644
> --- a/src/sdpd.h
> +++ b/src/sdpd.h
> @@ -6,6 +6,7 @@
>   *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
>   *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
>   *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com>
> + *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.

I prefer that we actually see major code contributions that justify a
copyright here before you start adding it. And so let the maintainers
worry about that later on. I don't wanna see just random copyright
additions for obvious fixes or changes that are most likely even derived
from existing code.
 
> +#define EIR_DATA_LENGTH  240
> +
> +#define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
> +#define EIR_UUID16_ALL              0x03  /* 16-bit UUID, all listed */
> +#define EIR_UUID128_SOME            0x06  /* 128-bit UUID, more available */
> +#define EIR_UUID128_ALL             0x07  /* 128-bit UUID, all listed */
> +#define EIR_NAME_SHORT              0x08  /* shortened local name */
> +#define EIR_NAME_COMPLETE           0x09  /* complete local name */
> +#define EIR_DEVICE_ID               0x10  /* device ID */
> +#define EIR_TX_POWER                0x0A  /* Transmit power level */
> +

If you wanna do this, then this is a separate patch up-front. Don't
intermix this with adding support for UUID-128 entries. I want proper
splits here.

Regards

Marcel



^ permalink raw reply

* Proposed API for HDP
From: José Antonio Santos Cadenas @ 2010-07-08 17:12 UTC (permalink / raw)
  To: linux-bluetooth

Hi all,

This is the new design of the HDP API that we designed using the Marcel's recomendations.

Regards.


BlueZ D-Bus Health API description
**********************************

	Santiago Carot-Nemesio <sancane@gmail.com>
	José Antonio Santos-Cadenas <santoscadenas@gmail.com>
	Elvis Pfützenreuter <epx@signove.com>

Health Device Profile hierarchy
===============================

Service		org.bluez
Interface	org.bluez.HealthAdapter
Object path	[variable prefix]/{hci0,hci1,...}

Methods:

	path	CreateApplication(object path, dict config)

		Returns the path of the new created application. The path
		parameter is the path of the object with the callbacks to
		notify events (see org.bluez.HealthAgent at the end of this
		document)
		This petition starts an mcap instance and also register a proper
		record in the SDP if is needed.

		Dict is defined as bellow:
		{
		  "end_points" : [{ (optional)
			"role" : ("source" or "sink"), (mandatory)
			"specs" :[{ (mandatory)
				"data_type" : uint16, (mandatory)
				"description" : string, (optional)
			}]
		  }]
		}

		Application will be closed by the call or implicitly when the
		programs leaves the bus.

		Possible errors: org.bluez.Error.InvalidArguments

	void	ReleaseApplication(path application)

		Closes the HDP application identified by the object path. Also
		application will be closed if the process that started it leaves
		the bus. If there is a SDP record associated to this application
		it will be removed.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.NotFound

	array	GetRemoteApplications(path application)

		This method will return an array with the paths of all the
		remote instances found in remote devices.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.NotFound

--------------------------------------------------------------------------------

Service		org.bluez
Interface	org.bluez.HealthDevice
Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX

Methods:

	void Refresh()

		This method searches for HDP applications in the remote device
		and notifies them to the appropriate agents.

--------------------------------------------------------------------------------

Service		org.bluez
Interface	org.bluez.HealthDeviceApplication
Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/hdp_YYYY

Methods:

	array GetProperties()

		Gets the information of the remote application published on its
		SDP record. The returned data format is as follows:

		{
			"end_points": [
				"mdepid": uint8,
				"role"  : "source" or "sink" ,
				"specs" : [{
					"dtype"       : uint16,
					"description" : string, (optional)
					}]
				]
		}

	object Connect(path local_application_id)

		Connects the local application with the remote application.

		Only the bus client that created the local session will be able
		to create connections using it.

		If the Device is already connected with an other application an
		org.bluez.Error.AlreadyConnected error will be received.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.AlreadyConnected
				org.bluez.Error.HealthError

	void Disconnect()

		Disconnect from the remote application the state will also be
		deleted. And no future reconnections will be possible. For
		keeping the state the method Pause of the health link should be
		used.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.NotFound
				org.bluez.Error.HealthError

	boolean Echo(array{byte})

		Sends an echo petition to the remote intance. Returns True if
		response matches with the buffer sent. If some error is detected
		False value is returned and the associated MCL is closed.

	path OpenDataChannel(byte mdepid, string conf)

		Creates a new data channel with the indicated config to the
		remote MCAP Data End Point (MDEP).
		The configuration should indicate the channel quality of
		service using one of this values "reliable", "streaming", "any".

		Returns the data channel path.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.HealthError

	void ReconnectDataChannel(path data_channel)

		Reconnects a previously created data channel indicated by its
		path.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.HealthError
				org.bluez.Error.NotFound

	int GetDataChannelFileDescriptor(path data_channel)

		Gets a file descriptor where data can be read or written.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.NotFound
				org.bluez.Error.HealthError

	void DeleteDataChannel(path data_channel)

		Deletes a data channel so it will not be available to use.

		Possible errors: org.bluez.Error.InvalidArguments
				org.bluez.Error.NotFound
				org.bluez.Error.HealthError

	void DeleteAllDataChannels()

		Deletes all data channels so they will not be available for
		future use. Typically this function is called when the
		connection with the remote device will be closed permanently.

		Possible errors: org.bluez.Error.HealthError

	dict GetDataChannelStatus()

		Return a dictionary with all the data channels that can be used
		to send data right now. The dictionary is formed like follows:

		{
			"reliable": [channel_path_r1, channel_path_r2, ...],
			"streaming" : [channel_path_s1, channel_path_s2, ...]
		}

		The fist reliable data channel will always be the first data
		channel in reliable array.

HealthAgent hierarchy
=====================

(this object is implemented by the HDP user in order to receive notifications)

Service		unique name
Interface	org.bluez.HealthAgent
Object path	freely definable

Methods:

	void DeviceApplicationDiscovered(object path)

		This method is called when a device containing an hdp
		application is connected. The object path is the application
		path. The method will be called one time for each
		application.

	void DeviceConnected(object path)

		This method is called whenever a new connection has been
		established over the control channel of the current HDP
		application. The object path paremeter contains the object path
		of the connected HealthDevice.

	void DevicePaused(object path)

		This method is called when a MCL is closed. Future reconnections
		will be notified using the DeviceRestarted callback.
		All data channels associated to this device will be closed and
		a reconnection will be needed before using them again.

	void DeviceResumed(object path)

		This method is called whenever a MCL is reconnected. All data
		channels associated are still closed but they will be able to be
		reconnected skipping the configuration process.

	void DeviceDisconnected(object path)

		This method is called when a remote device is disconnected or
		removed from MCAP cache. Any future reconnections will fail.
		Also all data channels associated to this device will be closed.

	void CreatedDataChannel(object path, path data_channel, string conf)

		This method is called when a new data channel is created.

		The path contains the object path of the HealthDeviceApplication
		where the new connection is created, the data_channel is the
		path for identify the data channel and conf is the quality of
		service of the data channel ("reliable" or "streaming").

	void DataChannelReconnected(object path, path data_channel, string conf)

		This method is called when a closed data channel is reconnected
		by the remote device.

		Conf will be "reliable" or "streaming".

		TThe path contains the object path of the
		HealthDeviceApplication where the new connection is reconnected,
		the data_channel is the path for identify the data channel and
		conf is the quality of service of the data channel ("reliable"
		or "streaming").

	void DeletedDataChannel(object path, path data_channel)

		This method is called when a data channel is deleted.

		After this call the data channel path will not be valid and can
		be reused for future creation of data channels.

	void DeletedAllDataChannels(object path)

		This method is called when all data channels are deleted.

		The path contains the object path of the HealthDeviceApplication
		where the data channels are deleted.

^ permalink raw reply

* Re: What is the motivation for conn->power_save
From: Andrei Emeltchenko @ 2010-07-08 15:07 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Nick Pelly, linux-bluetooth
In-Reply-To: <1263366291.922.5.camel@localhost.localdomain>

Hi,

On Wed, Jan 13, 2010 at 10:04 AM, Marcel Holtmann <marcel@holtmann.org> wro=
te:
> Hi Nick,
>
>> >>> >> If I understand correctly, conn->power_save prevents the host sta=
ck
>> >>> >> from requesting active mode if it was not the host stack that
>> >>> >> requested sniff mode.
>> >>> >>
>> >>> >> I don't understand the motivation for this. If we have ACL data t=
o
>> >>> >> send, then it seems like a good idea for the host stack to explic=
itly
>> >>> >> request active mode, regardless of the reason that we entered sni=
ff
>> >>> >> mode.
>> >>> >>
>> >>> >> We want to enter active mode more aggressively when setting up SC=
O
>> >>> >> connections, to avoid a 5 second delay with certain sniff modes. =
But
>> >>> >> the conn->power_save code is getting in the way and doesn't appea=
r to
>> >>> >> be useful in the first place.
>> >>> >
>> >>> > we have discussed this a few times. And if you lock through the co=
de
>> >>> > history then you see that initially we just took devices out of sn=
iff
>> >>> > mode if we had to send data. However with HID devices this falls f=
lat on
>> >>> > its face. They need to stay in control of sniff mode if they initi=
ated
>> >>> > it. Some of them crash and others just drain the battery. With sni=
ff
>> >>> > mode you can send small amounts of data even while in sniff and fo=
r HID
>> >>> > that is sometimes used. So the remote side better not interfere.
>> >>> >
>> >>> > What we really need is a socket option where we can control this o=
n a
>> >>> > per socket basis if we take devices out of sniff mode. And one ext=
ra
>> >>> > case might be when we try to establish a SCO channel, because then=
 it is
>> >>> > clearly not an HID device. However even A2DP has this sort of prob=
lems
>> >>> > sometimes where the stream setup takes time.
>> >>>
>> >>> Makes sense. Thanks for the explanation.
>> >>
>> >> this means you will be working on a patch for this :)
>>
>> Actually, I want to put a patch together for a socket option to not
>> use power_save (so that we *always* exit sniff mode when sending ACL
>> data). We're seeing this problem with the Plantronics Voyager 855
>> which enters sniff mode during A2DP.
>>
>> Given that power_save is just for HID devices, my preferred design is
>> to disable power_save by default, and have an L2CAP socket option to
>> turn on power_save that would be used by HID L2CAP sockets.
>> Unfortunately this would require userspace HID code to use the new
>> socket option to keep current behavior. But it seems preferable to the
>> alternative of having every single other L2CAP socket use a new socket
>> option just to disable power_save for the sake of HID.
>
> actually you still mix up the meaning of the power_save option. From the
> stack side, the automatic sniff mode is off by default. You have to
> enable via sysfs first. The power_save option is just to control when
> sniff mode is activated and the remote enters sniff mode, that we are
> not getting out of it if we have ACL data.
>
> In conclusion, I am fine with a socket option that allows to control
> sniff mode (preferable with interval details) and sniff subrate details
> so that we can use them for that ACL link.
>
> So go ahead and work on this. We can fix userspace easily since a new
> socket can be detected easily with newer kernels.

We have found that some Nokia BT headsets stop working after idle
period when they enter
"power save" mode.

Do we have any solution for this problem? So far I see good enough
patch :-)) below:

http://android.git.kernel.org/?p=3Dkernel/common.git;a=3Dblobdiff;f=3Dnet/b=
luetooth/hci_conn.c;h=3Dfa8b412205cd89546b4a325c558c68040eeaf491;hp=3D0cf25=
114a3f576fc2788a549eb96d0087dd39b44;hb=3Dd8488237646920cd71ef43e5f3ae1001c6=
f4cf7b;hpb=3D3f68e5050c5ae559f56d5da9202cb88928d42b36

-       if (conn->mode !=3D HCI_CM_SNIFF || !conn->power_save)
+       if (conn->mode !=3D HCI_CM_SNIFF /* || !conn->power_save */)

Nick have you done socket option for "power_save"?

Regards,
Andrei

^ permalink raw reply

* Re: bluetooth data rate vs VDP
From: Luiz Augusto von Dentz @ 2010-07-08 14:05 UTC (permalink / raw)
  To: Viral Mehta; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <70376CA23424B34D86F1C7DE6B997343068C875F6F@VSHINMSMBX01.vshodc.lntinfotech.com>

Hi,

On Thu, Jul 8, 2010 at 2:49 PM, Viral Mehta <Viral.Mehta@lntinfotech.com> wrote:
> I want to send RAW video data. For e.g., read from /dev/fb0 and stream it...
> Is it possible at the first hand? (I guess, in theory, yes)

Yes, it is possible, but it probably will require a lot more bandwidth
than something encoded.

> I also had a question whether encoding/decoding is done by VDP profile
> or I have to write some application on top of VDP profile. ??

The profile doesn't do anything, it only defines, but yes you most
likely will be reading rtp data from bluetooth socket and then you
have do decode it yourself.

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* RE: [RFC] Bluetooth: Add firmware load infrastructure for BT devices
From: Marcel Holtmann @ 2010-07-08 13:42 UTC (permalink / raw)
  To: Shanmugamkamatchi Balashanmugam
  Cc: Perelet, Oleg, linux-bluetooth@vger.kernel.org
In-Reply-To: <44EE5C37ADC36343B0625A05DD408C4850DB2A787C@CHEXMB-01.global.atheros.com>

Hi Bala,

> Firmware loading to target RAM needs to be done once when the device is inserted.  Firmware loading will not be required every time 
> the device goes from DOWN to UP. I think each HCI driver requires
> a separate firmware loading code as firmware loading is 
> different for different interfaces.  Please advice if my understanding is wrong.
> 
> I initially thought of registration 
> mechanism with btusb transport driver to load firmware, but before
> the device is inserted btusb will not be loaded and registering the 
> firmware load function with btusb was not possible.
> 
> Please advice alternate solution to load firmware from transport driver.

my advise would be to just build devices that change their USB VID/PID
after the firmware got loaded. That way it is easy to have a firmware
loading driver and just btusb for real operation. Why is it so hard to
build just simple hardware that would just work.

Regards

Marcel



^ permalink raw reply

* RE: [RFC] Bluetooth: Add firmware load infrastructure for BT devices
From: Shanmugamkamatchi Balashanmugam @ 2010-07-08 12:25 UTC (permalink / raw)
  To: Perelet, Oleg, Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <BCDE476F204B134B8B235FB275BC3AD80FC355337C@NALASEXMB01.na.qualcomm.com>



-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Perelet, Oleg
Sent: Wednesday, July 07, 2010 2:00 AM
To: Marcel Holtmann; Shanmugamkamatchi Balashanmugam
Cc: linux-bluetooth@vger.kernel.org
Subject: RE: [RFC] Bluetooth: Add firmware load infrastructure for BT devices

>> Added support to load firmware to target RAM from Bluetooth USB transport
>> driver. 

>we have discussed this a long time ago and the better approach would be
>to create a setup stage for all HCI drivers. For example for special HCI
>commands to set BD_ADDR and other details. Maybe also a firmware loading
>stage should be used. Making this USB specific sounds pretty much wrong
>to me at this point. At least SDIO might have similar issues.

>>The current approach looks more hackish than actually nicely integrated.

>Thanks for bringing up old topic. We discussed this few years ago and >things been somehow stalled. Besides, USB, SDIO there's UART which is used >in a lot of embedded platforms and everybody hacks custom code around.

>Overall Marcel suggests to have intermediate stage between DOWN and UP >states for hci device aka - SETUP (call it any name).


>Here are low level BT setup states that I "think" are common for majority >of embedded implementations:

>1. low level GPIO, CLC etc setup - can not talk to chip before that.

>2. Initial firmware/patch download - at this state one can talk HCI to >chip, but chip is barely functional, firmware, patches etc are downloaded >at this stage.

>3. "Run time config download" (often combined with #2, but I suggest to >separate) this is when BDADDR is programmed and chip run time parameters >for given platform are set up. For majority of chips this stage also >defines Sleep algorithm to be used. There are few ways of doing BT sleep - >HCI, UART signaling or usage of extra WAKE GPIO's to determine sleep >condition. Most of them require initial HCI setup.

>4. Enable Sleep and low power mode. Currently everybody hardcodes this >step, some platforms have programmatic ifaces (aka sysfs)

>5. WiFI coex setup if needed.

>Feel free to add more here ....

>At this stage hci can be brought to UP stage and be functional.


>All of that is tight with RFKILL of course and also suspend/resume entries >in transport driver. I'm also not doing in to details of sleep mode >implementation in this thread but welcome to discuss it in separate thread.

>Oleg.

Thanks for the comments.
Firmware loading to target RAM needs to be done once when the device is inserted.  Firmware loading will not be required every time 
the device goes from DOWN to UP. I think each HCI driver requires
a separate firmware loading code as firmware loading is 
different for different interfaces.  Please advice if my understanding is wrong.

I initially thought of registration 
mechanism with btusb transport driver to load firmware, but before
the device is inserted btusb will not be loaded and registering the 
firmware load function with btusb was not possible.

Please advice alternate solution to load firmware from transport driver.

Regards,
Bala.

^ permalink raw reply

* RE: bluetooth data rate vs VDP
From: Viral Mehta @ 2010-07-08 11:49 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <AANLkTikuMXwdV8gZegBN_fzY0NzVZcL6GZ7tcM61mWcl@mail.gmail.com>

Hi,
Thanks for the reply
>From: Luiz Augusto von Dentz [luiz.dentz@gmail.com]
>On Thu, Jul 8, 2010 at 9:04 AM, Viral Mehta <Viral.Mehta@lntinfotech.com> wrote:

>> Then how can a profile like "Video Distribution Profile" work at such a low speed. If I am not wrong VDP is used for streaming of Video, how can >Video streaming be achieved at such a lower data rate ?

>For low/webcam quality is more than enough I guess, if you think about
>it is not that different from using a phone such as N900/iphone and do
>a video call over 3G , so I don't see any problem in doing it over
>bluetooth, just use the same codec and you will going to get about the
>same thing. Also the think with vdp is that if the device supports the
>same codec as used in the video call you can pretty much sent it as it
>is, no additional encoding/decoding.

I want to send RAW video data. For e.g., read from /dev/fb0 and stream it...
Is it possible at the first hand? (I guess, in theory, yes)
I also had a question whether encoding/decoding is done by VDP profile
or I have to write some application on top of VDP profile. ??

>> Is there something like data rate can be increased with VDP like profile ?

>Yes, bluetooth 3.0.

--
Luiz Augusto von Dentz
Computer Engineer

______________________________________________________________________

This Email may contain confidential or privileged information for the intended recipient (s) If you are not the intended recipient, please do not use or disseminate the information, notify the sender and delete it from your system.

______________________________________________________________________

^ permalink raw reply

* RE: [PATCH] Added empty VCARD N: parameter handling
From: ext-jablonski.radoslaw @ 2010-07-08 11:48 UTC (permalink / raw)
  To: marcel; +Cc: linux-bluetooth
In-Reply-To: <1278534304.10421.9.camel@localhost.localdomain>

Hi!
I've realized that previous solution was little conflicted with PBAP spec:)
Now I've found real source of the problem with generating VCARDS( for empty=
 N: parameter no unnecessary characters should be inserted - and in current=
 code there was 4 semicolons in that place)
For BH-903 it works great - now I need to make some testing with various ca=
rkits.=20
If everything will work as expected then final patch will be available tomm=
orow morning.

BR,
Radek
________________________________________
From: ext Marcel Holtmann [marcel@holtmann.org]
Sent: Wednesday, July 07, 2010 11:25 PM
To: Radoslaw Jablonski (EXT-Comarch/Helsinki)
Cc: linux-bluetooth@vger.kernel.org
Subject: RE: [PATCH] Added empty VCARD N: parameter handling

Hi,

> I've made necessary changes to the code. Now it should look much better:)
> New version of patch is inserted below.

and please use git send-email. Otherwise we can't apply it with git am.

> From 45dfcf8f9dfacd8937a1a1d14146bd0da04eca25 Mon Sep 17 00:00:00 2001
> From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
> Date: Wed, 7 Jul 2010 17:18:31 +0300
> Subject: [PATCH] Added empty VCARD N: parameter handling
>
> Some of the devices are expecting that N: parameter in VCARD is always fi=
lled (by example Nokia BH-903)
> When this field is empty (N:;;;;) then list of dialed/incoming calls on c=
arkit is useless - carkit then shows only blank lines and it's impossible t=
o determine who made call ( phone number are invisible too in this case)
>
> If none of the contact fields is available, then setting telephone number=
 as the first attribute for "N:" parameter.
> Carkit will see that number as contact name - it is only used in case whe=
n none of more detailed contact information is available on the phone.
> ---
>  plugins/vcard.c |   21 +++++++++++++++++++++
>  1 files changed, 21 insertions(+), 0 deletions(-)
>
> diff --git a/plugins/vcard.c b/plugins/vcard.c
> index 5948a4a..ab1349c 100644
> --- a/plugins/vcard.c
> +++ b/plugins/vcard.c
> @@ -123,6 +123,20 @@ static void add_slash(char *dest, const char *src, i=
nt len_max, int len)
>       return;
>  }
>
> +/* checks if there is at least one present contact field with personal d=
ata */
> +static gboolean contact_fields_present( struct phonebook_contact * conta=
ct)
> +{

It is (struct ... contact *contact). See other code for proper placement
of whitespaces.

> +     if ((contact->family && strlen(contact->family)) ||
> +                     (contact->given && strlen(contact->given)) ||
> +                     (contact->additional && strlen(contact->additional)=
) ||
> +                     (contact->prefix && strlen(contact->prefix)) ||
> +                     (contact->suffix && strlen(contact->suffix)))
> +             return TRUE;
> +
> +     /* none of the personal data fields is present*/
> +     return FALSE;
> +}

        if (contact->family && strlen(contact->family) > 0)
                return TRUE;

        if (contact->given && strlen(contact->given) > 0)
                return TRUE;

        ...

        return FALSE;

That is a more readable version of this function.

> +
>  static void vcard_printf_begin(GString *vcards, uint8_t format)
>  {
>       vcard_printf(vcards, "BEGIN:VCARD");
> @@ -136,6 +150,13 @@ static void vcard_printf_begin(GString *vcards, uint=
8_t format)
>  static void vcard_printf_name(GString *vcards,
>                                       struct phonebook_contact *contact)
>  {
> +     if (contact_fields_present(contact) =3D=3D FALSE) {
> +             /* if all fields are empty we're using first phone number a=
s name */
> +             struct phonebook_number *number =3D contact->numbers->data;
> +             vcard_printf(vcards, "N:%s;;;;", number->tel);
> +             return;
> +     }
> +
>       vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
>                               contact->given, contact->additional,
>                               contact->prefix, contact->suffix);

Regards

Marcel=

^ permalink raw reply

* Re: [PATCH 3/3] Extended support for generating dictionary value of service UUIDs
From: Luiz Augusto von Dentz @ 2010-07-08 11:36 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, johan.hedberg, marcel, rshaffer
In-Reply-To: <1278540518-18620-4-git-send-email-ingas@codeaurora.org>

Hi,

On Thu, Jul 8, 2010 at 1:08 AM, Inga Stotland <ingas@codeaurora.org> wrote:
> ---
> =A0src/adapter.c =A0| =A0103 ++++++++++++++++++++++++++++++++++++++++++++=
+++++++++--
> =A0src/adapter.h =A0| =A0 =A04 +-
> =A0src/dbus-hci.c | =A0 =A07 ++--
> =A0src/sdpd.h =A0 =A0 | =A0 =A02 +
> =A04 files changed, 107 insertions(+), 9 deletions(-)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 8a05356..9be12e7 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -2716,6 +2716,7 @@ static void append_dict_valist(DBusMessageIter *ite=
r,
> =A0 =A0 =A0 =A0DBusMessageIter dict;
> =A0 =A0 =A0 =A0const char *key;
> =A0 =A0 =A0 =A0int type;
> + =A0 =A0 =A0 int n_elements;
> =A0 =A0 =A0 =A0void *val;
>
> =A0 =A0 =A0 =A0dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
> @@ -2727,7 +2728,12 @@ static void append_dict_valist(DBusMessageIter *it=
er,
> =A0 =A0 =A0 =A0while (key) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0type =3D va_arg(var_args, int);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0val =3D va_arg(var_args, void *);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dict_append_entry(&dict, key, type, val);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (type =3D=3D DBUS_TYPE_ARRAY) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 n_elements =3D va_arg(var_a=
rgs, int);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (n_elements > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dict_append=
_array(&dict, key, DBUS_TYPE_STRING, val, n_elements);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dict_append_entry(&dict, ke=
y, type, val);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0key =3D va_arg(var_args, char *);
> =A0 =A0 =A0 =A0}

Maybe you should separate this from the rest since they will probably
be more use of arrays in dictionaries in the future.

--=20
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: bluetooth data rate vs VDP
From: Luiz Augusto von Dentz @ 2010-07-08 11:29 UTC (permalink / raw)
  To: Viral Mehta; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <70376CA23424B34D86F1C7DE6B997343068C875F67@VSHINMSMBX01.vshodc.lntinfotech.com>

Hi,

On Thu, Jul 8, 2010 at 9:04 AM, Viral Mehta <Viral.Mehta@lntinfotech.com> wrote:
> Hi,
> I am new to bluetooth and sorry if posting at a wrong place.
>
> I have a very basic question,
> As I read through documents, Bluetooth 2 can support max data rate of 2Mbps or upto 3Mbps.

If you mean EDR, yes it is up to 3Mbps, but with Bluetooth 3.0 you can
much higher data rate.

> Then how can a profile like "Video Distribution Profile" work at such a low speed. If I am not wrong VDP is used for streaming of Video, how can Video streaming be achieved at such a lower data rate ?

For low/webcam quality is more than enough I guess, if you think about
it is not that different from using a phone such as N900/iphone and do
a video call over 3G , so I don't see any problem in doing it over
bluetooth, just use the same codec and you will going to get about the
same thing. Also the think with vdp is that if the device supports the
same codec as used in the video call you can pretty much sent it as it
is, no additional encoding/decoding.

> Is there something like data rate can be increased with VDP like profile ?

Yes, bluetooth 3.0.

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* [PATCHv2] Bluetooth: Check l2cap pending status before sending l2cap connect request
From: Emeltchenko Andrei @ 2010-07-08  9:14 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

Due to race condition in L2CAP state machine L2CAP Connection Request
may be sent twice for SDP with the same source channel id. Problems
reported connecting to Apple products, some carkit, Blackberry phones.

...
2010-06-07 21:18:03.651031 < ACL data: handle 1 flags 0x02 dlen 12
    L2CAP(s): Connect req: psm 1 scid 0x0040
2010-06-07 21:18:03.653473 > HCI Event: Number of Completed Packets (0x13) plen 5
    handle 1 packets 1
2010-06-07 21:18:03.653808 > HCI Event: Auth Complete (0x06) plen 3
    status 0x00 handle 1
2010-06-07 21:18:03.653869 < ACL data: handle 1 flags 0x02 dlen 12
    L2CAP(s): Connect req: psm 1 scid 0x0040
...

Patch uses L2CAP_CONF_CONNECT_PEND flag to mark that L2CAP Connection
Request has been sent already.

Modified version of Ville Tervo patch.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
---
 net/bluetooth/l2cap.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index bb00015..18c3702 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -401,6 +401,11 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
 	l2cap_send_sframe(pi, control);
 }
 
+static inline int __l2cap_no_conn_pending(struct sock *sk)
+{
+	return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+}
+
 static void l2cap_do_start(struct sock *sk)
 {
 	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -409,12 +414,13 @@ static void l2cap_do_start(struct sock *sk)
 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
 			return;
 
-		if (l2cap_check_security(sk)) {
+		if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
 			struct l2cap_conn_req req;
 			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
 			req.psm  = l2cap_pi(sk)->psm;
 
 			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
 			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
 					L2CAP_CONN_REQ, sizeof(req), &req);
@@ -464,12 +470,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 		}
 
 		if (sk->sk_state == BT_CONNECT) {
-			if (l2cap_check_security(sk)) {
+			if (l2cap_check_security(sk) &&
+					__l2cap_no_conn_pending(sk)) {
 				struct l2cap_conn_req req;
 				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
 				req.psm  = l2cap_pi(sk)->psm;
 
 				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
 				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
 					L2CAP_CONN_REQ, sizeof(req), &req);
@@ -2914,7 +2922,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		l2cap_pi(sk)->ident = 0;
 		l2cap_pi(sk)->dcid = dcid;
 		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-
 		l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
 
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
@@ -4406,6 +4413,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 				req.psm  = l2cap_pi(sk)->psm;
 
 				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
 				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
 					L2CAP_CONN_REQ, sizeof(req), &req);
-- 
1.7.0.4


^ permalink raw reply related

* bluetooth data rate vs VDP
From: Viral Mehta @ 2010-07-08  6:04 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi,
I am new to bluetooth and sorry if posting at a wrong place.

I have a very basic question,
As I read through documents, Bluetooth 2 can support max data rate of 2Mbps or upto 3Mbps.

Then how can a profile like "Video Distribution Profile" work at such a low speed. If I am not wrong VDP is used for streaming of Video, how can Video streaming be achieved at such a lower data rate ?
Is there something like data rate can be increased with VDP like profile ?

Thanks,

This Email may contain confidential or privileged information for the intended recipient (s) If you are not the intended recipient, please do not use or disseminate the information, notify the sender and delete it from your system.

______________________________________________________________________

^ permalink raw reply

* Re: Next BlueZ developer meeting
From: Marcel Holtmann @ 2010-07-08  2:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1278379702.2789.27.camel@localhost.localdomain>

Hello once more,

> > our next BlueZ developer meeting will be held as mini-summit as part of
> > the LinuxCon in Boston.
> > 
> > 	http://events.linuxfoundation.org/events/linuxcon/mini-summits
> > 
> > I like to invite interested developers to join us in Boston. The summit
> > will be held on Sunday, 8th and Monday, 9th of July.
> 
> I obviously meant 8th and 9th of August. Sorry for the confusion.

I just got reminded that the registration fee for LinuxCon increases on
July, 15th. So if you already know that you are attending you might
wanna register sooner than later. The link is here:

http://events.linuxfoundation.org/component/registrationpro/?func=details&did=27

Regards

Marcel



^ permalink raw reply

* [PATCH 3/3] Extended support for generating dictionary value of service UUIDs
From: Inga Stotland @ 2010-07-07 22:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: johan.hedberg, marcel, rshaffer, Inga Stotland
In-Reply-To: <1278540518-18620-1-git-send-email-ingas@codeaurora.org>

---
 src/adapter.c  |  103 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/adapter.h  |    4 +-
 src/dbus-hci.c |    7 ++--
 src/sdpd.h     |    2 +
 4 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8a05356..9be12e7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2716,6 +2716,7 @@ static void append_dict_valist(DBusMessageIter *iter,
 	DBusMessageIter dict;
 	const char *key;
 	int type;
+	int n_elements;
 	void *val;
 
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
@@ -2727,7 +2728,12 @@ static void append_dict_valist(DBusMessageIter *iter,
 	while (key) {
 		type = va_arg(var_args, int);
 		val = va_arg(var_args, void *);
-		dict_append_entry(&dict, key, type, val);
+		if (type == DBUS_TYPE_ARRAY) {
+			n_elements = va_arg(var_args, int);
+			if (n_elements > 0)
+				dict_append_array(&dict, key, DBUS_TYPE_STRING, val, n_elements);
+		} else
+			dict_append_entry(&dict, key, type, val);
 		key = va_arg(var_args, char *);
 	}
 
@@ -2758,8 +2764,84 @@ static void emit_device_found(const char *path, const char *address,
 	g_dbus_send_message(connection, signal);
 }
 
+static int get_uuid_count_eir (uint8_t *eir_data)
+{
+	uint8_t len = 0;
+	int count = 0;
+
+	while (len < EIR_DATA_LENGTH) {
+		uint8_t type = eir_data[1];
+		uint8_t field_len = eir_data[0];
+		if ((type == EIR_UUID16_SOME) || (type == EIR_UUID16_ALL))
+			count += field_len/2;
+		else if ((type == EIR_UUID32_SOME) || (type == EIR_UUID32_ALL))
+			count += field_len/4;
+		else if ((type == EIR_UUID128_SOME) || (type == EIR_UUID128_ALL))
+			count += field_len/16;
+		len += field_len + 1;
+		eir_data += field_len + 1;
+	}
+
+	return count;
+}
+
+static void get_uuids_eir(char **uuids, uint8_t *eir_data)
+{
+	uint8_t len = 0;
+
+	/* Count UUID16, UUID32 and UUID128 */
+	while (len < EIR_DATA_LENGTH) {
+		uint8_t field_len = eir_data[0];
+		uint8_t type = eir_data[1];
+		int count;
+		uuid_t service;
+		int size;
+		uint8_t *data = &eir_data[2];
+		int i, k;
+
+		/* Generate uuids in SDP format (EIR data is Little Endian) */
+		if ((type == EIR_UUID16_SOME) || (type == EIR_UUID16_ALL)) {
+			size = 2;
+			count = field_len/size;
+			service.type = SDP_UUID16;
+			for (i = 0; i < count; i++) {
+				uint16_t val16 = data[1];
+				val16 = (val16<<8) + data[0];
+				service.value.uuid16 = val16;
+				*uuids++ = bt_uuid2string(&service);
+				data += size;
+			}
+		} else if ((type == EIR_UUID32_SOME) || (type == EIR_UUID32_ALL)) {
+			size = 4;
+			count = field_len/size;
+			service.type = SDP_UUID32;
+			for (i = 0; i < count; i++) {
+				uint32_t val32 = data[3];
+				for (k = size-2; k >= 0; k--)
+					val32 = (val32<<8) + data[k];
+				service.value.uuid32 = val32;
+				*uuids++ = bt_uuid2string(&service);
+				data += size;
+			}
+		} else if ((type == EIR_UUID128_SOME) || (type == EIR_UUID128_ALL)) {
+			size = 16;
+			count = field_len/size;
+			service.type = SDP_UUID128;
+			for (i = 0; i < count; i++) {
+				for (k = 0; k < size; k++)
+					service.value.uuid128.data[k] = data[size-k-1];
+				*uuids++ = bt_uuid2string(&service);
+				data += size;
+			}
+		}
+
+		len += field_len + 1;
+		eir_data += field_len + 1;
+	}
+}
+
 void adapter_emit_device_found(struct btd_adapter *adapter,
-				struct remote_dev_info *dev)
+				struct remote_dev_info *dev, uint8_t *eir_data)
 {
 	struct btd_device *device;
 	char peer_addr[18], local_addr[18];
@@ -2767,6 +2849,8 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 	dbus_bool_t paired = FALSE;
 	dbus_int16_t rssi = dev->rssi;
 	char *alias;
+	char **uuids = NULL;
+	int uuid_count = 0;
 
 	ba2str(&dev->bdaddr, peer_addr);
 	ba2str(&adapter->bdaddr, local_addr);
@@ -2786,6 +2870,15 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 	} else
 		alias = g_strdup(dev->alias);
 
+	/* Extract UUIDs from extended inquiry response if any*/
+	if (eir_data != NULL)
+		uuid_count = get_uuid_count_eir(eir_data);
+
+	if (uuid_count > 0) {
+		uuids = g_new0(char *, uuid_count + 1);
+		get_uuids_eir(uuids, eir_data);
+	}
+
 	emit_device_found(adapter->path, paddr,
 			"Address", DBUS_TYPE_STRING, &paddr,
 			"Class", DBUS_TYPE_UINT32, &dev->class,
@@ -2795,15 +2888,17 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
 			"Alias", DBUS_TYPE_STRING, &alias,
 			"LegacyPairing", DBUS_TYPE_BOOLEAN, &dev->legacy,
 			"Paired", DBUS_TYPE_BOOLEAN, &paired,
+			"UUIDs", DBUS_TYPE_ARRAY, &uuids, uuid_count,
 			NULL);
 
 	g_free(alias);
+	g_strfreev(uuids);
 }
 
 void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				int8_t rssi, uint32_t class, const char *name,
 				const char *alias, gboolean legacy,
-				name_status_t name_status)
+				name_status_t name_status, uint8_t *eir_data)
 {
 	struct remote_dev_info *dev, match;
 
@@ -2842,7 +2937,7 @@ done:
 	adapter->found_devices = g_slist_sort(adapter->found_devices,
 						(GCompareFunc) dev_rssi_cmp);
 
-	adapter_emit_device_found(adapter, dev);
+	adapter_emit_device_found(adapter, dev, eir_data);
 }
 
 int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr)
diff --git a/src/adapter.h b/src/adapter.h
index 4c3bc04..7726eca 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -114,10 +114,10 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
 void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				int8_t rssi, uint32_t class, const char *name,
 				const char *alias, gboolean legacy,
-				name_status_t name_status);
+								  name_status_t name_status, uint8_t *eir_data);
 int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr);
 void adapter_emit_device_found(struct btd_adapter *adapter,
-				struct remote_dev_info *dev);
+				struct remote_dev_info *dev, uint8_t *eir_data);
 void adapter_update_oor_devices(struct btd_adapter *adapter);
 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
 void adapter_setname_complete(bdaddr_t *local, uint8_t status);
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index b83506f..912af02 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -515,7 +516,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
 	if (dev) {
 		adapter_update_found_devices(adapter, peer, rssi, class,
 						NULL, NULL, dev->legacy,
-						NAME_NOT_REQUIRED);
+						NAME_NOT_REQUIRED, data);
 		return;
 	}
 
@@ -566,7 +567,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
 
 	/* add in the list to track name sent/pending */
 	adapter_update_found_devices(adapter, peer, rssi, class, name, alias,
-					legacy, name_status);
+					legacy, name_status, data);
 
 	g_free(name);
 	g_free(alias);
@@ -642,7 +643,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status,
 	if (dev_info) {
 		g_free(dev_info->name);
 		dev_info->name = g_strdup(name);
-		adapter_emit_device_found(adapter, dev_info);
+		adapter_emit_device_found(adapter, dev_info, NULL);
 	}
 
 	if (device)
diff --git a/src/sdpd.h b/src/sdpd.h
index 8fd8bbe..38677d3 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -39,6 +39,8 @@
 
 #define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
 #define EIR_UUID16_ALL              0x03  /* 16-bit UUID, all listed */
+#define EIR_UUID32_SOME             0x04  /* 32-bit UUID, more available */
+#define EIR_UUID32_ALL              0x05  /* 32-bit UUID, all listed */
 #define EIR_UUID128_SOME            0x06  /* 128-bit UUID, more available */
 #define EIR_UUID128_ALL             0x07  /* 128-bit UUID, all listed */
 #define EIR_NAME_SHORT              0x08  /* shortened local name */
-- 
1.7.1

-- 
Inga Stotland
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH 2/3] Update EIR whenever record is added or removed
From: Inga Stotland @ 2010-07-07 22:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: johan.hedberg, marcel, rshaffer, Inga Stotland
In-Reply-To: <1278540518-18620-1-git-send-email-ingas@codeaurora.org>

---
 plugins/service.c |   19 +++++++++++++++++++
 src/adapter.c     |   24 +++++++++++++++++++++++-
 src/adapter.h     |    2 ++
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/plugins/service.c b/plugins/service.c
index 96280bd..8ec4df4 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -445,6 +446,8 @@ static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
 				strerror(EIO));
 	}
 
+	adapter_update_ext_inquiry_response(&src);
+
 	return dbus_message_new_method_return(msg);
 }
 
@@ -516,6 +519,7 @@ static DBusMessage *add_service_record(DBusConnection *conn,
 	const char *sender, *record;
 	dbus_uint32_t handle;
 	int err;
+	bdaddr_t addr;
 
 	if (dbus_message_get_args(msg, NULL,
 			DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)
@@ -526,6 +530,13 @@ static DBusMessage *add_service_record(DBusConnection *conn,
 	if (err < 0)
 		return failed_strerror(msg, err);
 
+	if (serv_adapter->adapter)
+		adapter_get_address(serv_adapter->adapter, &addr);
+	else
+		bacpy(&addr, BDADDR_ANY);
+
+	adapter_update_ext_inquiry_response(&addr);
+
 	reply = dbus_message_new_method_return(msg);
 	if (!reply)
 		return NULL;
@@ -550,6 +561,7 @@ static DBusMessage *remove_service_record(DBusConnection *conn,
 	struct service_adapter *serv_adapter = data;
 	dbus_uint32_t handle;
 	const char *sender;
+	bdaddr_t addr;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
 						DBUS_TYPE_INVALID) == FALSE)
@@ -560,6 +572,13 @@ static DBusMessage *remove_service_record(DBusConnection *conn,
 	if (remove_record(conn, sender, serv_adapter, handle) < 0)
 		return not_available(msg);
 
+	if (serv_adapter->adapter)
+		adapter_get_address(serv_adapter->adapter, &addr);
+	else
+		bacpy(&addr, BDADDR_ANY);
+
+	adapter_update_ext_inquiry_response(&addr);
+
 	return dbus_message_new_method_return(msg);
 }
 
diff --git a/src/adapter.c b/src/adapter.c
index 2a6ac18..8a05356 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -820,7 +821,7 @@ static DBusMessage *set_pairable_timeout(DBusConnection *conn,
 
 static void update_ext_inquiry_response(struct btd_adapter *adapter)
 {
-	uint8_t fec = 0, data[240];
+	uint8_t fec = 0, data[EIR_DATA_LENGTH];
 	struct hci_dev *dev = &adapter->dev;
 	int dd;
 
@@ -846,6 +847,27 @@ static void update_ext_inquiry_response(struct btd_adapter *adapter)
 	hci_close_dev(dd);
 }
 
+void adapter_update_ext_inquiry_response(const bdaddr_t *src)
+{
+	struct btd_adapter *adapter;
+	GSList *adapters;
+
+	if (bacmp(src, BDADDR_ANY) != 0) {
+		adapter = manager_find_adapter(src);
+		if (adapter)
+			update_ext_inquiry_response(adapter);
+		else
+			error("Updating EIR failed: device not found");
+	} else {
+
+		/* Update extended inquiry reponse for ANY adapter */
+		for (adapters = manager_get_adapters(); adapters; adapters = adapters->next) {
+			adapter = adapters->data;
+			update_ext_inquiry_response(adapter);
+		}
+	}
+}
+
 void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status)
 {
 	uint8_t class[3];
diff --git a/src/adapter.h b/src/adapter.h
index 71d3387..4c3bc04 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -126,6 +127,7 @@ void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
 void adapter_service_remove(const bdaddr_t *bdaddr, void *rec);
 sdp_list_t *adapter_get_services(struct btd_adapter *adapter);
 void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
+void adapter_update_ext_inquiry_response(const bdaddr_t *src);
 
 struct agent *adapter_get_agent(struct btd_adapter *adapter);
 void adapter_add_connection(struct btd_adapter *adapter,
-- 
1.7.1

-- 
Inga Stotland
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH 1/3] Support for adding UUID128 to extended inquiry response
From: Inga Stotland @ 2010-07-07 22:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: johan.hedberg, marcel, rshaffer, Inga Stotland
In-Reply-To: <1278540518-18620-1-git-send-email-ingas@codeaurora.org>

---
 src/sdpd-service.c |  108 ++++++++++++++++++++++++++++++++++++++++++++--------
 src/sdpd.h         |   12 ++++++
 2 files changed, 104 insertions(+), 16 deletions(-)

diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index cdbb4f4..1bb79a7 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -6,6 +6,7 @@
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -49,6 +50,8 @@
 #include "manager.h"
 #include "adapter.h"
 
+#define SIZEOF_UUID128 16
+
 static sdp_record_t *server = NULL;
 
 static uint16_t did_vendor = 0x0000;
@@ -174,41 +177,102 @@ static void update_svclass_list(const bdaddr_t *src)
 
 }
 
+static void eir_generate_uuid128(sdp_list_t *list, uint8_t *ptr, uint16_t *eir_len)
+{
+	int i, k, index = 0;
+	uint16_t len = *eir_len;
+	uint8_t *uuid128;
+	gboolean truncated = FALSE;
+
+	/* Store UUID128 in place, skip 2 bytes to insert type and length later */
+	uuid128 = ptr + 2;
+
+	for (; list; list = list->next) {
+		sdp_record_t *rec = (sdp_record_t *) list->data;
+
+		if (rec->svclass.type != SDP_UUID128)
+			continue;
+
+		/* Stop if not enough space to put next UUID128 */
+		if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+			truncated = TRUE;
+			break;
+		}
+
+		/* Check for duplicates, EIR data is Little Endian */
+		for (i = 0; i < index; i++) {
+			for (k = 0; k < SIZEOF_UUID128; k++) {
+				if (uuid128[i*SIZEOF_UUID128 + k] !=
+					rec->svclass.value.uuid128.data[SIZEOF_UUID128 - k])
+					break;
+			}
+			if (k == SIZEOF_UUID128)
+				break;
+		}
+
+		if (i < index)
+			continue;
+
+		/* EIR data is Little Endian */
+		for (k = 0; k < SIZEOF_UUID128; k++)
+			uuid128[index*SIZEOF_UUID128 + k] =
+				rec->svclass.value.uuid128.data[SIZEOF_UUID128 - 1 - k];
+
+		len += SIZEOF_UUID128;
+		index++;
+	}
+
+	if (index > 0 || truncated) {
+		/* EIR Data length */
+		ptr[0] = (index * SIZEOF_UUID128) + 1;
+		/* EIR Data type */
+		ptr[1] = (truncated) ? EIR_UUID128_SOME : EIR_UUID128_ALL;
+		len += 2;
+		*eir_len = len;
+	}
+}
+
 void create_ext_inquiry_response(const char *name,
 					int8_t tx_power, sdp_list_t *services,
 					uint8_t *data)
 {
 	sdp_list_t *list = services;
 	uint8_t *ptr = data;
-	uint16_t uuid[24];
+	uint16_t eir_len = 0;
+	uint16_t uuid16[EIR_DATA_LENGTH/2];
 	int i, index = 0;
+	gboolean truncated = FALSE;
 
 	if (name) {
 		int len = strlen(name);
 
+		/* EIR Data type */
 		if (len > 48) {
 			len = 48;
-			ptr[1] = 0x08;
+			ptr[1] = EIR_NAME_SHORT;
 		} else
-			ptr[1] = 0x09;
+			ptr[1] = EIR_NAME_COMPLETE;
 
+		/* EIR Data length */
 		ptr[0] = len + 1;
 
 		memcpy(ptr + 2, name, len);
 
-		ptr += len + 2;
+		eir_len += (len + 2);
+		ptr += (len + 2);
 	}
 
 	if (tx_power != 0) {
 		*ptr++ = 2;
-		*ptr++ = 0x0a;
+		*ptr++ = EIR_TX_POWER;
 		*ptr++ = (uint8_t) tx_power;
+		eir_len += 3;
 	}
 
 	if (did_vendor != 0x0000) {
 		uint16_t source = 0x0002;
 		*ptr++ = 9;
-		*ptr++ = 0x10;
+		*ptr++ = EIR_DEVICE_ID;
 		*ptr++ = (source & 0x00ff);
 		*ptr++ = (source & 0xff00) >> 8;
 		*ptr++ = (did_vendor & 0x00ff);
@@ -217,10 +281,10 @@ void create_ext_inquiry_response(const char *name,
 		*ptr++ = (did_product & 0xff00) >> 8;
 		*ptr++ = (did_version & 0x00ff);
 		*ptr++ = (did_version & 0xff00) >> 8;
+		eir_len += 10;
 	}
 
-	ptr[1] = 0x03;
-
+	/* Group all UUID16 types */
 	for (; list; list = list->next) {
 		sdp_record_t *rec = (sdp_record_t *) list->data;
 
@@ -233,30 +297,42 @@ void create_ext_inquiry_response(const char *name,
 		if (rec->svclass.value.uuid16 == PNP_INFO_SVCLASS_ID)
 			continue;
 
-		if (index > 23) {
-			ptr[1] = 0x02;
+		/* Stop if not enough space to put next UUID16 */
+		if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+			truncated = TRUE;
 			break;
 		}
 
+		/* Check for duplicates */
 		for (i = 0; i < index; i++)
-			if (uuid[i] == rec->svclass.value.uuid16)
+			if (uuid16[i] == rec->svclass.value.uuid16)
 				break;
 
-		if (i == index - 1)
+		if (i < index)
 			continue;
 
-		uuid[index++] = rec->svclass.value.uuid16;
+		uuid16[index++] = rec->svclass.value.uuid16;
+		eir_len += sizeof(uint16_t);
 	}
 
 	if (index > 0) {
-		ptr[0] = (index * 2) + 1;
+		/* EIR Data length */
+		ptr[0] = (index * sizeof(uint16_t)) + 1;
+		/* EIR Data type */
+		ptr[1] = (truncated) ? EIR_UUID16_SOME : EIR_UUID16_ALL;
+
 		ptr += 2;
+		eir_len += 2;
 
 		for (i = 0; i < index; i++) {
-			*ptr++ = (uuid[i] & 0x00ff);
-			*ptr++ = (uuid[i] & 0xff00) >> 8;
+			*ptr++ = (uuid16[i] & 0x00ff);
+			*ptr++ = (uuid16[i] & 0xff00) >> 8;
 		}
 	}
+
+	/* Group all UUID128 types */
+	if (eir_len <= EIR_DATA_LENGTH - 2)
+		eir_generate_uuid128(services, ptr, &eir_len);
 }
 
 void register_public_browse_group(void)
diff --git a/src/sdpd.h b/src/sdpd.h
index e93b0b6..8fd8bbe 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -6,6 +6,7 @@
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com>
+ *  Copyright (C) 2010, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -34,6 +35,17 @@
 #define SDPDBG(fmt...)
 #endif
 
+#define EIR_DATA_LENGTH  240
+
+#define EIR_UUID16_SOME             0x02  /* 16-bit UUID, more available */
+#define EIR_UUID16_ALL              0x03  /* 16-bit UUID, all listed */
+#define EIR_UUID128_SOME            0x06  /* 128-bit UUID, more available */
+#define EIR_UUID128_ALL             0x07  /* 128-bit UUID, all listed */
+#define EIR_NAME_SHORT              0x08  /* shortened local name */
+#define EIR_NAME_COMPLETE           0x09  /* complete local name */
+#define EIR_DEVICE_ID               0x10  /* device ID */
+#define EIR_TX_POWER                0x0A  /* Transmit power level */
+
 typedef struct request {
 	bdaddr_t device;
 	bdaddr_t bdaddr;
-- 
1.7.1

-- 
Inga Stotland
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH v2 0/3] Enhanced support for extended inquiry response
From: Inga Stotland @ 2010-07-07 22:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: johan.hedberg, marcel, rshaffer

EIR is updated whenever local SDP record database changes. 
Added support for UUID128 service descriptors in EIR to allow peek at available
services offered by a remote device without establishing SDP connection. 


-- 
Inga Stotland
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* RE: [PATCH] Added empty VCARD N: parameter handling
From: Marcel Holtmann @ 2010-07-07 20:25 UTC (permalink / raw)
  To: ext-jablonski.radoslaw; +Cc: linux-bluetooth
In-Reply-To: <090FE800A758CA439B2752C082AC3DEF037828C921@NOK-EUMSG-06.mgdnok.nokia.com>

Hi,

> I've made necessary changes to the code. Now it should look much better:)
> New version of patch is inserted below.

and please use git send-email. Otherwise we can't apply it with git am.

> From 45dfcf8f9dfacd8937a1a1d14146bd0da04eca25 Mon Sep 17 00:00:00 2001
> From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
> Date: Wed, 7 Jul 2010 17:18:31 +0300
> Subject: [PATCH] Added empty VCARD N: parameter handling
> 
> Some of the devices are expecting that N: parameter in VCARD is always filled (by example Nokia BH-903)
> When this field is empty (N:;;;;) then list of dialed/incoming calls on carkit is useless - carkit then shows only blank lines and it's impossible to determine who made call ( phone number are invisible too in this case)
> 
> If none of the contact fields is available, then setting telephone number as the first attribute for "N:" parameter.
> Carkit will see that number as contact name - it is only used in case when none of more detailed contact information is available on the phone.
> ---
>  plugins/vcard.c |   21 +++++++++++++++++++++
>  1 files changed, 21 insertions(+), 0 deletions(-)
> 
> diff --git a/plugins/vcard.c b/plugins/vcard.c
> index 5948a4a..ab1349c 100644
> --- a/plugins/vcard.c
> +++ b/plugins/vcard.c
> @@ -123,6 +123,20 @@ static void add_slash(char *dest, const char *src, int len_max, int len)
>  	return;
>  }
>  
> +/* checks if there is at least one present contact field with personal data */
> +static gboolean contact_fields_present( struct phonebook_contact * contact)
> +{

It is (struct ... contact *contact). See other code for proper placement
of whitespaces.

> +	if ((contact->family && strlen(contact->family)) ||
> +			(contact->given && strlen(contact->given)) ||
> +			(contact->additional && strlen(contact->additional)) ||
> +			(contact->prefix && strlen(contact->prefix)) ||
> +			(contact->suffix && strlen(contact->suffix)))
> +		return TRUE;
> +
> +	/* none of the personal data fields is present*/
> +	return FALSE;
> +}

	if (contact->family && strlen(contact->family) > 0)
		return TRUE;

	if (contact->given && strlen(contact->given) > 0)
		return TRUE;

	...

	return FALSE;

That is a more readable version of this function.

> +
>  static void vcard_printf_begin(GString *vcards, uint8_t format)
>  {
>  	vcard_printf(vcards, "BEGIN:VCARD");
> @@ -136,6 +150,13 @@ static void vcard_printf_begin(GString *vcards, uint8_t format)
>  static void vcard_printf_name(GString *vcards,
>  					struct phonebook_contact *contact)
>  {
> +	if (contact_fields_present(contact) == FALSE) {
> +		/* if all fields are empty we're using first phone number as name */
> +		struct phonebook_number *number = contact->numbers->data;
> +		vcard_printf(vcards, "N:%s;;;;", number->tel);
> +		return;
> +	}
> +
>  	vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
>  				contact->given, contact->additional,
>  				contact->prefix, contact->suffix);

Regards

Marcel



^ permalink raw reply

* RE: [PATCH] Added empty VCARD N: parameter handling
From: ext-jablonski.radoslaw @ 2010-07-07 14:20 UTC (permalink / raw)
  To: marcel; +Cc: linux-bluetooth
In-Reply-To: <1278508613.2789.114.camel@localhost.localdomain>

Hi!
I've made necessary changes to the code. Now it should look much better:)
New version of patch is inserted below.

>From 45dfcf8f9dfacd8937a1a1d14146bd0da04eca25 Mon Sep 17 00:00:00 2001
From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
Date: Wed, 7 Jul 2010 17:18:31 +0300
Subject: [PATCH] Added empty VCARD N: parameter handling

Some of the devices are expecting that N: parameter in VCARD is always fill=
ed (by example Nokia BH-903)
When this field is empty (N:;;;;) then list of dialed/incoming calls on car=
kit is useless - carkit then shows only blank lines and it's impossible to =
determine who made call ( phone number are invisible too in this case)

If none of the contact fields is available, then setting telephone number a=
s the first attribute for "N:" parameter.
Carkit will see that number as contact name - it is only used in case when =
none of more detailed contact information is available on the phone.
---
 plugins/vcard.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/plugins/vcard.c b/plugins/vcard.c
index 5948a4a..ab1349c 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -123,6 +123,20 @@ static void add_slash(char *dest, const char *src, int=
 len_max, int len)
 	return;
 }
=20
+/* checks if there is at least one present contact field with personal dat=
a */
+static gboolean contact_fields_present( struct phonebook_contact * contact=
)
+{
+	if ((contact->family && strlen(contact->family)) ||
+			(contact->given && strlen(contact->given)) ||
+			(contact->additional && strlen(contact->additional)) ||
+			(contact->prefix && strlen(contact->prefix)) ||
+			(contact->suffix && strlen(contact->suffix)))
+		return TRUE;
+
+	/* none of the personal data fields is present*/
+	return FALSE;
+}
+
 static void vcard_printf_begin(GString *vcards, uint8_t format)
 {
 	vcard_printf(vcards, "BEGIN:VCARD");
@@ -136,6 +150,13 @@ static void vcard_printf_begin(GString *vcards, uint8_=
t format)
 static void vcard_printf_name(GString *vcards,
 					struct phonebook_contact *contact)
 {
+	if (contact_fields_present(contact) =3D=3D FALSE) {
+		/* if all fields are empty we're using first phone number as name */
+		struct phonebook_number *number =3D contact->numbers->data;
+		vcard_printf(vcards, "N:%s;;;;", number->tel);
+		return;
+	}
+
 	vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
 				contact->given, contact->additional,
 				contact->prefix, contact->suffix);
--=20
1.6.0.4


BR,
Radek
________________________________________
From: ext Marcel Holtmann [marcel@holtmann.org]
Sent: Wednesday, July 07, 2010 4:16 PM
To: Radoslaw Jablonski (EXT-Comarch/Helsinki)
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH] Added empty VCARD N: parameter handling

Hi Radek,

using git send-email would be a bit better here. Then we have the
patches inline.

> From 6d88e3d7c1a5014e60ca8f53f7163e3a51148530 Mon Sep 17 00:00:00 2001
> From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
> Date: Wed, 7 Jul 2010 15:07:58 +0300
> Subject: [PATCH] Added empty N: parameter handling in VCARD
>
> Some of the devices are expecting that N: parameter in VCARD is always fi=
lled (by example Nokia BH-903)
> When this field is empty (N:;;;;) then list of dialed/incoming calls on c=
arkit is useless.
>
> If none of fields is available then setting telephone number as the first=
 attribute for "N:" parameter.
> Carkit will see that number as contact name - it is only used in case whe=
n none of more detailed contact information is available on phone.
> ---
>  plugins/vcard.c |   17 ++++++++++++++---
>  1 files changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/plugins/vcard.c b/plugins/vcard.c
> index 5948a4a..b2ab30a 100644
> --- a/plugins/vcard.c
> +++ b/plugins/vcard.c
> @@ -136,9 +136,20 @@ static void vcard_printf_begin(GString *vcards, uint=
8_t format)
>  static void vcard_printf_name(GString *vcards,
>                                         struct phonebook_contact *contact=
)
>  {
> -       vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
> -                               contact->given, contact->additional,
> -                               contact->prefix, contact->suffix);
> +       /* at least one of fields is present */
> +       if ((contact->family && strlen(contact->family)) ||
> +               (contact->given && strlen (contact->given)) ||
> +               (contact->additional && strlen(contact->additional)) ||
> +               (contact->prefix && strlen (contact->prefix)) ||
> +               (contact->suffix && strlen (contact->suffix)))
> +               vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
> +                                               contact->given, contact->=
additional,
> +                                               contact->prefix, contact-=
>suffix);

The extra if clauses require two level of indentation. Otherwise you
can't tell which is part of the if clause and which is code.

Also it is strlen(...). No extra space.

And I would prefer to split this into an extra function just doing this
test. This if clause is too big.

> +       else {
> +               /* if all fields are empty we're using  first phone numbe=
r as name */
> +               struct phonebook_number *number =3D contact->numbers->dat=
a;
> +               vcard_printf(vcards, "N:%s;;;;", number->tel);
> +       }
>  }

So I prefer the whole thing like this:

        /* if all fields are empty we're using  first phone number as name =
*/
        if (required_fields_present(contact) =3D=3D FALSE) {
                struct phonebook_number *number =3D contact->numbers->data;
                vcard_printf(vcards, "N:%s;;;;", number->tel);
                return;
        }

        vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
                ...

This way it is a lot easier to read and understand what is the special
case and what would be the default.

Regards

Marcel

^ permalink raw reply related

* Re: [PATCHv2] Bluetooth: Check l2cap pending status before sending l2cap connect request
From: Marcel Holtmann @ 2010-07-07 14:10 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth
In-Reply-To: <1278493543-25290-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

> Due to race condition in L2CAP state machine L2CAP Connection Request
> may be sent twice for SDP with the same source channel id. Problems
> reported connecting to Apple products, some carkit, Blackberry phones.
> 
> ...
> 2010-06-07 21:18:03.651031 < ACL data: handle 1 flags 0x02 dlen 12
>     L2CAP(s): Connect req: psm 1 scid 0x0040
> 2010-06-07 21:18:03.653473 > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 1 packets 1
> 2010-06-07 21:18:03.653808 > HCI Event: Auth Complete (0x06) plen 3
>     status 0x00 handle 1
> 2010-06-07 21:18:03.653869 < ACL data: handle 1 flags 0x02 dlen 12
>     L2CAP(s): Connect req: psm 1 scid 0x0040
> ...
> 
> Patch uses L2CAP_CONF_CONNECT_PEND flag to mark that L2CAP Connection
> Request has been sent already.
> 
> Modified version of Ville Tervo patch.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
>  net/bluetooth/l2cap.c |   14 +++++++++++---
>  1 files changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index bb00015..899cca5 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -401,6 +401,11 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
>  	l2cap_send_sframe(pi, control);
>  }
>  
> +static inline int l2cap_check_pending(struct sock *sk)
> +{
> +	return l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND;
> +}
> +

I changed my mind about the naming here. It was a bad proposal on my
side. So something like __no_connect_pend (positive check) as a define
is better.

>  static void l2cap_do_start(struct sock *sk)
>  {
>  	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
> @@ -409,12 +414,13 @@ static void l2cap_do_start(struct sock *sk)
>  		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
>  			return;
>  
> -		if (l2cap_check_security(sk)) {
> +		if (l2cap_check_security(sk) && !l2cap_check_pending(sk)) {
>  			struct l2cap_conn_req req;
>  			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
>  			req.psm  = l2cap_pi(sk)->psm;
>  
>  			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
> +			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
>  
>  			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
>  					L2CAP_CONN_REQ, sizeof(req), &req);
> @@ -464,12 +470,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
>  		}
>  
>  		if (sk->sk_state == BT_CONNECT) {
> -			if (l2cap_check_security(sk)) {
> +			if (l2cap_check_security(sk) &&
> +					!l2cap_check_pending(sk)) {
>  				struct l2cap_conn_req req;
>  				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
>  				req.psm  = l2cap_pi(sk)->psm;
>  
>  				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
> +				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
>  
>  				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
>  					L2CAP_CONN_REQ, sizeof(req), &req);
> @@ -2914,7 +2922,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
>  		l2cap_pi(sk)->ident = 0;
>  		l2cap_pi(sk)->dcid = dcid;
>  		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
> -
>  		l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
>  
>  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
> @@ -4406,6 +4413,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
>  				req.psm  = l2cap_pi(sk)->psm;
>  
>  				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
> +				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
>  
>  				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
>  					L2CAP_CONN_REQ, sizeof(req), &req);

Rest looks fine to me.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Added empty VCARD N: parameter handling
From: Marcel Holtmann @ 2010-07-07 13:16 UTC (permalink / raw)
  To: ext-jablonski.radoslaw; +Cc: linux-bluetooth
In-Reply-To: <090FE800A758CA439B2752C082AC3DEF037828C920@NOK-EUMSG-06.mgdnok.nokia.com>

Hi Radek,

using git send-email would be a bit better here. Then we have the
patches inline.

> From 6d88e3d7c1a5014e60ca8f53f7163e3a51148530 Mon Sep 17 00:00:00 2001
> From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
> Date: Wed, 7 Jul 2010 15:07:58 +0300
> Subject: [PATCH] Added empty N: parameter handling in VCARD
> 
> Some of the devices are expecting that N: parameter in VCARD is always filled (by example Nokia BH-903)
> When this field is empty (N:;;;;) then list of dialed/incoming calls on carkit is useless.
> 
> If none of fields is available then setting telephone number as the first attribute for "N:" parameter.
> Carkit will see that number as contact name - it is only used in case when none of more detailed contact information is available on phone.
> ---
>  plugins/vcard.c |   17 ++++++++++++++---
>  1 files changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/plugins/vcard.c b/plugins/vcard.c
> index 5948a4a..b2ab30a 100644
> --- a/plugins/vcard.c
> +++ b/plugins/vcard.c
> @@ -136,9 +136,20 @@ static void vcard_printf_begin(GString *vcards, uint8_t format)
>  static void vcard_printf_name(GString *vcards,
>                                         struct phonebook_contact *contact)
>  {
> -       vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
> -                               contact->given, contact->additional,
> -                               contact->prefix, contact->suffix);
> +       /* at least one of fields is present */
> +       if ((contact->family && strlen(contact->family)) ||
> +               (contact->given && strlen (contact->given)) ||
> +               (contact->additional && strlen(contact->additional)) ||
> +               (contact->prefix && strlen (contact->prefix)) ||
> +               (contact->suffix && strlen (contact->suffix)))
> +               vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
> +                                               contact->given, contact->additional,
> +                                               contact->prefix, contact->suffix);

The extra if clauses require two level of indentation. Otherwise you
can't tell which is part of the if clause and which is code.

Also it is strlen(...). No extra space.

And I would prefer to split this into an extra function just doing this
test. This if clause is too big.

> +       else {
> +               /* if all fields are empty we're using  first phone number as name */
> +               struct phonebook_number *number = contact->numbers->data;
> +               vcard_printf(vcards, "N:%s;;;;", number->tel);
> +       }
>  }

So I prefer the whole thing like this:

	/* if all fields are empty we're using  first phone number as name */
	if (required_fields_present(contact) == FALSE) {
		struct phonebook_number *number = contact->numbers->data;
		vcard_printf(vcards, "N:%s;;;;", number->tel);
		return;
	}

	vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
		...

This way it is a lot easier to read and understand what is the special
case and what would be the default.

Regards

Marcel



^ permalink raw reply

* [PATCH] Added empty VCARD N: parameter handling
From: ext-jablonski.radoslaw @ 2010-07-07 12:45 UTC (permalink / raw)
  To: linux-bluetooth

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

Some of the devices are expecting that N: parameter in VCARD is always filled (by example Nokia BH-903)
When this field is empty (N:;;;;) then list of dialed/incoming calls on carkit is useless - carkit then shows only blank lines and it's impossible to determine who made call ( phone number are invisible too in this case)
    
If none of the contact fields is available, then setting telephone number as the first attribute for "N:" parameter.
Carkit will see that number as contact name - it is only used in case when none of more detailed contact information is available on the phone.

BR,
Radek

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Added-empty-N-parameter-handling-in-VCARD.patch --]
[-- Type: text/x-patch; name="0001-Added-empty-N-parameter-handling-in-VCARD.patch", Size: 1946 bytes --]

From 6d88e3d7c1a5014e60ca8f53f7163e3a51148530 Mon Sep 17 00:00:00 2001
From: Radoslaw Jablonski <ext-jablonski.radoslaw@nokia.com>
Date: Wed, 7 Jul 2010 15:07:58 +0300
Subject: [PATCH] Added empty N: parameter handling in VCARD

Some of the devices are expecting that N: parameter in VCARD is always filled (by example Nokia BH-903)
When this field is empty (N:;;;;) then list of dialed/incoming calls on carkit is useless.

If none of fields is available then setting telephone number as the first attribute for "N:" parameter.
Carkit will see that number as contact name - it is only used in case when none of more detailed contact information is available on phone.
---
 plugins/vcard.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/plugins/vcard.c b/plugins/vcard.c
index 5948a4a..b2ab30a 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -136,9 +136,20 @@ static void vcard_printf_begin(GString *vcards, uint8_t format)
 static void vcard_printf_name(GString *vcards,
 					struct phonebook_contact *contact)
 {
-	vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
-				contact->given, contact->additional,
-				contact->prefix, contact->suffix);
+	/* at least one of fields is present */
+	if ((contact->family && strlen(contact->family)) ||
+		(contact->given && strlen (contact->given)) ||
+		(contact->additional && strlen(contact->additional)) ||
+		(contact->prefix && strlen (contact->prefix)) ||
+		(contact->suffix && strlen (contact->suffix)))
+		vcard_printf(vcards, "N:%s;%s;%s;%s;%s", contact->family,
+						contact->given, contact->additional,
+						contact->prefix, contact->suffix);
+	else {
+		/* if all fields are empty we're using  first phone number as name */
+		struct phonebook_number *number = contact->numbers->data;
+		vcard_printf(vcards, "N:%s;;;;", number->tel);
+	}
 }
 
 static void vcard_printf_fullname(GString *vcards, const char *text)
-- 
1.6.0.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox