From: Johan Hedberg <johan.hedberg@gmail.com>
To: Marcel Holtmann <marcel@holtmann.org>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH 1/7] Bluetooth: mgmt: Add support for switching to LE peripheral mode
Date: Tue, 23 Oct 2012 23:26:26 +0300 [thread overview]
Message-ID: <20121023202626.GA12042@x220.ger.corp.intel.com> (raw)
In-Reply-To: <1351018879.1785.44.camel@aeonflux>
Hi Marcel,
On Tue, Oct 23, 2012, Marcel Holtmann wrote:
> > --- a/net/bluetooth/hci_event.c
> > +++ b/net/bluetooth/hci_event.c
> > @@ -786,6 +786,9 @@ static void hci_set_le_support(struct hci_dev *hdev)
> > if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
> > hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
> > &cp);
> > + else if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
> > + hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(cp.le),
> > + &cp.le);
>
> What is this doing and why it is correct? I am failing to see this. We
> need to enable LE host supported first anyway.
The first if-statement checks if the host feature bits are what we want
them to be, and if not send the WRITE_LE_HOST_SUPPORTED command. The
else if part (if the host features are already correct and don't need
updating) enables advertising if necessary. There's a similar check for
HCI_LE_PERIPHERAL in the command complete handler for
HCI_OP_WRITE_LE_HOST_SUPPORTED in case the first if statement was
triggered. FWIW, I have actually tested this both with hciconfig and
btmgmt and it works fine.
> > +static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
> > +{
> > + __u8 *sent, status = *((__u8 *) skb->data);
> > +
> > + BT_DBG("%s status 0x%2.2x", hdev->name, status);
> > +
> > + sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
> > + if (!sent)
> > + return;
> > +
> > + hci_dev_lock(hdev);
> > +
> > + if (!status) {
> > + if (*sent)
> > + set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
> > + else
> > + clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
> > + } else {
> > + if (*sent)
> > + clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
> > + else
> > + set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
> > + }
>
> Are you sure we want to based LE peripheral enabling based on if we
> advertise or not. I can see cases where we are a peripheral, but might
> want to not always advertise.
These set_bit/clear_bit calls are actually all no-op in the case that
the mgmt interface is used (since the LE_PERIPHERAL flag is already
modified when receiving the mgmt command). The only reason I put them
here is so that the reported mgmt settings remain correct and we reject
connection initiation and scanning if "hciconfig hci0 leadv" or similar
is used.
The simplistic way I thought we'd initially keep peripheral mode is
that it always implies advertising (unless a connection exists).
Otherwise the user would need to switch to LE-off or Central mode.
> > @@ -1213,48 +1242,71 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> > goto unlock;
> > }
> >
> > - val = !!cp->val;
> > - enabled = !!(hdev->host_features[0] & LMP_HOST_LE);
> > + if (!valid_le_mode(cp->val)) {
> > + err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
> > + MGMT_STATUS_INVALID_PARAMS);
> > + goto unlock;
> > + }
> >
> > - if (!hdev_is_powered(hdev) || val == enabled) {
> > - bool changed = false;
> > + if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
> > + err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
> > + MGMT_STATUS_BUSY);
> > + goto unlock;
> > + }
> > +
> > + new_mode = cp->val;
> > + old_mode = get_le_mode(hdev);
> > +
> > + BT_DBG("%s old_mode %u new_mode %u", hdev->name, old_mode, new_mode);
> > +
> > + if (new_mode == old_mode) {
> > + err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
> > + goto unlock;
> > + }
> > +
> > + if (old_mode == MGMT_LE_PERIPHERAL || new_mode == MGMT_LE_PERIPHERAL)
> > + change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
> >
> > - if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
> > + if (!hdev_is_powered(hdev)) {
> > + if (old_mode == MGMT_LE_OFF || new_mode == MGMT_LE_OFF)
> > change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
> > - changed = true;
> > - }
> >
> > err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
> > if (err < 0)
> > goto unlock;
> >
> > - if (changed)
> > - err = new_settings(hdev, sk);
> > + err = new_settings(hdev, sk);
> >
> > goto unlock;
> > }
> >
> > - if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
> > - err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
> > - MGMT_STATUS_BUSY);
> > - goto unlock;
> > - }
> > -
> > cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
> > if (!cmd) {
> > err = -ENOMEM;
> > goto unlock;
> > }
> >
> > + if ((old_mode != MGMT_LE_OFF && new_mode == MGMT_LE_PERIPHERAL) ||
> > + old_mode == MGMT_LE_PERIPHERAL) {
> > + u8 adv_enable = (new_mode == MGMT_LE_PERIPHERAL);
> > +
> > + err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE,
> > + sizeof(adv_enable), &adv_enable);
> > + if (err < 0)
> > + mgmt_pending_remove(cmd);
> > +
> > + goto unlock;
> > + }
> > +
>
> this gets a bit complicated. We either need more comments or split this
> out in separate helper functions.
I actually spent over a half a day trying to figure out an easy way to
simplify this, but the best I got was those two simple helper functions.
So I think I'll opt for just adding good code comments.
Johan
next prev parent reply other threads:[~2012-10-23 20:26 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-23 16:53 [PATCH 0/7] Bluetooth: Improved single-mode and LE peripheral support Johan Hedberg
2012-10-23 16:53 ` [PATCH 1/7] Bluetooth: mgmt: Add support for switching to LE peripheral mode Johan Hedberg
2012-10-23 19:01 ` Marcel Holtmann
2012-10-23 20:26 ` Johan Hedberg [this message]
2012-10-23 21:49 ` Marcel Holtmann
2012-10-23 16:53 ` [PATCH 2/7] Bluetooth: mgmt: Restrict BR/EDR settings to BR/EDR-only adapters Johan Hedberg
2012-10-23 18:51 ` Anderson Lizardo
2012-10-23 19:03 ` Marcel Holtmann
2012-10-23 19:02 ` Marcel Holtmann
2012-10-23 19:31 ` Anderson Lizardo
2012-10-23 20:48 ` Johan Hedberg
2012-10-23 21:46 ` Marcel Holtmann
2012-10-24 12:11 ` Anderson Lizardo
2012-10-24 15:14 ` Marcel Holtmann
2012-10-23 16:53 ` [PATCH 3/7] Bluetooth: Disallow LE scanning and connecting in peripheral mode Johan Hedberg
2012-10-23 18:42 ` Anderson Lizardo
2012-10-23 20:59 ` Johan Hedberg
2012-10-23 21:37 ` Marcel Holtmann
2012-10-23 16:53 ` [PATCH 4/7] Bluetooth: Add support for setting LE advertising data Johan Hedberg
2012-10-23 18:30 ` Anderson Lizardo
2012-10-23 21:26 ` Johan Hedberg
2012-10-25 0:00 ` Anderson Lizardo
2012-10-23 16:53 ` [PATCH 5/7] Bluetooth: Fix updating host feature bits for LE Johan Hedberg
2012-10-23 19:04 ` Marcel Holtmann
2012-10-23 16:54 ` [PATCH 6/7] Bluetooth: Sort feature test macros by bitmask location Johan Hedberg
2012-10-23 19:06 ` Marcel Holtmann
2012-10-23 16:54 ` [PATCH 7/7] Bluetooth: Make use feature test macros Johan Hedberg
2012-10-23 19:06 ` Marcel Holtmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121023202626.GA12042@x220.ger.corp.intel.com \
--to=johan.hedberg@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).