* Re: [PATCH] HID:magicmouse: This fixes a connection problem with the magicmouse.
From: Jiri Kosina @ 2010-05-12 13:41 UTC (permalink / raw)
To: Justin P. Mattock; +Cc: linux-bluetooth, linux-kernel, mdpoole
In-Reply-To: <4BEAAF9C.909@gmail.com>
On Wed, 12 May 2010, Justin P. Mattock wrote:
> > > --- a/drivers/hid/hid-magicmouse.c
> > > +++ b/drivers/hid/hid-magicmouse.c
> > > @@ -354,7 +354,7 @@ static int magicmouse_probe(struct hid_device *hdev,
> > > goto err_free;
> > > }
> > >
> > > - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT& ~HID_CONNECT_HIDINPUT);
> > > + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > >
> > This is not particularly right, as we'll end up having dangling input
> > device.
> >
> > The problem is, that when HIDRAW is not set, hid_hw_start() returns ENODEV
> > as no subsystem has claimed the device, and probe routine bails out. Which
> > is not what we want.
> >
> > Does the testing patch below fix the problems you are seeing?
> >
> >
> >
> works good.. rebooted a few times mouse connects. suspended a few times
> mouse reconnects.
I'd be glad if you could also double-check that device removal and
re-connecting it works well as well with this patch.
> > diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
> > index 0d471fc..f10d56a 100644
> > --- a/drivers/hid/hid-magicmouse.c
> > +++ b/drivers/hid/hid-magicmouse.c
> > @@ -354,12 +354,15 @@ static int magicmouse_probe(struct hid_device *hdev,
> > goto err_free;
> > }
> >
> > - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT& ~HID_CONNECT_HIDINPUT);
> > + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > if (ret) {
> > dev_err(&hdev->dev, "magicmouse hw start failed\n");
> > goto err_free;
> > }
> >
> > + /* we are handling the input ourselves */
> > + hidinput_disconnect(hdev);
> > +
> > report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
> > if (!report) {
> > dev_err(&hdev->dev, "unable to register touch report\n");
> >
> >
>
> looks good over here.. If you'd like I can re-du this patch, add your
> sign off etc.. and re-send, or not worry.. either way this little
> quirk/problem is fixed.
No problem, once you confirm that device removal wasn't broken again and
if I don't hear any objections from Michael, I will queue the patch
myself.
Thanks,
--
Jiri Kosina
SUSE Labs, Novell Inc.
^ permalink raw reply
* Re: [PATCH] HID:magicmouse: This fixes a connection problem with the magicmouse.
From: Justin P. Mattock @ 2010-05-12 13:39 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-bluetooth, linux-kernel, mdpoole
In-Reply-To: <alpine.LNX.2.00.1005121456150.28092@pobox.suse.cz>
On 05/12/2010 05:58 AM, Jiri Kosina wrote:
> On Tue, 11 May 2010, Justin P. Mattock wrote:
>
>
>> With the latest HEAD, I've noticed that I needed to add: HIDRAW=y in
>> order for my apple magicmouse to connect. After receiving some posts, it
>> seems this it not the case(HIDRAW just relays HID events to userspace).
>>
>> The bisect results of this issue resulted in commit: HID:magicmouse: fix
>> oops after device removal.
>> (hash:28918c211d86b6eeb70182c523800c7bc442960c)
>>
>> After examining this commit, I've noticed that HID_CONNECT_DEFAULT has
>> also an entry in there of HID_CONNECT_HIDINPUT, not sure what "~" means,
>>
> ~ is zeroing out the HID_CONENCT_HIDINPUT bits from the connect mask, as
> magicmouse driver is handling the input itself.
>
>
ah.. cool thanks for that..(I still have lots to learn(so many
expressions)).
>> before HID_CONNECT_HIDINPUT, but after removing
>> this(correct me if I'm wrong)"double" definition,
>> I'm able to have my magicmouse connect without the
>> need of HIDRAW, and also this in dmesg:
>>
>> magicmouse 0005:05AC:030D.0004: claimed by neither input, hiddev nor hidraw
>> magicmouse 0005:05AC:030D.0004: magicmouse hw start failed
>>
>> and as well as the crash that the above commit fixes when waking
>> up from suspend(mouse connects perfectly upon wakeup).
>>
>> Please have a look, and if this works, take it
>> if theres another solution let me know.
>> (so I can enjoy the power of the magicmouse!!).
>>
>>
>> Signed-off-by: Justin P. Mattock<justinmattock@gmail.com>
>>
>> ---
>> drivers/hid/hid-magicmouse.c | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
>> index 0d471fc..0de5e96 100644
>> --- a/drivers/hid/hid-magicmouse.c
>> +++ b/drivers/hid/hid-magicmouse.c
>> @@ -354,7 +354,7 @@ static int magicmouse_probe(struct hid_device *hdev,
>> goto err_free;
>> }
>>
>> - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT& ~HID_CONNECT_HIDINPUT);
>> + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>>
> This is not particularly right, as we'll end up having dangling input
> device.
>
> The problem is, that when HIDRAW is not set, hid_hw_start() returns ENODEV
> as no subsystem has claimed the device, and probe routine bails out. Which
> is not what we want.
>
> Does the testing patch below fix the problems you are seeing?
>
>
>
works good.. rebooted a few times
mouse connects. suspended a few times mouse reconnects.
> diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
> index 0d471fc..f10d56a 100644
> --- a/drivers/hid/hid-magicmouse.c
> +++ b/drivers/hid/hid-magicmouse.c
> @@ -354,12 +354,15 @@ static int magicmouse_probe(struct hid_device *hdev,
> goto err_free;
> }
>
> - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT& ~HID_CONNECT_HIDINPUT);
> + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> if (ret) {
> dev_err(&hdev->dev, "magicmouse hw start failed\n");
> goto err_free;
> }
>
> + /* we are handling the input ourselves */
> + hidinput_disconnect(hdev);
> +
> report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
> if (!report) {
> dev_err(&hdev->dev, "unable to register touch report\n");
>
>
looks good over here.. If you'd like I can re-du
this patch, add your sign off etc.. and re-send,
or not worry.. either way this little quirk/problem
is fixed.
Justin P. Mattock
^ permalink raw reply
* Re: [PATCH 0/2] Groundwork for Sixaxis paring into bluez.
From: Antonio Ospite @ 2010-05-12 13:12 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Bastien Nocera, linux-bluetooth, cbe-oss-dev
In-Reply-To: <1272917756-31098-1-git-send-email-ospite@studenti.unina.it>
[-- Attachment #1: Type: text/plain, Size: 1686 bytes --]
On Mon, 3 May 2010 22:15:54 +0200
Antonio Ospite <ospite@studenti.unina.it> wrote:
> Hi,
>
> These changes are in preparation of seamless integration of the Sixaxis
> pairing procedure into bluez. It was about time :)
>
Ping, and comments below.
> The first one cleans up the quirks handling.
>
> The second one adds a sysfs interface to set and get the device and master
> bdaddr, this is needed in order to setup the host for pairing. This kernel
> interface is a mere workaround for the lack of features of hidraw[1], if
> someone wants to add the missing features to hidraw I will be happy to drop
> this one, otherwise consider queuing these for 2.6.35 if it's too late for
> 2.6.34.
>
I guess the silence here was also because this particular
hackish solution must not look very good to you. If there's really a
strong objection to it I might consider extending hidraw capabilities by
adding some ioctls, maybe I just need some extra motivation.
Regards,
Antonio
> Thanks,
> Antonio
>
> [1] http://www.spinics.net/lists/linux-input/msg08311.html
>
>
> Antonio Ospite (2):
> hid/hid-sony: Apply sixaxis quirks only to sixaxis
> hid/hid-sony: get and set Sixaxis bdaddr via sysfs
>
> drivers/hid/hid-sony.c | 170 +++++++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 155 insertions(+), 15 deletions(-)
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH] HID:magicmouse: This fixes a connection problem with the magicmouse.
From: Jiri Kosina @ 2010-05-12 12:58 UTC (permalink / raw)
To: Justin P. Mattock; +Cc: linux-bluetooth, linux-kernel, mdpoole
In-Reply-To: <1273595363-4020-1-git-send-email-justinmattock@gmail.com>
On Tue, 11 May 2010, Justin P. Mattock wrote:
> With the latest HEAD, I've noticed that I needed to add: HIDRAW=y in
> order for my apple magicmouse to connect. After receiving some posts, it
> seems this it not the case(HIDRAW just relays HID events to userspace).
>
> The bisect results of this issue resulted in commit: HID:magicmouse: fix
> oops after device removal.
> (hash:28918c211d86b6eeb70182c523800c7bc442960c)
>
> After examining this commit, I've noticed that HID_CONNECT_DEFAULT has
> also an entry in there of HID_CONNECT_HIDINPUT, not sure what "~" means,
~ is zeroing out the HID_CONENCT_HIDINPUT bits from the connect mask, as
magicmouse driver is handling the input itself.
> before HID_CONNECT_HIDINPUT, but after removing
> this(correct me if I'm wrong)"double" definition,
> I'm able to have my magicmouse connect without the
> need of HIDRAW, and also this in dmesg:
>
> magicmouse 0005:05AC:030D.0004: claimed by neither input, hiddev nor hidraw
> magicmouse 0005:05AC:030D.0004: magicmouse hw start failed
>
> and as well as the crash that the above commit fixes when waking
> up from suspend(mouse connects perfectly upon wakeup).
>
> Please have a look, and if this works, take it
> if theres another solution let me know.
> (so I can enjoy the power of the magicmouse!!).
>
>
> Signed-off-by: Justin P. Mattock <justinmattock@gmail.com>
>
> ---
> drivers/hid/hid-magicmouse.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
> index 0d471fc..0de5e96 100644
> --- a/drivers/hid/hid-magicmouse.c
> +++ b/drivers/hid/hid-magicmouse.c
> @@ -354,7 +354,7 @@ static int magicmouse_probe(struct hid_device *hdev,
> goto err_free;
> }
>
> - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT);
> + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
This is not particularly right, as we'll end up having dangling input
device.
The problem is, that when HIDRAW is not set, hid_hw_start() returns ENODEV
as no subsystem has claimed the device, and probe routine bails out. Which
is not what we want.
Does the testing patch below fix the problems you are seeing?
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 0d471fc..f10d56a 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -354,12 +354,15 @@ static int magicmouse_probe(struct hid_device *hdev,
goto err_free;
}
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT);
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
dev_err(&hdev->dev, "magicmouse hw start failed\n");
goto err_free;
}
+ /* we are handling the input ourselves */
+ hidinput_disconnect(hdev);
+
report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
if (!report) {
dev_err(&hdev->dev, "unable to register touch report\n");
--
Jiri Kosina
SUSE Labs, Novell Inc.
^ permalink raw reply related
* Re: HDP proposed API (ver 0.3)
From: José Antonio Santos Cadenas @ 2010-05-12 11:25 UTC (permalink / raw)
To: Daniel Abraham
Cc: linux-bluetooth, Elvis Pfützenreuter, Santiago Carot,
Raul Herbster
In-Reply-To: <AANLkTik5a4HBJZ_FYZ00xdnTiOtGmsdatn0EnV_joHjx@mail.gmail.com>
Hi Daniel,
first of all thanks for your comments.
El Wednesday 12 May 2010 12:45:28 Daniel Abraham escribió:
> On Wed, May 12, 2010 at 12:26 PM, José Antonio Santos Cadenas
>
> <jcaden@libresoft.es> wrote:
> > This api is a clean up of the previous one the changes.
> >
> > We've added a new object that uses device path to get the sessions
> > allocated on this device (as somebody recommended in other thread,
> > I think Luiz, Elvis or both, but I can't find the exact email). The
> > discovery of new remote session should be done using device drivers,
> > which is compliant with the BlueZ style.
> >
> > Discussions still in progress:
> >
> > - Fd-passing issue: As Elvis, Santiago and I discussed yesterday on
> > IRC we think that the best propose is as follows (please Elvis correct
> > me if I misunderstood something yesterday):
> > Reconnections should be implicit and the data channel should
> > be perceived by the application layer as connected all the time.
> > When the application tries to write in a closed data channel, HDP
> > will perform the data channel reconnection and if it fails, then the
> > channel will be present as closed.
> > The implementation for this this behaviour will use pipes. Each
> > data channel will use 2 pipes to do fd-passing to the application. The
> > upper layer will write in this pipes and HDP will redirect it through
> > the l2cap socket, in this operation, HDP can reconnect if th l2cap
> > socket is closed.
> >
> > - Sessions issues: We still think that session are necessary because they
> > are mentioned in the standard and in the whitepaper and we think that
> > bluez should follow the standards in order to pass PTS for allow
> > Bluetooth SIG certifications. Any comment in this respect are welcome to
> > improve the API usability and conformity with Bluez APIs.
> >
> > - Paths issues: It will be great to find names and paths that are good
> > for everybody, comments and suggestion on this respect are also welcome.
> >
> > I hope we can fix this API asap. All comments or ideas are welcome.
> >
> > Regards.
> >
> > --------------------------------------------------
> >
> > BlueZ D-Bus HDP 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.Hdp
> > Object path [variable prefix]/{hci0,hci1,...}
> >
> > Methods object CreateSession(object path, dict config)
> >
> > Returns the object path for the new HDP session.
> > The path parameter is the path of the remote
> > object with the callbacks to notify events (see
> > org.bluez.HdpAgent at the end of this document)
> > This petition starts an mcap session and also
> > register in the SDP 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
> >
> > Session will be closed by the call or implicitly
> > when the programs leaves the bus.
> >
> > Possible errors: org.bluez.Error.InvalidArguments
> >
> > void CloseSession(object path)
> >
> > Closes the HDP session identified by the object
> > path. Also session will be closed if the process that started it is
> > removed from the D-Bus.
> >
> > Possible errors: org.bluez.Error.InvalidArguments
> > org.bluez.Error.NotFound
> >
> > -------------------------------------------------------------------------
> > -------
> >
> > Service org.bluez
> > Interface org.bluez.Hdp
> > Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
> >
> > Methods array GetSessions()
> >
> > Gets the information of the remote sessions
> > present in this device and published on its SDP record. The returned
> > data follows this format.
> >
> > [{"session_id": "a session identification as
> > string", "data_spec" : session data spec,
> > "end_points":
> > ["mdepid": uint8,
> > "role" : "source" or "sink" ,
> > "specs" : [{
> > "dtype" : uint16,
> > "description" : string,
> > (optional) }]
> > ]
> > }]
> >
> > -------------------------------------------------------------------------
> > -------
> >
> > Service org.bluez
> > Interface org.bluez.HdpSession
> > Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}
> >
> > object Connect(remote_session_id)
> >
> > Connects with the remote session and returns its
> > object path.
> >
> > Possible errors: org.bluez.Error.InvalidArguments
> > org.bluez.Error.HdpError
> >
> > void Disconnect(object device, boolean delete)
> >
> > Disconnect from the remote device. If delete is
> > true, any status will also be deleted. Otherwise, the status will be
> > kept for allowing future reconnections.
> >
> > Possible errors: org.bluez.Error.InvalidArguments
> > org.bluez.Error.NotFound
> > org.bluez.Error.HdpError
> >
> > -------------------------------------------------------------------------
> > -------
> >
> > Service org.bluez
> > Interface org.bluez.HdpRemoteSession
> > Object path [variable
> > prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_session_id
> >
> > boolean Echo(array{byte})
> >
> > Sends an echo petition to the remote session.
> > Return 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.
> > Returns the data channel id.
> >
> > Possible errors: org.bluez.Error.InvalidArguments
> > org.bluez.Error.HdpError
> >
> > array GetDcFd(uint16 mdlid)
>
> "getdcfd" doesn't seem to me as a "friendly" name. Any way to make it
> better, please?
You are right, I forgot to change this name, thank you for the notice. I
suggest:
GetDataChannelFileDescriptor
Which is more compliant with the rest of the API.
>
> > 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.HdpError
> >
> > 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.HdpError
> >
> > 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.HdpError
> >
> > 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": [id1, ..., idz],
> > "best_effort" : [idx, ..., idy]
> > }
> >
> > The fist reliable data channel will always be the
> > first data channel in reliable array.
> >
> > HDPAgent hierarchy
> > ==================
> >
> > (this object is implemented by the HDP client an receives notifications)
> >
> > Service unique name
> > Interface org.bluez.HdpAgent
> > Object path freely definable
> >
> > void DeviceConnected(object path)
> >
> > This method is called whenever a new device
> > connection has been established over the control channel of the current
> > HDP session. The object path contains the object path of the remote
> > device.
> >
> > void DeviceDisconnected(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)
> >
> > This method is called when a new data channel is
> > created The path contains the object path of the device whith the new
> > connection is created and the mdlid the data channel identificator.
> >
> > 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.
>
> Question from a user's perspective: why define an agent? Why not
> define the above as signal callbacks in the relevant object? (same as
> most APIs in "bluez/docs").
Because the this notifications are only relevant for the process that created
the session and this process should be the unique that receives this events.
If you define signals, everybody in the bus can be subscribed to them, this is
a problem in two ways:
- Noise in the bus
- "Privacy" issue because just the owner of the session should be notified
of the session events.
>
> The only places I saw where agents are used are: BlueZ pairing (remote
> device object doesn't necessarily exist yet, so no way to register for
> its events, so an agent is required), and obexd (callback methods for
> authroization of transactions return a significant value, i.e. not a
> simple signal, so an agent is also required).
>
> But none of these conditions apply in the HDP agent above. So is there
> another reason?
I explained above.
If we are wrong and signals can be cached only by one process it is OK for us
to change this.
>
> Also, why not add properties for
> connected/disconnected/opened/closed/etc. states? (And then
> "GetProperties()" method, and "PropertyChanged(name, value)" signal).
> For example, see "bluez/docs/network-api.txt"...
Because this notifications concern to objects that are being created and
destroyed (in the case of devices) and created or closed data channels, so new
data channels ids are created or destroyed when this method are called. I
can't see how properties can help here. The channel may exist or not I think
that properties are not a good option in this case.
Regards.
> --
> 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
* Question about HID proxy firmware
From: Janusz Krzysztofik @ 2010-05-12 11:14 UTC (permalink / raw)
To: linux-bluetooth
Hi,
Sorry for bothering linux bluetooth developers with my problem, but I was not
able to find any active users list.
I have this device plugged into my workstation:
# dmesg
...
usb 4-1: new full speed USB device using uhci_hcd and address 9
usb 4-1: New USB device found, idVendor=04bf, idProduct=0320
usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 4-1: Product: Turbo Bluetooth Adapter
usb 4-1: Manufacturer: Ezurio
...
# lsusb
...
Bus 004 Device 009: ID 04bf:0320 TDK Corp. Bluetooth Adapter
...
# hciconfig hci0 version
hci0: Type: BR/EDR Bus: USB
BD Address: 00:80:98:97:6A:15 ACL MTU: 384:8 SCO MTU: 64:8
HCI Version: 2.0 (0x3) Revision: 0xa5c
LMP Version: 2.0 (0x3) Subversion: 0xa5c
Manufacturer: Cambridge Silicon Radio (10)
# bccmd chiprev
Chip revision: 0x0026 (BC4-External)
# hciconfig hci0 revision
hci0: Type: BR/EDR Bus: USB
BD Address: 00:80:98:97:6A:15 ACL MTU: 384:8 SCO MTU: 64:8
Unified 21c
Chip version: BlueCore4-External
Max key size: 128 bit
SCO mapping: HCI
# bccmd buildname
Build name: cyt_8unified_fl_bt2.0_21_0510281131_encr128 2005-11-07
#
# dfutool archive /tmp/ezurio.dfu
Available devices with DFU support:
1) Bus 004 Device 002: ID 04bf:0320 Interface 2
Select device (abort with 0): 1
Firmware upload ... 674148 bytes
vclass ~ # dfutool verify /tmp/ezurio.dfu
Filename ezurio.dfu
Filesize 674164
Checksum 0f26e33d
DFU suffix 52 26 20 03 bf 04 00 01 55 46 44 10 3d e3 26 0f
idVendor 04bf
idProduct 0320
bcdDevice 2652
bcdDFU 1.0
ucDfuSignature DFU
bLength 16
dwCRC 0f26e33d
Firmware type CSR-dfu2
Firmware check valid checksum
AFAICT, the device firmware doesn't provide HID proxy functionality, that I
would find rather usefull if present.
Is it possible to replace the device's firmware with one that can act as HID
proxy? Is Apple BluetoothFirmwareUpdate2.0.1.dmg provided GenericCSR.dfu
firmware compatible with BlueCore4? If not, what are my options?
Thanks,
Janusz
^ permalink raw reply
* Re: HDP proposed API (ver 0.3)
From: Daniel Abraham @ 2010-05-12 10:45 UTC (permalink / raw)
To: jcaden
Cc: linux-bluetooth, Elvis Pfützenreuter, Santiago Carot,
Raul Herbster
In-Reply-To: <201005121126.12859.jcaden@libresoft.es>
On Wed, May 12, 2010 at 12:26 PM, José Antonio Santos Cadenas
<jcaden@libresoft.es> wrote:
> This api is a clean up of the previous one the changes.
>
> We've added a new object that uses device path to get the sessions
> allocated on this device (as somebody recommended in other thread,
> I think Luiz, Elvis or both, but I can't find the exact email). The discovery
> of new remote session should be done using device drivers, which is
> compliant with the BlueZ style.
>
> Discussions still in progress:
>
> - Fd-passing issue: As Elvis, Santiago and I discussed yesterday on
> IRC we think that the best propose is as follows (please Elvis correct
> me if I misunderstood something yesterday):
> Reconnections should be implicit and the data channel should
> be perceived by the application layer as connected all the time.
> When the application tries to write in a closed data channel, HDP
> will perform the data channel reconnection and if it fails, then the channel
> will be present as closed.
> The implementation for this this behaviour will use pipes. Each data
> channel will use 2 pipes to do fd-passing to the application. The upper
> layer will write in this pipes and HDP will redirect it through the l2cap socket,
> in this operation, HDP can reconnect if th l2cap socket is closed.
>
> - Sessions issues: We still think that session are necessary because they
> are mentioned in the standard and in the whitepaper and we think that
> bluez should follow the standards in order to pass PTS for allow Bluetooth SIG
> certifications. Any comment in this respect are welcome to improve the API
> usability and conformity with Bluez APIs.
>
> - Paths issues: It will be great to find names and paths that are good for
> everybody, comments and suggestion on this respect are also welcome.
>
> I hope we can fix this API asap. All comments or ideas are welcome.
>
> Regards.
>
> --------------------------------------------------
>
> BlueZ D-Bus HDP 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.Hdp
> Object path [variable prefix]/{hci0,hci1,...}
>
> Methods object CreateSession(object path, dict config)
>
> Returns the object path for the new HDP session.
> The path parameter is the path of the remote object
> with the callbacks to notify events (see
> org.bluez.HdpAgent at the end of this document)
> This petition starts an mcap session and also register
> in the SDP 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
>
> Session will be closed by the call or implicitly when
> the programs leaves the bus.
>
> Possible errors: org.bluez.Error.InvalidArguments
>
> void CloseSession(object path)
>
> Closes the HDP session identified by the object path.
> Also session will be closed if the process that started
> it is removed from the D-Bus.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.NotFound
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.Hdp
> Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
>
> Methods array GetSessions()
>
> Gets the information of the remote sessions present
> in this device and published on its SDP record. The
> returned data follows this format.
>
> [{"session_id": "a session identification as string",
> "data_spec" : session data spec,
> "end_points":
> ["mdepid": uint8,
> "role" : "source" or "sink" ,
> "specs" : [{
> "dtype" : uint16,
> "description" : string, (optional)
> }]
> ]
> }]
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.HdpSession
> Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}
>
> object Connect(remote_session_id)
>
> Connects with the remote session and returns its object
> path.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.HdpError
>
> void Disconnect(object device, boolean delete)
>
> Disconnect from the remote device. If delete is true, any
> status will also be deleted. Otherwise, the status will
> be kept for allowing future reconnections.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.NotFound
> org.bluez.Error.HdpError
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.HdpRemoteSession
> Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_session_id
>
> boolean Echo(array{byte})
>
> Sends an echo petition to the remote session. Return 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.
> Returns the data channel id.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.HdpError
>
> array GetDcFd(uint16 mdlid)
"getdcfd" doesn't seem to me as a "friendly" name. Any way to make it
better, please?
>
> 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.HdpError
>
> 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.HdpError
>
> 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.HdpError
>
> 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": [id1, ..., idz],
> "best_effort" : [idx, ..., idy]
> }
>
> The fist reliable data channel will always be the first
> data channel in reliable array.
>
> HDPAgent hierarchy
> ==================
>
> (this object is implemented by the HDP client an receives notifications)
>
> Service unique name
> Interface org.bluez.HdpAgent
> Object path freely definable
>
> void DeviceConnected(object path)
>
> This method is called whenever a new device connection
> has been established over the control channel of the
> current HDP session. The object path contains the object
> path of the remote device.
>
> void DeviceDisconnected(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)
>
> This method is called when a new data channel is created
> The path contains the object path of the device whith
> the new connection is created and the mdlid the data
> channel identificator.
>
> 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.
Question from a user's perspective: why define an agent? Why not
define the above as signal callbacks in the relevant object? (same as
most APIs in "bluez/docs").
The only places I saw where agents are used are: BlueZ pairing (remote
device object doesn't necessarily exist yet, so no way to register for
its events, so an agent is required), and obexd (callback methods for
authroization of transactions return a significant value, i.e. not a
simple signal, so an agent is also required).
But none of these conditions apply in the HDP agent above. So is there
another reason?
Also, why not add properties for
connected/disconnected/opened/closed/etc. states? (And then
"GetProperties()" method, and "PropertyChanged(name, value)" signal).
For example, see "bluez/docs/network-api.txt"...
^ permalink raw reply
* [PATCH 20/25] Prepare MCAP library to process responses to standard op. codes
From: Santiago Carot-Nemesio @ 2010-05-12 10:00 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Santiago Carot Nemesio
In-Reply-To: <1273486527-7855-20-git-send-email-sancane@gmail.com>
From: Santiago Carot Nemesio <sancane@gmail.com>
---
mcap/mcap.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 80 insertions(+), 1 deletions(-)
diff --git a/mcap/mcap.c b/mcap/mcap.c
index 2554cd9..5b53ee8 100644
--- a/mcap/mcap.c
+++ b/mcap/mcap.c
@@ -1161,9 +1161,88 @@ static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
}
}
+static gboolean check_rsp(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
+{
+ mcap4B_rsp *rsp;
+ GError *gerr = NULL;
+
+ /* Check if the response matches with the last request */
+ if ((cmd[0] != MCAP_ERROR_RSP) && ((mcl->lcmd[0] + 1) != cmd[0]))
+ goto close_mcl;
+
+ if (len < 4)
+ goto close_mcl;
+
+ rsp = (mcap4B_rsp *)cmd;
+
+ if (rsp->rc == MCAP_REQUEST_NOT_SUPPORTED) {
+ debug("Remote does not support opcodes");
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_REQUEST_NOT_SUPPORTED,
+ "%s", error2str(rsp->rc));
+ mcap_notify_error(mcl, gerr);
+ g_error_free(gerr);
+
+ g_free(mcl->lcmd);
+ mcl->lcmd = NULL;
+ mcl->ctrl &= ~MCAP_CTRL_STD_OP;
+ mcl->req = MCL_AVAILABLE;
+ update_mcl_state(mcl);
+ return FALSE;
+ }
+
+ if (rsp->rc == MCAP_UNSPECIFIED_ERROR)
+ goto close_mcl;
+
+ return TRUE;
+close_mcl:
+ if (rsp->rc == MCAP_UNSPECIFIED_ERROR)
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_UNSPECIFIED_ERROR,
+ "%s", error2str(rsp->rc));
+ else
+ g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Protocol error");
+ mcap_notify_error(mcl, gerr);
+ g_error_free(gerr);
+ mcl->ms->mcl_disconnected_cb(mcl, mcl->ms->user_data);
+ mcap_cache_mcl(mcl);
+ return FALSE;
+}
+
static void proc_response(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
{
- /* TODO: Process response */
+ gboolean close;
+ RELEASE_TIMER(mcl);
+
+ if (!check_rsp(mcl, cmd, len))
+ return;
+
+ switch (cmd[0]) {
+ case MCAP_ERROR_RSP:
+ error("MCAP_ERROR_RSP received");
+ close = TRUE;
+ break;
+ case MCAP_MD_CREATE_MDL_RSP:
+ /* close = process_md_create_mdl_rsp(mcl, cmd, len); */
+ break;
+ case MCAP_MD_RECONNECT_MDL_RSP:
+ /* close = process_md_reconnect_mdl_rsp(mcl, cmd, len); */
+ break;
+ case MCAP_MD_ABORT_MDL_RSP:
+ /* close = process_md_abort_mdl_rsp(mcl, cmd, len); */
+ break;
+ case MCAP_MD_DELETE_MDL_RSP:
+ /* close = process_md_delete_mdl_rsp(mcl, cmd, len); */
+ break;
+ default:
+ debug("Unknown cmd response received (op code = %d)",cmd[0]);
+ close = TRUE;
+ break;
+ }
+
+ if (close) {
+ mcl->ms->mcl_disconnected_cb(mcl, mcl->ms->user_data);
+ mcap_cache_mcl(mcl);
+ }
}
static void rsend_req(struct mcap_mcl *mcl)
--
1.6.3.3
^ permalink raw reply related
* [PATCH 17/25] Support for sending md_delete_mdl_req command
From: Santiago Carot-Nemesio @ 2010-05-12 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Santiago Carot Nemesio
In-Reply-To: <1273486527-7855-17-git-send-email-sancane@gmail.com>
From: Santiago Carot Nemesio <sancane@gmail.com>
---
mcap/mcap.c | 211 ++++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 145 insertions(+), 66 deletions(-)
diff --git a/mcap/mcap.c b/mcap/mcap.c
index 1d01937..75d3d58 100644
--- a/mcap/mcap.c
+++ b/mcap/mcap.c
@@ -76,6 +76,88 @@ static void (*proc_req[])(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) = {
static void mcap_cache_mcl(struct mcap_mcl *mcl);
static void mcap_uncache_mcl(struct mcap_mcl *mcl);
+static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl connection");
+}
+
+static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl clsoed");
+}
+
+static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl deleted");
+}
+
+static void default_mdl_aborted_cb(struct mcap_mdl *mdl, gpointer data)
+{
+ debug("MCAP Unmanaged mdl aborted");
+}
+
+static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl,
+ uint8_t mdepid, uint16_t mdlid,
+ uint8_t *conf, gpointer data)
+{
+ debug("MCAP mdl remote connection aborted");
+ /* Due to this callback is not managed this request won't be supported */
+ return MCAP_REQUEST_NOT_SUPPORTED;
+}
+
+static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl,
+ gpointer data)
+{
+ debug("MCAP mdl remote reconnection aborted");
+ /* Due to this callback is not managed this request won't be supported */
+ return MCAP_REQUEST_NOT_SUPPORTED;
+}
+
+static void set_default_cb(struct mcap_mcl *mcl)
+{
+ if (!mcl->cb)
+ mcl->cb = g_new0(struct mcap_mdl_cb, 1);
+
+ mcl->cb->mdl_connected = default_mdl_connected_cb;
+ mcl->cb->mdl_closed = default_mdl_closed_cb;
+ mcl->cb->mdl_deleted = default_mdl_deleted_cb;
+ mcl->cb->mdl_aborted = default_mdl_aborted_cb;
+ mcl->cb->mdl_conn_req = default_mdl_conn_req_cb;
+ mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb;
+}
+
+static char *error2str(uint8_t rc)
+{
+ switch (rc) {
+ case MCAP_SUCCESS:
+ return "Success";
+ case MCAP_INVALID_OP_CODE:
+ return "Invalid Op Code";
+ case MCAP_INVALID_PARAM_VALUE:
+ return "Ivalid Parameter Value";
+ case MCAP_INVALID_MDEP:
+ return "Invalid MDEP";
+ case MCAP_MDEP_BUSY:
+ return "MDEP Busy";
+ case MCAP_INVALID_MDL:
+ return "Invalid MDL";
+ case MCAP_MDL_BUSY:
+ return "MDL Busy";
+ case MCAP_INVALID_OPERATION:
+ return "Invalid Operation";
+ case MCAP_RESOURCE_UNAVAILABLE:
+ return "Resource Unavailable";
+ case MCAP_UNSPECIFIED_ERROR:
+ return "Unspecified Error";
+ case MCAP_REQUEST_NOT_SUPPORTED:
+ return "Request Not Supported";
+ case MCAP_CONFIGURATION_REJECTED:
+ return "Configuration Rejected";
+ default:
+ return "Unknown Response Code";
+ }
+}
+
static void mcap_send_std_opcode(struct mcap_mcl *mcl, uint8_t *cmd,
uint32_t size, GError **err)
{
@@ -357,86 +439,83 @@ void mcap_req_mdl_reconnect(struct mcap_mdl *mdl,
mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
}
-static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
+static void send_delete_req(GError **err, struct mcap_mcl *mcl,
+ struct mcap_mdl_op_cb *con, uint16_t mdlid)
{
- debug("MCAP Unmanaged mdl connection");
-}
+ uint8_t *cmd;
-static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data)
-{
- debug("MCAP Unmanaged mdl clsoed");
-}
+ cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdlid);
+ mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
+ if (*err) {
+ g_free(cmd);
+ return;
+ }
-static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data)
-{
- debug("MCAP Unmanaged mdl deleted");
-}
+ mcl->priv_data = con;
-static void default_mdl_aborted_cb(struct mcap_mdl *mdl, gpointer data)
-{
- debug("MCAP Unmanaged mdl aborted");
+ mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl);
}
-static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl,
- uint8_t mdepid, uint16_t mdlid,
- uint8_t *conf, gpointer data)
+void mcap_req_mdl_delete_all(struct mcap_mcl *mcl, GError **err,
+ mcap_mdl_del_cb delete_cb, gpointer user_data)
{
- debug("MCAP mdl remote connection aborted");
- /* Due to this callback is not managed this request won't be supported */
- return MCAP_REQUEST_NOT_SUPPORTED;
-}
+ GSList *l;
+ struct mcap_mdl *mdl;
+ struct mcap_mdl_op_cb *con;
-static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl,
- gpointer data)
-{
- debug("MCAP mdl remote reconnection aborted");
- /* Due to this callback is not managed this request won't be supported */
- return MCAP_REQUEST_NOT_SUPPORTED;
-}
+ debug("MCL in state: %d", mcl->state);
+ if (!mcl->mdls) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "There are not MDLs created");
+ return;
+ }
-static void set_default_cb(struct mcap_mcl *mcl)
-{
- if (!mcl->cb)
- mcl->cb = g_new0(struct mcap_mdl_cb, 1);
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdl->state != MDL_WAITING)
+ mdl->state = MDL_DELETING;
+ }
- mcl->cb->mdl_connected = default_mdl_connected_cb;
- mcl->cb->mdl_closed = default_mdl_closed_cb;
- mcl->cb->mdl_deleted = default_mdl_deleted_cb;
- mcl->cb->mdl_aborted = default_mdl_aborted_cb;
- mcl->cb->mdl_conn_req = default_mdl_conn_req_cb;
- mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb;
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = NULL;
+ con->cb.del = delete_cb;
+ con->user_data = user_data;
+
+ send_delete_req(err, mcl, con, MCAP_ALL_MDLIDS);
+ if (*err)
+ g_free(con);
}
-static char *error2str(uint8_t rc)
+void mcap_req_mdl_deletion(struct mcap_mdl *mdl, GError **err,
+ mcap_mdl_del_cb delete_cb, gpointer user_data)
{
- switch (rc) {
- case MCAP_SUCCESS:
- return "Success";
- case MCAP_INVALID_OP_CODE:
- return "Invalid Op Code";
- case MCAP_INVALID_PARAM_VALUE:
- return "Ivalid Parameter Value";
- case MCAP_INVALID_MDEP:
- return "Invalid MDEP";
- case MCAP_MDEP_BUSY:
- return "MDEP Busy";
- case MCAP_INVALID_MDL:
- return "Invalid MDL";
- case MCAP_MDL_BUSY:
- return "MDL Busy";
- case MCAP_INVALID_OPERATION:
- return "Invalid Operation";
- case MCAP_RESOURCE_UNAVAILABLE:
- return "Resource Unavailable";
- case MCAP_UNSPECIFIED_ERROR:
- return "Unspecified Error";
- case MCAP_REQUEST_NOT_SUPPORTED:
- return "Request Not Supported";
- case MCAP_CONFIGURATION_REJECTED:
- return "Configuration Rejected";
- default:
- return "Unknown Response Code";
+ struct mcap_mcl *mcl= mdl->mcl;
+ struct mcap_mdl_op_cb *con;
+ GSList *l;
+
+ l = g_slist_find(mcl->mdls, mdl);
+
+ if (!l) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL,
+ "%s" , error2str(MCAP_INVALID_MDEP));
+ return;
}
+
+ if (mdl->state == MDL_WAITING) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
+ "Mdl is not created");
+ return;
+ }
+ mdl->state = MDL_DELETING;
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = mdl;
+ con->cb.del = delete_cb;
+ con->user_data = user_data;
+
+ send_delete_req(err, mcl, con, mdl->mdlid);
+ if (*err)
+ g_free(con);
}
static void update_mcl_state(struct mcap_mcl *mcl)
--
1.6.3.3
^ permalink raw reply related
* [PATCH 14/25] Support for managing creation of data channels
From: Santiago Carot-Nemesio @ 2010-05-12 9:58 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Santiago Carot Nemesio
In-Reply-To: <1273486527-7855-14-git-send-email-sancane@gmail.com>
From: Santiago Carot Nemesio <sancane@gmail.com>
---
mcap/mcap.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 171 insertions(+), 1 deletions(-)
diff --git a/mcap/mcap.c b/mcap/mcap.c
index 6d548b9..3d442d1 100644
--- a/mcap/mcap.c
+++ b/mcap/mcap.c
@@ -49,6 +49,18 @@ struct connect_mcl {
gpointer user_data; /* Callback user data */
};
+typedef union {
+ mcap_mdl_operation_cb op;
+ mcap_mdl_operation_conf_cb op_conf;
+ mcap_mdl_del_cb del;
+} mcap_cb_type;
+
+struct mcap_mdl_op_cb {
+ struct mcap_mdl *mdl; /* MDL for this operation */
+ mcap_cb_type cb; /* Operation callback */
+ gpointer user_data; /* Callback user data */
+};
+
/* MCAP finite state machine functions */
static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len);
static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len);
@@ -179,6 +191,38 @@ static void set_default_cb(struct mcap_mcl *mcl)
mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb;
}
+static char *error2str(uint8_t rc)
+{
+ switch (rc) {
+ case MCAP_SUCCESS:
+ return "Success";
+ case MCAP_INVALID_OP_CODE:
+ return "Invalid Op Code";
+ case MCAP_INVALID_PARAM_VALUE:
+ return "Ivalid Parameter Value";
+ case MCAP_INVALID_MDEP:
+ return "Invalid MDEP";
+ case MCAP_MDEP_BUSY:
+ return "MDEP Busy";
+ case MCAP_INVALID_MDL:
+ return "Invalid MDL";
+ case MCAP_MDL_BUSY:
+ return "MDL Busy";
+ case MCAP_INVALID_OPERATION:
+ return "Invalid Operation";
+ case MCAP_RESOURCE_UNAVAILABLE:
+ return "Resource Unavailable";
+ case MCAP_UNSPECIFIED_ERROR:
+ return "Unspecified Error";
+ case MCAP_REQUEST_NOT_SUPPORTED:
+ return "Request Not Supported";
+ case MCAP_CONFIGURATION_REJECTED:
+ return "Configuration Rejected";
+ default:
+ return "Unknown Response Code";
+ }
+}
+
static void update_mcl_state(struct mcap_mcl *mcl)
{
GSList *l;
@@ -833,6 +877,86 @@ static void proc_cmd(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
proc_req[mcl->state](mcl, cmd, len);
}
+static gboolean mdl_event_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+
+ struct mcap_mdl *mdl = data;
+ gboolean notify;
+
+ debug("Close MDL %d", mdl->mdlid);
+
+ notify = (mdl->state == MDL_CONNECTED);
+ shutdown_mdl(mdl);
+
+ update_mcl_state(mdl->mcl);
+
+ if (notify)
+ /*Callback to upper layer */
+ mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
+
+ return FALSE;
+}
+
+static void mcap_connect_mdl_cb(GIOChannel *chan, GError *conn_err,
+ gpointer data)
+{
+ struct mcap_mdl_op_cb *con = data;
+ struct mcap_mdl *mdl = con->mdl;
+ mcap_mdl_operation_cb cb = con->cb.op;
+ gpointer user_data = con->user_data;
+
+ g_free(con);
+ debug("mdl connect callback");
+
+ if (conn_err) {
+ debug("ERROR: mdl connect callback");
+ mdl->state = MDL_CLOSED;
+ g_io_channel_unref(mdl->dc);
+ mdl->dc = NULL;
+ cb(mdl, conn_err, user_data);
+ return;
+ }
+
+ mdl->state = MDL_CONNECTED;
+ mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mdl_event_cb, mdl);
+
+ cb(mdl, conn_err, user_data);
+}
+
+void mcap_mdl_connect(struct mcap_mdl *mdl, BtIOType BtType, uint16_t dcpsm,
+ GError **err, mcap_mdl_operation_cb connect_cb, gpointer user_data)
+{
+ struct mcap_mdl_op_cb *con;
+
+ if (mdl->state != MDL_WAITING) {
+ g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL,
+ "%s", error2str(MCAP_INVALID_MDL));
+ return;
+ }
+
+ con = g_new0(struct mcap_mdl_op_cb, 1);
+ con->mdl = mdl;
+ con->cb.op = connect_cb;
+ con->user_data = user_data;
+
+ /* TODO: Check if BtIOType is ERTM or Streaming before continue */
+
+ mdl->dc = bt_io_connect(BtType, mcap_connect_mdl_cb, con,
+ NULL, err,
+ BT_IO_OPT_SOURCE_BDADDR, &mdl->mcl->ms->src,
+ BT_IO_OPT_DEST_BDADDR, &mdl->mcl->addr,
+ BT_IO_OPT_PSM, dcpsm,
+ BT_IO_OPT_MTU, MCAP_DC_MTU,
+ BT_IO_OPT_SEC_LEVEL, mdl->mcl->ms->sec,
+ BT_IO_OPT_INVALID);
+ if (*err) {
+ debug("MDL Connection error");
+ mdl->state = MDL_CLOSED;
+ g_free(con);
+ }
+}
+
static gboolean mcl_control_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
{
@@ -916,6 +1040,20 @@ static void mcap_connect_mcl_cb(GIOChannel *chan, GError *conn_err,
}
}
+static void connect_dc_event_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ struct mcap_mdl *mdl = user_data;
+ struct mcap_mcl *mcl = mdl->mcl;
+
+ mdl->state = MDL_CONNECTED;
+ mdl->dc = g_io_channel_ref(chan);
+ mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) mdl_event_cb, mdl);
+
+ mcl->state = MCL_ACTIVE;
+ mcl->cb->mdl_connected(mdl, mcl->cb->user_data);
+}
+
void mcap_create_mcl(struct mcap_session *ms,
const bdaddr_t *addr,
uint16_t ccpsm,
@@ -968,7 +1106,39 @@ void mcap_create_mcl(struct mcap_session *ms,
static void confirm_dc_event_cb(GIOChannel *chan, gpointer user_data)
{
- /* TODO: Check if we can connect this data channel */
+ struct mcap_session *ms = user_data;
+ struct mcap_mcl *mcl;
+ struct mcap_mdl *mdl;
+ GError *err = NULL;
+ bdaddr_t dst;
+ GSList *l;
+
+ bt_io_get(chan, BT_IO_L2CAP, &err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ mcl = find_mcl(ms->mcls, &dst);
+ if (!mcl || (mcl->state != MCL_PENDING))
+ goto drop;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdl->state == MDL_WAITING) {
+ if (!bt_io_accept(chan, connect_dc_event_cb, mdl, NULL,
+ &err)) {
+ error("MDL accept error %s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+ return;
+ }
+ }
+drop:
g_io_channel_shutdown(chan, TRUE, NULL);
}
--
1.6.3.3
^ permalink raw reply related
* [PATCH 10/25] Process md_create_mdl_req command in state connected
From: Santiago Carot-Nemesio @ 2010-05-12 9:56 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Santiago Carot Nemesio
In-Reply-To: <1273486527-7855-10-git-send-email-sancane@gmail.com>
From: Santiago Carot Nemesio <sancane@gmail.com>
---
mcap/mcap.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 151 insertions(+), 2 deletions(-)
diff --git a/mcap/mcap.c b/mcap/mcap.c
index 3a4b2b9..1bc3ed5 100644
--- a/mcap/mcap.c
+++ b/mcap/mcap.c
@@ -95,6 +95,40 @@ static int send4B_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
return sent;
}
+static int send5B_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
+ uint16_t mdl, uint8_t param)
+{
+ uint8_t *rsp;
+ mcap5B_rsp *suc;
+ int sent;
+
+ rsp = g_malloc0(sizeof(mcap5B_rsp));
+
+ suc = (mcap5B_rsp *)rsp;
+ suc->op = oc;
+ suc->rc = rc;
+ suc->mdl = htons(mdl);
+ suc->param = param;
+
+ sent = mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), rsp,
+ sizeof(mcap5B_rsp));
+ g_free(rsp);
+ return sent;
+}
+
+static gint compare_mdl(gconstpointer a, gconstpointer b)
+{
+ const struct mcap_mdl *mdla = a;
+ const struct mcap_mdl *mdlb = b;
+
+ if (mdla->mdlid == mdlb->mdlid)
+ return 0;
+ else if (mdla->mdlid < mdlb->mdlid)
+ return -1;
+ else
+ return 1;
+}
+
static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
{
debug("MCAP Unmanaged mdl connection");
@@ -425,11 +459,126 @@ bdaddr_t mcap_mcl_get_addr(struct mcap_mcl *mcl)
return mcl->addr;
}
-/* Function used to process commands depending of MCL state */
+static void error_cmd_rsp(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
+{
+ uint16_t mdlr;
+
+ if (cmd[0] <= MCAP_MD_DELETE_MDL_RSP) {
+ /* Standard Op Code request is invalid in current state */
+ error("Invalid cmd received (op code = %d) in state %d",
+ cmd[0], mcl->state);
+ /* Get mdlid sended to generate appropriate response if it is possible */
+ mdlr = len < sizeof(mcap_md_req) ? MCAP_MDLID_RESERVED :
+ ntohs(((mcap_md_req *)cmd)->mdl);
+ send4B_cmd(mcl, cmd[0]+1, MCAP_INVALID_OPERATION, mdlr);
+ } else {
+ error("Unknown cmd request received (op code = %d) in state %d",
+ cmd[0], mcl->state);
+ send4B_cmd(mcl, MCAP_ERROR_RSP, MCAP_INVALID_OP_CODE,
+ MCAP_MDLID_RESERVED);
+ }
+}
+
+static struct mcap_mdl *get_mdl(struct mcap_mcl *mcl, uint16_t mdlid)
+{
+ GSList *l;
+ struct mcap_mdl *mdl;
+
+ for (l = mcl->mdls; l; l = l->next) {
+ mdl = l->data;
+ if (mdlid == mdl->mdlid)
+ return mdl;
+ }
+
+ return NULL;
+}
+
+static void process_md_create_mdl_req(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
+{
+ mcap_md_create_mdl_req *req;
+ struct mcap_mdl *mdl;
+ uint16_t mdl_id;
+ uint8_t mdep_id;
+ uint8_t cfga, conf;
+ uint8_t rsp;
+
+ if (len != sizeof(mcap_md_create_mdl_req)) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP,
+ MCAP_INVALID_PARAM_VALUE, MCAP_MDLID_RESERVED);
+ return;
+ }
+
+ req = (mcap_md_create_mdl_req *)cmd;
+
+ mdl_id = ntohs(req->mdl);
+ if ((mdl_id < MCAP_MDLID_INITIAL) || (mdl_id > MCAP_MDLID_FINAL)) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL, mdl_id);
+ return;
+ }
+
+ mdep_id = req->mdep;
+ if (mdep_id > MCAP_MDEPID_FINAL) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDEP, mdl_id);
+ return;
+ }
+
+ cfga = conf = req->conf;
+ /* Callback to upper layer */
+ rsp = mcl->cb->mdl_conn_req(mcl, mdep_id, mdl_id, &conf,
+ mcl->cb->user_data);
+ if (mcl->state == MCL_IDLE) {
+ /* MCL has been closed int the callback */
+ return;
+ }
+
+ if ((cfga != 0) && (cfga != conf)) {
+ /* Remote device set default configuration but upper profile */
+ /* has changed it. Protocol Error: force closing the MCL by */
+ /* remote device using UNSPECIFIED_ERROR response */
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_UNSPECIFIED_ERROR,
+ mdl_id);
+ return;
+ }
+ if (rsp != MCAP_SUCCESS) {
+ send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id);
+ return;
+ }
+ mdl = get_mdl(mcl, mdl_id);
+ if (!mdl) {
+ mdl = g_malloc0(sizeof(struct mcap_mdl));
+ mdl->mcl = mcl;
+ mdl->mdlid = mdl_id;
+ } else if (mdl->state == MDL_CONNECTED) {
+ /* MCAP specification says that we should close the MCL if
+ * it is open when we receive a MD_CREATE_MDL_REQ */
+ shutdown_mdl(mdl);
+ }
+ mdl->mdep_id = mdep_id;
+ mdl->state = MDL_WAITING;
+ mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
+
+ mcl->state = MCL_PENDING;
+ send5B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_SUCCESS, mdl_id, conf);
+}
+
+
+/* Function used to process commands depending of MCL state */
static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
{
- /* TODO: Proccessing commands in CONNECTED state */
+ switch (cmd[0]) {
+ case MCAP_MD_CREATE_MDL_REQ:
+ process_md_create_mdl_req(mcl, cmd, len);
+ break;
+ case MCAP_MD_RECONNECT_MDL_REQ:
+ /*process_md_reconnect_mdl_req(mcl, cmd, len);*/
+ break;
+ case MCAP_MD_DELETE_MDL_REQ:
+ /*process_md_delete_mdl_req(mcl, cmd, len);*/
+ break;
+ default:
+ error_cmd_rsp(mcl, cmd, len);
+ }
}
static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
--
1.6.3.3
^ permalink raw reply related
* Re: HDP proposed API (ver 0.3)
From: José Antonio Santos Cadenas @ 2010-05-12 9:39 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Elvis Pfützenreuter, Santiago Carot, Raul Herbster
In-Reply-To: <201005121126.12859.jcaden@libresoft.es>
El Wednesday 12 May 2010 11:26:12 José Antonio Santos Cadenas escribió:
> This api is a clean up of the previous one the changes.
>
> We've added a new object that uses device path to get the sessions
> allocated on this device (as somebody recommended in other thread,
> I think Luiz, Elvis or both, but I can't find the exact email). The discovery
> of new remote session should be done using device drivers, which is
> compliant with the BlueZ style.
>
> Discussions still in progress:
>
> - Fd-passing issue: As Elvis, Santiago and I discussed yesterday on
> IRC we think that the best propose is as follows (please Elvis correct
> me if I misunderstood something yesterday):
> Reconnections should be implicit and the data channel should
> be perceived by the application layer as connected all the time.
> When the application tries to write in a closed data channel, HDP
> will perform the data channel reconnection and if it fails, then the channel
> will be present as closed.
> The implementation for this this behaviour will use pipes. Each data
> channel will use 2 pipes to do fd-passing to the application. The upper
> layer will write in this pipes and HDP will redirect it through the l2cap socket,
> in this operation, HDP can reconnect if th l2cap socket is closed.
>
> - Sessions issues: We still think that session are necessary because they
> are mentioned in the standard and in the whitepaper and we think that
> bluez should follow the standards in order to pass PTS for allow Bluetooth SIG
> certifications. Any comment in this respect are welcome to improve the API
> usability and conformity with Bluez APIs.
>
> - Paths issues: It will be great to find names and paths that are good for
> everybody, comments and suggestion on this respect are also welcome.
>
> I hope we can fix this API asap. All comments or ideas are welcome.
>
> Regards.
>
> --------------------------------------------------
>
> BlueZ D-Bus HDP 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.Hdp
> Object path [variable prefix]/{hci0,hci1,...}
>
> Methods object CreateSession(object path, dict config)
>
> Returns the object path for the new HDP session.
> The path parameter is the path of the remote object
> with the callbacks to notify events (see
> org.bluez.HdpAgent at the end of this document)
> This petition starts an mcap session and also register
> in the SDP 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)
About explicitly set the mdepids, we (Santiago and me) think that HDP should
assign them automatically, this way less protocol issues are exposed to the
application layer as Luiz suggested. The HDP client should only use mdeps when
connecting to a remote data channel. HDP will assign a unique mdepid
to each element of "end_points" array.
> "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
>
> Session will be closed by the call or implicitly when
> the programs leaves the bus.
>
> Possible errors: org.bluez.Error.InvalidArguments
>
> void CloseSession(object path)
>
> Closes the HDP session identified by the object path.
> Also session will be closed if the process that started
> it is removed from the D-Bus.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.NotFound
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.Hdp
> Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
>
> Methods array GetSessions()
>
> Gets the information of the remote sessions present
> in this device and published on its SDP record. The
> returned data follows this format.
>
> [{"session_id": "a session identification as string",
> "data_spec" : session data spec,
> "end_points":
> ["mdepid": uint8,
> "role" : "source" or "sink" ,
> "specs" : [{
> "dtype" : uint16,
> "description" : string, (optional)
> }]
> ]
> }]
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.HdpSession
> Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}
>
> object Connect(remote_session_id)
>
> Connects with the remote session and returns its object
> path.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.HdpError
>
> void Disconnect(object device, boolean delete)
>
> Disconnect from the remote device. If delete is true, any
> status will also be deleted. Otherwise, the status will
> be kept for allowing future reconnections.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.NotFound
> org.bluez.Error.HdpError
>
> --------------------------------------------------------------------------------
>
> Service org.bluez
> Interface org.bluez.HdpRemoteSession
> Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_session_id
>
> boolean Echo(array{byte})
>
> Sends an echo petition to the remote session. Return 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.
> Returns the data channel id.
>
> Possible errors: org.bluez.Error.InvalidArguments
> org.bluez.Error.HdpError
>
> array GetDcFd(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.HdpError
>
> 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.HdpError
>
> 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.HdpError
>
> 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": [id1, ..., idz],
> "best_effort" : [idx, ..., idy]
> }
>
> The fist reliable data channel will always be the first
> data channel in reliable array.
>
> HDPAgent hierarchy
> ==================
>
> (this object is implemented by the HDP client an receives notifications)
>
> Service unique name
> Interface org.bluez.HdpAgent
> Object path freely definable
>
> void DeviceConnected(object path)
>
> This method is called whenever a new device connection
> has been established over the control channel of the
> current HDP session. The object path contains the object
> path of the remote device.
>
> void DeviceDisconnected(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)
>
> This method is called when a new data channel is created
> The path contains the object path of the device whith
> the new connection is created and the mdlid the data
> channel identificator.
>
> 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
* HDP proposed API (ver 0.3)
From: José Antonio Santos Cadenas @ 2010-05-12 9:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Elvis Pfützenreuter, Santiago Carot, Raul Herbster
This api is a clean up of the previous one the changes.
We've added a new object that uses device path to get the sessions
allocated on this device (as somebody recommended in other thread,
I think Luiz, Elvis or both, but I can't find the exact email). The discovery
of new remote session should be done using device drivers, which is
compliant with the BlueZ style.
Discussions still in progress:
- Fd-passing issue: As Elvis, Santiago and I discussed yesterday on
IRC we think that the best propose is as follows (please Elvis correct
me if I misunderstood something yesterday):
Reconnections should be implicit and the data channel should
be perceived by the application layer as connected all the time.
When the application tries to write in a closed data channel, HDP
will perform the data channel reconnection and if it fails, then the channel
will be present as closed.
The implementation for this this behaviour will use pipes. Each data
channel will use 2 pipes to do fd-passing to the application. The upper
layer will write in this pipes and HDP will redirect it through the l2cap socket,
in this operation, HDP can reconnect if th l2cap socket is closed.
- Sessions issues: We still think that session are necessary because they
are mentioned in the standard and in the whitepaper and we think that
bluez should follow the standards in order to pass PTS for allow Bluetooth SIG
certifications. Any comment in this respect are welcome to improve the API
usability and conformity with Bluez APIs.
- Paths issues: It will be great to find names and paths that are good for
everybody, comments and suggestion on this respect are also welcome.
I hope we can fix this API asap. All comments or ideas are welcome.
Regards.
--------------------------------------------------
BlueZ D-Bus HDP 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.Hdp
Object path [variable prefix]/{hci0,hci1,...}
Methods object CreateSession(object path, dict config)
Returns the object path for the new HDP session.
The path parameter is the path of the remote object
with the callbacks to notify events (see
org.bluez.HdpAgent at the end of this document)
This petition starts an mcap session and also register
in the SDP 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
Session will be closed by the call or implicitly when
the programs leaves the bus.
Possible errors: org.bluez.Error.InvalidArguments
void CloseSession(object path)
Closes the HDP session identified by the object path.
Also session will be closed if the process that started
it is removed from the D-Bus.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.NotFound
--------------------------------------------------------------------------------
Service org.bluez
Interface org.bluez.Hdp
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
Methods array GetSessions()
Gets the information of the remote sessions present
in this device and published on its SDP record. The
returned data follows this format.
[{"session_id": "a session identification as string",
"data_spec" : session data spec,
"end_points":
["mdepid": uint8,
"role" : "source" or "sink" ,
"specs" : [{
"dtype" : uint16,
"description" : string, (optional)
}]
]
}]
--------------------------------------------------------------------------------
Service org.bluez
Interface org.bluez.HdpSession
Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}
object Connect(remote_session_id)
Connects with the remote session and returns its object
path.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.HdpError
void Disconnect(object device, boolean delete)
Disconnect from the remote device. If delete is true, any
status will also be deleted. Otherwise, the status will
be kept for allowing future reconnections.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.NotFound
org.bluez.Error.HdpError
--------------------------------------------------------------------------------
Service org.bluez
Interface org.bluez.HdpRemoteSession
Object path [variable prefix]/{hci0,hci1,...}/{hdp0,hdp1,...}/rem_session_id
boolean Echo(array{byte})
Sends an echo petition to the remote session. Return 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.
Returns the data channel id.
Possible errors: org.bluez.Error.InvalidArguments
org.bluez.Error.HdpError
array GetDcFd(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.HdpError
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.HdpError
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.HdpError
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": [id1, ..., idz],
"best_effort" : [idx, ..., idy]
}
The fist reliable data channel will always be the first
data channel in reliable array.
HDPAgent hierarchy
==================
(this object is implemented by the HDP client an receives notifications)
Service unique name
Interface org.bluez.HdpAgent
Object path freely definable
void DeviceConnected(object path)
This method is called whenever a new device connection
has been established over the control channel of the
current HDP session. The object path contains the object
path of the remote device.
void DeviceDisconnected(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)
This method is called when a new data channel is created
The path contains the object path of the device whith
the new connection is created and the mdlid the data
channel identificator.
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: [PATCH] Initial support for MCAP
From: Santiago Carot-Nemesio @ 2010-05-12 8:45 UTC (permalink / raw)
To: Raul Herbster; +Cc: Santiago Carot-Nemesio, linux-bluetooth
In-Reply-To: <AANLkTikVs1YfnusOO8sRO9xbbOcZNU6STTlkygFvpNv3@mail.gmail.com>
Hi Raul,
This patch is applied over a old version of MCAP (first that I sent).
New version (splited in 25 patches) fix more of typo error that you are
commented and Gustavo already notified.
El mar, 11-05-2010 a las 19:00 -0300, Raul Herbster escribió:
> Hi Santiago,
>
> only typo errors:
>
> diff --git a/mcap/mcap.c b/mcap/mcap.c
> index 404d7be..6142938 100644
> --- a/mcap/mcap.c
> +++ b/mcap/mcap.c
> @@ -116,7 +116,7 @@ struct mcap_mcl {
> #define MCAP_CTRL_CACHED 0x01 /* MCL is cached */
> #define MCAP_CTRL_STD_OP 0x02 /* Support for standard op
> codes */
> #define MCAP_CTRL_SYNC_OP 0x04 /* Support for
> synchronization commands */
> -#define MCAP_CTRL_CONN 0x08 /* MCL is in connectcting
> process */
> +#define MCAP_CTRL_CONN 0x08 /* MCL is in connecting
> process */
This error is already fixed in my previous patch. Be careful, above
definitions are not yet included in mcap.c, update you work tree from
latest patches ;)
> #define MCAP_CTRL_FREE 0x10 /* MCL is marked as
> releasable */
> #define MCAP_CTRL_NOCACHE 0x20 /* MCL is marked as not
> cacheable */
>
> @@ -242,7 +242,7 @@ static char *error2str(uint8_t rc)
> return "Invalid Operation";
> case MCAP_RESOURCE_UNAVAILABLE:
> return "Resource Unavailable";
> - case MCAP_UNESPECIFIED_ERROR:
> + case MCAP_UNSPECIFIED_ERROR:
You're right, I'll redo the patch to fix all "UNESPECIFIED" erroneous
word.
> return "Unspecified Error";
> case MCAP_REQUEST_NOT_SUPPORTED:
> return "Request Not Supported";
> @@ -1056,8 +1056,8 @@ static void process_md_create_mdl_req(struct
> mcap_mcl *mcl, uint8_t *cmd, uint32
> if ((cfga != 0) && (cfga != conf)) {
> /* Remote device set default configuration but upper profile
> */
> /* has changed it. Protocol Error: force closing the MCL by
> */
> - /* remote device using UNESPECIFIED_ERROR response */
> - send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP,
> MCAP_UNESPECIFIED_ERROR,
> + /* remote device using UNSPECIFIED_ERROR response */
> + send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP,
> MCAP_UNSPECIFIED_ERROR,
> mdl_id);
> return;
> }
> @@ -1548,13 +1548,13 @@ static gboolean check_rsp(struct mcap_mcl
> *mcl, uint8_t *cmd, uint32_t len)
> return FALSE;
> }
>
> - if (rsp->rc == MCAP_UNESPECIFIED_ERROR)
> + if (rsp->rc == MCAP_UNSPECIFIED_ERROR)
> goto close_mcl;
>
> return TRUE;
> close_mcl:
> - if (rsp->rc == MCAP_UNESPECIFIED_ERROR)
> - g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_UNESPECIFIED_ERROR,
> + if (rsp->rc == MCAP_UNSPECIFIED_ERROR)
> + g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_UNSPECIFIED_ERROR,
> "%s", error2str(rsp->rc));
> else
> g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
> diff --git a/mcap/mcap.h b/mcap/mcap.h
> index 598e6ce..77c83c2 100644
> --- a/mcap/mcap.h
> +++ b/mcap/mcap.h
> @@ -76,7 +76,7 @@ extern "C" {
> #define MCAP_MDL_BUSY 0x06
> #define MCAP_INVALID_OPERATION 0x07
> #define MCAP_RESOURCE_UNAVAILABLE 0x08
> -#define MCAP_UNESPECIFIED_ERROR 0x09
> +#define MCAP_UNSPECIFIED_ERROR 0x09
> #define MCAP_REQUEST_NOT_SUPPORTED 0x0A
> #define MCAP_CONFIGURATION_REJECTED 0x0B
> /*RESERVED 0x0C-0xFF*/
> diff --git a/mcap/mcap_lib.h b/mcap/mcap_lib.h
> index fd3eb74..d75e0f0 100644
> --- a/mcap/mcap_lib.h
> +++ b/mcap/mcap_lib.h
> @@ -45,7 +45,7 @@ typedef enum {
> MCAP_ERROR_MDL_BUSY,
> MCAP_ERROR_INVALID_OPERATION,
> MCAP_ERROR_RESOURCE_UNAVAILABLE,
> - MCAP_ERROR_UNESPECIFIED_ERROR,
> + MCAP_ERROR_UNSPECIFIED_ERROR,
> MCAP_ERROR_REQUEST_NOT_SUPPORTED,
> MCAP_ERROR_CONFIGURATION_REJECTED,
> /* MCAP Internal Errors */
> @@ -79,7 +79,7 @@ typedef void (* mcap_mdl_operation_cb) (struct
> mcap_mdl *mdl, GError *err,
> gpointer data);
> typedef void (* mcap_mdl_del_cb) (GError *err, gpointer data);
>
> -/* Next function should return an MCAP appropiate response code */
> +/* Next function should return an MCAP appropriate response code */
Ok, we don't see that. I'll change it too.
> typedef uint8_t (* mcap_remote_mdl_conn_req_cb) (struct mcap_mcl
> *mcl,
> uint8_t mdepid, uint16_t mdlid,
> uint8_t *conf, gpointer data);
>
>
> []' s
> --Raul
>
Thanks fore typo errors but I suggest to you work with latest patches I
sent 2 days ago.
Regards.
^ permalink raw reply
* Re: [PATCH 03/25] Release resources depending if MCAP should cache or not a MCL
From: Santiago Carot-Nemesio @ 2010-05-12 7:05 UTC (permalink / raw)
To: Raul Herbster; +Cc: Santiago Carot-Nemesio, linux-bluetooth
In-Reply-To: <AANLkTilMh75dW1rUlmOV_AZ7UZqGX1vv_nyZu9qaJgKX@mail.gmail.com>
El mar, 11-05-2010 a las 19:09 -0300, Raul Herbster escribió:
> Hi Santiago,
>
> 2010/5/10 Santiago Carot-Nemesio <sancane@gmail.com>:
> > From: Santiago Carot Nemesio <sancane@gmail.com>
> >
> > ---
> > mcap/mcap.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 files changed, 81 insertions(+), 2 deletions(-)
> >
> > diff --git a/mcap/mcap.c b/mcap/mcap.c
> > index 1c94452..7d34b95 100644
> > --- a/mcap/mcap.c
> > +++ b/mcap/mcap.c
> > @@ -36,14 +36,93 @@
> >
> > #define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
> >
> > +#define RELEASE_TIMER(__mcl) do { \
> > + g_source_remove(__mcl->tid); \
> > + __mcl->tid = 0; \
> > +} while(0)
> > +
> > +static void shutdown_mdl(struct mcap_mdl *mdl)
> > +{
> > + mdl->state = MDL_CLOSED;
> > +
> > + g_source_remove(mdl->wid);
> > +
> > + if (mdl->dc) {
> > + g_io_channel_shutdown(mdl->dc, TRUE, NULL);
> > + g_io_channel_unref(mdl->dc);
> > + mdl->dc = NULL;
> > + }
> > +}
> > +
> > +static void mcap_free_mdls(struct mcap_mcl *mcl, gboolean save)
> > +{
> > + GSList *l;
> > + struct mcap_mdl *mdl;
> > +
> > + if (!mcl->mdls)
> > + return;
> > +
> > + for (l = mcl->mdls; l; l = l->next) {
> > + mdl = l->data;
> > + shutdown_mdl(mdl);
> > + if (!save)
> > + g_free(mdl);
> > + }
> > +
> > + if (!save) {
> > + g_slist_free(mcl->mdls);
> > + mcl->mdls = NULL;
> > + }
> > +}
> > +
> > +static void mcap_mcl_free(struct mcap_mcl *mcl, gboolean save)
> > +{
> > + gboolean store = ((!(mcl->ctrl & MCAP_CTRL_FREE)) && save);
> > +
> > + if (mcl->tid) {
> > + RELEASE_TIMER(mcl);
> > + }
> > +
> > + if (mcl->cc) {
> > + g_io_channel_shutdown(mcl->cc, TRUE, NULL);
> > + g_io_channel_unref(mcl->cc);
> > + mcl->cc = NULL;
> > + }
> > +
> > + g_source_remove(mcl->wid);
> > + if (mcl->lcmd) {
> > + g_free(mcl->lcmd);
> > + mcl->lcmd = NULL;
> > + }
> > +
> > + if (mcl->priv_data) {
> > + g_free(mcl->priv_data);
> > + mcl->priv_data = NULL;
> > + }
> > +
> > + mcap_free_mdls(mcl, store);
> > +
> > + if (mcl->cb && !store) {
> > + g_free(mcl->cb);
> > + mcl->cb = NULL;
> > + }
> > +
> > + mcl->state = MCL_IDLE;
> > +
> > + if (store)
> > + return;
> > +
> > + g_free(mcl);
> > +}
> > +
>
> According to MCL state machine, if there're no more data channels (but
> a control channel still exists), the current MCL state is CONNECTED.
> Functions shutdown_mdl and mcap_free_mdls should update MCL state
> machine properly.
That's rigth and it is done when an MDL is closed, the function that
does that is update_mcl_state that is executed when the appropriate MDL
is clsoed, deleted or aborted. Seeing the "mdl_event_cb" callback
function that is tied to the data channel, you can see that if last MDL
is closed, the resulting state for the MCL will be CONNECTED.
The function that you are seeing is "mcap_mcl_free" that is used to
shutdown an MCL, it means all MDLs + Control channel, above function
should close the control channel and all data channels (shutdown MDLS)
and resulting state for the MCL is IDLE because control channel is
closed too.
Please, revise thats parts of the code and you will see that it is
rigth.
Thanks for the comment, and please, don't hesitate in make more comments
about the code if you think that are necessary more explanations.
Regards.
>
>
> []' s
> --Raul
> --
> 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
* [l2cap 6/6] Bluetooth: Only check SAR bits if frame is I-frame
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273633558-10576-5-git-send-email-padovan@profusion.mobi>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index dbd43d1..2192b9c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -4123,7 +4123,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if (l2cap_check_fcs(pi, skb))
goto drop;
- if (__is_sar_start(control))
+ if (__is_sar_start(control) && __is_iframe(control))
len -= 2;
if (pi->fcs == L2CAP_FCS_CRC16)
--
1.6.4.4
^ permalink raw reply related
* [l2cap 5/6] Bluetooth: Check packet FCS earlier
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273633558-10576-4-git-send-email-padovan@profusion.mobi>
This way, if FCS is enabled and the packet is corrupted, we just drop it
without read it len, which could be corrupted.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 6b5226d..dbd43d1 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -4115,25 +4115,25 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull(skb, 2);
len = skb->len;
+ /*
+ * We can just drop the corrupted I-frame here.
+ * Receiver will miss it and start proper recovery
+ * procedures and ask retransmission.
+ */
+ if (l2cap_check_fcs(pi, skb))
+ goto drop;
+
if (__is_sar_start(control))
len -= 2;
if (pi->fcs == L2CAP_FCS_CRC16)
len -= 2;
- /*
- * We can just drop the corrupted I-frame here.
- * Receiver will miss it and start proper recovery
- * procedures and ask retransmission.
- */
if (len > pi->mps) {
l2cap_send_disconn_req(pi->conn, sk);
goto drop;
}
- if (l2cap_check_fcs(pi, skb))
- goto drop;
-
req_seq = __get_reqseq(control);
req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
if (req_seq_offset < 0)
@@ -4173,6 +4173,9 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull(skb, 2);
len = skb->len;
+ if (l2cap_check_fcs(pi, skb))
+ goto drop;
+
if (__is_sar_start(control))
len -= 2;
@@ -4182,9 +4185,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if (len > pi->mps || len < 4 || __is_sframe(control))
goto drop;
- if (l2cap_check_fcs(pi, skb))
- goto drop;
-
tx_seq = __get_txseq(control);
if (pi->expected_tx_seq == tx_seq)
--
1.6.4.4
^ permalink raw reply related
* [l2cap 4/6] Bluetooth: Fix ERTM vars increment
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273633558-10576-3-git-send-email-padovan@profusion.mobi>
They should be modulo 64 ;)
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 784bbed..6b5226d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3746,7 +3746,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
l2cap_ertm_reassembly_sdu(sk, skb, control);
l2cap_pi(sk)->buffer_seq_srej =
(l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
- tx_seq++;
+ tx_seq = (tx_seq + 1) % 64;
}
}
@@ -3782,10 +3782,11 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
l2cap_send_sframe(pi, control);
new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
- new->tx_seq = pi->expected_tx_seq++;
+ new->tx_seq = pi->expected_tx_seq;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
list_add_tail(&new->list, SREJ_LIST(sk));
}
- pi->expected_tx_seq++;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
}
static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
--
1.6.4.4
^ permalink raw reply related
* [l2cap 3/6] Bluetooth: Check skb_clone return to avoid NULL dereference
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273633558-10576-2-git-send-email-padovan@profusion.mobi>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 93667ac..784bbed 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1337,6 +1337,8 @@ static int l2cap_streaming_send(struct sock *sk)
while ((skb = sk->sk_send_head)) {
tx_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!tx_skb)
+ break;
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
@@ -1422,6 +1424,8 @@ static int l2cap_ertm_send(struct sock *sk)
}
tx_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!tx_skb)
+ break;
bt_cb(skb)->retries++;
--
1.6.4.4
^ permalink raw reply related
* [l2cap 2/6] Bluetooth: Fix drop of packets with invalid req_seq/tx_seq
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273633558-10576-1-git-send-email-padovan@profusion.mobi>
We can't use an unsigned var since we are expecting negatives value
there too.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index a7e14c0..93667ac 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3790,7 +3790,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
u8 tx_seq = __get_txseq(rx_control);
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
- u8 tx_seq_offset, expected_tx_seq_offset;
+ int tx_seq_offset, expected_tx_seq_offset;
int num_to_ack = (pi->tx_win/6) + 1;
int err = 0;
@@ -4075,7 +4075,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
struct sock *sk;
struct l2cap_pinfo *pi;
u16 control, len;
- u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset;
+ u8 tx_seq, req_seq;
+ int next_tx_seq_offset, req_seq_offset;
sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
if (!sk) {
--
1.6.4.4
^ permalink raw reply related
* [l2cap 1/6] Bluetooth: Tweaks to l2cap_send_i_or_rr_or_rnr() flow
From: Gustavo F. Padovan @ 2010-05-12 3:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: marcel, gustavo
In-Reply-To: <1273513181-28258-2-git-send-email-gustavo@padovan.org>
l2cap_send_sframe() already set the F-bit if we set L2CAP_CONN_SEND_FBIT
and unset L2CAP_CONN_SEND_FBIT after send the F-bit.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/l2cap.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e8c8f8b..a7e14c0 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3364,10 +3364,9 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
- control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
+ control |= L2CAP_SUPER_RCV_NOT_READY;
l2cap_send_sframe(pi, control);
pi->conn_state |= L2CAP_CONN_RNR_SENT;
- pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
}
if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
--
1.6.4.4
^ permalink raw reply related
* Re: [PATCH 03/25] Release resources depending if MCAP should cache or not a MCL
From: Raul Herbster @ 2010-05-11 22:09 UTC (permalink / raw)
To: Santiago Carot-Nemesio; +Cc: linux-bluetooth
In-Reply-To: <1273486527-7855-3-git-send-email-sancane@gmail.com>
Hi Santiago,
2010/5/10 Santiago Carot-Nemesio <sancane@gmail.com>:
> From: Santiago Carot Nemesio <sancane@gmail.com>
>
> ---
> mcap/mcap.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 81 insertions(+), 2 deletions(-)
>
> diff --git a/mcap/mcap.c b/mcap/mcap.c
> index 1c94452..7d34b95 100644
> --- a/mcap/mcap.c
> +++ b/mcap/mcap.c
> @@ -36,14 +36,93 @@
>
> #define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
>
> +#define RELEASE_TIMER(__mcl) do { \
> + g_source_remove(__mcl->tid); \
> + __mcl->tid = 0; \
> +} while(0)
> +
> +static void shutdown_mdl(struct mcap_mdl *mdl)
> +{
> + mdl->state = MDL_CLOSED;
> +
> + g_source_remove(mdl->wid);
> +
> + if (mdl->dc) {
> + g_io_channel_shutdown(mdl->dc, TRUE, NULL);
> + g_io_channel_unref(mdl->dc);
> + mdl->dc = NULL;
> + }
> +}
> +
> +static void mcap_free_mdls(struct mcap_mcl *mcl, gboolean save)
> +{
> + GSList *l;
> + struct mcap_mdl *mdl;
> +
> + if (!mcl->mdls)
> + return;
> +
> + for (l = mcl->mdls; l; l = l->next) {
> + mdl = l->data;
> + shutdown_mdl(mdl);
> + if (!save)
> + g_free(mdl);
> + }
> +
> + if (!save) {
> + g_slist_free(mcl->mdls);
> + mcl->mdls = NULL;
> + }
> +}
> +
> +static void mcap_mcl_free(struct mcap_mcl *mcl, gboolean save)
> +{
> + gboolean store = ((!(mcl->ctrl & MCAP_CTRL_FREE)) && save);
> +
> + if (mcl->tid) {
> + RELEASE_TIMER(mcl);
> + }
> +
> + if (mcl->cc) {
> + g_io_channel_shutdown(mcl->cc, TRUE, NULL);
> + g_io_channel_unref(mcl->cc);
> + mcl->cc = NULL;
> + }
> +
> + g_source_remove(mcl->wid);
> + if (mcl->lcmd) {
> + g_free(mcl->lcmd);
> + mcl->lcmd = NULL;
> + }
> +
> + if (mcl->priv_data) {
> + g_free(mcl->priv_data);
> + mcl->priv_data = NULL;
> + }
> +
> + mcap_free_mdls(mcl, store);
> +
> + if (mcl->cb && !store) {
> + g_free(mcl->cb);
> + mcl->cb = NULL;
> + }
> +
> + mcl->state = MCL_IDLE;
> +
> + if (store)
> + return;
> +
> + g_free(mcl);
> +}
> +
According to MCL state machine, if there're no more data channels (but
a control channel still exists), the current MCL state is CONNECTED.
Functions shutdown_mdl and mcap_free_mdls should update MCL state
machine properly.
[]' s
--Raul
^ permalink raw reply
* Fail to store link key for Blackberry
From: Ed Tsang @ 2010-05-11 20:48 UTC (permalink / raw)
To: Bluettooth Linux
Hi,
I was having trouble pairing with Blackberry (bluez-4.60). It was paired, but the next connection require pair again.
hcidump: "Link Key Request Negative Reply"
check /var/lib/bluetooth/xxx/linkkeys not there.
Delete the device from BB side, went through pairing again
hcidump: > Link key Notification .. type 6 (Changed Combination key)
but ../linkkeys still not there.
Trace down to dbus-hci.c hcid_dbus_link_key_notify()
/* Only store the link key if one of the following is true:
2. this is a changed combination key and there was a previously
stored one */
...
if (key_type < 0x03 || (key_type == 0x06 && old_key_type != 0xff) ||
...
if I change it to the following, then the ../linkkeys is stored and paring with the Blackberry only need to do once
if (key_type < 0x03 || (key_type == 0x06) ||
Look to me " hcidump: Link key Notification .. type 6 (Changed Combination key) " the "6" is coming from Blackberry.
I tried deleted the device from the Blackberry, delete the device and remove the battery from the Blackberry....
hcidump > link key notification still type 6.
/* * 2. this is a changed combination key and there was a previously
* stored one */
in general make sense until we encounter device like this or for whatever reason, we lost the local link
key for the device, then we might be stuck in "pairing everytime connect".
Any comment?
Ed
^ permalink raw reply
* Re: [bugreport]
From: Iain Hibbert @ 2010-05-11 17:23 UTC (permalink / raw)
To: Serhiy Kachaniuk; +Cc: linux-bluetooth
In-Reply-To: <AANLkTilEsIYKxwdD4ZLbYaIExMlHfEmpuOnj8BKeI4XP@mail.gmail.com>
On Tue, 11 May 2010, Serhiy Kachaniuk wrote:
> Yeah, i see that this device is a little buggy, but it worked in
> previous version of bluez, so maybe it is possible to make it work
> again for current version?
I think the problem may be that the kernel itself now relies on setting
the default link policy before accepting connections, so that the link
policy does not need to be set after the connection is complete and there
will be no window of uncertainty.
I am only an observer here, and don't know if this has been done with the
conscious knowledge that older devices will no longer work or if it was a
mistake.. but I can suggest that Bluetooth dongles are cheap, and you
will likely find better connectivity with a 2.x + EDR device anyway..
regards,
iain
^ permalink raw reply
* Re: [bugreport]
From: Serhiy Kachaniuk @ 2010-05-11 16:40 UTC (permalink / raw)
To: Iain Hibbert; +Cc: linux-bluetooth
In-Reply-To: <1273589222.840882.854.nullmailer@galant.ukfsn.org>
2010/5/11 Iain Hibbert:
>
> Serhiy, from your message on the ubuntu bug report
>
>> Maybe the reason is that this dongle doesn't support reading/writing of
>> 'Default Link Policy Settings' ?
>
> and this command was introduced in spec version 1.2, and your device
> reports
>
>> HCI Ver: 1.1 (0x1) HCI Rev: 0x3 LMP Ver: 1.1 (0x1) LMP Subver: 0x800
>
> so yes, that is likely the problem as it is too old.
>
> That bluez has no handling for the possibility that the command may not be
> supported is possibly a bug or possibly an indication that older devices
> are no longer to be supported, I can't really say which.
>
Yeah, i see that this device is a little buggy, but it worked in
previous version of bluez, so maybe it is possible to make it work
again for current version?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox