Linux bluetooth development
 help / color / mirror / Atom feed
* Re: HDP proposed API(0.5)
From: José Antonio Santos Cadenas @ 2010-05-17 21:40 UTC (permalink / raw)
  To: João Paulo Rechi Vita; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikCmZydkLG863_MbrMhiNlWx5GecQaXitr1q0xX@mail.gmail.com>

El Monday 17 May 2010 23:17:58 João Paulo Rechi Vita escribió:
> On Mon, May 17, 2010 at 11:54, José Antonio Santos Cadenas
> 
> <jcaden@libresoft.es> wrote:
> > Hope the last one :)
> > 
> > ----------------------------
> > 
> > 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         object CreateInstance(object path, dict config)
> > 
> >                        Returns the path for the new HealthInstance
> > object. The path parameter is the path of the remote 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 in the SDP if is needed
> >                        Dict is defined as bellow:
> >                        { "data_spec" : The data_spec is the data exchange
> >                                        specification (see section 5.2.10
> > of the specification document) possible values:
> >                                                0x00 = reserved,
> >                                                0x01 [IEEE 11073-20601],
> >                                                0x02..0xff reserved,
> >                                        (optional)
> >                          "end_points" : [{ (optional)
> >                                "mdepid" : uint8, (optional)
> >                                "role" : ("source" or "sink"), (mandatory)
> >                                "specs" :[{ (mandatory)
> >                                        "data_type" : uint16, (mandatory)
> >                                        "description" : string, (optional)
> >                                }]
> >                          }]
> >                        }
> > 
> >                        if "data_spec" is not set, no SDP record will be
> >                        registered, so all the other data in the
> > dictionary will be ignored
> > 
> >                        Instance will be closed by the call or implicitly
> > when the programs leaves the bus.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> > 
> >                void CloseInstance(object path)
> > 
> >                        Closes the HDP instance identified by the object
> > path. Also instance will be closed if the process that started leaves
> > the bus. If there is a SDP record associated to this instance it will be
> > removed.
> > 
> >                        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         array GetHealthInstances()
> > 
> >                        Gets the information of the remote instances
> > present in this device and published on its SDP record. The returned
> > data follows this format.
> > 
> >                        [{"id": "an instance identification as string",
> >                         "data_spec" : data spec,
> >                         "end_points":
> >                                ["mdepid": uint8,
> >                                 "role"  : "source" or "sink" ,
> >                                 "specs" : [{
> >                                        "dtype"       : uint16,
> >                                        "description" : string, (optional)
> >                                 }]
> >                                ]
> >                        }];
> > 
> > -------------------------------------------------------------------------
> > -------
> > 
> > Service         org.bluez
> > Interface       org.bluez.HealthInstance
> > Object path     [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}
> > 
> >                object Connect(remote_instance_id)
> > 
> >                        Connects with the remote instance and returns its
> > object path. To get the session ids on a remote device, you must run the
> > GetHealthInstances in the HealthDevice object.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> >                                        org.bluez.Error.HealthError
> > 
> >                void Disconnect(object device, boolean cache)
> > 
> >                        Disconnect from the remote device. If chahe is
> > false, state will also be deleted. Otherwise, the state will be kept for
> > allowing future reconnections until the adapter is removed.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> >                                        org.bluez.Error.NotFound
> >                                        org.bluez.Error.HealthError
> > 
> > -------------------------------------------------------------------------
> > -------
> > 
> > Service         org.bluez
> > Interface       org.bluez.HealthLink
> > Object path     [variable
> > prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_inst_id
> > 
> >                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.
> > 
> >                uint16 OpenDataChannel(byte mdepid, byte config)
> > 
> >                        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. In the current version
> > of HDP, valid values are 0x01 for reliable channels and 0x02 for
> > streaming data channel.
> > 
> >                        Returns the data channel id.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> >                                        org.bluez.Error.HealthError
> > 
> >                array GetDataChannelFileDescriptor(uint16 mdlid)
> 
> Wouldn't be better to pass the fd through the LinkConnected call on
> Agent? Doing it here allows any process to get the fds.

Originally we thought about doing like that. But Elvis suggested to centralize 
all the ways that you get the file descriptor in just one place and we thought 
that it was a great idea. In addition, think that you will need this call 
because the LinkConnected call is only called when the connection is initiated 
by the remote HDP instance but the connections initiated by your side will not 
be notified. About the "security" issue you mentioned, we are planing to 
control who can call this methods only the process that initiated the HDP 
instance will receive a response to this methods, any other process will 
receive an error.

> 
> >                        Gets a file descriptor where data can be read or
> >                        written for receive or sent by the data channel.
> >                        Returns an array of file descriptors one for write
> >                        and other for read.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> >                                        org.bluez.Error.NotFound
> >                                        org.bluez.Error.HealthError
> > 
> >                void DeleteDataChannel(uint16 mdlid)
> > 
> >                        Deletes a data channel so it will not be available
> > for use.
> > 
> >                        Possible errors: org.bluez.Error.InvalidArguments
> >                                        org.bluez.Error.NotFound
> >                                        org.bluez.Error.HealthError
> > 
> >                void DeleteAllDataChannels()
> > 
> >                        Deletes all data channels so it will not be
> > available for 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": [mdlid_r1, mdlid_r2, ...],
> >                                "streaming" : [mdlid_s1, mdlid_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 client an receives notifications)
> > 
> > Service         unique name
> > Interface       org.bluez.HealthAgent
> > Object path     freely definable
> > 
> >                void LinkConnected(object path)
> > 
> >                        This method is called whenever a new connection
> >                        has been established over the control channel of
> > the current HDP instance. The object path paremeter contains the object
> > path of the created HealthLink.
> > 
> >                void LinkDisconnected(object path)
> > 
> >                        This method is called when a remote device is
> >                        disconnected definitively. Any future
> > reconnections will fail. Also all data channels associated to this
> > device will be closed.
> > 
> >                void CreatedDataChannel(object path, uint16 mdlid, byte
> > conf)
> > 
> >                        This method is called when a new data channel is
> > created The path contains the object path of the HealthLink where the
> > new connection is created, the mdlid is the data channel identificator
> > and conf is the que quality of service of the data channel (0x01
> > reliable, 0x02 streaming).
> > 
> >                void DeletedDataChannel(object path, uint16 mdlid)
> > 
> >                        This method is called when a data channel is
> > closed. After this call the data channel will not be valid and can be
> > reused for future created data channels. --
> > To unsubscribe from this list: send the line "unsubscribe
> > linux-bluetooth" in the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: HDP proposed API(0.5)
From: Gustavo F. Padovan @ 2010-05-17 21:38 UTC (permalink / raw)
  To: João Paulo Rechi Vita; +Cc: jcaden, linux-bluetooth
In-Reply-To: <AANLkTikCmZydkLG863_MbrMhiNlWx5GecQaXitr1q0xX@mail.gmail.com>

Hi,

* João Paulo Rechi Vita <jprvita@gmail.com> [2010-05-17 18:17:58 -0300]:

<snip>

> On Mon, May 17, 2010 at 11:54, José Antonio Santos Cadenas
> <jcaden@libresoft.es> wrote:
> >
> >                array GetDataChannelFileDescriptor(uint16 mdlid)
> >
> 
> Wouldn't be better to pass the fd through the LinkConnected call on
> Agent? Doing it here allows any process to get the fds.

I was thinking about the MCAP in kernel implementation, my conclusion is
that we can solve one of the biggest problem of HDP API if we do it in
kernel: the transparency of MCAP reconnection. HDP will open an MCAP
socket and pass it to the user(IEEE app). Then if we need a
reconnection, MCAP will transparently reconnect changing the L2CAP
channel to transmit the data without the need to change the socket
opened with the userspace.

Keep the MCAP socket open means that we are keeping the MCL state for
further reconnection.

Doing it inside the kernel removes a big amount of complexity of HDP and
IEEE profiles, since we won't need any pipe or change of fd. That could
be a killer feature to make it in the kernel.

Any comments? Is this reasonable?

<snip>

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: HDP proposed API(0.5)
From: João Paulo Rechi Vita @ 2010-05-17 21:17 UTC (permalink / raw)
  To: jcaden; +Cc: linux-bluetooth
In-Reply-To: <201005171654.36923.jcaden@libresoft.es>

T24gTW9uLCBNYXkgMTcsIDIwMTAgYXQgMTE6NTQsIEpvc8OpIEFudG9uaW8gU2FudG9zIENhZGVu
YXMKPGpjYWRlbkBsaWJyZXNvZnQuZXM+IHdyb3RlOgo+IEhvcGUgdGhlIGxhc3Qgb25lIDopCj4K
PiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4KPiBCbHVlWiBELUJ1cyBIZWFsdGggQVBJ
IGRlc2NyaXB0aW9uCj4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgo+Cj4gwqAg
wqAgwqAgwqBTYW50aWFnbyBDYXJvdC1OZW1lc2lvIDxzYW5jYW5lQGdtYWlsLmNvbT4KPiDCoCDC
oCDCoCDCoEpvc8OpIEFudG9uaW8gU2FudG9zLUNhZGVuYXMgPHNhbnRvc2NhZGVuYXNAZ21haWwu
Y29tPgo+IMKgIMKgIMKgIMKgRWx2aXMgUGbDvHR6ZW5yZXV0ZXIgPGVweEBzaWdub3ZlLmNvbT4K
Pgo+IEhlYWx0aCBEZXZpY2UgUHJvZmlsZSBoaWVyYXJjaHkKPiA9PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09Cj4KPiBTZXJ2aWNlIMKgIMKgIMKgIMKgIG9yZy5ibHVlego+IEludGVyZmFj
ZSDCoCDCoCDCoCBvcmcuYmx1ZXouSGVhbHRoQWRhcHRlcgo+IE9iamVjdCBwYXRoIMKgIMKgIFt2
YXJpYWJsZSBwcmVmaXhdL3toY2kwLGhjaTEsLi4ufQo+Cj4gTWV0aG9kcyDCoCDCoCDCoCDCoCBv
YmplY3QgQ3JlYXRlSW5zdGFuY2Uob2JqZWN0IHBhdGgsIGRpY3QgY29uZmlnKQo+Cj4gwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBSZXR1cm5zIHRoZSBwYXRoIGZvciB0aGUgbmV3
IEhlYWx0aEluc3RhbmNlIG9iamVjdC4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoFRoZSBwYXRoIHBhcmFtZXRlciBpcyB0aGUgcGF0aCBvZiB0aGUgcmVtb3RlIG9iamVjdAo+
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgd2l0aCB0aGUgY2FsbGJhY2tzIHRv
IG5vdGlmeSBldmVudHMgKHNlZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
b3JnLmJsdWV6LkhlYWx0aEFnZW50IGF0IHRoZSBlbmQgb2YgdGhpcyBkb2N1bWVudCkKPiDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFRoaXMgcGV0aXRpb24gc3RhcnRzIGFuIG1j
YXAgaW5zdGFuY2UgYW5kIGFsc28gcmVnaXN0ZXIKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoGluIHRoZSBTRFAgaWYgaXMgbmVlZGVkCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqBEaWN0IGlzIGRlZmluZWQgYXMgYmVsbG93Ogo+IMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgeyAiZGF0YV9zcGVjIiA6IFRoZSBkYXRhX3NwZWMgaXMgdGhl
IGRhdGEgZXhjaGFuZ2UKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoHNwZWNpZmljYXRpb24gKHNlZSBzZWN0aW9uIDUuMi4xMCBvZgo+
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgdGhlIHNwZWNpZmljYXRpb24gZG9jdW1lbnQpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwb3NzaWJsZSB2YWx1ZXM6Cj4gwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAweDAwID0gcmVzZXJ2ZWQsCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAweDAxIFtJRUVFIDEx
MDczLTIwNjAxXSwKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoDB4MDIuLjB4ZmYgcmVzZXJ2ZWQsCj4gwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAob3B0
aW9uYWwpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAiZW5kX3BvaW50
cyIgOiBbeyAob3B0aW9uYWwpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAibWRlcGlkIiA6IHVpbnQ4LCAob3B0aW9uYWwpCj4gwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAicm9sZSIgOiAoInNvdXJjZSIgb3IgInNp
bmsiKSwgKG1hbmRhdG9yeSkKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCJzcGVjcyIgOlt7IChtYW5kYXRvcnkpCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAiZGF0YV90eXBlIiA6IHVpbnQx
NiwgKG1hbmRhdG9yeSkKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCJkZXNjcmlwdGlvbiIgOiBzdHJpbmcsIChvcHRpb25hbCkKPiDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoH1dCj4gwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9XQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgfQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBp
ZiAiZGF0YV9zcGVjIiBpcyBub3Qgc2V0LCBubyBTRFAgcmVjb3JkIHdpbGwgYmUKPiDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJlZ2lzdGVyZWQsIHNvIGFsbCB0aGUgb3RoZXIg
ZGF0YSBpbiB0aGUgZGljdGlvbmFyeQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgd2lsbCBiZSBpZ25vcmVkCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oEluc3RhbmNlIHdpbGwgYmUgY2xvc2VkIGJ5IHRoZSBjYWxsIG9yIGltcGxpY2l0bHkgd2hlbgo+
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdGhlIHByb2dyYW1zIGxlYXZlcyB0
aGUgYnVzLgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBQb3NzaWJsZSBl
cnJvcnM6IG9yZy5ibHVlei5FcnJvci5JbnZhbGlkQXJndW1lbnRzCj4KPiDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoHZvaWQgQ2xvc2VJbnN0YW5jZShvYmplY3QgcGF0aCkKPgo+IMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgQ2xvc2VzIHRoZSBIRFAgaW5zdGFuY2UgaWRlbnRpZmll
ZCBieSB0aGUgb2JqZWN0IHBhdGguCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqBBbHNvIGluc3RhbmNlIHdpbGwgYmUgY2xvc2VkIGlmIHRoZSBwcm9jZXNzIHRoYXQgc3RhcnRl
ZAo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGVhdmVzIHRoZSBidXMuIElm
IHRoZXJlIGlzIGEgU0RQIHJlY29yZCBhc3NvY2lhdGVkIHRvCj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqB0aGlzIGluc3RhbmNlIGl0IHdpbGwgYmUgcmVtb3ZlZC4KPgo+IMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUG9zc2libGUgZXJyb3JzOiBvcmcuYmx1
ZXouRXJyb3IuSW52YWxpZEFyZ3VtZW50cwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgb3JnLmJsdWV6LkVycm9yLk5vdEZvdW5kCj4K
PiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+Cj4gU2VydmljZSDCoCDCoCDCoCDCoCBvcmcuYmx1
ZXoKPiBJbnRlcmZhY2UgwqAgwqAgwqAgb3JnLmJsdWV6LkhlYWx0aERldmljZQo+IE9iamVjdCBw
YXRoIMKgIMKgIFt2YXJpYWJsZSBwcmVmaXhdL3toY2kwLGhjaTEsLi4ufS9kZXZfWFhfWFhfWFhf
WFhfWFhfWFgKPgo+IE1ldGhvZHMgwqAgwqAgwqAgwqAgYXJyYXkgR2V0SGVhbHRoSW5zdGFuY2Vz
KCkKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgR2V0cyB0aGUgaW5mb3Jt
YXRpb24gb2YgdGhlIHJlbW90ZSBpbnN0YW5jZXMgcHJlc2VudAo+IMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgaW4gdGhpcyBkZXZpY2UgYW5kIHB1Ymxpc2hlZCBvbiBpdHMgU0RQ
IHJlY29yZC4gVGhlCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZXR1cm5l
ZCBkYXRhIGZvbGxvd3MgdGhpcyBmb3JtYXQuCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoFt7ImlkIjogImFuIGluc3RhbmNlIGlkZW50aWZpY2F0aW9uIGFzIHN0cmluZyIs
Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgImRhdGFfc3BlYyIgOiBkYXRh
IHNwZWMsCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgImVuZF9wb2ludHMi
Ogo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgWyJtZGVw
aWQiOiB1aW50OCwKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCAicm9sZSIgwqA6ICJzb3VyY2UiIG9yICJzaW5rIiAsCj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgInNwZWNzIiA6IFt7Cj4gwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAiZHR5cGUiIMKg
IMKgIMKgIDogdWludDE2LAo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgImRlc2NyaXB0aW9uIiA6IHN0cmluZywgKG9wdGlvbmFsKQo+
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH1dCj4gwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBdCj4gwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9XTsKPgo+IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
Cj4KPiBTZXJ2aWNlIMKgIMKgIMKgIMKgIG9yZy5ibHVlego+IEludGVyZmFjZSDCoCDCoCDCoCBv
cmcuYmx1ZXouSGVhbHRoSW5zdGFuY2UKPiBPYmplY3QgcGF0aCDCoCDCoCBbdmFyaWFibGUgcHJl
Zml4XS97aGNpMCxoY2kxLC4uLn0ve2hkcDAsaGRwMSwuLi59Cj4KPiDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoG9iamVjdCBDb25uZWN0KHJlbW90ZV9pbnN0YW5jZV9pZCkKPgo+IMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgQ29ubmVjdHMgd2l0aCB0aGUgcmVtb3RlIGluc3RhbmNl
IGFuZCByZXR1cm5zIGl0cyBvYmplY3QKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoHBhdGguIFRvIGdldCB0aGUgc2Vzc2lvbiBpZHMgb24gYSByZW1vdGUgZGV2aWNlLCB5b3UK
PiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG11c3QgcnVuIHRoZSBHZXRIZWFs
dGhJbnN0YW5jZXMgaW4gdGhlIEhlYWx0aERldmljZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgb2JqZWN0Lgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqBQb3NzaWJsZSBlcnJvcnM6IG9yZy5ibHVlei5FcnJvci5JbnZhbGlkQXJndW1lbnRzCj4gwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBv
cmcuYmx1ZXouRXJyb3IuSGVhbHRoRXJyb3IKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdm9p
ZCBEaXNjb25uZWN0KG9iamVjdCBkZXZpY2UsIGJvb2xlYW4gY2FjaGUpCj4KPiDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoERpc2Nvbm5lY3QgZnJvbSB0aGUgcmVtb3RlIGRldmlj
ZS4gSWYgY2hhaGUgaXMgZmFsc2UsCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqBzdGF0ZSB3aWxsIGFsc28gYmUgZGVsZXRlZC4gT3RoZXJ3aXNlLCB0aGUgc3RhdGUgd2lsbCBi
ZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKga2VwdCBmb3IgYWxsb3dpbmcg
ZnV0dXJlIHJlY29ubmVjdGlvbnMgdW50aWwgdGhlIGFkYXB0ZXIKPiDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoGlzIHJlbW92ZWQuCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoFBvc3NpYmxlIGVycm9yczogb3JnLmJsdWV6LkVycm9yLkludmFsaWRBcmd1
bWVudHMKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoG9yZy5ibHVlei5FcnJvci5Ob3RGb3VuZAo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgb3JnLmJsdWV6LkVycm9yLkhl
YWx0aEVycm9yCj4KPiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+Cj4gU2VydmljZSDCoCDCoCDC
oCDCoCBvcmcuYmx1ZXoKPiBJbnRlcmZhY2UgwqAgwqAgwqAgb3JnLmJsdWV6LkhlYWx0aExpbmsK
PiBPYmplY3QgcGF0aCDCoCDCoCBbdmFyaWFibGUgcHJlZml4XS97aGNpMCxoY2kxLC4uLn0ve2hk
cDAsaGRwMSwuLi59L3JlbV9pbnN0X2lkCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGJvb2xl
YW4gRWNobyhhcnJheXtieXRlfSkKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgU2VuZHMgYW4gZWNobyBwZXRpdGlvbiB0byB0aGUgcmVtb3RlIGludGFuY2UuIFJldHVybnMK
PiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFRydWUgaWYgcmVzcG9uc2UgbWF0
Y2hlcyB3aXRoIHRoZSBidWZmZXIgc2VudC4gSWYgc29tZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgZXJyb3IgaXMgZGV0ZWN0ZWQgRmFsc2UgdmFsdWUgaXMgcmV0dXJuZWQg
YW5kIHRoZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYXNzb2NpYXRlZCBN
Q0wgaXMgY2xvc2VkLgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB1aW50MTYgT3BlbkRhdGFD
aGFubmVsKGJ5dGUgbWRlcGlkLCBieXRlIGNvbmZpZykKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgQ3JlYXRlcyBhIG5ldyBkYXRhIGNoYW5uZWwgd2l0aCB0aGUgaW5kaWNh
dGVkIGNvbmZpZwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdG8gdGhlIHJl
bW90ZSBNQ0FQIERhdGEgRW5kIFBvaW50IChNREVQKS4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoFRoZSBjb25maWd1cmF0aW9uIHNob3VsZCBpbmRpY2F0ZSB0aGUgY2hhbm5l
bCBxdWFsaXR5IG9mCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZXJ2aWNl
LiBJbiB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIEhEUCwgdmFsaWQgdmFsdWVzIGFyZQo+IMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgMHgwMSBmb3IgcmVsaWFibGUgY2hhbm5lbHMg
YW5kIDB4MDIgZm9yIHN0cmVhbWluZyBkYXRhCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqBjaGFubmVsLgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBS
ZXR1cm5zIHRoZSBkYXRhIGNoYW5uZWwgaWQuCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoFBvc3NpYmxlIGVycm9yczogb3JnLmJsdWV6LkVycm9yLkludmFsaWRBcmd1bWVu
dHMKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoG9yZy5ibHVlei5FcnJvci5IZWFsdGhFcnJvcgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqBhcnJheSBHZXREYXRhQ2hhbm5lbEZpbGVEZXNjcmlwdG9yKHVpbnQxNiBtZGxpZCkKPgoK
V291bGRuJ3QgYmUgYmV0dGVyIHRvIHBhc3MgdGhlIGZkIHRocm91Z2ggdGhlIExpbmtDb25uZWN0
ZWQgY2FsbCBvbgpBZ2VudD8gRG9pbmcgaXQgaGVyZSBhbGxvd3MgYW55IHByb2Nlc3MgdG8gZ2V0
IHRoZSBmZHMuCgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgR2V0cyBhIGZp
bGUgZGVzY3JpcHRvciB3aGVyZSBkYXRhIGNhbiBiZSByZWFkIG9yCj4gwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqB3cml0dGVuIGZvciByZWNlaXZlIG9yIHNlbnQgYnkgdGhlIGRh
dGEgY2hhbm5lbC4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFJldHVybnMg
YW4gYXJyYXkgb2YgZmlsZSBkZXNjcmlwdG9ycyBvbmUgZm9yIHdyaXRlCj4gwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBhbmQgb3RoZXIgZm9yIHJlYWQuCj4KPiDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFBvc3NpYmxlIGVycm9yczogb3JnLmJsdWV6LkVycm9y
LkludmFsaWRBcmd1bWVudHMKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoG9yZy5ibHVlei5FcnJvci5Ob3RGb3VuZAo+IMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgb3JnLmJs
dWV6LkVycm9yLkhlYWx0aEVycm9yCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHZvaWQgRGVs
ZXRlRGF0YUNoYW5uZWwodWludDE2IG1kbGlkKQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqBEZWxldGVzIGEgZGF0YSBjaGFubmVsIHNvIGl0IHdpbGwgbm90IGJlIGF2YWls
YWJsZSBmb3IKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVzZS4KPgo+IMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgUG9zc2libGUgZXJyb3JzOiBvcmcuYmx1
ZXouRXJyb3IuSW52YWxpZEFyZ3VtZW50cwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgb3JnLmJsdWV6LkVycm9yLk5vdEZvdW5kCj4g
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqBvcmcuYmx1ZXouRXJyb3IuSGVhbHRoRXJyb3IKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
dm9pZCBEZWxldGVBbGxEYXRhQ2hhbm5lbHMoKQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqBEZWxldGVzIGFsbCBkYXRhIGNoYW5uZWxzIHNvIGl0IHdpbGwgbm90IGJlIGF2
YWlsYWJsZQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZm9yIHVzZS4gVHlw
aWNhbGx5IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gdGhlCj4gwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqBjb25uZWN0aW9uIHdpdGggdGhlIHJlbW90ZSBkZXZpY2Ugd2ls
bCBiZSBjbG9zZWQKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBlcm1hbmVu
dGx5Cj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFBvc3NpYmxlIGVycm9y
czogb3JnLmJsdWV6LkVycm9yLkhlYWx0aEVycm9yCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oGRpY3QgR2V0RGF0YUNoYW5uZWxTdGF0dXMoKQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqBSZXR1cm4gYSBkaWN0aW9uYXJ5IHdpdGggYWxsIHRoZSBkYXRhIGNoYW5uZWxz
IHRoYXQKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNhbiBiZSB1c2VkIHRv
IHNlbmQgZGF0YSByaWdodCBub3cuIFRoZSBkaWN0aW9uYXJ5Cj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqBpcyBmb3JtZWQgbGlrZSBmb2xsb3dzOgo+IMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgewo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgInJlbGlhYmxlIjogW21kbGlkX3IxLCBtZGxpZF9yMiwgLi4uXSwKPiDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCJzdHJlYW1pbmci
IDogW21kbGlkX3MxLCBtZGxpZF9zMiwgLi4uXQo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgfQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBUaGUgZmlz
dCByZWxpYWJsZSBkYXRhIGNoYW5uZWwgd2lsbCBhbHdheXMgYmUgdGhlIGZpcnN0Cj4gwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBkYXRhIGNoYW5uZWwgaW4gcmVsaWFibGUgYXJy
YXkuCj4KPiBIZWFsdGhBZ2VudCBoaWVyYXJjaHkKPiA9PT09PT09PT09PT09PT09PT0KPgo+ICh0
aGlzIG9iamVjdCBpcyBpbXBsZW1lbnRlZCBieSB0aGUgSERQIGNsaWVudCBhbiByZWNlaXZlcyBu
b3RpZmljYXRpb25zKQo+Cj4gU2VydmljZSDCoCDCoCDCoCDCoCB1bmlxdWUgbmFtZQo+IEludGVy
ZmFjZSDCoCDCoCDCoCBvcmcuYmx1ZXouSGVhbHRoQWdlbnQKPiBPYmplY3QgcGF0aCDCoCDCoCBm
cmVlbHkgZGVmaW5hYmxlCj4KPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHZvaWQgTGlua0Nvbm5l
Y3RlZChvYmplY3QgcGF0aCkKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
VGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW5ldmVyIGEgbmV3IGNvbm5lY3Rpb24KPiDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGhhcyBiZWVuIGVzdGFibGlzaGVkIG92ZXIgdGhl
IGNvbnRyb2wgY2hhbm5lbCBvZiB0aGUKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoGN1cnJlbnQgSERQIGluc3RhbmNlLiBUaGUgb2JqZWN0IHBhdGggcGFyZW1ldGVyIGNvbnRh
aW5zCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB0aGUgb2JqZWN0IHBhdGgg
b2YgdGhlIGNyZWF0ZWQgSGVhbHRoTGluay4KPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdm9p
ZCBMaW5rRGlzY29ubmVjdGVkKG9iamVjdCBwYXRoKQo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiBhIHJlbW90ZSBkZXZpY2Ug
aXMKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGRpc2Nvbm5lY3RlZCBkZWZp
bml0aXZlbHkuIEFueSBmdXR1cmUgcmVjb25uZWN0aW9ucwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgd2lsbCBmYWlsLiBBbHNvIGFsbCBkYXRhIGNoYW5uZWxzIGFzc29jaWF0
ZWQgdG8gdGhpcwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZGV2aWNlIHdp
bGwgYmUgY2xvc2VkLgo+Cj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB2b2lkIENyZWF0ZWREYXRh
Q2hhbm5lbChvYmplY3QgcGF0aCwgdWludDE2IG1kbGlkLCBieXRlIGNvbmYpCj4KPiDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuIGEg
bmV3IGRhdGEgY2hhbm5lbCBpcyBjcmVhdGVkCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqBUaGUgcGF0aCBjb250YWlucyB0aGUgb2JqZWN0IHBhdGggb2YgdGhlIEhlYWx0aExp
bmsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHdoZXJlIHRoZSBuZXcgY29u
bmVjdGlvbiBpcyBjcmVhdGVkLCB0aGUgbWRsaWQgaXMgdGhlCj4gwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqBkYXRhIGNoYW5uZWwgaWRlbnRpZmljYXRvciBhbmQgY29uZiBpcyB0
aGUgcXVlIHF1YWxpdHkKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG9mIHNl
cnZpY2Ugb2YgdGhlIGRhdGEgY2hhbm5lbCAoMHgwMSByZWxpYWJsZSwgMHgwMgo+IMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgc3RyZWFtaW5nKS4KPgo+IMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgdm9pZCBEZWxldGVkRGF0YUNoYW5uZWwob2JqZWN0IHBhdGgsIHVpbnQxNiBtZGxp
ZCkKPgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgVGhpcyBtZXRob2QgaXMg
Y2FsbGVkIHdoZW4gYSBkYXRhIGNoYW5uZWwgaXMgY2xvc2VkLgo+IMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgQWZ0ZXIgdGhpcyBjYWxsIHRoZSBkYXRhIGNoYW5uZWwgd2lsbCBu
b3QgYmUgdmFsaWQgYW5kCj4gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjYW4g
YmUgcmV1c2VkIGZvciBmdXR1cmUgY3JlYXRlZCBkYXRhIGNoYW5uZWxzLgo+IC0tCj4gVG8gdW5z
dWJzY3JpYmUgZnJvbSB0aGlzIGxpc3Q6IHNlbmQgdGhlIGxpbmUgInVuc3Vic2NyaWJlIGxpbnV4
LWJsdWV0b290aCIgaW4KPiB0aGUgYm9keSBvZiBhIG1lc3NhZ2UgdG8gbWFqb3Jkb21vQHZnZXIu
a2VybmVsLm9yZwo+IE1vcmUgbWFqb3Jkb21vIGluZm8gYXQgwqBodHRwOi8vdmdlci5rZXJuZWwu
b3JnL21ham9yZG9tby1pbmZvLmh0bWwKPgoKCgotLSAKSm/Do28gUGF1bG8gUmVjaGkgVml0YQpo
dHRwOi8vanBydml0YS53b3JkcHJlc3MuY29tLwo=

^ permalink raw reply

* Re: [PATCH] Bluetooth: Add blacklist support for incoming connections
From: Johan Hedberg @ 2010-05-17 20:42 UTC (permalink / raw)
  To: jaikumar Ganesh; +Cc: linux-bluetooth
In-Reply-To: <AANLkTil3cZu0tfsemxC2DrXTW7gmXU8-MXYKeWyS9t0M@mail.gmail.com>

Hi Jaikumar,

On Mon, May 17, 2010, jaikumar Ganesh wrote:
> Is there any use case for this that we are trying to solve i.e why are we
> maintaining the list at the baseband level itself rather than reject it
> somewhere in the upper layers or in the app that uses Bluez?

E.g. in the case that some device keeps spamming us with pairing
requests it's good to be able block them on a low level. Also this way
there doesn't need to be duplicate code in each application to handle
misbehaving devices. Furthermore, applications would probably want to
keep serving legitimate devices while dealing with rogue devices at the
same time. This feature allows the applications to simply shut out the
misbehaving device on a low level and not worry about it after that
(which in turn should hopefully simplify the application logic).

End user and application concerns aside, what I'm personally looking
forward to using this feature for is at the UPF's. It has happened quite
often that platforms (particularly car kits and headsets) forget to
delete our bdaddr after the test session and keep spamming us with
connect requests throughout the rest of the event. This kind of behavior
makes testing more difficult and messes up HCI traces, so having a
simple switch to block out a device will be nice.

Johan

^ permalink raw reply

* Re: [PATCH] Kernel crash when krfcomm is preempted by l2cap tasklet
From: Gustavo F. Padovan @ 2010-05-17 19:06 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: Bluettooth Linux, marcel
In-Reply-To: <AANLkTimyNqIdMoZ6J6InYRzD1JNl1Fsv-CdVpd84pjot@mail.gmail.com>

Hi Andrei,

* Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-05-17 12:45:=
50 +0300]:

> Hi Gustavo,
>=20
> Thanks for reviewing the patch. Please check new patches attached and
> comments below:
>=20
> On Sun, May 16, 2010 at 11:31 AM, Gustavo F. Padovan
> <gustavo@padovan.org> wrote:
> > Hi Andrei,
> >
> > * Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-05-14 18=
:39:40 +0300]:
> >
> >> Hi all,
> >>
> >> We have a bug with race condition between l2cap tasklet and krfcomm pr=
ocess.
> >>
> >> When sending following sequence:
> >>
> >> ...
> >> No. =A0 =A0 Time =A0 =A0 =A0 =A0Source =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
Destination =A0 =A0 =A0 =A0 =A0 Protocol Info
> >> =A0 =A0 =A089 1.951202 =A0 =A0 =A0 =A0 =A0 =A0RFCOMM =A0 Rcvd DISC DLC=
I=3D20
> >> =A0 =A0 =A090 1.951324 =A0 =A0 =A0 =A0 =A0 =A0RFCOMM =A0 Sent UA DLCI=
=3D20
> >> =A0 =A0 =A091 1.959381 =A0 =A0 =A0 =A0 =A0 =A0HCI_EVT =A0 Number of Co=
mpleted Packets
> >> =A0 =A0 =A092 1.966461 =A0 =A0 =A0 =A0 =A0 =A0RFCOMM =A0 Rcvd DISC DLC=
I=3D0
> >> =A0 =A0 =A093 1.966492 =A0 =A0 =A0 =A0 =A0 =A0L2CAP =A0 =A0Rcvd Discon=
nect Request
> >> =A0 =A0 =A094 1.972595 =A0 =A0 =A0 =A0 =A0 =A0L2CAP =A0 =A0Sent Discon=
nect Response
> >>
> >> ...
> >>
> >> krfcommd kernel thread is preempted with l2cap tasklet which remove l2=
cap_conn
> >> (L2CAP connection handler structure). Then rfcomm thread tries to send=
 RFCOMM
> >> UA which is reply to RFCOMM DISC and when de-referencing l2cap_conn cr=
ash
> >> happens.
> >>
> >> ...
> >> [ =A0694.175933] Unable to handle kernel NULL pointer dereference at
> >> virtual address 00000000
> >> [ =A0694.184936] pgd =3D c0004000
> >> [ =A0694.187683] [00000000] *pgd=3D00000000
> >> [ =A0694.191711] Internal error: Oops: 5 [#1] PREEMPT
> >> [ =A0694.196350] last sysfs file:
> >> /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
> >> [ =A0694.260375] CPU: 0 =A0 =A0Not tainted =A0(2.6.32.10 #1)
> >> [ =A0694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
> >> [ =A0694.270721] LR is at 0xd7017303
> >> ...
> >> [ =A0694.525085] Backtrace:
> >> [ =A0694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap])
> >> from [<c02f2cc8>] (sock_sendmsg+0xb8
> >> [ =A0694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>]
> >> (kernel_sendmsg+0x48/0x80)
> >> ...
> >>
> >> I have a patch which fixes the issue but not sure that there is no
> >> better way. Waiting for comments.
> >>
> >> Currently I am investigating possibility to:
> >> - implement l2cap_conn reference counting
> >
> > sock_owned_by_user() gives the same effect as a ref count. See comments=
 below.
> >
>=20
> Yes. For this cases this is enough. But proper refcounting is always
> better than this "effects" ;)
>=20
> >> - use socket backlog queue to process l2cap packets later when socket =
is not
> >> owned by the process.
> >
> > You actually don't need a backlog queue here. You can process the signal
> > packet, skipping the l2cap_chan_del() call;
> >
> ...
> >> + =A0 =A0 /* sk is locked in krfcomm process */
> >> + =A0 =A0 if (sock_owned_by_user(sk)) {
> >> + =A0 =A0 =A0 =A0 =A0 =A0 BT_DBG("sk %p is owned by user", sk);
> >> + =A0 =A0 =A0 =A0 =A0 =A0 bh_unlock_sock(sk);
> >> + =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> >> + =A0 =A0 }
> >
> > That's wrong. Use the sock_owned_by_user() only to avoid the
> > l2cap_chan_del() call, so you can process all the rest of the function
> > and send the Disconnect Response.
>=20
> I have changed the patch so that it only prevents l2cap_chan_del
> -		l2cap_chan_del(sk, ECONNREFUSED);
> +		/* delete l2cap channel if sk is not owned by user */
> +		if (!sock_owned_by_user(sk))
> +			l2cap_chan_del(sk, ECONNREFUSED);
>=20
> Then still l2cap_sock_kill(sk) removes sk but in the second patch sk is
> hold with sock_hold(sk) until rfcomm is still processing packet.

Hmm, I missed the l2cap_sock_kill(). So I guess you can invert the if
condition and unlock the socket and return if sock is owned by user,
right?

Marcel, do you agree with that change?

>=20
> > The same check should be added to l2cap_connect_rsp() and
> > l2cap_disconnect_rsp(), since they call l2cap_chan_del() under bh
> > context as well. ;)
>=20
> Added.
>=20
> Regards,
> Andrei Emeltchenko

> From 8531c8add8a378fc24b92f2c2311b01a7b1f63fc Mon Sep 17 00:00:00 2001
> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> Date: Mon, 17 May 2010 12:10:46 +0300
> Subject: [PATCH 1/2] Bluetooth: Check sk is not owned before freeing l2ca=
p_conn
>=20
> Check that socket sk is not locked in user process before removing
> l2cap connection handler.
>=20
> krfcommd kernel thread may be preempted with l2cap tasklet which remove
> l2cap_conn structure. If krfcommd is in process of sending of RFCOMM reply
> (like "RFCOMM UA" reply to "RFCOMM DISC") then kernel crash happens.
>=20
> ...
> [  694.175933] Unable to handle kernel NULL pointer dereference at virtua=
l address 00000000
> [  694.184936] pgd =3D c0004000
> [  694.187683] [00000000] *pgd=3D00000000
> [  694.191711] Internal error: Oops: 5 [#1] PREEMPT
> [  694.196350] last sysfs file: /sys/devices/platform/hci_h4p/firmware/hc=
i_h4p/loading
> [  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
> [  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
> [  694.270721] LR is at 0xd7017303
> ...
> [  694.525085] Backtrace:
> [  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap]) from [=
<c02f2cc8>] (sock_sendmsg+0xb8/0xd8)
> [  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>] (ke=
rnel_sendmsg+0x48/0x80)
> ...
>=20
> Modified version after comments of Gustavo F. Padovan <gustavo@padovan.or=
g>
>=20
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
>  net/bluetooth/l2cap.c |   14 +++++++++++---
>  1 files changed, 11 insertions(+), 3 deletions(-)
>=20
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index bb00015..794f2b7 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -2927,7 +2927,9 @@ static inline int l2cap_connect_rsp(struct l2cap_co=
nn *conn, struct l2cap_cmd_hd
>  		break;
> =20
>  	default:
> -		l2cap_chan_del(sk, ECONNREFUSED);
> +		/* delete l2cap channel if sk is not owned by user */
> +		if (!sock_owned_by_user(sk))
> +			l2cap_chan_del(sk, ECONNREFUSED);
>  		break;
>  	}
> =20
> @@ -3135,7 +3137,10 @@ static inline int l2cap_disconnect_req(struct l2ca=
p_conn *conn, struct l2cap_cmd
>  		del_timer(&l2cap_pi(sk)->ack_timer);
>  	}
> =20
> -	l2cap_chan_del(sk, ECONNRESET);
> +	/* delete l2cap channel if sk is not owned by user */
> +	if (!sock_owned_by_user(sk))
> +		l2cap_chan_del(sk, ECONNRESET);
> +
>  	bh_unlock_sock(sk);
> =20
>  	l2cap_sock_kill(sk);
> @@ -3167,7 +3172,10 @@ static inline int l2cap_disconnect_rsp(struct l2ca=
p_conn *conn, struct l2cap_cmd
>  		del_timer(&l2cap_pi(sk)->ack_timer);
>  	}
> =20
> -	l2cap_chan_del(sk, 0);
> +	/* delete l2cap channel if sk is not owned by user */
> +	if (!sock_owned_by_user(sk))
> +		l2cap_chan_del(sk, 0);
> +
>  	bh_unlock_sock(sk);
> =20
>  	l2cap_sock_kill(sk);
> --=20
> 1.7.0.4
>=20

> From 99ffb4e41ff46022cbc52f3c947425791de7fa39 Mon Sep 17 00:00:00 2001
> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> Date: Mon, 17 May 2010 12:28:06 +0300
> Subject: [PATCH 2/2] Bluetooth: Prevent sk freeing in tasklet using refco=
unt
>=20
> Socket sk may be freed in tasklet while still be in use in krfcommd
> process. Use refcount to mark sk as used.
>=20
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
>  net/bluetooth/l2cap.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
>=20
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 794f2b7..bf762d6 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -1724,6 +1724,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, s=
truct socket *sock, struct ms
>  	if (msg->msg_flags & MSG_OOB)
>  		return -EOPNOTSUPP;
> =20
> +	sock_hold(sk);
>  	lock_sock(sk);
> =20
>  	if (sk->sk_state !=3D BT_CONNECTED) {
> @@ -1808,6 +1809,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, s=
truct socket *sock, struct ms
> =20
>  done:
>  	release_sock(sk);
> +	sock_put(sk);
>  	return err;
>  }
> =20
> --=20
> 1.7.0.4
>=20


--=20
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH 1/2] Add dynamic debug feature
From: Gustavo F. Padovan @ 2010-05-17 16:53 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1274102952.26613.20.camel@localhost.localdomain>

Hi Marcel,

* Marcel Holtmann <marcel@holtmann.org> [2010-05-17 15:29:12 +0200]:

> Hi Gustavo,
> 
> > It is still needed a sed work in the sources to changes debug() to DBG()
> > 
> > Thanks, to Vinicius Gomes that helped me sort out a linking issue with
> > this patch.
> > ---
> >  src/logging.c |   64 +++++++++++++++++++++++++++++++++++++++++---------------
> >  src/logging.h |   28 +++++++++++++++++++++++-
> >  src/main.c    |   34 ++++++++++++++----------------
> >  tracer/main.c |   24 +++++----------------
> >  4 files changed, 95 insertions(+), 55 deletions(-)
> > 

...

> 
> For the tracer lets do syslog manually and not intersect it with the
> dynamic debug here. You might wanna send this as a separate patch to
> remove the usage of start_logging first from it.

Thanks for the comments.

> 
> And then in the end we should rename this to src/log.c of course to make
> it match with ConnMan and oFono.

Do you have others tasks in mind to make more parts of BlueZ match
ConnMan and oFono? I can work on them as part of my GSoC. ;)

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH] Avoid multiple inclusions of adapter.h
From: Johan Hedberg @ 2010-05-17 16:06 UTC (permalink / raw)
  To: Jose Antonio Santos Cadenas; +Cc: linux-bluetooth
In-Reply-To: <1273747136-8816-1-git-send-email-santoscadenas@gmail.com>

Hi,

On Thu, May 13, 2010, Jose Antonio Santos Cadenas wrote:
> ---
>  src/adapter.h |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/src/adapter.h b/src/adapter.h
> index 9b4ce10..8812ed8 100644
> --- a/src/adapter.h
> +++ b/src/adapter.h
> @@ -22,6 +22,9 @@
>   *
>   */
>  
> +#ifndef __ADAPTER_H__
> +#define __ADAPTER_H__
> +
>  #include <bluetooth/bluetooth.h>
>  #include <dbus/dbus.h>
>  #include <glib.h>
> @@ -183,3 +186,5 @@ struct btd_adapter_ops {
>  int btd_register_adapter_ops(struct btd_adapter_ops *btd_adapter_ops);
>  void btd_adapter_cleanup_ops(struct btd_adapter_ops *btd_adapter_ops);
>  int adapter_ops_setup(void);
> +
> +#endif /* __ADAPTER_H__ */

Lack of these defines is actually intentional for headsers which aren't
part of any public library. The intention is to keep the header
dependencies simple and get errors as soon as there's a circular
dependency between them.

Johan

^ permalink raw reply

* [PATCH v2] Bluetooth: Add blacklist support for incoming connections
From: johan.hedberg @ 2010-05-17 15:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Johan Hedberg

From: Johan Hedberg <johan.hedberg@nokia.com>

In some circumstances it could be desirable to reject incoming
connections on the baseband level. This patch adds this feature through
two new ioctl's: HCIBLOCKADDR and HCIUNBLOCKADDR. Both take a simple
Bluetooth address as a parameter. BDADDR_ANY can be used with
HCIUNBLOCKADDR to remove all devices from the blacklist.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 fs/compat_ioctl.c                |    2 +
 include/net/bluetooth/hci.h      |    3 +
 include/net/bluetooth/hci_core.h |    8 +++
 net/bluetooth/hci_core.c         |    2 +
 net/bluetooth/hci_event.c        |    2 +-
 net/bluetooth/hci_sock.c         |   90 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 106 insertions(+), 1 deletions(-)

diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 641640d..1863896 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1328,6 +1328,8 @@ COMPATIBLE_IOCTL(HCISETLINKPOL)
 COMPATIBLE_IOCTL(HCISETLINKMODE)
 COMPATIBLE_IOCTL(HCISETACLMTU)
 COMPATIBLE_IOCTL(HCISETSCOMTU)
+COMPATIBLE_IOCTL(HCIBLOCKADDR)
+COMPATIBLE_IOCTL(HCIUNBLOCKADDR)
 COMPATIBLE_IOCTL(HCIINQUIRY)
 COMPATIBLE_IOCTL(HCIUARTSETPROTO)
 COMPATIBLE_IOCTL(HCIUARTGETPROTO)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fc0c502..ca2518e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -100,6 +100,9 @@ enum {
 #define HCISETACLMTU	_IOW('H', 227, int)
 #define HCISETSCOMTU	_IOW('H', 228, int)
 
+#define HCIBLOCKADDR	_IOW('H', 230, int)
+#define HCIUNBLOCKADDR	_IOW('H', 231, int)
+
 #define HCIINQUIRY	_IOR('H', 240, int)
 
 /* HCI timeouts */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ce3c99e..ffe7827 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -62,6 +62,11 @@ struct hci_conn_hash {
 	unsigned int     sco_num;
 };
 
+struct bdaddr_list {
+	struct list_head list;
+	bdaddr_t bdaddr;
+};
+
 struct hci_dev {
 	struct list_head list;
 	spinlock_t	lock;
@@ -125,6 +130,7 @@ struct hci_dev {
 
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
+	struct bdaddr_list	blacklist;
 
 	struct hci_dev_stats	stat;
 
@@ -422,6 +428,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
 int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
 int hci_inquiry(void __user *arg);
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4ad2319..669b0db 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -922,6 +922,8 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	hci_conn_hash_init(hdev);
 
+	INIT_LIST_HEAD(&hdev->blacklist.list);
+
 	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
 	atomic_set(&hdev->promisc, 0);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6c57fc7..1efaf50 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -952,7 +952,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
 
 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
 
-	if (mask & HCI_LM_ACCEPT) {
+	if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
 		/* Connection accepted */
 		struct inquiry_entry *ie;
 		struct hci_conn *conn;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 38f08f6..7668c73 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -165,6 +165,86 @@ static int hci_sock_release(struct socket *sock)
 	return 0;
 }
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct list_head *p;
+	struct bdaddr_list *blacklist = &hdev->blacklist;
+
+	list_for_each(p, &blacklist->list) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		if (bacmp(bdaddr, &b->bdaddr) == 0)
+			return b;
+	}
+
+	return NULL;
+}
+
+static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+{
+	bdaddr_t bdaddr;
+	struct bdaddr_list *entry;
+
+	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+		return -EFAULT;
+
+	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+		return -EBADF;
+
+	if (hci_blacklist_lookup(hdev, &bdaddr))
+		return -EEXIST;
+
+	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	bacpy(&entry->bdaddr, &bdaddr);
+
+	list_add(&entry->list, &hdev->blacklist.list);
+
+	return 0;
+}
+
+static int hci_blacklist_clear(struct hci_dev *hdev)
+{
+	struct list_head *p, *n;
+	struct bdaddr_list *blacklist = &hdev->blacklist;
+
+	list_for_each_safe(p, n, &blacklist->list) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		list_del(p);
+		kfree(b);
+	}
+
+	return 0;
+}
+
+static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+{
+	bdaddr_t bdaddr;
+	struct bdaddr_list *entry;
+
+	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+		return -EFAULT;
+
+	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+		return hci_blacklist_clear(hdev);
+
+	entry = hci_blacklist_lookup(hdev, &bdaddr);
+	if (!entry)
+		return -ENOENT;
+
+	list_del(&entry->list);
+	kfree(entry);
+
+	return 0;
+}
+
 /* Ioctls that require bound socket */
 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
 {
@@ -194,6 +274,16 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
 	case HCIGETAUTHINFO:
 		return hci_get_auth_info(hdev, (void __user *) arg);
 
+	case HCIBLOCKADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EACCES;
+		return hci_blacklist_add(hdev, (void __user *) arg);
+
+	case HCIUNBLOCKADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EACCES;
+		return hci_blacklist_del(hdev, (void __user *) arg);
+
 	default:
 		if (hdev->ioctl)
 			return hdev->ioctl(hdev, cmd, arg);
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Bluetooth: Add blacklist support for incoming connections
From: Marcel Holtmann @ 2010-05-17 15:39 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, Johan Hedberg
In-Reply-To: <1274109587-26638-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> In some circumstances it could be desirable to reject incoming
> connections on the baseband level. This patch adds this feature through
> two new ioctl's: HCIBLOCKADDR and HCIUNBLOCKADDR. Both take a simple
> Bluetooth address as a parameter. BDADDR_ANY can be used with
> HCIUNBLOCKADDR to remove all devices from the blacklist.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> ---
>  fs/compat_ioctl.c                |    2 +
>  include/net/bluetooth/hci.h      |    3 +
>  include/net/bluetooth/hci_core.h |    8 +++
>  net/bluetooth/hci_core.c         |    2 +
>  net/bluetooth/hci_event.c        |    2 +-
>  net/bluetooth/hci_sock.c         |   90 ++++++++++++++++++++++++++++++++++++++
>  6 files changed, 106 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
> index 641640d..1863896 100644
> --- a/fs/compat_ioctl.c
> +++ b/fs/compat_ioctl.c
> @@ -1328,6 +1328,8 @@ COMPATIBLE_IOCTL(HCISETLINKPOL)
>  COMPATIBLE_IOCTL(HCISETLINKMODE)
>  COMPATIBLE_IOCTL(HCISETACLMTU)
>  COMPATIBLE_IOCTL(HCISETSCOMTU)
> +COMPATIBLE_IOCTL(HCIBLOCKADDR)
> +COMPATIBLE_IOCTL(HCIUNBLOCKADDR)
>  COMPATIBLE_IOCTL(HCIINQUIRY)
>  COMPATIBLE_IOCTL(HCIUARTSETPROTO)
>  COMPATIBLE_IOCTL(HCIUARTGETPROTO)
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index fc0c502..ca2518e 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -100,6 +100,9 @@ enum {
>  #define HCISETACLMTU	_IOW('H', 227, int)
>  #define HCISETSCOMTU	_IOW('H', 228, int)
>  
> +#define HCIBLOCKADDR	_IOW('H', 230, int)
> +#define HCIUNBLOCKADDR	_IOW('H', 231, int)
> +
>  #define HCIINQUIRY	_IOR('H', 240, int)
>  
>  /* HCI timeouts */
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index ce3c99e..ffe7827 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -62,6 +62,11 @@ struct hci_conn_hash {
>  	unsigned int     sco_num;
>  };
>  
> +struct bdaddr_list {
> +	struct list_head list;
> +	bdaddr_t bdaddr;
> +};
> +
>  struct hci_dev {
>  	struct list_head list;
>  	spinlock_t	lock;
> @@ -125,6 +130,7 @@ struct hci_dev {
>  
>  	struct inquiry_cache	inq_cache;
>  	struct hci_conn_hash	conn_hash;
> +	struct bdaddr_list	blacklist;
>  
>  	struct hci_dev_stats	stat;
>  
> @@ -422,6 +428,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
>  int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
>  int hci_inquiry(void __user *arg);
>  
> +struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
> +
>  void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
>  
>  int hci_recv_frame(struct sk_buff *skb);
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 4ad2319..669b0db 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -922,6 +922,8 @@ int hci_register_dev(struct hci_dev *hdev)
>  
>  	hci_conn_hash_init(hdev);
>  
> +	INIT_LIST_HEAD(&hdev->blacklist.list);
> +
>  	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
>  
>  	atomic_set(&hdev->promisc, 0);
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 6c57fc7..4d651fc 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -952,7 +952,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
>  
>  	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
>  
> -	if (mask & HCI_LM_ACCEPT) {
> +	if (mask & HCI_LM_ACCEPT && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {

to make this a bit more readable and clear, this should be like this:

	if ((mask & HCI_LM_ACCEPT) && !hci_blacklist(....

Otherwise patch looks fine:

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* [PATCH] Bluetooth: Add blacklist support for incoming connections
From: johan.hedberg @ 2010-05-17 15:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Johan Hedberg

From: Johan Hedberg <johan.hedberg@nokia.com>

In some circumstances it could be desirable to reject incoming
connections on the baseband level. This patch adds this feature through
two new ioctl's: HCIBLOCKADDR and HCIUNBLOCKADDR. Both take a simple
Bluetooth address as a parameter. BDADDR_ANY can be used with
HCIUNBLOCKADDR to remove all devices from the blacklist.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 fs/compat_ioctl.c                |    2 +
 include/net/bluetooth/hci.h      |    3 +
 include/net/bluetooth/hci_core.h |    8 +++
 net/bluetooth/hci_core.c         |    2 +
 net/bluetooth/hci_event.c        |    2 +-
 net/bluetooth/hci_sock.c         |   90 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 106 insertions(+), 1 deletions(-)

diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 641640d..1863896 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1328,6 +1328,8 @@ COMPATIBLE_IOCTL(HCISETLINKPOL)
 COMPATIBLE_IOCTL(HCISETLINKMODE)
 COMPATIBLE_IOCTL(HCISETACLMTU)
 COMPATIBLE_IOCTL(HCISETSCOMTU)
+COMPATIBLE_IOCTL(HCIBLOCKADDR)
+COMPATIBLE_IOCTL(HCIUNBLOCKADDR)
 COMPATIBLE_IOCTL(HCIINQUIRY)
 COMPATIBLE_IOCTL(HCIUARTSETPROTO)
 COMPATIBLE_IOCTL(HCIUARTGETPROTO)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fc0c502..ca2518e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -100,6 +100,9 @@ enum {
 #define HCISETACLMTU	_IOW('H', 227, int)
 #define HCISETSCOMTU	_IOW('H', 228, int)
 
+#define HCIBLOCKADDR	_IOW('H', 230, int)
+#define HCIUNBLOCKADDR	_IOW('H', 231, int)
+
 #define HCIINQUIRY	_IOR('H', 240, int)
 
 /* HCI timeouts */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ce3c99e..ffe7827 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -62,6 +62,11 @@ struct hci_conn_hash {
 	unsigned int     sco_num;
 };
 
+struct bdaddr_list {
+	struct list_head list;
+	bdaddr_t bdaddr;
+};
+
 struct hci_dev {
 	struct list_head list;
 	spinlock_t	lock;
@@ -125,6 +130,7 @@ struct hci_dev {
 
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
+	struct bdaddr_list	blacklist;
 
 	struct hci_dev_stats	stat;
 
@@ -422,6 +428,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
 int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
 int hci_inquiry(void __user *arg);
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4ad2319..669b0db 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -922,6 +922,8 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	hci_conn_hash_init(hdev);
 
+	INIT_LIST_HEAD(&hdev->blacklist.list);
+
 	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
 	atomic_set(&hdev->promisc, 0);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6c57fc7..4d651fc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -952,7 +952,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
 
 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
 
-	if (mask & HCI_LM_ACCEPT) {
+	if (mask & HCI_LM_ACCEPT && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
 		/* Connection accepted */
 		struct inquiry_entry *ie;
 		struct hci_conn *conn;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 38f08f6..7668c73 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -165,6 +165,86 @@ static int hci_sock_release(struct socket *sock)
 	return 0;
 }
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct list_head *p;
+	struct bdaddr_list *blacklist = &hdev->blacklist;
+
+	list_for_each(p, &blacklist->list) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		if (bacmp(bdaddr, &b->bdaddr) == 0)
+			return b;
+	}
+
+	return NULL;
+}
+
+static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+{
+	bdaddr_t bdaddr;
+	struct bdaddr_list *entry;
+
+	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+		return -EFAULT;
+
+	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+		return -EBADF;
+
+	if (hci_blacklist_lookup(hdev, &bdaddr))
+		return -EEXIST;
+
+	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	bacpy(&entry->bdaddr, &bdaddr);
+
+	list_add(&entry->list, &hdev->blacklist.list);
+
+	return 0;
+}
+
+static int hci_blacklist_clear(struct hci_dev *hdev)
+{
+	struct list_head *p, *n;
+	struct bdaddr_list *blacklist = &hdev->blacklist;
+
+	list_for_each_safe(p, n, &blacklist->list) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		list_del(p);
+		kfree(b);
+	}
+
+	return 0;
+}
+
+static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+{
+	bdaddr_t bdaddr;
+	struct bdaddr_list *entry;
+
+	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+		return -EFAULT;
+
+	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+		return hci_blacklist_clear(hdev);
+
+	entry = hci_blacklist_lookup(hdev, &bdaddr);
+	if (!entry)
+		return -ENOENT;
+
+	list_del(&entry->list);
+	kfree(entry);
+
+	return 0;
+}
+
 /* Ioctls that require bound socket */
 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
 {
@@ -194,6 +274,16 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
 	case HCIGETAUTHINFO:
 		return hci_get_auth_info(hdev, (void __user *) arg);
 
+	case HCIBLOCKADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EACCES;
+		return hci_blacklist_add(hdev, (void __user *) arg);
+
+	case HCIUNBLOCKADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EACCES;
+		return hci_blacklist_del(hdev, (void __user *) arg);
+
 	default:
 		if (hdev->ioctl)
 			return hdev->ioctl(hdev, cmd, arg);
-- 
1.7.0.4


^ permalink raw reply related

* HDP proposed API(0.5)
From: José Antonio Santos Cadenas @ 2010-05-17 14:54 UTC (permalink / raw)
  To: linux-bluetooth

Hope the last one :)

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

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		object CreateInstance(object path, dict config)

			Returns the path for the new HealthInstance object.
			The path parameter is the path of the remote 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
			in the SDP if is needed
			Dict is defined as bellow:
			{ "data_spec" : The data_spec is the data exchange
					specification (see section 5.2.10 of
					the specification document)
					possible values:
						0x00 = reserved,
						0x01 [IEEE 11073-20601],
						0x02..0xff reserved,
					(optional)
			  "end_points" : [{ (optional)
				"mdepid" : uint8, (optional)
				"role" : ("source" or "sink"), (mandatory)
				"specs" :[{ (mandatory)
					"data_type" : uint16, (mandatory)
					"description" : string, (optional)
				}]
			  }]
			}

			if "data_spec" is not set, no SDP record will be
			registered, so all the other data in the dictionary
			will be ignored

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

			Possible errors: org.bluez.Error.InvalidArguments

		void CloseInstance(object path)

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

			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		array GetHealthInstances()

			Gets the information of the remote instances present
			in this device and published on its SDP record. The
			returned data follows this format.

			[{"id": "an instance identification as string",
			 "data_spec" : data spec,
			 "end_points":
				["mdepid": uint8,
				 "role"  : "source" or "sink" ,
				 "specs" : [{
					"dtype"       : uint16,
					"description" : string, (optional)
				 }]
				]
			}];

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

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

		object Connect(remote_instance_id)

			Connects with the remote instance and returns its object
			path. To get the session ids on a remote device, you
			must run the GetHealthInstances in the HealthDevice
			object.

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

		void Disconnect(object device, boolean cache)

			Disconnect from the remote device. If chahe is false,
			state will also be deleted. Otherwise, the state will be
			kept for allowing future reconnections until the adapter
			is removed.

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

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

Service		org.bluez
Interface	org.bluez.HealthLink
Object path	[variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_inst_id

		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.

		uint16 OpenDataChannel(byte mdepid, byte config)

			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. In the current version of HDP, valid values are
			0x01 for reliable channels and 0x02 for streaming data
			channel.

			Returns the data channel id.

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

		array GetDataChannelFileDescriptor(uint16 mdlid)

			Gets a file descriptor where data can be read or
			written for receive or sent by the data channel.
			Returns an array of file descriptors one for write
			and other for read.

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

		void DeleteDataChannel(uint16 mdlid)

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

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

		void DeleteAllDataChannels()

			Deletes all data channels so it will not be available
			for 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": [mdlid_r1, mdlid_r2, ...],
				"streaming" : [mdlid_s1, mdlid_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 client an receives notifications)

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

		void LinkConnected(object path)

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

		void LinkDisconnected(object path)

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

		void CreatedDataChannel(object path, uint16 mdlid, byte conf)

			This method is called when a new data channel is created
			The path contains the object path of the HealthLink
			where the new connection is created, the mdlid is the
			data channel identificator and conf is the que quality
			of service of the data channel (0x01 reliable, 0x02
			streaming).

		void DeletedDataChannel(object path, uint16 mdlid)

			This method is called when a data channel is closed.
			After this call the data channel will not be valid and
			can be reused for future created data channels.

^ permalink raw reply

* Re: Software caused connection abort (103 )
From: john michelle @ 2010-05-17 14:32 UTC (permalink / raw)
  To: Gustavo F. Padovan, linux-bluetooth
In-Reply-To: <AANLkTin3FNuVegPI013fzLQn7YsHzpfr7ZymnCG1mpt-@mail.gmail.com>

One more Addition

>> The problem happens when you are already tranfering
>> SCO data?

yes,  it happens only during transferring SCO data

john


On Mon, May 17, 2010 at 5:21 PM, john michelle <jhnmichelle@gmail.com> wrote:
>> Hi Jonh,
>>
>> First of all, don't do top posting in this mailing list. ;)
>>
>
> Thanks for the advise , will keep that in mind for future posts.
>
>> In which bluez/kernel version the problem started? Any hardware update
>> during this time? The problem happens when you are already tranfering
>> SCO data?
>>
>
> I tried bluez versions 3.XX  and kernel 2.6.26(I think) the problem
> occurs and the kernel panics with no core dumps.then i tried with
> bluez 4.53-4.62 with
> Kernel 2.6.31 and 2.6.32. the connection abort problem occurs but the
> kernel doesn't
> Panic. regarding the hardware update you mean the dongle or the box.Anyway
> i changed both and tried different box's, this even happens on a box
> with 2 giga ram
> And core2 processor . as for the dongles i am using trust
>
> http://www.twenga.co.uk/prices-Bluetooth-2-USB-Adapter-10m-BT-2250p-TRUST-Wireless-network-card-adapter-176178-0
>
>  and also using no name dongles all the same problem.
>
>> Please post the output of hcidump when the connection abort happens.
>>
>
> well that is going to be a hard one since i have more than one dongle in place
> And very hard to predict which one will crash.i will work on this and update
> You as soon as i have the hcidump log.
>
>
>
>> I tried reproduce this issue in L2CAP but it is a bit hard, lets
>> say it happen once in a thousand, so it's not easy to track it. I have
>> to try reproduce that using the SCO, but I'm not used to that layer yet.
>> ;)
>
> I hoped that it happens 1 in 1000 in SCO , but it actually happens 1 in 15
>
>
> John
>
>
>
>>
>> Regards,
>>
>>>
>>> John
>>>
>>> On Fri, May 7, 2010 at 3:53 PM, Gustavo F. Padovan <gustavo@padovan.org> wrote:
>>> > * john michelle <jhnmichelle@gmail.com> [2010-05-07 15:49:05 -0400]:
>>> >
>>> >> Hi Bluetooth hackers,
>>> >>
>>> >> i am having this consistent problem with bluez , from time to time i
>>> >> get the error Software caused connection abort (103 )
>>> >> And the bluetooth stick seems to disconnect and reconnects. this
>>> >> happens during an sco connection and it occurs even
>>> >> More when i am having the voice stream comming through the internet
>>> >> rather than the lan.i don't know what exact
>>> >> Details you need to solve this problem please tell me and i will give
>>> >> you an immediate reply . i have linux kernel 2.6.33 and bluez 4.62
>>> >
>>> > I get the same problem sometimes when testing ERTM with l2test. So the
>>> > problem is on l2cap too. I didn't have time to debug this yet. Now that
>>> > someone else have confirmed it too, I'll to take a look at the problem.
>>> >
>>> >>
>>
>> --
>> Gustavo F. Padovan
>> http://padovan.org
>>
>

^ permalink raw reply

* Re: Software caused connection abort (103 )
From: john michelle @ 2010-05-17 14:21 UTC (permalink / raw)
  To: Gustavo F. Padovan, linux-bluetooth
In-Reply-To: <20100517023917.GI23754@vigoh>

> Hi Jonh,
>
> First of all, don't do top posting in this mailing list. ;)
>

Thanks for the advise , will keep that in mind for future posts.

> In which bluez/kernel version the problem started? Any hardware update
> during this time? The problem happens when you are already tranfering
> SCO data?
>

I tried bluez versions 3.XX  and kernel 2.6.26(I think) the problem
occurs and the kernel panics with no core dumps.then i tried with
bluez 4.53-4.62 with
Kernel 2.6.31 and 2.6.32. the connection abort problem occurs but the
kernel doesn't
Panic. regarding the hardware update you mean the dongle or the box.Anyway
i changed both and tried different box's, this even happens on a box
with 2 giga ram
And core2 processor . as for the dongles i am using trust

http://www.twenga.co.uk/prices-Bluetooth-2-USB-Adapter-10m-BT-2250p-TRUST-Wireless-network-card-adapter-176178-0

 and also using no name dongles all the same problem.

> Please post the output of hcidump when the connection abort happens.
>

well that is going to be a hard one since i have more than one dongle in place
And very hard to predict which one will crash.i will work on this and update
You as soon as i have the hcidump log.



> I tried reproduce this issue in L2CAP but it is a bit hard, lets
> say it happen once in a thousand, so it's not easy to track it. I have
> to try reproduce that using the SCO, but I'm not used to that layer yet.
> ;)

I hoped that it happens 1 in 1000 in SCO , but it actually happens 1 in 15


John



>
> Regards,
>
>>
>> John
>>
>> On Fri, May 7, 2010 at 3:53 PM, Gustavo F. Padovan <gustavo@padovan.org> wrote:
>> > * john michelle <jhnmichelle@gmail.com> [2010-05-07 15:49:05 -0400]:
>> >
>> >> Hi Bluetooth hackers,
>> >>
>> >> i am having this consistent problem with bluez , from time to time i
>> >> get the error Software caused connection abort (103 )
>> >> And the bluetooth stick seems to disconnect and reconnects. this
>> >> happens during an sco connection and it occurs even
>> >> More when i am having the voice stream comming through the internet
>> >> rather than the lan.i don't know what exact
>> >> Details you need to solve this problem please tell me and i will give
>> >> you an immediate reply . i have linux kernel 2.6.33 and bluez 4.62
>> >
>> > I get the same problem sometimes when testing ERTM with l2test. So the
>> > problem is on l2cap too. I didn't have time to debug this yet. Now that
>> > someone else have confirmed it too, I'll to take a look at the problem.
>> >
>> >>
>
> --
> Gustavo F. Padovan
> http://padovan.org
>

^ permalink raw reply

* Re: [PATCH 1/2] Add dynamic debug feature
From: Marcel Holtmann @ 2010-05-17 13:29 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <1273549901-28856-1-git-send-email-gustavo@padovan.org>

Hi Gustavo,

> It is still needed a sed work in the sources to changes debug() to DBG()
> 
> Thanks, to Vinicius Gomes that helped me sort out a linking issue with
> this patch.
> ---
>  src/logging.c |   64 +++++++++++++++++++++++++++++++++++++++++---------------
>  src/logging.h |   28 +++++++++++++++++++++++-
>  src/main.c    |   34 ++++++++++++++----------------
>  tracer/main.c |   24 +++++----------------
>  4 files changed, 95 insertions(+), 55 deletions(-)
> 
> diff --git a/src/logging.c b/src/logging.c
> index 704f848..a9956be 100644
> --- a/src/logging.c
> +++ b/src/logging.c
> @@ -29,9 +29,9 @@
>  #include <stdarg.h>
>  #include <syslog.h>
>  
> -#include "logging.h"
> +#include <glib.h>
>  
> -static volatile int debug_enabled = 0;
> +#include "logging.h"
>  
>  static inline void vinfo(const char *format, va_list ap)
>  {
> @@ -64,9 +64,6 @@ void debug(const char *format, ...)
>  {
>  	va_list ap;
>  
> -	if (!debug_enabled)
> -		return;
> -
>  	va_start(ap, format);
>  
>  	vsyslog(LOG_DEBUG, format, ap);
> @@ -74,26 +71,57 @@ void debug(const char *format, ...)
>  	va_end(ap);
>  }
>  
> -void toggle_debug(void)
> -{
> -	debug_enabled = (debug_enabled + 1) % 2;
> -}
> +extern struct bluez_debug_desc __start___debug[];
> +extern struct bluez_debug_desc __stop___debug[];

the prefix for bluetoothd is actually btd_.
 
> -void enable_debug(void)
> -{
> -	debug_enabled = 1;
> -}
> +static gchar **enabled = NULL;
>  
> -void disable_debug(void)
> +static gboolean is_enabled(struct bluez_debug_desc *desc)
>  {
> -	debug_enabled = 0;
> +        int i;
> +
> +        if (enabled == NULL)
> +                return 0;
> +
> +        for (i = 0; enabled[i] != NULL; i++) {
> +                if (desc->name != NULL && g_pattern_match_simple(enabled[i],
> +                                                        desc->name) == TRUE)
> +                        return 1;
> +                if (desc->file != NULL && g_pattern_match_simple(enabled[i],
> +                                                        desc->file) == TRUE)
> +                        return 1;
> +        }
> +
> +        return 0;
>  }
>  
> -void start_logging(const char *ident, const char *message, ...)
> +void start_logging(const char *debug, int detach, const char *ident, const char *message, ...)
>  {

Lets remove the ident and message stuff and just hardcode it. You are
working off a some old stuff where we thought to make this generic, but
that is pointless. So while you are touching this, lets stop it now and
remove any old cruft.

> +	int option = LOG_NDELAY | LOG_PID;
> +	struct bluez_debug_desc *desc;

Prefix should be btd_ here as well.

And while at it, please sync these into __btd_log_init() and
__btd_log_cleanup() like we do for oFono and ConnMan.

> +	const char *name = NULL, *file = NULL;
>  	va_list ap;
>  
> -	openlog(ident, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
> +	if (debug != NULL)
> +		enabled = g_strsplit_set(debug, ":, ", 0);
> +
> +	for (desc = __start___debug; desc < __stop___debug; desc++) {
> +		if (file != NULL || name != NULL) {
> +			if (g_strcmp0(desc->file, file) == 0) {
> +				if (desc->name == NULL)
> +					desc->name = name;
> +			} else
> +				file = NULL;
> +		}
> +
> +		if (is_enabled(desc))
> +			desc->flags |= BLUEZ_DEBUG_FLAG_PRINT;
> +	}
> +
> +	if (!detach)
> +		option |= LOG_PERROR;
> +
> +	openlog(ident, option, LOG_DAEMON);
>  
>  	va_start(ap, message);
>  
> @@ -105,4 +133,6 @@ void start_logging(const char *ident, const char *message, ...)
>  void stop_logging(void)
>  {
>  	closelog();
> +
> +	g_strfreev(enabled);
>  }
> diff --git a/src/logging.h b/src/logging.h
> index 2e9d564..b1a58a8 100644
> --- a/src/logging.h
> +++ b/src/logging.h
> @@ -30,9 +30,33 @@ void debug(const char *format, ...) __attribute__((format(printf, 1, 2)));
>  void toggle_debug(void);
>  void enable_debug(void);
>  void disable_debug(void);
> -void start_logging(const char *ident, const char *message, ...);
> +void start_logging(const char *debug, int detach, const char *ident, const char *message, ...);
>  void stop_logging(void);
>  
> -#define DBG(fmt, arg...)  debug("%s: " fmt "\n" , __FUNCTION__ , ## arg)
> +struct bluez_debug_desc {
> +        const char *name;
> +        const char *file;
> +#define BLUEZ_DEBUG_FLAG_DEFAULT (0)
> +#define BLUEZ_DEBUG_FLAG_PRINT   (1 << 0)
> +        unsigned int flags;
> +} __attribute__((aligned(8)));

Prefix btd_ and BTD_ please.

> +
> +/**
> + * DBG:
> + * @fmt: format string
> + * @arg...: list of arguments
> + *
> + * Simple macro around debug() which also include the function
> + * name it is called in.
> + */
> +#define DBG(fmt, arg...) do { \
> +        static struct bluez_debug_desc __bluez_debug_desc \
> +        __attribute__((used, section("__debug"), aligned(8))) = { \
> +                .file = __FILE__, .flags = BLUEZ_DEBUG_FLAG_DEFAULT, \
> +        }; \
> +        if (__bluez_debug_desc.flags & BLUEZ_DEBUG_FLAG_PRINT) \
> +                debug("%s:%s() " fmt, \
> +                                        __FILE__, __FUNCTION__ , ## arg); \
> +} while (0)
>  
>  #endif /* __LOGGING_H */
> diff --git a/src/main.c b/src/main.c
> index 014d8b6..c090493 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -288,13 +288,8 @@ static void sig_term(int sig)
>  	g_main_loop_quit(event_loop);
>  }
>  
> -static void sig_debug(int sig)
> -{
> -	toggle_debug();
> -}
> -
> +static gchar *option_debug = NULL;
>  static gboolean option_detach = TRUE;
> -static gboolean option_debug = FALSE;
>  static gboolean option_udev = FALSE;
>  
>  static guint last_adapter_timeout = 0;
> @@ -327,12 +322,22 @@ void btd_stop_exit_timer(void)
>  	last_adapter_timeout = 0;
>  }
>  
> +static gboolean parse_debug(const char *key, const char *value, gpointer user_data, GError **error)
> +{
> +	option_debug = g_strdup(value);
> +	if (!option_debug)
> +		option_debug = g_strdup("*");
> +
> +	return TRUE;
> +}

This looks too complicated and weird. Why not check for value == NULL
directly?

>  static GOptionEntry options[] = {
>  	{ "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
>  				G_OPTION_ARG_NONE, &option_detach,
>  				"Don't run as daemon in background" },
> -	{ "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
> -				"Enable debug information output" },
> +	{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
> +				G_OPTION_ARG_CALLBACK, parse_debug,
> +				"Enable debug information output", "DEBUG" },
>  	{ "udev", 'u', 0, G_OPTION_ARG_NONE, &option_udev,
>  				"Run from udev mode of operation" },
>  	{ NULL },
> @@ -392,7 +397,8 @@ int main(int argc, char *argv[])
>  
>  	umask(0077);
>  
> -	start_logging("bluetoothd", "Bluetooth daemon %s", VERSION);
> +	start_logging(option_debug, option_detach,
> +			"bluetoothd", "Bluetooth daemon %s", VERSION);
>  
>  	memset(&sa, 0, sizeof(sa));
>  	sa.sa_flags = SA_NOCLDSTOP;
> @@ -400,17 +406,9 @@ int main(int argc, char *argv[])
>  	sigaction(SIGTERM, &sa, NULL);
>  	sigaction(SIGINT,  &sa, NULL);
>  
> -	sa.sa_handler = sig_debug;
> -	sigaction(SIGUSR2, &sa, NULL);
> -
>  	sa.sa_handler = SIG_IGN;
>  	sigaction(SIGPIPE, &sa, NULL);
>  
> -	if (option_debug == TRUE) {
> -		info("Enabling debug information");
> -		enable_debug();
> -	}
> -
>  	config = load_config(CONFIGDIR "/main.conf");
>  
>  	parse_config(config);
> @@ -446,7 +444,7 @@ int main(int argc, char *argv[])
>  
>  	rfkill_init();
>  
> -	debug("Entering main loop");
> +	DBG("Entering main loop");
>  
>  	g_main_loop_run(event_loop);
>  
> diff --git a/tracer/main.c b/tracer/main.c
> index 5ec5ff2..0257e00 100644
> --- a/tracer/main.c
> +++ b/tracer/main.c
> @@ -48,20 +48,15 @@ static void sig_term(int sig)
>  	g_main_loop_quit(event_loop);
>  }
>  
> -static void sig_debug(int sig)
> -{
> -	toggle_debug();
> -}
> -

For the tracer lets do syslog manually and not intersect it with the
dynamic debug here. You might wanna send this as a separate patch to
remove the usage of start_logging first from it.

And then in the end we should rename this to src/log.c of course to make
it match with ConnMan and oFono.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH v2 1/1] Makes extract_svclass_uuid function public
From: Elvis Pfützenreuter @ 2010-05-17 13:24 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1274102035.26613.7.camel@localhost.localdomain>

Indeed I was. sdp_get_service_classes returns a list of UUIDs already, =
so no need to extract.=20

On 17/05/2010, at 10:13, Marcel Holtmann wrote:

> Hi Elvis,
>=20
>> This patch makes the extract_svclass_uuid function public,
>> so it may be used by applications that link to libbluetooth.
>=20
> I really like to see how you are planning to use this function. It is
> not a problem to make it public, but I am concerned you might be
> misusing it.
>=20
> Regards
>=20
> Marcel
>=20
>=20

^ permalink raw reply

* Re: [PATCH v2 1/1] Makes extract_svclass_uuid function public
From: Marcel Holtmann @ 2010-05-17 13:13 UTC (permalink / raw)
  To: Elvis Pfützenreuter; +Cc: linux-bluetooth
In-Reply-To: <1273763316-28425-1-git-send-email-epx@signove.com>

Hi Elvis,

> This patch makes the extract_svclass_uuid function public,
> so it may be used by applications that link to libbluetooth.

I really like to see how you are planning to use this function. It is
not a problem to make it public, but I am concerned you might be
misusing it.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Kernel crash when krfcomm is preempted by l2cap tasklet
From: Andrei Emeltchenko @ 2010-05-17  9:45 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: Bluettooth Linux
In-Reply-To: <20100516083122.GA21819@vigoh>

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

Hi Gustavo,

Thanks for reviewing the patch. Please check new patches attached and
comments below:

On Sun, May 16, 2010 at 11:31 AM, Gustavo F. Padovan
<gustavo@padovan.org> wrote:
> Hi Andrei,
>
> * Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-05-14 18:39:40 +0300]:
>
>> Hi all,
>>
>> We have a bug with race condition between l2cap tasklet and krfcomm process.
>>
>> When sending following sequence:
>>
>> ...
>> No.     Time        Source                Destination           Protocol Info
>>      89 1.951202            RFCOMM   Rcvd DISC DLCI=20
>>      90 1.951324            RFCOMM   Sent UA DLCI=20
>>      91 1.959381            HCI_EVT   Number of Completed Packets
>>      92 1.966461            RFCOMM   Rcvd DISC DLCI=0
>>      93 1.966492            L2CAP    Rcvd Disconnect Request
>>      94 1.972595            L2CAP    Sent Disconnect Response
>>
>> ...
>>
>> krfcommd kernel thread is preempted with l2cap tasklet which remove l2cap_conn
>> (L2CAP connection handler structure). Then rfcomm thread tries to send RFCOMM
>> UA which is reply to RFCOMM DISC and when de-referencing l2cap_conn crash
>> happens.
>>
>> ...
>> [  694.175933] Unable to handle kernel NULL pointer dereference at
>> virtual address 00000000
>> [  694.184936] pgd = c0004000
>> [  694.187683] [00000000] *pgd=00000000
>> [  694.191711] Internal error: Oops: 5 [#1] PREEMPT
>> [  694.196350] last sysfs file:
>> /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
>> [  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
>> [  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
>> [  694.270721] LR is at 0xd7017303
>> ...
>> [  694.525085] Backtrace:
>> [  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap])
>> from [<c02f2cc8>] (sock_sendmsg+0xb8
>> [  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>]
>> (kernel_sendmsg+0x48/0x80)
>> ...
>>
>> I have a patch which fixes the issue but not sure that there is no
>> better way. Waiting for comments.
>>
>> Currently I am investigating possibility to:
>> - implement l2cap_conn reference counting
>
> sock_owned_by_user() gives the same effect as a ref count. See comments below.
>

Yes. For this cases this is enough. But proper refcounting is always
better than this "effects" ;)

>> - use socket backlog queue to process l2cap packets later when socket is not
>> owned by the process.
>
> You actually don't need a backlog queue here. You can process the signal
> packet, skipping the l2cap_chan_del() call;
>
...
>> +     /* sk is locked in krfcomm process */
>> +     if (sock_owned_by_user(sk)) {
>> +             BT_DBG("sk %p is owned by user", sk);
>> +             bh_unlock_sock(sk);
>> +             return 0;
>> +     }
>
> That's wrong. Use the sock_owned_by_user() only to avoid the
> l2cap_chan_del() call, so you can process all the rest of the function
> and send the Disconnect Response.

I have changed the patch so that it only prevents l2cap_chan_del
-		l2cap_chan_del(sk, ECONNREFUSED);
+		/* delete l2cap channel if sk is not owned by user */
+		if (!sock_owned_by_user(sk))
+			l2cap_chan_del(sk, ECONNREFUSED);

Then still l2cap_sock_kill(sk) removes sk but in the second patch sk is
hold with sock_hold(sk) until rfcomm is still processing packet.

> The same check should be added to l2cap_connect_rsp() and
> l2cap_disconnect_rsp(), since they call l2cap_chan_del() under bh
> context as well. ;)

Added.

Regards,
Andrei Emeltchenko

[-- Attachment #2: 0001-Bluetooth-Check-sk-is-not-owned-before-freeing-l2cap.patch --]
[-- Type: text/x-patch, Size: 2654 bytes --]

From 8531c8add8a378fc24b92f2c2311b01a7b1f63fc Mon Sep 17 00:00:00 2001
From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Date: Mon, 17 May 2010 12:10:46 +0300
Subject: [PATCH 1/2] Bluetooth: Check sk is not owned before freeing l2cap_conn

Check that socket sk is not locked in user process before removing
l2cap connection handler.

krfcommd kernel thread may be preempted with l2cap tasklet which remove
l2cap_conn structure. If krfcommd is in process of sending of RFCOMM reply
(like "RFCOMM UA" reply to "RFCOMM DISC") then kernel crash happens.

...
[  694.175933] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[  694.184936] pgd = c0004000
[  694.187683] [00000000] *pgd=00000000
[  694.191711] Internal error: Oops: 5 [#1] PREEMPT
[  694.196350] last sysfs file: /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
[  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
[  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
[  694.270721] LR is at 0xd7017303
...
[  694.525085] Backtrace:
[  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap]) from [<c02f2cc8>] (sock_sendmsg+0xb8/0xd8)
[  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>] (kernel_sendmsg+0x48/0x80)
...

Modified version after comments of Gustavo F. Padovan <gustavo@padovan.org>

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..794f2b7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2927,7 +2927,9 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		break;
 
 	default:
-		l2cap_chan_del(sk, ECONNREFUSED);
+		/* delete l2cap channel if sk is not owned by user */
+		if (!sock_owned_by_user(sk))
+			l2cap_chan_del(sk, ECONNREFUSED);
 		break;
 	}
 
@@ -3135,7 +3137,10 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 		del_timer(&l2cap_pi(sk)->ack_timer);
 	}
 
-	l2cap_chan_del(sk, ECONNRESET);
+	/* delete l2cap channel if sk is not owned by user */
+	if (!sock_owned_by_user(sk))
+		l2cap_chan_del(sk, ECONNRESET);
+
 	bh_unlock_sock(sk);
 
 	l2cap_sock_kill(sk);
@@ -3167,7 +3172,10 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 		del_timer(&l2cap_pi(sk)->ack_timer);
 	}
 
-	l2cap_chan_del(sk, 0);
+	/* delete l2cap channel if sk is not owned by user */
+	if (!sock_owned_by_user(sk))
+		l2cap_chan_del(sk, 0);
+
 	bh_unlock_sock(sk);
 
 	l2cap_sock_kill(sk);
-- 
1.7.0.4


[-- Attachment #3: 0002-Bluetooth-Prevent-sk-freeing-in-tasklet-using-refcou.patch --]
[-- Type: text/x-patch, Size: 1066 bytes --]

From 99ffb4e41ff46022cbc52f3c947425791de7fa39 Mon Sep 17 00:00:00 2001
From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Date: Mon, 17 May 2010 12:28:06 +0300
Subject: [PATCH 2/2] Bluetooth: Prevent sk freeing in tasklet using refcount

Socket sk may be freed in tasklet while still be in use in krfcommd
process. Use refcount to mark sk as used.

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

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 794f2b7..bf762d6 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1724,6 +1724,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
+	sock_hold(sk);
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_CONNECTED) {
@@ -1808,6 +1809,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 done:
 	release_sock(sk);
+	sock_put(sk);
 	return err;
 }
 
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Instantly fix non-UTF-8 local device names during device configuration phase
From: Fabian Greffrath @ 2010-05-17  8:39 UTC (permalink / raw)
  To: Stefan Seyfried, linux-bluetooth
In-Reply-To: <20100506150228.GA20880@jh-x301>

Am 06.05.2010 17:03, schrieb Johan Hedberg:
> BlueZ will (or at least should) set the name for the adapter as follows:
>
> 1. If there's a name in /var/lib/bluetooth/... use that
> 2. Else if there's a name in main.conf use that
> 3. If all else fails set the name to "BlueZ"

Hm, IIRC it was set to $(hostname)-$(hci-id) last time I established a 
connection.

> So I fail to see why this patch is needed at all. It sounds like there's
> something else wrong in the initialization process which makes the
> initialzation fail if the adapter contains some invalid default name (we
> shouldn't as far as I see be trying to read the name at all from the
> adapter before we've written it ourselves from the host side). I.e. I
> suspect the patch might be just working around the real issue instead of
> fixing it.

Yes, obviously Bluez fails to set a reasonable device name if the 
initial device name isn't already valid. However, I believe Bluez 
shouldn't necessarily be expected to handle invalid device names, as 
they clearly violate the specs. Instead, if Bluez detects an invalid 
name, it should convert it into a valid name as soon in the 
initialization process as possible. This sounds just naturally to me 
and is exactly what my patch does.

Cheers,
Fabian

^ permalink raw reply

* Re: Software caused connection abort (103 )
From: Gustavo F. Padovan @ 2010-05-17  2:39 UTC (permalink / raw)
  To: john michelle; +Cc: linux-bluetooth
In-Reply-To: <AANLkTilSynGNcpdq8h5YJQVD8e5MMyUDq55WzsB05AA2@mail.gmail.com>

Hi Jonh,

First of all, don't do top posting in this mailing list. ;)

* john michelle <jhnmichelle@gmail.com> [2010-05-13 17:39:29 -0400]:

> Hi Gustavo,
> 
> Any update on the software caused connection abort issue, it's happenning more
> And more making bluez unstable for our application

In which bluez/kernel version the problem started? Any hardware update
during this time? The problem happens when you are already tranfering
SCO data?

Please post the output of hcidump when the connection abort happens.

I tried reproduce this issue in L2CAP but it is a bit hard, lets
say it happen once in a thousand, so it's not easy to track it. I have
to try reproduce that using the SCO, but I'm not used to that layer yet.
;)

Regards,

> 
> John
> 
> On Fri, May 7, 2010 at 3:53 PM, Gustavo F. Padovan <gustavo@padovan.org> wrote:
> > * john michelle <jhnmichelle@gmail.com> [2010-05-07 15:49:05 -0400]:
> >
> >> Hi Bluetooth hackers,
> >>
> >> i am having this consistent problem with bluez , from time to time i
> >> get the error Software caused connection abort (103 )
> >> And the bluetooth stick seems to disconnect and reconnects. this
> >> happens during an sco connection and it occurs even
> >> More when i am having the voice stream comming through the internet
> >> rather than the lan.i don't know what exact
> >> Details you need to solve this problem please tell me and i will give
> >> you an immediate reply . i have linux kernel 2.6.33 and bluez 4.62
> >
> > I get the same problem sometimes when testing ERTM with l2test. So the
> > problem is on l2cap too. I didn't have time to debug this yet. Now that
> > someone else have confirmed it too, I'll to take a look at the problem.
> >
> >>

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* RE: [PATCH] Dial-up Networking profile API
From: Zhang, Zhenhua @ 2010-05-17  2:20 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20100517021829.GG23754@vigoh>

Hi Padovan,

Gustavo F. Padovan wrote:
> Hi Zhenhua,
> 
> * Zhang, Zhenhua <zhenhua.zhang@intel.com> [2010-05-10 08:41:59
> +0800]: 
> 
> ...
> 
>>> +DUNAgent hierarchy
>>> +===============
>>> +
>>> +Service         unique name
>>> +Interface       org.bluez.DUNAgent
>>> +Object path     freely definable
>>> +
>>> +Methods		void NewConnection(filedescriptor fd)
>>> +
>>> +			This method gets called whenever a new DUN
>>> +			connection has been established.  The objectpath
>>> +			contains the object path of the remote
>>> device.  This
>>> +			method assumes that DBus daemon with
>>> file descriptor
>>> +			passing capability is being used.
>>> +
>>> +			The agent should only return
>>> successfully once the
>>> +			establishment of the data call has been fineshed
>> 
>> A typo 'fineshed' should be 'finished'.
> 
> Thanks. ;)
> 
>> 
>>> +			without problems.
>>> +
>>> +			Possible Errors:
>>> org.bluez.Error.InvalidArguments
>>> +					 org.bluez.Error.Failed
>>> +
>>> +		void Release()
>>> +
>>> +			This method gets called whenever the service daemon
>>> +			unregisters the agent.
>> 
>> Compared with hfp-api.txt, I think we should also add the
> sentence like "or whenever the Adapter where the DUNAgent
> registers itself is removed".
> 
> Or we can remove that sentence from hfp-api, since when a
> adapter is removed bluetoothd relaese all agents on that adapter.
> 

Well. It's all upon on you. I am fine. :-)

> Regards,
> 
> --
> Gustavo F. Padovan
> http://padovan.org

Regards,
Zhenhua


^ permalink raw reply

* Re: [PATCH] Dial-up Networking profile API
From: Gustavo F. Padovan @ 2010-05-17  2:18 UTC (permalink / raw)
  To: Zhang, Zhenhua; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <33AB447FBD802F4E932063B962385B351E79EBA6@shsmsx501.ccr.corp.intel.com>

Hi Zhenhua,

* Zhang, Zhenhua <zhenhua.zhang@intel.com> [2010-05-10 08:41:59 +0800]:

...

> > +DUNAgent hierarchy
> > +===============
> > +
> > +Service         unique name
> > +Interface       org.bluez.DUNAgent
> > +Object path     freely definable
> > +
> > +Methods		void NewConnection(filedescriptor fd)
> > +
> > +			This method gets called whenever a new DUN
> > +			connection has been established.  The objectpath
> > +			contains the object path of the remote
> > device.  This
> > +			method assumes that DBus daemon with
> > file descriptor
> > +			passing capability is being used.
> > +
> > +			The agent should only return
> > successfully once the
> > +			establishment of the data call has been fineshed
> 
> A typo 'fineshed' should be 'finished'.

Thanks. ;)

> 
> > +			without problems.
> > +
> > +			Possible Errors:
> > org.bluez.Error.InvalidArguments
> > +					 org.bluez.Error.Failed
> > +
> > +		void Release()
> > +
> > +			This method gets called whenever the service daemon
> > +			unregisters the agent.
> 
> Compared with hfp-api.txt, I think we should also add the sentence like "or whenever the Adapter where the DUNAgent registers itself is removed".

Or we can remove that sentence from hfp-api, since when a adapter is
removed bluetoothd relaese all agents on that adapter.


Regards,

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH] Kernel crash when krfcomm is preempted by l2cap tasklet
From: Gustavo F. Padovan @ 2010-05-16  8:31 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: Bluettooth Linux
In-Reply-To: <AANLkTilNBHEMhl7rFK7DemxPQu3LN2QGWSsL7b-e9Yl3@mail.gmail.com>

Hi Andrei,

* Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-05-14 18:39:40 +0300]:

> Hi all,
> 
> We have a bug with race condition between l2cap tasklet and krfcomm process.
> 
> When sending following sequence:
> 
> ...
> No.     Time        Source                Destination           Protocol Info
>      89 1.951202            RFCOMM   Rcvd DISC DLCI=20
>      90 1.951324            RFCOMM   Sent UA DLCI=20
>      91 1.959381            HCI_EVT   Number of Completed Packets
>      92 1.966461            RFCOMM   Rcvd DISC DLCI=0
>      93 1.966492            L2CAP    Rcvd Disconnect Request
>      94 1.972595            L2CAP    Sent Disconnect Response
> 
> ...
> 
> krfcommd kernel thread is preempted with l2cap tasklet which remove l2cap_conn
> (L2CAP connection handler structure). Then rfcomm thread tries to send RFCOMM
> UA which is reply to RFCOMM DISC and when de-referencing l2cap_conn crash
> happens.
> 
> ...
> [  694.175933] Unable to handle kernel NULL pointer dereference at
> virtual address 00000000
> [  694.184936] pgd = c0004000
> [  694.187683] [00000000] *pgd=00000000
> [  694.191711] Internal error: Oops: 5 [#1] PREEMPT
> [  694.196350] last sysfs file:
> /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
> [  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
> [  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
> [  694.270721] LR is at 0xd7017303
> ...
> [  694.525085] Backtrace:
> [  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap])
> from [<c02f2cc8>] (sock_sendmsg+0xb8
> [  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>]
> (kernel_sendmsg+0x48/0x80)
> ...
> 
> I have a patch which fixes the issue but not sure that there is no
> better way. Waiting for comments.
> 
> Currently I am investigating possibility to:
> - implement l2cap_conn reference counting

sock_owned_by_user() gives the same effect as a ref count. See comments below.

> - use socket backlog queue to process l2cap packets later when socket is not
> owned by the process.

You actually don't need a backlog queue here. You can process the signal
packet, skipping the l2cap_chan_del() call;

> From 955a821e1ee66cd6f9717ea4a2e9b3dfdafdc22a Mon Sep 17 00:00:00 2001
> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> Date: Fri, 14 May 2010 17:56:39 +0300
> Subject: [PATCH] Bluetooth: Check sk is not used before freeing
> 
> Check that socket sk is not locked in user process before removing
> l2cap connection handler and sk.
> 
> rfcomm kernel thread may be preempted with l2cap tasklet which remove l2cap_conn
> (L2CAP connection handler structure). Then rfcomm thread tries to send RFCOMM
> UA which is reply to RFCOMM DISC and when de-referencing l2cap_conn crash
> can happen.
> 
> ...
> [  694.175933] Unable to handle kernel NULL pointer dereference at virtual address 00000000
> [  694.184936] pgd = c0004000
> [  694.187683] [00000000] *pgd=00000000
> [  694.191711] Internal error: Oops: 5 [#1] PREEMPT
> [  694.196350] last sysfs file: /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
> [  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
> [  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
> [  694.270721] LR is at 0xd7017303
> 
> ...
> 
> [  694.525085] Backtrace:
> [  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap]) from [<c02f2cc8>] (sock_sendmsg+0xb8/0xd8)
> [  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>] (kernel_sendmsg+0x48/0x80)
> ...
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
>  net/bluetooth/l2cap.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index bb00015..7eb9a58 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -3119,6 +3119,13 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
>  	if (!sk)
>  		return 0;
>  
> +	/* sk is locked in krfcomm process */
> +	if (sock_owned_by_user(sk)) {
> +		BT_DBG("sk %p is owned by user", sk);
> +		bh_unlock_sock(sk);
> +		return 0;
> +	}

That's wrong. Use the sock_owned_by_user() only to avoid the
l2cap_chan_del() call, so you can process all the rest of the function
and send the Disconnect Response.

The same check should be added to l2cap_connect_rsp() and
l2cap_disconnect_rsp(), since they call l2cap_chan_del() under bh
context as well. ;)

>  	rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
>  	rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
>  	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
> -- 
> 1.7.0.4
> 

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH 20/37] drivers/bluetooth: Use kmemdup
From: Gustavo F. Padovan @ 2010-05-16  4:53 UTC (permalink / raw)
  To: Julia Lawall
  Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, kernel-janitors
In-Reply-To: <Pine.LNX.4.64.1005152318590.21345@ask.diku.dk>

* Julia Lawall <julia@diku.dk> [2010-05-15 23:19:15 +0200]:

> From: Julia Lawall <julia@diku.dk>
> 
> Use kmemdup when some other buffer is immediately copied into the
> allocated region.
> 
> A simplified version of the semantic patch that makes this change is as
> follows: (http://coccinelle.lip6.fr/)
> 
> // <smpl>
> @@
> expression from,to,size,flag;
> statement S;
> @@
> 
> -  to = \(kmalloc\|kzalloc\)(size,flag);
> +  to = kmemdup(from,size,flag);
>    if (to==NULL || ...) S
> -  memcpy(to, from, size);
> // </smpl>
> 
> Signed-off-by: Julia Lawall <julia@diku.dk>
> 
> ---
>  drivers/bluetooth/bcm203x.c |    3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff -u -p a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
> --- a/drivers/bluetooth/bcm203x.c
> +++ b/drivers/bluetooth/bcm203x.c
> @@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_inte
>  
>  	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
>  
> -	data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
> +	data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
>  	if (!data->fw_data) {
>  		BT_ERR("Can't allocate memory for firmware image");
>  		release_firmware(firmware);
> @@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_inte
>  		return -ENOMEM;
>  	}
>  
> -	memcpy(data->fw_data, firmware->data, firmware->size);
>  	data->fw_size = firmware->size;
>  	data->fw_sent = 0;


Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* [PATCH 20/37] drivers/bluetooth: Use kmemdup
From: Julia Lawall @ 2010-05-15 21:19 UTC (permalink / raw)
  To: Marcel Holtmann, linux-bluetooth, linux-kernel, kernel-janitors

From: Julia Lawall <julia@diku.dk>

Use kmemdup when some other buffer is immediately copied into the
allocated region.

A simplified version of the semantic patch that makes this change is as
follows: (http://coccinelle.lip6.fr/)

// <smpl>
@@
expression from,to,size,flag;
statement S;
@@

-  to = \(kmalloc\|kzalloc\)(size,flag);
+  to = kmemdup(from,size,flag);
   if (to==NULL || ...) S
-  memcpy(to, from, size);
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>

---
 drivers/bluetooth/bcm203x.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff -u -p a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_inte
 
 	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
 
-	data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
+	data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
 	if (!data->fw_data) {
 		BT_ERR("Can't allocate memory for firmware image");
 		release_firmware(firmware);
@@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_inte
 		return -ENOMEM;
 	}
 
-	memcpy(data->fw_data, firmware->data, firmware->size);
 	data->fw_size = firmware->size;
 	data->fw_sent = 0;
 

^ permalink raw reply

* Re: Software caused connection abort (103 )
From: john michelle @ 2010-05-15 11:52 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <AANLkTilSynGNcpdq8h5YJQVD8e5MMyUDq55WzsB05AA2@mail.gmail.com>

Hi all,

It seems that i am not the only one who is reporting this problem
below is other reporters

http://www.mp3car.com/vbulletin/linux/125997-hfp-linux-bluetooth-hands-free-5.html

even an older post show this bug

http://osdir.com/ml/linux.bluez.user/2004-04/msg00016.html

I hope we got someone attention.


John

On Fri, May 14, 2010 at 12:39 AM, john michelle <jhnmichelle@gmail.com> wrote:
> Hi Gustavo,
>
> Any update on the software caused connection abort issue, it's happenning more
> And more making bluez unstable for our application
>
> John
>
> On Fri, May 7, 2010 at 3:53 PM, Gustavo F. Padovan <gustavo@padovan.org> wrote:
>> * john michelle <jhnmichelle@gmail.com> [2010-05-07 15:49:05 -0400]:
>>
>>> Hi Bluetooth hackers,
>>>
>>> i am having this consistent problem with bluez , from time to time i
>>> get the error Software caused connection abort (103 )
>>> And the bluetooth stick seems to disconnect and reconnects. this
>>> happens during an sco connection and it occurs even
>>> More when i am having the voice stream comming through the internet
>>> rather than the lan.i don't know what exact
>>> Details you need to solve this problem please tell me and i will give
>>> you an immediate reply . i have linux kernel 2.6.33 and bluez 4.62
>>
>> I get the same problem sometimes when testing ERTM with l2test. So the
>> problem is on l2cap too. I didn't have time to debug this yet. Now that
>> someone else have confirmed it too, I'll to take a look at the problem.
>>
>>>
>>> John
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>> --
>> Gustavo F. Padovan
>> http://padovan.org
>>
>

^ permalink raw reply


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