diff mbox series

[bug#52470] services: bluetooth: Add missing config parameters

Message ID 20211213192014.8386-1-db@minikn.xyz
State Accepted
Headers show
Series [bug#52470] services: bluetooth: Add missing config parameters | expand

Commit Message

Demis Balbach Dec. 13, 2021, 7:20 p.m. UTC
---
 gnu/services/desktop.scm | 332 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 328 insertions(+), 4 deletions(-)

Comments

Demis Balbach Dec. 13, 2021, 7:36 p.m. UTC | #1
Hello,

this patch adds all (as far as I know) missing config parameters to the
bluetooth-service.

I added all config parameters (that were missing) that are defined in
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf

If a default value was given, e.g.:

--8<---------------cut here---------------start------------->8---
# Specify the policy to the JUST-WORKS repairing initiated by peer
# Possible values: "never", "confirm", "always"
# Defaults to "never" <------------------------------------------
#JustWorksRepairing = never
--8<---------------cut here---------------end--------------->8---

I used that default value. However, there are other paramaters
(everthing under `[BR]' and almost everything under `[LE]') that don't
specify default values. They are always integers as one can see here:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/btd.h#n39

So I took a nonsensical value like `-1' and only printed the in question
with the user provided line if it did not equal -1.

This approach isn't pretty, but it worked for me, however please give
feedback regarding that.
My guile-fu is bad so I'm sure there's plenty room for improvement.

Here is the config I tested it with:

--8<---------------cut here---------------start------------->8---
(define-module (base-system)
  #:use-module (gnu)
  #:use-module (gnu services desktop)
  #:use-module (srfi srfi-1))

(define base-operating-system
  (operating-system

   ;; Machine settings
   (host-name "geekcave")
   (timezone "Europe/Berlin")
   (locale "en_US.utf8")
   (keyboard-layout (keyboard-layout "us" "altgr-intl"))

   ;; Services
   (services (append (list
                      (service bluetooth-service-type (bluetooth-configuration
                                                       (name "test")
                                                       (class "0x123")
                                                       (discoverable-timeout 60)
                                                       (always-pairable? #f)
                                                       (pairable-timeout 20)
                                                       (device-id "bluetooth:123")
                                                       (reverse-service-discovery? #f)
                                                       (name-resolving? #f)
                                                       (debug-keys? #t)
                                                       (controller-mode 'le)
                                                       (multi-profile 'multiple)
                                                       (fast-connectable? #t)
                                                       (privacy 'network/on)
                                                       (just-works-repairing 'confirm)
                                                       (temporary-timeout 10)
                                                       (refresh-discovery? #f)
                                                       (experimental 'd4992530-b9ec-469f-ab01-6c481c47da1c)
                                                       (remote-name-request-retry-delay 20)
                                                       (page-scan-type #xFFF)
                                                       (page-scan-interval #x0)
                                                       (page-scan-window #x1)
                                                       (inquiry-scan-type #xFFFF)
                                                       (inquiry-scan-interval #x123)
                                                       (inquiry-scan-window 23890)
                                                       (link-supervision-timeout 13)
                                                       (page-timeout 9)
                                                       (min-sniff-interval 0)
                                                       (max-sniff-interval 2)
                                                       (min-advertisement-interval 0)
                                                       (max-advertisement-interval 2)
                                                       (multi-advertisement-rotation-interval 3)
                                                       (scan-interval-auto-connect 0)
                                                       (scan-window-auto-connect 0)
                                                       (scan-interval-suspend 0)
                                                       (scan-window-suspend 0)
                                                       (scan-interval-discovery 0)
                                                       (scan-window-discovery 0)
                                                       (scan-interval-adv-monitor 0)
                                                       (scan-window-adv-monitor 0)
                                                       (scan-interval-connect 0)
                                                       (scan-window-connect 0)
                                                       (min-connection-interval 0)
                                                       (max-connection-interval 1)
                                                       (connection-latency 10)
                                                       (connection-supervision-timeout 34)
                                                       (autoconnect-timeout 4)
                                                       (adv-mon-allowlist-scan-duration 20)
                                                       (adv-mon-no-filter-scan-duration 30)
                                                       (enable-adv-mon-interleave-scan 0)
                                                       (cache 'yes)
                                                       (key-size 15)
                                                       (exchange-mtu 23)
                                                       (att-channels 1)
                                                       (session-mode 'ertm)
                                                       (stream-mode 'streaming)
                                                       (reconnect-uuids (list ""))
                                                       (reconnect-attempts 3)
                                                       (reconnect-intervals (list 2 4 49))
                                                       (auto-enable? #t)
                                                       (resume-delay 29)
                                                       (rssi-sampling-period "0x10"))))
                     %base-services))

   ;; Boot loader
   (bootloader (bootloader-configuration
                (bootloader grub-efi-bootloader)
                (target "/boot/efi")
                (timeout 3)))

   ;; File systems
   (file-systems (cons* (file-system ;; System partition
                         (device (file-system-label "GUIX"))
                         (mount-point "/")
                         (type "btrfs"))
                        (file-system ;; Boot partition
                         (device (file-system-label "BOOT"))
                         (mount-point "/boot/efi")
                         (type "vfat"))
                        %base-file-systems))))
base-operating-system
--8<---------------cut here---------------end--------------->8---
Josselin Poiret Dec. 14, 2021, 1:03 p.m. UTC | #2
Hello,

Demis Balbach <db@minikn.xyz> writes:

> Hello,
>
> this patch adds all (as far as I know) missing config parameters to
> the bluetooth-service.

Nice work!

> I used that default value. However, there are other paramaters
> (everthing under `[BR]' and almost everything under `[LE]') that don't
> specify default values. They are always integers as one can see here:
>
> https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/btd.h#n39
>
> So I took a nonsensical value like `-1' and only printed the in
> question with the user provided line if it did not equal -1.

Since Guile isn't typed, the usual approach is to use `#f` for default
values, and then use `(if (bluetooth-configuration-inquiry-scan-window
config) ...)` for example.  Any value other than #f will be considered
as truthful for conditionals (see "(guile)Booleans").

> +   (if (not (eq? -1 (bluetooth-configuration-page-scan-type config)))
> +       (string-append
> +        "\nPageScanType = "
> +        (number->string (bluetooth-configuration-page-scan-type config))) "")

Small nitpick, I'd rather have `""`, the else part of this if syntax, on
its own line, aligned with `(string-append`.

Could you also document the `bluetooth-service-type` Scheme value in
doc/guix.texi, as well as `bluetooth-configuration`, if that's not too
much to ask?  I only see one for `bluetooth-service` right now.  I'm not
sure if all configuration values should be documented there though,
since there are a lot.

By the way, shouldn't `bluetooth-service` be deprecated, given how
simple it is to use the `-type` version?

What do others think?

Best,
Josselin Poiret
Demis Balbach Dec. 14, 2021, 2:51 p.m. UTC | #3
On 2021-12-14 14:03, Josselin Poiret wrote:

Hello,

> Since Guile isn't typed, the usual approach is to use `#f` for default
> values, and then use `(if (bluetooth-configuration-inquiry-scan-window
> config) ...)` for example.  Any value other than #f will be considered
> as truthful for conditionals (see "(guile)Booleans").

I tried that, and I could have sworn I got an error regarding the
type. I was under the impression that the default values' type set the
type for the whole field. But I was wrong of course because I tested
your suggestion and it worked.

> Small nitpick, I'd rather have `""`, the else part of this if syntax, on
> its own line, aligned with `(string-append`.

Please do nitpick. I appreciate it. I think the `[General]` part looks
pretty messy indentation-wise, but I don't really know what layout to
settle on.

> Could you also document the `bluetooth-service-type` Scheme value in
> doc/guix.texi, as well as `bluetooth-configuration`, if that's not too
> much to ask?  I only see one for `bluetooth-service` right now.  I'm not
> sure if all configuration values should be documented there though,
> since there are a lot.

Sure. How can I test the changes to the documentation? Like generating a
pdf or something along those lines.

> By the way, shouldn't `bluetooth-service` be deprecated, given how
> simple it is to use the `-type` version?

I'm not the one to answer that :)

> What do others think?
>
> Best,
> Josselin Poiret
Demis Balbach Dec. 14, 2021, 8:50 p.m. UTC | #4
On 2021-12-14 14:03, Josselin Poiret wrote:

I've added a new patch. ID: 52489.
Please check for spelling mistakes/typos.

This kind of work is very repetitive and thus prone to errors.
Demis Balbach Dec. 19, 2021, 1:11 p.m. UTC | #5
Hello Liliana,

thanks for your input on https://issues.guix.gnu.org/52575.
I will continue the discussion about it here.

You prepend most of your comments with "Why not do ...". I have an
universal answer for that: I don't know :) I did what I did with the
limited Guile knowledge at my disposal. I'm still learning everyday and
therefore am thankful for your recommendations.

> Is it really a good idea to use a string-encoded number here?  Why not
> a number?  Why not two?  A pair or list of symbols mayhaps?
It should be a number, you are correct.

> You maybe want to have a <device-id> record here, but fair enough, a
> string works too.
I can see the benefit of that, but maybe that's something for another
patch. I can add a `;;; MAYBE: ` comment to the implementation however
if that's desired.

> Why have a key network/on?  Why not use 'on and 'network and document,
> that they function the same due to (insert implementation detail).
I think this point we need to discuss. I tried to implement things as
close as possible to the "original" keys/values in
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf

Specifically for the `privacy` key, you can see the implementation here
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n68,

in particular

--8<---------------cut here---------------start------------->8---
# Possible values for LE mode: "off", "network/on", "device"
# Possible values for Dual mode: "off", "network/on", "device",
# "limited-network", "limited-device"
--8<---------------cut here---------------end--------------->8---

Now, I don't think it's a good idea to introduce arbitrary values for
Guix, meaning split `network/on` in `'network` and `'on`. In my opinion
(which may very well be wrong) the config values applicable in Guix
should match those in the resulting config file as close as possible.

For a user coming to Guix who already worked with the bluetooth configuration on
another distro, seeing `'network` and/or `'on` (but not `'network/on`)
as possible config values, is confusing, at least I think it is.

> Why a list of UUIDs?  Wouldn't it make more sense to use symbols like
> 'debug, 'll-privacy, 'quality-report, etc.?
> On that note, we have a UUID type, so use it.
I actually didn't know there's a UUID type. This makes more sense. But
not a list as only one value can be applied. Also I would advise
introducing symbol like `'ll-privacy` and the like because of what I
said earlier.

> Should be a boolean.
Same point here. I used boolean types whereever the config value need
was `true`/`false`. In this particular case (I don't know why) the
bluetooth implementations expects `0`/`1` instead of the former. This is
why I kept it a number. However, in this case I think it's okay to
deviate from the original implementation because `0` and false / `1` and
`true` are universally understood as being equivalent (By this of course
I mean the user would set `#f`/`#t`, the written value however would
still be `0`/`1`).

> Might want to rename/alias 'yes to 'paired.
Again, same point here. `'paired` would be an arbitrary value only Guix
have.

> You probably want to write that as "an integer 7 <= N <= 16".
...
>As above.
Yes, absolutely.

> Again, make sure that your code works with UUIDs here if it doesn't
> already.
Will do.

> Use numbers, not strings.
Will do.

I'll create a new patch with all the things altered I agree about. I'll
leave the rest until we have talked about the points I made.
Demis Balbach Dec. 19, 2021, 1:19 p.m. UTC | #6
> I actually didn't know there's a UUID type. This makes more sense. But
> not a list as only one value can be applied. Also I would advise
> introducing symbol like `'ll-privacy` and the like because of what I
> said earlier.

Typo: I meant "advise AGAINST introducing ... "
diff mbox series

Patch

diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index 64d0e85301..23b730d7d4 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -402,14 +402,338 @@  (define-record-type* <bluetooth-configuration>
   bluetooth-configuration make-bluetooth-configuration
   bluetooth-configuration?
   (bluez bluetooth-configuration-bluez (default bluez))
-  (auto-enable? bluetooth-configuration-auto-enable? (default #f)))
+
+  ;;; [General]
+  (name bluetooth-configuration-name (default "BlueZ"))
+  (class bluetooth-configuration-class (default "0x000000"))
+  (discoverable-timeout
+   bluetooth-configuration-discoverable-timeout (default 180))
+  (always-pairable? bluetooth-configuration-always-pairable? (default #f))
+  (pairable-timeout bluetooth-configuration-pairable-timeout (default 0))
+  (device-id bluetooth-configuration-device-id (default ""))
+  (reverse-service-discovery?
+   bluetooth-configuration-reverse-service-discovery (default #t))
+  (name-resolving? bluetooth-configuration-name-resolving? (default #t))
+  (debug-keys? bluetooth-configuration-debug-keys? (default #f))
+
+  ;;; Possible values:
+  ;;; 'dual, 'bredr, 'le
+  (controller-mode bluetooth-configuration-controller-mode (default 'dual))
+
+  ;;; Possible values:
+  ;;; 'off, 'single, 'multiple
+  (multi-profile bluetooth-configuration-multi-profile (default 'off))
+  (fast-connectable? bluetooth-configuration-fast-connectable? (default #f))
+
+  ;;; Possible values:
+  ;;; for LE mode: 'off, 'network/on, 'device
+  ;;; for Dual mode: 'off, 'network/on', 'device, 'limited-network, 'limited-device
+  ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n68
+  (privacy bluetooth-configuration-privacy (default 'off))
+
+  ;;; Possible values:
+  ;;; 'never, 'confirm, 'always
+  (just-works-repairing
+   bluetooth-configuration-just-works-repairing (default 'never))
+  (temporary-timeout bluetooth-configuration-temporary-timeout (default 30))
+  (refresh-discovery? bluetooth-configuration-refresh-discovery (default #t))
+
+  ;;; Possible values: 'true, 'false, <UUID>
+  ;;; Possible UUIDs:
+  ;;; d4992530-b9ec-469f-ab01-6c481c47da1c (BlueZ Experimental Debug)
+  ;;; 671b10b5-42c0-4696-9227-eb28d1b049d6 (BlueZ Experimental Simultaneous Central and Peripheral)
+  ;;; 15c0a148-c273-11ea-b3de-0242ac130004 (BlueZ Experimental LL privacy)
+  ;;; 330859bc-7506-492d-9370-9a6f0614037f (BlueZ Experimental Bluetooth Quality Report)
+  ;;; a6695ace-ee7f-4fb9-881a-5fac66c629af (BlueZ Experimental Offload Codecs)
+  ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n110
+  (experimental bluetooth-configuration-experimental (default 'false))
+  (remote-name-request-retry-delay
+   bluetooth-configuration-remote-name-request-retry-delay (default 300))
+
+  ;;; [BR]
+  (page-scan-type bluetooth-configuration-page-scan-type (default -1))
+  (page-scan-interval bluetooth-configuration-page-scan-interval (default -1))
+  (page-scan-window bluetooth-configuration-page-scan-window (default 'nil))
+  (inquiry-scan-type bluetooth-configuration-inquiry-scan-type (default 'nil))
+  (inquiry-scan-interval bluetooth-configuration-inquiry-scan-interval (default -1))
+  (inquiry-scan-window bluetooth-configuration-inquiry-scan-window (default 'nil))
+  (link-supervision-timeout bluetooth-configuration-link-supervision-timeout (default -1))
+  (page-timeout bluetooth-configuration-page-timeout (default -1))
+  (min-sniff-interval bluetooth-configuration-min-sniff-interval (default -1))
+  (max-sniff-interval bluetooth-configuration-max-sniff-interval (default -1))
+
+  ;;; [LE]
+  (min-advertisement-interval
+   bluetooth-configuration-min-advertisement-interval (default -1))
+  (max-advertisement-interval
+   bluetooth-configuration-max-advertisement-interval (default -1))
+  (multi-advertisement-rotation-interval
+   bluetooth-configuration-multi-advertisement-rotation-interval (default -1))
+  (scan-interval-auto-connect
+   bluetooth-configuration-scan-interval-auto-connect (default 'nil))
+  (scan-window-auto-connect
+   bluetooth-configuration-scan-window-auto-connect (default 'nil))
+  (scan-interval-suspend
+   bluetooth-configuration-scan-interval-suspend (default 'nil))
+  (scan-window-suspend
+   bluetooth-configuration-scan-window-suspend (default 'nil))
+  (scan-interval-discovery
+   bluetooth-configuration-scan-interval-discovery (default 'nil))
+  (scan-window-discovery
+   bluetooth-configuration-scan-window-discovery (default 'nil))
+  (scan-interval-adv-monitor
+   bluetooth-configuration-scan-interval-adv-monitor (default 'nil))
+  (scan-window-adv-monitor
+   bluetooth-configuration-scan-window-adv-monitor (default 'nil))
+  (scan-interval-connect
+   bluetooth-configuration-scan-interval-connect (default 'nil))
+  (scan-window-connect
+   bluetooth-configuration-scan-window-connect (default 'nil))
+  (min-connection-interval
+   bluetooth-configuration-min-connection-interval (default -1))
+  (max-connection-interval
+   bluetooth-configuration-max-connection-interval (default -1))
+  (connection-latency
+   bluetooth-configuration-connection-latency (default -1))
+  (connection-supervision-timeout
+   bluetooth-configuration-connection-supervision-timeout (default -1))
+  (autoconnect-timeout
+   bluetooth-configuration-autoconnect-timeout (default -1))
+  (adv-mon-allowlist-scan-duration
+   bluetooth-configuration-adv-mon-allowlist-scan-duration (default 300))
+  (adv-mon-no-filter-scan-duration
+   bluetooth-configuration-adv-mon-no-filter-scan-duration (default 500))
+  (enable-adv-mon-interleave-scan
+   bluetooth-configuration-enable-adv-mon-interleave-scan (default 1))
+
+  ;;; [GATT]
+  ;;; Possible values: 'yes, 'no, 'always
+  (cache bluetooth-configuration-cache (default 'always))
+
+  ;;; Possible values: 7 ... 16, 0 (don't care)
+  (key-size bluetooth-configuration-key-size (default 0))
+
+  ;;; Possible values: 23 ... 517
+  (exchange-mtu bluetooth-configuration-exchange-mtu (default 517))
+
+  ;;; Possible values: 1 ... 5
+  (att-channels bluetooth-configuration-att-channels (default 3))
+
+  ;;; [AVDTP]
+  ;;; Possible values: 'basic, 'ertm
+  (session-mode bluetooth-configuration-session-mode (default 'basic))
+
+  ;;; Possible values: 'basic, 'streaming
+  (stream-mode bluetooth-configuration-stream-mode (default 'basic))
+
+  ;;; [Policy]
+  (reconnect-uuids bluetooth-configuration-reconnect-uuids (default '()))
+  (reconnect-attempts bluetooth-configuration-reconnect-attempts (default 7))
+  (reconnect-intervals bluetooth-configuration-reconnect-intervals
+                       (default (list 1 2 4 8 16 32 64)))
+  (auto-enable? bluetooth-configuration-auto-enable? (default #f))
+  (resume-delay bluetooth-configuration-resume-delay (default 2))
+
+  ;;; [AdvMon]
+  ;;; Possible values:
+  ;;; "0x00", "0xFF",
+  ;;; "N = 0x00" ... "N = 0xFF"
+  ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n286
+  (rssi-sampling-period bluetooth-configuration-rssi-sampling-period
+                        (default "0xFF")))
 
 (define (bluetooth-configuration-file config)
   "Return a configuration file for the systemd bluetooth service, as a string."
   (string-append
-   "[Policy]\n"
-   "AutoEnable=" (bool (bluetooth-configuration-auto-enable?
-                        config))))
+   "[General]"
+   "\nName = " (bluetooth-configuration-name config)
+   "\nClass = " (bluetooth-configuration-class config)
+   "\nDiscoverableTimeout = " (number->string
+                               (bluetooth-configuration-discoverable-timeout
+                                config))
+   "\nAlwaysPairable = " (bool (bluetooth-configuration-always-pairable?
+                                config))
+   "\nPairableTimeout = " (number->string
+                           (bluetooth-configuration-pairable-timeout
+                            config))
+   (if (not (string-null? (bluetooth-configuration-device-id config)))
+       (string-append "\nDeviceID = " (bluetooth-configuration-device-id config))
+       "")
+   "\nReverseServiceDiscovery = " (bool
+                                   (bluetooth-configuration-reverse-service-discovery
+                                    config))
+   "\nNameResolving = " (bool (bluetooth-configuration-name-resolving? config))
+   "\nDebugKeys = " (bool (bluetooth-configuration-debug-keys? config))
+   "\nControllerMode = " (symbol->string
+                          (bluetooth-configuration-controller-mode config))
+   "\nMultiProfile = " (symbol->string (bluetooth-configuration-multi-profile
+                                        config))
+   "\nFastConnectable = " (bool (bluetooth-configuration-fast-connectable? config))
+   "\nPrivacy = " (symbol->string (bluetooth-configuration-privacy config))
+   "\nJustWorksRepairing = " (symbol->string
+                              (bluetooth-configuration-just-works-repairing config))
+   "\nTemporaryTimeout = " (number->string
+                            (bluetooth-configuration-temporary-timeout config))
+   "\nRefreshDiscovery = " (bool (bluetooth-configuration-refresh-discovery config))
+   "\nExperimental = " (symbol->string (bluetooth-configuration-experimental config))
+   "\nRemoteNameRequestRetryDelay = " (number->string
+                                       (bluetooth-configuration-remote-name-request-retry-delay
+                                        config))
+   "\n[BR]"
+   (if (not (eq? -1 (bluetooth-configuration-page-scan-type config)))
+       (string-append
+        "\nPageScanType = "
+        (number->string (bluetooth-configuration-page-scan-type config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-page-scan-interval config)))
+       (string-append
+        "\nPageScanInterval = "
+        (number->string (bluetooth-configuration-page-scan-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-page-scan-window config)))
+       (string-append
+        "\nPageScanWindow = "
+        (number->string (bluetooth-configuration-page-scan-window config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-inquiry-scan-type config)))
+       (string-append
+        "\nInquiryScanType = "
+        (number->string (bluetooth-configuration-inquiry-scan-type config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-inquiry-scan-interval config)))
+       (string-append
+        "\nInquiryScanInterval = "
+        (number->string (bluetooth-configuration-inquiry-scan-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-inquiry-scan-window config)))
+       (string-append
+        "\nInquiryScanWindow = "
+        (number->string (bluetooth-configuration-inquiry-scan-window config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-link-supervision-timeout config)))
+       (string-append
+        "\nLinkSupervisionTimeout = "
+        (number->string (bluetooth-configuration-link-supervision-timeout config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-page-timeout config)))
+       (string-append
+        "\nPageTimeout = "
+        (number->string (bluetooth-configuration-page-timeout config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-min-sniff-interval config)))
+       (string-append
+        "\nMinSniffInterval = "
+        (number->string (bluetooth-configuration-min-sniff-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-max-sniff-interval config)))
+       (string-append
+        "\nMaxSniffInterval = "
+        (number->string (bluetooth-configuration-max-sniff-interval config))) "")
+
+   "\n[LE]"
+   (if (not (eq? -1 (bluetooth-configuration-min-advertisement-interval config)))
+       (string-append
+        "\nMinAdvertisementInterval = "
+        (number->string (bluetooth-configuration-min-advertisement-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-max-advertisement-interval config)))
+       (string-append
+        "\nMaxAdvertisementInterval = "
+        (number->string (bluetooth-configuration-max-advertisement-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-multi-advertisement-rotation-interval config)))
+       (string-append
+        "\nMultiAdvertisementRotationInterval = "
+        (number->string
+         (bluetooth-configuration-multi-advertisement-rotation-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-interval-auto-connect config)))
+       (string-append
+        "\nScanIntervalAutoConnect = "
+        (number->string (bluetooth-configuration-scan-interval-auto-connect config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-window-auto-connect config)))
+       (string-append
+        "\nScanWindowAutoConnect = "
+        (number->string (bluetooth-configuration-scan-window-auto-connect config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-interval-suspend config)))
+       (string-append
+        "\nScanIntervalSuspend = "
+        (number->string (bluetooth-configuration-scan-interval-suspend config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-window-suspend config)))
+       (string-append
+        "\nScanWindowSuspend = "
+        (number->string (bluetooth-configuration-scan-window-suspend config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-interval-discovery config)))
+       (string-append
+        "\nScanIntervalDiscovery = "
+        (number->string (bluetooth-configuration-scan-interval-discovery config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-window-discovery config)))
+       (string-append
+        "\nScanWindowDiscovery = "
+        (number->string (bluetooth-configuration-scan-window-discovery config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-interval-adv-monitor config)))
+       (string-append
+        "\nScanIntervalAdvMonitor = "
+        (number->string (bluetooth-configuration-scan-interval-adv-monitor config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-window-adv-monitor config)))
+       (string-append
+        "\nScanWindowAdvMonitor = "
+        (number->string (bluetooth-configuration-scan-window-adv-monitor config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-interval-connect config)))
+       (string-append
+        "\nScanIntervalConnect = "
+        (number->string (bluetooth-configuration-scan-interval-connect config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-scan-window-connect config)))
+       (string-append
+        "\nScanWindowConnect = "
+        (number->string (bluetooth-configuration-scan-window-connect config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-min-connection-interval config)))
+       (string-append
+        "\nMinConnectionInterval = "
+        (number->string (bluetooth-configuration-min-connection-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-max-connection-interval config)))
+       (string-append
+        "\nMaxConnectionInterval = "
+        (number->string (bluetooth-configuration-max-connection-interval config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-connection-latency config)))
+       (string-append
+        "\nConnectionLatency = "
+        (number->string (bluetooth-configuration-connection-latency config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-connection-supervision-timeout config)))
+       (string-append
+        "\nConnectionSupervisionTimeout = "
+        (number->string (bluetooth-configuration-connection-supervision-timeout config))) "")
+   (if (not (eq? -1 (bluetooth-configuration-autoconnect-timeout config)))
+       (string-append
+        "\nAutoconnecttimeout = "
+        (number->string (bluetooth-configuration-autoconnect-timeout config))) "")
+
+   "\nAdvMonAllowlistScanDuration = " (number->string
+                                       (bluetooth-configuration-adv-mon-allowlist-scan-duration
+                                        config))
+   "\nAdvMonNoFilterScanDuration = " (number->string
+                                      (bluetooth-configuration-adv-mon-no-filter-scan-duration
+                                       config))
+   "\nEnableAdvMonInterleaveScan = " (number->string
+                                      (bluetooth-configuration-enable-adv-mon-interleave-scan
+                                       config))
+
+   "\n[GATT]"
+   "\nCache = " (symbol->string (bluetooth-configuration-cache config))
+   "\nKeySize = " (number->string (bluetooth-configuration-key-size config))
+   "\nExchangeMTU = " (number->string (bluetooth-configuration-exchange-mtu config))
+   "\nChannels = " (number->string (bluetooth-configuration-att-channels config))
+
+   "\n[AVDTP]"
+   "\nSessionMode = " (symbol->string (bluetooth-configuration-session-mode config))
+   "\nStreamMode = " (symbol->string (bluetooth-configuration-stream-mode config))
+
+   "\n[Policy]"
+   (if (not (eq? '() (bluetooth-configuration-reconnect-uuids config)))
+       (string-append
+        "\nReconnectUUIDs = "
+        (string-join (bluetooth-configuration-reconnect-uuids config) ",")) "")
+   "\nReconnectAttempts = " (number->string
+                             (bluetooth-configuration-reconnect-attempts config))
+   "\nReconnectIntervals = " (string-join
+                              (map number->string
+                                   (bluetooth-configuration-reconnect-intervals
+                                    config))
+                              ",")
+   "\nAutoEnable = " (bool (bluetooth-configuration-auto-enable?
+                            config))
+   "\nResumeDelay = " (number->string (bluetooth-configuration-resume-delay config))
+
+   "\n[AdvMon]"
+   "\nRSSISamplingPeriod = " (bluetooth-configuration-rssi-sampling-period config)))
 
 (define (bluetooth-directory config)
   (computed-file "etc-bluetooth"