* [PATCH] Fix not deleting stored keys when a new one is created
From: Luiz Augusto von Dentz @ 2010-08-05 13:58 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
When a new link key is created but it doesn't match any criteria to be
stored any previouly one should be removed from filesystem.
This can be reproduced by the following steps:
1. Pair devices normally so that a valid link key is stored
2. Remove link key on remote device
3. Attempt to do a rfcomm connection with security level higher than low
This can be triggered in some other ways but right now this is the
easiest since kernel will switch the authentication requirements in this
case, here is the hcidump output:
< HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
bdaddr xx:xx:xx:xx:xx:xx capability 0x01 oob 0x00 auth 0x00
Capability: DisplayYesNo (OOB data not present)
Authentication: No Bonding (No MITM Protection)
...
> HCI Event: Link Key Notification (0x18) plen 23
bdaddr xx:xx:xx:xx:xx:xx key 26D32FBEF7B7CBD7923CA391A2DE600F type 4
Type: Unauthenticated Combination Key
...
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
bdaddr xx:xx:xx:xx:xx:xx key 38E2BC10B26148FBC264E0DBA2535F1B
> HCI Event: Auth Complete (0x06) plen 3
status 0x05 handle 1
Error: Authentication Failure
Note that the reason this is reproducible with a single rfcomm connection
might be a bug in kernel, but there is clearly a problem in the daemon
too since link keys doesn't match.
So link keys information should be available while connected even in
cases where bonding is not required, to fix this everytime there is a new
link key the old one is clear, to make sure this actually work with those
keys that are not stored persistently all keys are cached in memory so
they are always accessible via device object as long the object exists,
this changes should also enable the code path bellow:
/* Don't use unauthenticated combination keys if MITM is
* required */
if (type == 0x04 && req.type != 0xff && (req.type & 0x01))
and follow the recommendation of the simple pairing white paper which
says:
"Bonding is defined as the connection process where the link key
and connection information are stored in non-volatile memory.
Thus bonding implies that the device’s link information is
available after the current connection ceases. If the link key
and current connection information are not stored, then the
connection process uses “Pairing”"
Devices which link key is not permanently stored are currently being
marked as temporary so their information will be lost once the connection
ceases.
---
src/dbus-hci.c | 23 +++++++++++------------
src/device.c | 31 ++++++++++++++++---------------
src/device.h | 5 +++--
src/security.c | 5 ++---
4 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index b83506f..c8b2ad6 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -674,11 +674,12 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return -ENODEV;
+ /* Check if there is a key cached in memory */
+ device_get_key(device, NULL, &old_key_type);
+
new_key_type = key_type;
if (key_type == 0x06) {
- if (device_get_debug_key(device, NULL))
- old_key_type = 0x03;
if (old_key_type != 0xff)
new_key_type = old_key_type;
else
@@ -697,12 +698,11 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
DBG("local auth 0x%02x and remote auth 0x%02x",
local_auth, remote_auth);
- /* Clear any previous debug key */
- device_set_debug_key(device, NULL);
+ /* Cache new link key */
+ device_set_key(device, key, new_key_type);
- /* Store the link key only in runtime memory if it's a debug
- * key, else store the link key persistently if one of the
- * following is true:
+ /* Link key are ALWAYS stored in runtime memory, they are also stored
+ * in filesystem persistently if one of the following is true:
* 1. this is a legacy link key
* 2. this is a changed combination key and there was a previously
* stored one
@@ -710,13 +710,12 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
* 4. the local side had dedicated bonding as a requirement
* 5. the remote side is using dedicated bonding since in that case
* also the local requirements are set to dedicated bonding
- * If none of the above match only keep the link key around for
+ * If none of the above match and only keep the link key around for
* this connection and set the temporary flag for the device.
*/
- if (new_key_type == 0x03) {
- DBG("Storing debug key in runtime memory");
- device_set_debug_key(device, key);
- } else if (key_type < 0x03 ||
+ if (new_key_type == 0x03)
+ temporary = FALSE;
+ else if (key_type < 0x03 ||
(key_type == 0x06 && old_key_type != 0xff) ||
(local_auth > 0x01 && remote_auth > 0x01) ||
(local_auth == 0x02 || local_auth == 0x03) ||
diff --git a/src/device.c b/src/device.c
index 6af76d1..059aec3 100644
--- a/src/device.c
+++ b/src/device.c
@@ -143,8 +143,8 @@ struct btd_device {
gboolean authorizing;
gint ref;
- gboolean has_debug_key;
- uint8_t debug_key[16];
+ uint8_t key[16];
+ uint8_t key_type;
};
static uint16_t uuid_list[] = {
@@ -1024,7 +1024,8 @@ struct btd_device *device_create(DBusConnection *conn,
device->auth = 0xff;
- if (read_link_key(&src, &device->bdaddr, NULL, NULL) == 0)
+ if (read_link_key(&src, &device->bdaddr, device->key,
+ &device->key_type) == 0)
device->paired = TRUE;
return btd_device_ref(device);
@@ -2399,26 +2400,26 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
return find_record_in_list(device->tmp_records, uuid);
}
-gboolean device_set_debug_key(struct btd_device *device, uint8_t *key)
+void device_set_key(struct btd_device *device, uint8_t *key, uint8_t type)
{
- if (key == NULL) {
- device->has_debug_key = FALSE;
- return TRUE;
- }
-
- memcpy(device->debug_key, key, 16);
- device->has_debug_key = TRUE;
+ /* Clear any previous key */
+ if (device->paired)
+ device_remove_bonding(device);
- return TRUE;
+ memcpy(device->key, key, 16);
+ device->key_type = type;
}
-gboolean device_get_debug_key(struct btd_device *device, uint8_t *key)
+gboolean device_get_key(struct btd_device *device, uint8_t *key, uint8_t *type)
{
- if (!device->has_debug_key)
+ if (!device->paired)
return FALSE;
if (key != NULL)
- memcpy(key, device->debug_key, 16);
+ memcpy(key, device->key, 16);
+
+ if (type != NULL)
+ *type = device->key_type;
return TRUE;
}
diff --git a/src/device.h b/src/device.h
index 5f75e61..229bc9e 100644
--- a/src/device.h
+++ b/src/device.h
@@ -79,8 +79,9 @@ gboolean device_is_authenticating(struct btd_device *device);
gboolean device_is_authorizing(struct btd_device *device);
void device_set_authorizing(struct btd_device *device, gboolean auth);
void device_set_renewed_key(struct btd_device *device, gboolean renewed);
-gboolean device_set_debug_key(struct btd_device *device, uint8_t *key);
-gboolean device_get_debug_key(struct btd_device *device, uint8_t *key);
+void device_set_key(struct btd_device *device, uint8_t *key, uint8_t type);
+gboolean device_get_key(struct btd_device *device, uint8_t *key,
+ uint8_t *type);
void device_add_connection(struct btd_device *device, DBusConnection *conn,
uint16_t handle);
void device_remove_connection(struct btd_device *device, DBusConnection *conn,
diff --git a/src/security.c b/src/security.c
index ca394e1..9d9e26f 100644
--- a/src/security.c
+++ b/src/security.c
@@ -329,9 +329,8 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
DBG("kernel auth requirements = 0x%02x", req.type);
- if (main_opts.debug_keys && device && device_get_debug_key(device, key))
- type = 0x03;
- else if (read_link_key(sba, dba, key, &type) < 0 || type == 0x03) {
+ if (device_get_key(device, key, &type) == FALSE ||
+ (type == 0x03 && main_opts.debug_keys == FALSE)) {
/* Link key not found */
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 6, dba);
return;
--
1.7.0.4
^ permalink raw reply related
* [PATCH] Changes in HDP API.
From: Jose Antonio Santos Cadenas @ 2010-08-05 13:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jose Antonio Santos Cadenas
In-Reply-To: <201008051129.38119.santoscadenas@gmail.com>
Now the connection is made directly to a device and bluetoothd daemon
guess the PSM connection and the MDEPID based on the data get from the
SDP record.
---
doc/health-api.txt | 105 ++++++++++++++++++++--------------------------------
1 files changed, 40 insertions(+), 65 deletions(-)
diff --git a/doc/health-api.txt b/doc/health-api.txt
index f469df3..89df8bd 100644
--- a/doc/health-api.txt
+++ b/doc/health-api.txt
@@ -14,12 +14,9 @@ Object path /org/bluez/
Methods:
- object CreateApplication(dict config, object agent)
+ object CreateApplication(dict config)
- Returns the path of the new registered application. The agent
- parameter is the path of the object with the callbacks to
- notify events (see org.bluez.HealthAgent at the end
- of this document).
+ Returns the path of the new registered application.
Dict is defined as bellow:
{
@@ -39,32 +36,33 @@ Methods:
Closes the HDP application identified by the object path. Also
application will be closed if the process that started it leaves
- the bus.
+ the bus. Only the creator of the application will be able to
+ destroy it.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.NotFound
+ org.bluez.Error.NotAllowed
--------------------------------------------------------------------------------
Service org.bluez
-Interface org.bluez.HealthApplication
-Object path [variable prefix]/health_app_ZZZZ
+Interface org.bluez.HealthDevice
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
Methods:
- void Echo(object service)
+ Boolean Echo()
Sends an echo petition to the remote service. Returns True if
response matches with the buffer sent. If some error is detected
- False value is returned and the associated MCL is closed.
+ False value is returned.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.OutOfRange
- object CreateChannel(object service, string type)
+ object CreateChannel(object application, string configuration)
- Creates a new data channel with the indicated config to the
- remote Service.
+ Creates a new data channel.
The configuration should indicate the channel quality of
service using one of this values "Reliable", "Streaming", "Any".
@@ -76,16 +74,27 @@ Methods:
void DestroyChannel(object channel)
- Destroys the data channel object.
+ Destroys the data channel object. Only the creator of the
+ channel or the creator of the HealtApplication that received the
+ data channel will be able to destroy it
Possible errors: org.bluez.Error.InvalidArguments
- orb.bluez.Error.NotFound
+ org.bluez.Error.NotFound
+ org.bluez.Error.NotAllowed
---------------------------------------------------------------------------------
+Signals:
-Service org.bluez
-Interface org.bluez.HealthService
-Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/hdp_YYYY
+ void ChannelConnected(object channel)
+
+ This signal is launched when a new data channel is created or
+ when a known data channel is reconnected.
+
+ void ChannelDeleted(object channel)
+
+ This signal is launched when a data channel is deleted.
+
+ After this signal the data channel path will not be valid and
+ its path can be reused for future data channels.
--------------------------------------------------------------------------------
@@ -94,6 +103,9 @@ Interface org.bluez.HealthChannel
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/
hdp_YYYY/channel_ZZ
+Only the process that created the data channel or the creator of the
+HealthApplication that received it will be able to call this methods.
+
Methods:
dict GetProperties()
@@ -101,17 +113,23 @@ Methods:
Returns all properties for the interface. See the properties
section for available properties.
+ Posible errors: org.bluez.Error.NotAllowed
+
fd Acquire()
Returns the file descriptor for this data channel. If the data
channel is not connected it will also reconnect.
Possible errors: org.bluez.Error.NotConnected
+ org.bluez.Error.NotAllowed
void Release()
Releases the fd. Application should also need to close() it.
+ Possible errors: org.bluez.Error.NotAcquired
+ org.bluez.Error.NotAllowed
+
Properties:
string Type (read only)
@@ -119,50 +137,7 @@ Properties:
The quality of service of the data channel. ("Reliable" or
"Streaming")
- object Service (read only)
-
- Identifies the Remote Service that is connected with. Maps with
- a HealthService object.
-
-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 Release()
-
- This method gets called when the service daemon unregisters the
- agent. An agent can use it to do cleanup tasks. There is no need
- to unregister the agent, because when this method gets called it
- has already been unregistered.
-
- void ServiceDiscovered(object service)
-
- This method is called when a device containing an HDP
- application is paired or when the method Update of the
- HealthManager is called and new HealthServices are discovered.
- The method will be called once for each HealthService.
-
- void ServiceRemoved(object service)
-
- This is called if during an Update some HealthServices
- have disappeared. The method is called once for each removed
- HealthService.
-
- void ChannelConnected(object channel)
-
- This method is called when a new data channel is created or when
- a known data channel is reconnected.
-
- void ChannelDeleted(object channel)
-
- This method is called when a data channel is deleted.
+ object Device (read only)
- After this call the data channel path will not be valid and can
- be reused for future creation of data channels.
+ Identifies the Remote Device that is connected with. Maps with
+ a HealthDevice object.
--
1.7.0.4
^ permalink raw reply related
* RE: L2cap Security And Role Switch
From: Waldemar.Rymarkiewicz @ 2010-08-05 12:54 UTC (permalink / raw)
To: mcprabhakaran; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikQMqvPQ8-Gv6CqSGgL0fv7ZV3ji4TQUvgkQFGe@mail.gmail.com>
Hi
>-----Original Message-----
>From: Prabhakaran M.C [mailto:mcprabhakaran@gmail.com]
>Sent: Thursday, August 05, 2010 2:44 PM
>To: Rymarkiewicz Waldemar
>Cc: linux-bluetooth@vger.kernel.org
>Subject: Re: L2cap Security And Role Switch
>
>Hi ,
>
>2010/8/5 <Waldemar.Rymarkiewicz@tieto.com>:
>> Hi,
>>
>>>-----Original Message-----
>>>From: Prabhakaran M.C [mailto:mcprabhakaran@gmail.com]
>>>Sent: Thursday, August 05, 2010 12:38 PM
>>>To: Rymarkiewicz Waldemar
>>>Cc: linux-bluetooth@vger.kernel.org
>>>Subject: Re: L2cap Security And Role Switch
>>>
>>>Hi Waldek,
>>>
>>>On Thu, Aug 5, 2010 at 3:37 PM,
>>><Waldemar.Rymarkiewicz@tieto.com> wrote:
>>>> Hi,
>>>>
>>>>>-----Original Message-----
>>>>>From: linux-bluetooth-owner@vger.kernel.org
>>>>>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of
>>>>>Prabhakaran M.C
>>>>>Sent: Wednesday, August 04, 2010 4:09 PM
>>>>>To: linux-bluetooth@vger.kernel.org
>>>>>Subject: Reg: L2cap Security And Role Switch
>>>>>
>>>>>Hello All,
>>>>>
>>>>> Whenever L2cap security is HIGH and remote device does
>role switch,
>>>>>Bluez accepts the Role switch and L2cap disconnects the channel
>>>>>because of HIGH security.
>>>>>
>>>>> For PAN profile, I would like to keep the L2cap security to HIGH
>>>>>since it involves internet browsing but the Widcomm stack
>>>always does
>>>>>a role switch in PAN connection and Bluez disconnects
>l2cap channel.
>>>>>
>>>>> Can someone please point in specification about the l2cap
>security
>>>>>level and Role switch relation. I tried to find out this
>but I could
>>>>>not get this behavior described in specification. Please
>>>provide your
>>>>>comments and inputs. Thanks in Advance.
>>>>>
>>>>>Thanks,
>>>>>Prabhakaran.
>>>>>--
>>>>
>>>> Note that HIGH sec level requires encription on the link.
>>>Role switch procedure turn off the encription before it starts
>>>switching roles and turn on it again after all. In 2.1 spec the
>>>controller handles switching off/on encription (pause/resume).
>>>>
>>>> Thanks,
>>>> /Waldek
>>>
>>> From the logs, the link was authenticated and encrypted.
>>>Then Widcomm stack disables the encryption, does a role switch,
>>>enables the encryption.
>>>After role switch bluez kernel disconnects l2cap channel due to HIGH
>>>security. I just want to know where this disconnection part
>is defined
>>>in spec. Or Bluez has to just reject the role switch
>operation instead
>>>of disconnection?
>>>
>>>--
>>>Thanks,
>>>Prabhakaran.
>>
>> As far as I know it's not defined in the spec. It's simply
>Bluez design. What I would like to see, the bluez should block
>outgoing data flow in l2cap for the period of role switch.
>> It's done in rfcomm this way, I guess (?).
>>
>> I agree, in my view the current desing in this use case is
>not perfect.
>>
>> Thanks,
>> /Waldek
>>
>>
>>
>>
>>
>>
>>
>
>Thanks for your response.
>One small correction here (My Bad). The l2cap channel is
>getting closed because encryption of the link goes down during
>role switch.
>"l2cap_check_encryption" function validates the encryption, if
>it is disabled and security is high then channel is getting
>closed by this function. Please let me know your comments about this.
>
>--
>Thanks,
>Prabhakaran.
As I said, if the encryption is disabled due to role switch, l2cap should block data flow and wait some time when the encription is switched on again. If this will not occur l2cap shoudl close the channel otherwise should continue as before the role switch.
Thanks,
/Waldek
^ permalink raw reply
* Re: L2cap Security And Role Switch
From: Prabhakaran M.C @ 2010-08-05 12:43 UTC (permalink / raw)
To: Waldemar.Rymarkiewicz; +Cc: linux-bluetooth
In-Reply-To: <99B09243E1A5DA4898CDD8B700111448096BA3C277@EXMB04.eu.tieto.com>
Hi ,
2010/8/5 <Waldemar.Rymarkiewicz@tieto.com>:
> Hi,
>
>>-----Original Message-----
>>From: Prabhakaran M.C [mailto:mcprabhakaran@gmail.com]
>>Sent: Thursday, August 05, 2010 12:38 PM
>>To: Rymarkiewicz Waldemar
>>Cc: linux-bluetooth@vger.kernel.org
>>Subject: Re: L2cap Security And Role Switch
>>
>>Hi Waldek,
>>
>>On Thu, Aug 5, 2010 at 3:37 PM,
>><Waldemar.Rymarkiewicz@tieto.com> wrote:
>>> Hi,
>>>
>>>>-----Original Message-----
>>>>From: linux-bluetooth-owner@vger.kernel.org
>>>>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of
>>>>Prabhakaran M.C
>>>>Sent: Wednesday, August 04, 2010 4:09 PM
>>>>To: linux-bluetooth@vger.kernel.org
>>>>Subject: Reg: L2cap Security And Role Switch
>>>>
>>>>Hello All,
>>>>
>>>> Whenever L2cap security is HIGH and remote device does role switch,
>>>>Bluez accepts the Role switch and L2cap disconnects the channel
>>>>because of HIGH security.
>>>>
>>>> For PAN profile, I would like to keep the L2cap security to HIGH
>>>>since it involves internet browsing but the Widcomm stack
>>always does
>>>>a role switch in PAN connection and Bluez disconnects l2cap channel.
>>>>
>>>> Can someone please point in specification about the l2cap security
>>>>level and Role switch relation. I tried to find out this but I could
>>>>not get this behavior described in specification. Please
>>provide your
>>>>comments and inputs. Thanks in Advance.
>>>>
>>>>Thanks,
>>>>Prabhakaran.
>>>>--
>>>
>>> Note that HIGH sec level requires encription on the link.
>>Role switch procedure turn off the encription before it
>>starts switching roles and turn on it again after all. In 2.1
>>spec the controller handles switching off/on encription (pause/resume).
>>>
>>> Thanks,
>>> /Waldek
>>
>> From the logs, the link was authenticated and encrypted.
>>Then Widcomm stack disables the encryption, does a role
>>switch, enables the encryption.
>>After role switch bluez kernel disconnects l2cap channel due
>>to HIGH security. I just want to know where this disconnection
>>part is defined in spec. Or Bluez has to just reject the role
>>switch operation instead of disconnection?
>>
>>--
>>Thanks,
>>Prabhakaran.
>
> As far as I know it's not defined in the spec. It's simply Bluez design. What I would like to see, the bluez should block outgoing data flow in l2cap for the period of role switch.
> It's done in rfcomm this way, I guess (?).
>
> I agree, in my view the current desing in this use case is not perfect.
>
> Thanks,
> /Waldek
>
>
>
>
>
>
>
Thanks for your response.
One small correction here (My Bad). The l2cap channel is getting
closed because encryption of the link goes down during role switch.
"l2cap_check_encryption" function validates the encryption, if it is
disabled and security is high then channel is getting closed by this
function. Please let me know your comments about this.
--
Thanks,
Prabhakaran.
^ permalink raw reply
* RE: L2cap Security And Role Switch
From: Waldemar.Rymarkiewicz @ 2010-08-05 10:53 UTC (permalink / raw)
To: mcprabhakaran; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikLE+ybEx=9SOQNEhc5hptMXmcuHwyX3EY69XYD@mail.gmail.com>
Hi,
>-----Original Message-----
>From: Prabhakaran M.C [mailto:mcprabhakaran@gmail.com]
>Sent: Thursday, August 05, 2010 12:38 PM
>To: Rymarkiewicz Waldemar
>Cc: linux-bluetooth@vger.kernel.org
>Subject: Re: L2cap Security And Role Switch
>
>Hi Waldek,
>
>On Thu, Aug 5, 2010 at 3:37 PM,
><Waldemar.Rymarkiewicz@tieto.com> wrote:
>> Hi,
>>
>>>-----Original Message-----
>>>From: linux-bluetooth-owner@vger.kernel.org
>>>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of
>>>Prabhakaran M.C
>>>Sent: Wednesday, August 04, 2010 4:09 PM
>>>To: linux-bluetooth@vger.kernel.org
>>>Subject: Reg: L2cap Security And Role Switch
>>>
>>>Hello All,
>>>
>>> Whenever L2cap security is HIGH and remote device does role switch,
>>>Bluez accepts the Role switch and L2cap disconnects the channel
>>>because of HIGH security.
>>>
>>> For PAN profile, I would like to keep the L2cap security to HIGH
>>>since it involves internet browsing but the Widcomm stack
>always does
>>>a role switch in PAN connection and Bluez disconnects l2cap channel.
>>>
>>> Can someone please point in specification about the l2cap security
>>>level and Role switch relation. I tried to find out this but I could
>>>not get this behavior described in specification. Please
>provide your
>>>comments and inputs. Thanks in Advance.
>>>
>>>Thanks,
>>>Prabhakaran.
>>>--
>>
>> Note that HIGH sec level requires encription on the link.
>Role switch procedure turn off the encription before it
>starts switching roles and turn on it again after all. In 2.1
>spec the controller handles switching off/on encription (pause/resume).
>>
>> Thanks,
>> /Waldek
>
> From the logs, the link was authenticated and encrypted.
>Then Widcomm stack disables the encryption, does a role
>switch, enables the encryption.
>After role switch bluez kernel disconnects l2cap channel due
>to HIGH security. I just want to know where this disconnection
>part is defined in spec. Or Bluez has to just reject the role
>switch operation instead of disconnection?
>
>--
>Thanks,
>Prabhakaran.
As far as I know it's not defined in the spec. It's simply Bluez design. What I would like to see, the bluez should block outgoing data flow in l2cap for the period of role switch.
It's done in rfcomm this way, I guess (?).
I agree, in my view the current desing in this use case is not perfect.
Thanks,
/Waldek
^ permalink raw reply
* Re: L2cap Security And Role Switch
From: Prabhakaran M.C @ 2010-08-05 10:38 UTC (permalink / raw)
To: Waldemar.Rymarkiewicz; +Cc: linux-bluetooth
In-Reply-To: <99B09243E1A5DA4898CDD8B700111448096BA3C23C@EXMB04.eu.tieto.com>
Hi Waldek,
On Thu, Aug 5, 2010 at 3:37 PM, <Waldemar.Rymarkiewicz@tieto.com> wrote:
> Hi,
>
>>-----Original Message-----
>>From: linux-bluetooth-owner@vger.kernel.org
>>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of
>>Prabhakaran M.C
>>Sent: Wednesday, August 04, 2010 4:09 PM
>>To: linux-bluetooth@vger.kernel.org
>>Subject: Reg: L2cap Security And Role Switch
>>
>>Hello All,
>>
>> Whenever L2cap security is HIGH and remote device does role
>>switch, Bluez accepts the Role switch and L2cap disconnects
>>the channel because of HIGH security.
>>
>> For PAN profile, I would like to keep the L2cap security to
>>HIGH since it involves internet browsing but the Widcomm stack
>>always does a role switch in PAN connection and Bluez
>>disconnects l2cap channel.
>>
>> Can someone please point in specification about the l2cap
>>security level and Role switch relation. I tried to find out
>>this but I could not get this behavior described in
>>specification. Please provide your comments and inputs. Thanks
>>in Advance.
>>
>>Thanks,
>>Prabhakaran.
>>--
>
> Note that HIGH sec level requires encription on the link. Role switch procedure turn off the encription before it starts switching roles and turn on it again after all. In 2.1 spec the controller handles switching off/on encription (pause/resume).
>
> Thanks,
> /Waldek
From the logs, the link was authenticated and encrypted.
Then Widcomm stack disables the encryption, does a role switch,
enables the encryption.
After role switch bluez kernel disconnects l2cap channel due to HIGH
security. I just want to know where this disconnection part is defined
in spec. Or Bluez has to just reject the role switch operation instead
of disconnection?
--
Thanks,
Prabhakaran.
^ permalink raw reply
* Re: [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: Johan Hedberg @ 2010-08-05 10:25 UTC (permalink / raw)
To: Inga Stotland; +Cc: linux-bluetooth, rshaffer, marcel
In-Reply-To: <1280962831-18147-8-git-send-email-ingas@codeaurora.org>
Hi Inga,
On Wed, Aug 04, 2010, Inga Stotland wrote:
> ---
> src/adapter.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> src/adapter.h | 4 +-
> src/dbus-hci.c | 6 ++--
> 3 files changed, 102 insertions(+), 8 deletions(-)
I've pushed the six other patches upstream, but I'm still a bit
concerned with this one. First there's a minor coding style issue:
> +static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
> +{
> + uint8_t len = 0;
> + char **uuids = NULL;
> + size_t total = 0;
Neither the uuids nor the total variable need to be initialized upon
declaration if you look at the function's code flow. In general
initialization upon declaration of variables is something that should be
avoided whenever not strictly needed since it can hide real issues that
the compiler would otherwise be able to catch.
Then, a more general concern about this function. It will receive data
as input that any nearby device that's discoverable has declared in
their EIR data. I.e. we need to be super strict about checking the
validity of the data and not make any assumptions about the correctness
of encoded field lengths etc. in order not to do buffer overflows. Have
you taken this into account when designing the function? Looking at it
it seems it might be possible to give it data that will cause some
buffer overflows (by e.g. placing a uuid list at the very end of the EIR
data with an invalid field length value).
Johan
^ permalink raw reply
* RE: L2cap Security And Role Switch
From: Waldemar.Rymarkiewicz @ 2010-08-05 10:07 UTC (permalink / raw)
To: mcprabhakaran, linux-bluetooth
In-Reply-To: <AANLkTimAktDFG+abbsMpgKfkNtmX3tqqhwXd-OZwgRWj@mail.gmail.com>
Hi,
>-----Original Message-----
>From: linux-bluetooth-owner@vger.kernel.org
>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of
>Prabhakaran M.C
>Sent: Wednesday, August 04, 2010 4:09 PM
>To: linux-bluetooth@vger.kernel.org
>Subject: Reg: L2cap Security And Role Switch
>
>Hello All,
>
> Whenever L2cap security is HIGH and remote device does role
>switch, Bluez accepts the Role switch and L2cap disconnects
>the channel because of HIGH security.
>
> For PAN profile, I would like to keep the L2cap security to
>HIGH since it involves internet browsing but the Widcomm stack
>always does a role switch in PAN connection and Bluez
>disconnects l2cap channel.
>
> Can someone please point in specification about the l2cap
>security level and Role switch relation. I tried to find out
>this but I could not get this behavior described in
>specification. Please provide your comments and inputs. Thanks
>in Advance.
>
>Thanks,
>Prabhakaran.
>--
Note that HIGH sec level requires encription on the link. Role switch procedure turn off the encription before it starts switching roles and turn on it again after all. In 2.1 spec the controller handles switching off/on encription (pause/resume).
Thanks,
/Waldek
^ permalink raw reply
* Re: Changes in HDP API
From: José Antonio Santos Cadenas @ 2010-08-05 9:29 UTC (permalink / raw)
To: Elvis Pfützenreuter; +Cc: linux-bluetooth
In-Reply-To: <0AEF6BD1-2A78-47E2-9445-87D78E4C85F8@signove.com>
El Wednesday 04 August 2010 20:22:29 Elvis Pfützenreuter escribió:
> On 04/08/2010, at 04:49, Jose Antonio Santos Cadenas wrote:
> > This patch makes some changes in the HDP API based in the conversation
> > that I had yesterday with Luiz and Elvis.
> >
> > I still have a doubt about the notification of devices in the agent. Luiz
> > commented that with this API the Agent and the Application could not be
> > in different processes, is this a problem?
>
> Is not a problem and IMHO it does not make sense at all. The Agent in HDP
> API context is as a mere vehicle for callbacks, because signals are seen
> by every process while the nature of health devices demands some
> privacy/secrecy (I have a faint memory about privacy being a general
> requirement for IEEE protocol as well as Continua certification.)
I've been thinking about this issue and I'm changing my opinion about this a
little bit. I will expose my "new" view and later today I will send a new API
proposal if you think this approach is OK.
In fact the privacy issue should concern to the data that is being transmitted
over the data channel, not the creation and destruction of the data channel.
If we start from that point. Sending new channel events as signals will not be
a privacy problem if we protect the data channel itself.
The DataChannel object (as is defined in the current API) could be protected
and only reply to method calls from the process owner of the application that
waited for this data channel (if it was opened by the remote side) or from the
creator of the data channel (if it was opened by the local side). This way
only this process will be able to get the file descriptor (what means get
access to the data) and to manage the connection closing, reconnecting or
deleting the data channel. So in this way the privacy of the data is
guaranteed.
An other thing to take into account is that all the application will be
bothered with signals of data channel creation an deletion even when they
could not use them. But I thing that this is not too much extra load because
in a typical scenario only one or two application will be interested in health
data channels.
>
> The agent is always coupled with an application. The most typical usage of
> BlueZ HDP is as sink role, which means the application creates the
> application, which publishes the role via SDP, and sits idle until some
> source connects, which is notified via the agent.
Regards.
^ permalink raw reply
* Re: [PATCH 5/9] Bluetooth: Fix incorrect setting of remote_tx_win for L2CAP ERTM.
From: Gustavo F. Padovan @ 2010-08-05 4:20 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <1280962146-22604-6-git-send-email-mathewm@codeaurora.org>
Hi Mat,
* Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:49:02 -0700]:
> remote_tx_win is intended to be set on receipt of an L2CAP
> configuration request. The value is used to determine the size of the
> transmit window on the remote side of an ERTM connection, so L2CAP
> can stop sending frames when that remote window is full.
>
> An incorrect remote_tx_win value will cause the stack to not fully
> utilize the tx window (performance impact), or to overfill the remote
> tx window (causing dropped frames or a disconnect).
>
> This patch removes an extra setting of remote_tx_win when a
> configuration response is received. The transmit window has a
> different meaning in a response - it is an informational value
> less than or equal to the local tx_win.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 8cf9569..f0f3c7c 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -2808,7 +2808,6 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
> if (*result == L2CAP_CONF_SUCCESS) {
> switch (rfc.mode) {
> case L2CAP_MODE_ERTM:
> - pi->remote_tx_win = rfc.txwin_size;
> pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
> pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
> pi->mps = le16_to_cpu(rfc.max_pdu_size);
I agree. But you may also want to remove the same check inside
l2cap_conf_rfc_get()
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* Re: [PATCH 4/9] Bluetooth: Fix endianness issue with L2CAP MPS configuration.
From: Gustavo F. Padovan @ 2010-08-05 4:00 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <1280962146-22604-5-git-send-email-mathewm@codeaurora.org>
Hi Mat,
* Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:49:01 -0700]:
> Incoming configuration values must be converted to native CPU order
> before use. This fixes a bug where a little-endian MPS value is
> compared to a native CPU value. On big-endian processors, this
> can cause ERTM and streaming mode segmentation to produce PDUs
> that are larger than the remote stack is expecting, or that would
> produce fragmented skbs that the current FCS code cannot handle.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap.c | 9 ++++-----
> 1 files changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 920a53f..8cf9569 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -2708,10 +2708,10 @@ done:
> case L2CAP_MODE_ERTM:
> pi->remote_tx_win = rfc.txwin_size;
> pi->remote_max_tx = rfc.max_transmit;
> - if (rfc.max_pdu_size > pi->conn->mtu - 10)
> - rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
>
> pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
> + if (pi->remote_mps > pi->conn->mtu - 10)
> + pi->remote_mps = pi->conn->mtu - 10;
What happened with thte "rfc.max_pdu_size =" attribution. We have the
send the value to through the RFC option. So what I do propose here is:
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 0f34e12..11d4405 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2705,7 +2705,7 @@ done:
case L2CAP_MODE_ERTM:
pi->remote_tx_win = rfc.txwin_size;
pi->remote_max_tx = rfc.max_transmit;
- if (rfc.max_pdu_size > pi->conn->mtu - 10)
+ if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
@@ -2723,7 +2723,7 @@ done:
break;
case L2CAP_MODE_STREAMING:
- if (rfc.max_pdu_size > pi->conn->mtu - 10)
+ if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
>
> rfc.retrans_timeout =
> le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
> @@ -2726,10 +2726,9 @@ done:
> break;
>
> case L2CAP_MODE_STREAMING:
> - if (rfc.max_pdu_size > pi->conn->mtu - 10)
> - rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10);
> -
> pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
> + if (pi->remote_mps > pi->conn->mtu - 10)
> + pi->remote_mps = pi->conn->mtu - 10;
>
> pi->conf_state |= L2CAP_CONF_MODE_DONE;
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply related
* Re: [PATCH 1/9] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming.
From: Gustavo F. Padovan @ 2010-08-05 3:38 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <1280962146-22604-2-git-send-email-mathewm@codeaurora.org>
HI Mat,
You are adding to spaces after "Bluetooth:" and the commit message, one is
fine. All the patches have this issue.
* Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:48:58 -0700]:
> This fixes a bug which caused the FCS setting to show L2CAP_FCS_CRC16
> with L2CAP modes other than ERTM or streaming. At present, this only
> affects the FCS value shown with getsockopt() for basic mode.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap.c | 17 +++++++++++++----
> 1 files changed, 13 insertions(+), 4 deletions(-)
>
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* Re: [PATCH 1/9] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming.
From: Gustavo F. Padovan @ 2010-08-05 3:32 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <1280962146-22604-2-git-send-email-mathewm@codeaurora.org>
Hi Mat,
* Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:48:58 -0700]:
> This fixes a bug which caused the FCS setting to show L2CAP_FCS_CRC16
> with L2CAP modes other than ERTM or streaming. At present, this only
> affects the FCS value shown with getsockopt() for basic mode.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap.c | 17 +++++++++++++----
> 1 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 9ba1e8e..a2706d9 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -3063,6 +3063,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
> return 0;
> }
>
> +static inline int l2cap_fcs_needed(struct l2cap_pinfo *pi)
> +{
> + if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
> + return 0;
> + else {
> + /* FCS is enabled if one or both sides request it. */
> + return !(pi->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
> + pi->fcs == L2CAP_FCS_CRC16;
> + }
Get ride of the else, just put the return !(pi->....
Also I would like to see the use case for the check for the ERTM and
Streaming before merge this patch. ;)
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* Re: [PATCH 2/9] Bluetooth: Change default ERTM retransmit timeout.
From: Gustavo F. Padovan @ 2010-08-05 3:29 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, marcel, rshaffer, linux-arm-msm
In-Reply-To: <1280962146-22604-3-git-send-email-mathewm@codeaurora.org>
Hi Mat,
* Mat Martineau <mathewm@codeaurora.org> [2010-08-04 15:48:59 -0700]:
> The L2CAP spec requires that the ERTM retransmit timeout be at least 2
> seconds for BR/EDR connections.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> include/net/bluetooth/l2cap.h | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 636724b..16e412f 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -33,7 +33,7 @@
> #define L2CAP_DEFAULT_FLUSH_TO 0xffff
> #define L2CAP_DEFAULT_TX_WINDOW 63
> #define L2CAP_DEFAULT_MAX_TX 3
> -#define L2CAP_DEFAULT_RETRANS_TO 1000 /* 1 second */
> +#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
> #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
> #define L2CAP_DEFAULT_MAX_PDU_SIZE 672
> #define L2CAP_DEFAULT_ACK_TO 200
The spec says that a 2 seconds retransmission timeout shall be used
after a move channel operation in a BR/EDR radio. (section 8.6.2.3)
For a normal ACL connection the default value is 1 second(section
8.6.2.1), so I prefer to keep L2CAP_DEFAULT_RETRANS_TO set to 1000.
--
Gustavo F. Padovan
http://padovan.org
^ permalink raw reply
* [PATCH 7/7] Add service UUIDs from EIR to device properties in "Device Found" signal.
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/adapter.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/adapter.h | 4 +-
src/dbus-hci.c | 6 ++--
3 files changed, 102 insertions(+), 8 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index c142a4a..d191014 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2749,8 +2749,94 @@ static void emit_device_found(const char *path, const char *address,
g_dbus_send_message(connection, signal);
}
+static char **get_eir_uuids(uint8_t *eir_data, size_t *uuid_count)
+{
+ uint8_t len = 0;
+ char **uuids = NULL;
+ size_t total = 0;
+ size_t uuid16_count = 0;
+ size_t uuid32_count = 0;
+ size_t uuid128_count = 0;
+ uint8_t *uuid16;
+ uint8_t *uuid32;
+ uint8_t *uuid128;
+ uuid_t service;
+ int i;
+
+ while (len < EIR_DATA_LENGTH) {
+ uint8_t type = eir_data[1];
+ uint8_t field_len = eir_data[0];
+
+ switch (type) {
+ case EIR_UUID16_SOME:
+ case EIR_UUID16_ALL:
+ uuid16_count = field_len / 2;
+ uuid16 = &eir_data[2];
+ break;
+ case EIR_UUID32_SOME:
+ case EIR_UUID32_ALL:
+ uuid32_count = field_len / 4;
+ uuid32 = &eir_data[2];
+ break;
+ case EIR_UUID128_SOME:
+ case EIR_UUID128_ALL:
+ uuid128_count = field_len / 16;
+ uuid128 = &eir_data[2];
+ break;
+ }
+
+ len += field_len + 1;
+ eir_data += field_len + 1;
+ }
+
+ total = uuid16_count + uuid32_count + uuid128_count;
+ *uuid_count = total;
+
+ if (!total)
+ return NULL;
+
+ uuids = g_new0(char *, total + 1);
+
+ /* Generate uuids in SDP format (EIR data is Little Endian) */
+ service.type = SDP_UUID16;
+ for (i = 0; i < uuid16_count; i++) {
+ uint16_t val16 = uuid16[1];
+
+ val16 = (val16 << 8) + uuid16[0];
+ service.value.uuid16 = val16;
+ uuids[i] = bt_uuid2string(&service);
+ uuid16 += 2;
+ }
+
+ service.type = SDP_UUID32;
+ for (i = uuid16_count; i < uuid32_count + uuid16_count; i++) {
+ uint32_t val32 = uuid32[3];
+ int k;
+
+ for (k = 2; k >= 0; k--)
+ val32 = (val32 << 8) + uuid32[k];
+
+ service.value.uuid32 = val32;
+ uuids[i] = bt_uuid2string(&service);
+ uuid32 += 4;
+ }
+
+ service.type = SDP_UUID128;
+ for (i = uuid32_count + uuid16_count; i < total; i++) {
+ int k;
+
+ for (k = 0; k < 16; k++)
+ service.value.uuid128.data[k] = uuid128[16 - k - 1];
+
+ uuids[i] = bt_uuid2string(&service);
+ uuid128 += 16;
+ }
+
+ return uuids;
+}
+
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];
@@ -2758,6 +2844,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;
+ size_t uuid_count = 0;
ba2str(&dev->bdaddr, peer_addr);
ba2str(&adapter->bdaddr, local_addr);
@@ -2777,6 +2865,10 @@ 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)
+ uuids = get_eir_uuids(eir_data, &uuid_count);
+
emit_device_found(adapter->path, paddr,
"Address", DBUS_TYPE_STRING, &paddr,
"Class", DBUS_TYPE_UINT32, &dev->class,
@@ -2786,15 +2878,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;
@@ -2833,7 +2927,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 8226514..a7eca0e 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -113,10 +113,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..6d27caa 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -515,7 +515,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 +566,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 +642,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)
--
1.7.2
--
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 6/7] Handle arrays in device properties dictionary.
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/adapter.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index b735bdd..c142a4a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2700,6 +2700,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,
@@ -2711,7 +2712,13 @@ 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 *);
}
--
1.7.2
--
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 5/7] Fix in logic to write EIR when SDP records are changed.
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
Whenever SDP service record is added/deleted/modified check for whether
class of device needs to be updated as well. If the update is
needed, proceed as before: new EIR will be written subsequently.
If the class of device is already present, just update EIR and return.
---
src/adapter.c | 69 ++++++++++++++++++++++++++++++--------------------------
1 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 4615326..b735bdd 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -206,6 +206,34 @@ void clear_found_devices_list(struct btd_adapter *adapter)
adapter->found_devices = NULL;
}
+static void update_ext_inquiry_response(struct btd_adapter *adapter)
+{
+ uint8_t fec = 0, data[240];
+ struct hci_dev *dev = &adapter->dev;
+ int dd;
+
+ if (!(dev->features[6] & LMP_EXT_INQ))
+ return;
+
+ memset(data, 0, sizeof(data));
+
+ dd = hci_open_dev(adapter->dev_id);
+ if (dd < 0)
+ return;
+
+ if (dev->ssp_mode > 0)
+ create_ext_inquiry_response((char *) dev->name,
+ adapter->tx_power,
+ adapter->services, data);
+
+ if (hci_write_ext_inquiry_response(dd, fec, data,
+ HCI_REQ_TIMEOUT) < 0)
+ error("Can't write extended inquiry response: %s (%d)",
+ strerror(errno), errno);
+
+ hci_close_dev(dd);
+}
+
static int adapter_set_service_classes(struct btd_adapter *adapter,
uint8_t value)
{
@@ -216,11 +244,16 @@ static int adapter_set_service_classes(struct btd_adapter *adapter,
adapter->wanted_cod &= 0x00ffff;
adapter->wanted_cod |= (value << 16);
- /* If we already have the CoD we want or the cache is enabled or an
- * existing CoD write is in progress just bail out */
- if (adapter->current_cod == adapter->wanted_cod ||
- adapter->cache_enable || adapter->pending_cod)
+ /* If the cache is enabled or an existing CoD write is in progress
+ * just bail out */
+ if (adapter->cache_enable || adapter->pending_cod)
+ return 0;
+
+ /* If we already have the CoD we want, update EIR and return */
+ if (adapter->current_cod == adapter->wanted_cod) {
+ update_ext_inquiry_response(adapter);
return 0;
+ }
DBG("Changing service classes to 0x%06x", adapter->wanted_cod);
@@ -818,34 +851,6 @@ static DBusMessage *set_pairable_timeout(DBusConnection *conn,
return dbus_message_new_method_return(msg);
}
-static void update_ext_inquiry_response(struct btd_adapter *adapter)
-{
- uint8_t fec = 0, data[240];
- struct hci_dev *dev = &adapter->dev;
- int dd;
-
- if (!(dev->features[6] & LMP_EXT_INQ))
- return;
-
- memset(data, 0, sizeof(data));
-
- dd = hci_open_dev(adapter->dev_id);
- if (dd < 0)
- return;
-
- if (dev->ssp_mode > 0)
- create_ext_inquiry_response((char *) dev->name,
- adapter->tx_power,
- adapter->services, data);
-
- if (hci_write_ext_inquiry_response(dd, fec, data,
- HCI_REQ_TIMEOUT) < 0)
- error("Can't write extended inquiry response: %s (%d)",
- strerror(errno), errno);
-
- hci_close_dev(dd);
-}
-
void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status)
{
uint8_t class[3];
--
1.7.2
--
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 4/7] Support for adding UUID128 to extended inquiry response
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/sdpd-service.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 63 insertions(+), 0 deletions(-)
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 5c56e2d..26ab9a5 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -49,6 +49,8 @@
#include "manager.h"
#include "adapter.h"
+#define SIZEOF_UUID128 16
+
static sdp_record_t *server = NULL;
static uint16_t did_vendor = 0x0000;
@@ -174,6 +176,63 @@ 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 UUIDs in place, skip 2 bytes to write type and length later */
+ uuid128 = ptr + 2;
+
+ for (; list; list = list->next) {
+ sdp_record_t *rec = (sdp_record_t *) list->data;
+ uint8_t *uuid128_data = rec->svclass.value.uuid128.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] !=
+ 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] =
+ 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)
@@ -271,6 +330,10 @@ void create_ext_inquiry_response(const char *name,
*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)
--
1.7.2
--
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 3/7] Clean up code that generates extended inquiry response.
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/sdpd-service.c | 44 +++++++++++++++++++++++++++++---------------
1 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 35e333d..5c56e2d 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -180,35 +180,41 @@ void create_ext_inquiry_response(const char *name,
{
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 +223,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,28 +239,36 @@ 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)
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;
}
}
}
--
1.7.2
--
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/7] Minor fix when skipping duplicate UUID16 from EIR.
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/sdpd-service.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index cdbb4f4..35e333d 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -242,7 +242,7 @@ void create_ext_inquiry_response(const char *name,
if (uuid[i] == rec->svclass.value.uuid16)
break;
- if (i == index - 1)
+ if (i < index)
continue;
uuid[index++] = rec->svclass.value.uuid16;
--
1.7.2
--
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/7] Spec constants for Extended Inquiry Response field types
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel, Inga Stotland
In-Reply-To: <1280962831-18147-1-git-send-email-ingas@codeaurora.org>
---
src/sdpd.h | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/src/sdpd.h b/src/sdpd.h
index e93b0b6..5bab869 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -34,6 +34,19 @@
#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_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 */
+#define EIR_NAME_COMPLETE 0x09 /* complete local name */
+#define EIR_TX_POWER 0x0A /* transmit power level */
+#define EIR_DEVICE_ID 0x10 /* device ID */
+
typedef struct request {
bdaddr_t device;
bdaddr_t bdaddr;
--
1.7.2
--
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 v8 0/7] Enhanced support for extended inquiry response
From: Inga Stotland @ 2010-08-04 23:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: rshaffer, johan.hedberg, marcel
EIR needs to be updated whenever local SDP record database changes.
Previously, when an SDP record was added/removed/updated, EIR would
be written in callback fired off HCI "Command Complete" event set off by
"Write Class Of Device" command. However, if the class of device did not
need to be updated, the EIR write was not happening either. This
implementation has been augmented to write new EIR when modification
in SDP database does not lead to updating of class of device.
Added support for UUID128 service descriptors in local EIR.
Service UUIDs are written to "device properties" dictionary when emitting
"Device Found" signal. This allows 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
* [PATCH 9/9] Bluetooth: Use 3-DH5 payload size for default ERTM max PDU size.
From: Mat Martineau @ 2010-08-04 22:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1280962146-22604-1-git-send-email-mathewm@codeaurora.org>
The previous value of 672 for L2CAP_DEFAULT_MAX_PDU_SIZE is based on
the default L2CAP MTU. That default MTU is calculated from the size
of two DH5 packets, minus ACL and L2CAP b-frame header overhead.
ERTM is used with newer basebands that typically support larger 3-DH5
packets, and i-frames and s-frames have more header overhead. With
clean RF conditions, basebands will typically attempt to use 1021-byte
3-DH5 packets for maximum throughput. Adjusting for 2 bytes of ACL
headers plus 10 bytes of worst-case L2CAP headers yields 1009 bytes
of payload.
This PDU size imposes less overhead for header bytes and gives the
baseband the option to choose 3-DH5 packets, but is small enough for
ERTM traffic to interleave well with other L2CAP or SCO data.
672-byte payloads do not allow the most efficient over-the-air
packet choice, and cannot achieve maximum throughput over BR/EDR.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
include/net/bluetooth/l2cap.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 16e412f..6c24144 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -35,7 +35,7 @@
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE 672
+#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_LOCAL_BUSY_TRIES 12
--
1.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 8/9] Bluetooth: Use a stream-oriented recvmsg with SOCK_STREAM L2CAP sockets.
From: Mat Martineau @ 2010-08-04 22:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1280962146-22604-1-git-send-email-mathewm@codeaurora.org>
L2CAP ERTM sockets can be opened with the SOCK_STREAM socket type,
which is a mandatory request for ERTM mode.
However, these sockets still have SOCK_SEQPACKET read semantics when
bt_sock_recvmsg() is used to pull data from the receive queue. If the
application is only reading part of a frame, then the unread portion
of the frame is discarded. If the application requests more bytes
than are in the current frame, only the current frame's data is
returned.
This patch utilizes common code derived from RFCOMM's recvmsg()
function to make L2CAP SOCK_STREAM reads behave like RFCOMM reads (and
other SOCK_STREAM sockets in general). The application may read one
byte at a time from the input stream and not lose any data, and may
also read across L2CAP frame boundaries.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
net/bluetooth/l2cap.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index f0f3c7c..b9de88d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1956,7 +1956,10 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
release_sock(sk);
- return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+ if (sock->type == SOCK_STREAM)
+ return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+ else
+ return bt_sock_recvmsg(iocb, sock, msg, len, flags);
}
static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
--
1.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 7/9] Bluetooth: Use common SOCK_STREAM receive code in RFCOMM.
From: Mat Martineau @ 2010-08-04 22:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1280962146-22604-1-git-send-email-mathewm@codeaurora.org>
To reduce code duplication, have rfcomm_sock_recvmsg() call
bt_sock_stream_recvmsg(). The common bt_sock_stream_recvmsg()
code is nearly identical, with the RFCOMM-specific functionality
for deferred setup and connection unthrottling left in
rfcomm_sock_recvmsg().
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
net/bluetooth/rfcomm/sock.c | 104 +++----------------------------------------
1 files changed, 6 insertions(+), 98 deletions(-)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 44a6232..4396f47 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -617,121 +617,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return sent;
}
-static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(sk_sleep(sk), &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
-
- if (!skb_queue_empty(&sk->sk_receive_queue) ||
- sk->sk_err ||
- (sk->sk_shutdown & RCV_SHUTDOWN) ||
- signal_pending(current) ||
- !timeo)
- break;
-
- set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- release_sock(sk);
- timeo = schedule_timeout(timeo);
- lock_sock(sk);
- clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(sk_sleep(sk), &wait);
- return timeo;
-}
-
static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{
struct sock *sk = sock->sk;
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
- int err = 0;
- size_t target, copied = 0;
- long timeo;
+ int len;
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
rfcomm_dlc_accept(d);
return 0;
}
- if (flags & MSG_OOB)
- return -EOPNOTSUPP;
-
- msg->msg_namelen = 0;
-
- BT_DBG("sk %p size %zu", sk, size);
+ len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags);
lock_sock(sk);
+ if (!(flags & MSG_PEEK) && len > 0)
+ atomic_sub(len, &sk->sk_rmem_alloc);
- target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
- timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-
- do {
- struct sk_buff *skb;
- int chunk;
-
- skb = skb_dequeue(&sk->sk_receive_queue);
- if (!skb) {
- if (copied >= target)
- break;
-
- if ((err = sock_error(sk)) != 0)
- break;
- if (sk->sk_shutdown & RCV_SHUTDOWN)
- break;
-
- err = -EAGAIN;
- if (!timeo)
- break;
-
- timeo = rfcomm_sock_data_wait(sk, timeo);
-
- if (signal_pending(current)) {
- err = sock_intr_errno(timeo);
- goto out;
- }
- continue;
- }
-
- chunk = min_t(unsigned int, skb->len, size);
- if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- if (!copied)
- copied = -EFAULT;
- break;
- }
- copied += chunk;
- size -= chunk;
-
- sock_recv_ts_and_drops(msg, sk, skb);
-
- if (!(flags & MSG_PEEK)) {
- atomic_sub(chunk, &sk->sk_rmem_alloc);
-
- skb_pull(skb, chunk);
- if (skb->len) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- break;
- }
- kfree_skb(skb);
-
- } else {
- /* put message back and return */
- skb_queue_head(&sk->sk_receive_queue, skb);
- break;
- }
- } while (size);
-
-out:
if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
-
release_sock(sk);
- return copied ? : err;
+
+ return len;
}
static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
--
1.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox