services: bluetooth: Add missing config parameters.

* doc/guix.texi (Desktop Services): Document 'bluetooth-service-type'
and 'bluetooth-configuration'.
* gnu/services/desktop.scm (<bluetooth-configuration>): Add many fields.
(bluetooth-configuration-file): Handle them.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Demis Balbach 2021-12-19 17:41:46 +01:00 committed by Ludovic Courtès
parent fcebc4aa12
commit 878578c0fa
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
2 changed files with 814 additions and 5 deletions

View File

@ -21378,6 +21378,448 @@ bluetooth keyboard or mouse.
Users need to be in the @code{lp} group to access the D-Bus service.
@end deffn
@deffn {Scheme Variable} bluetooth-service-type
This is the type for the @uref{https://bluez.org/, Linux Bluetooth Protocol
Stack} (BlueZ) system, which generates the @file{/etc/bluetooth/main.conf}
configuration file. The value for this type is a @command{bluetooth-configuration}
record as in this example:
@lisp
(service bluetooth-service-type)
@end lisp
See below for details about @code{bluetooth-configuration}.
@end deffn
@deftp {Data Type} bluetooth-configuration
Data type representing the configuration for @code{bluetooth-service}.
@table @asis
@item @code{bluez} (default: @code{bluez})
@code{bluez} package to use.
@item @code{name} (default: @code{"BlueZ"})
Default adapter name.
@item @code{class} (default: @code{#x000000})
Default device class. Only the major and minor device class bits are considered.
@item @code{discoverable-timeout} (default: @code{180})
How long to stay in discoverable mode before going back to non-discoverable. The
value is in seconds.
@item @code{always-pairable?} (default: @code{#f})
Always allow pairing even if there are no agents registered.
@item @code{pairable-timeout} (default: @code{0})
How long to stay in pairable mode before going back to non-discoverable. The
value is in seconds.
@item @code{device-id} (default: @code{#f})
Use vendor id source (assigner), vendor, product and version information for
DID profile support. The values are separated by ":" and @var{assigner}, @var{VID},
@var{PID} and @var{version}.
Possible values are:
@itemize @bullet
@item
@code{#f} to disable it,
@item
@code{"assigner:1234:5678:abcd"}, where @var{assigner} is either @code{usb} (default)
or @code{bluetooth}.
@end itemize
@item @code{reverse-service-discovery?} (default: @code{#t})
Do reverse service discovery for previously unknown devices that connect to
us. For BR/EDR this option is really only needed for qualification since the
BITE tester doesn't like us doing reverse SDP for some test cases, for LE
this disables the GATT client functionally so it can be used in system which
can only operate as peripheral.
@item @code{name-resolving?} (default: @code{#t})
Enable name resolving after inquiry. Set it to @code{#f} if you don't need
remote devices name and want shorter discovery cycle.
@item @code{debug-keys?} (default: @code{#f})
Enable runtime persistency of debug link keys. Default is false which makes
debug link keys valid only for the duration of the connection that they were
created for.
@item @code{controller-mode} (default: @code{'dual})
Restricts all controllers to the specified transport. @code{'dual} means both
BR/EDR and LE are enabled (if supported by the hardware).
Possible values are:
@itemize @bullet
@item
@code{'dual}
@item
@code{'bredr}
@item
@code{'le}
@end itemize
@item @code{multi-profile} (default: @code{'off})
Enables Multi Profile Specification support. This allows to specify if system
supports only Multiple Profiles Single Device (MPSD) configuration or both
Multiple Profiles Single Device (MPSD) and Multiple Profiles Multiple Devices
(MPMD) configurations.
Possible values are:
@itemize @bullet
@item
@code{'off}
@item
@code{'single}
@item
@code{'multiple}
@end itemize
@item @code{fast-connectable?} (default: @code{#f})
Permanently enables the Fast Connectable setting for adapters that support
it. When enabled other devices can connect faster to us, however the
tradeoff is increased power consumptions. This feature will fully work only
on kernel version 4.1 and newer.
@item @code{privacy} (default: @code{'off})
Default privacy settings.
@itemize @bullet
@item
@code{'off}: Disable local privacy
@item
@code{'network/on}: A device will only accept advertising packets from peer
devices that contain private addresses. It may not be compatible with some
legacy devices since it requires the use of RPA(s) all the time
@item
@code{'device}: A device in device privacy mode is only concerned about the
privacy of the device and will accept advertising packets from peer devices
that contain their Identity Address as well as ones that contain a private
address, even if the peer device has distributed its IRK in the past
@end itemize
and additionally, if @var{controller-mode} is set to @code{'dual}:
@itemize @bullet
@item
@code{'limited-network}: Apply Limited Discoverable Mode to advertising, which
follows the same policy as to BR/EDR that publishes the identity address when
discoverable, and Network Privacy Mode for scanning
@item
@code{'limited-device}: Apply Limited Discoverable Mode to advertising, which
follows the same policy as to BR/EDR that publishes the identity address when
discoverable, and Device Privacy Mode for scanning.
@end itemize
@item @code{just-works-repairing} (default: @code{'never})
Specify the policy to the JUST-WORKS repairing initiated by peer.
Possible values:
@itemize @bullet
@item
@code{'never}
@item
@code{'confirm}
@item
@code{'always}
@end itemize
@item @code{temporary-timeout} (default: @code{30})
How long to keep temporary devices around. The value is in seconds. @code{0}
disables the timer completely.
@item @code{refresh-discovery?} (default: @code{#t})
Enables the device to issue an SDP request to update known services when
profile is connected.
@item @code{experimental} (default: @code{#f})
Enables experimental features and interfaces, alternatively a list of UUIDs
can be given.
Possible values:
@itemize @bullet
@item
@code{#t}
@item
@code{#f}
@item
@code{(list (uuid <uuid-1>) (uuid <uuid-2>) ...)}.
@end itemize
List of possible UUIDs:
@itemize @bullet
@item
@code{d4992530-b9ec-469f-ab01-6c481c47da1c}: BlueZ Experimental Debug,
@item
@code{671b10b5-42c0-4696-9227-eb28d1b049d6}: BlueZ Experimental Simultaneous Central and Peripheral,
@item
@code{"15c0a148-c273-11ea-b3de-0242ac130004}: BlueZ Experimental LL privacy,
@item
@code{330859bc-7506-492d-9370-9a6f0614037f}: BlueZ Experimental Bluetooth Quality Report,
@item
@code{a6695ace-ee7f-4fb9-881a-5fac66c629af}: BlueZ Experimental Offload Codecs.
@end itemize
@item @code{remote-name-request-retry-delay} (default: @code{300})
The duration to avoid retrying to resolve a peer's name, if the previous
try failed.
@item @code{page-scan-type} (default: @code{#f})
BR/EDR Page scan activity type.
@item @code{page-scan-interval} (default: @code{#f})
BR/EDR Page scan activity interval.
@item @code{page-scan-window} (default: @code{#f})
BR/EDR Page scan activity window.
@item @code{inquiry-scan-type} (default: @code{#f})
BR/EDR Inquiry scan activity type.
@item @code{inquiry-scan-interval} (default: @code{#f})
BR/EDR Inquiry scan activity interval.
@item @code{inquiry-scan-window} (default: @code{#f})
BR/EDR Inquiry scan activity window.
@item @code{link-supervision-timeout} (default: @code{#f})
BR/EDR Link supervision timeout.
@item @code{page-timeout} (default: @code{#f})
BR/EDR Page timeout.
@item @code{min-sniff-interval} (default: @code{#f})
BR/EDR minimum sniff interval.
@item @code{max-sniff-interval} (default: @code{#f})
BR/EDR maximum sniff interval.
@item @code{min-advertisement-interval} (default: @code{#f})
LE minimum advertisement interval (used for legacy advertisement only).
@item @code{max-advertisement-interval} (default: @code{#f})
LE maximum advertisement interval (used for legacy advertisement only).
@item @code{multi-advertisement-rotation-interval} (default: @code{#f})
LE multiple advertisement rotation interval.
@item @code{scan-interval-auto-connect} (default: @code{#f})
LE scanning interval used for passive scanning supporting auto connect.
@item @code{scan-window-auto-connect} (default: @code{#f})
LE scanning window used for passive scanning supporting auto connect.
@item @code{scan-interval-suspend} (default: @code{#f})
LE scanning interval used for active scanning supporting wake from suspend.
@item @code{scan-window-suspend} (default: @code{#f})
LE scanning window used for active scanning supporting wake from suspend.
@item @code{scan-interval-discovery} (default: @code{#f})
LE scanning interval used for active scanning supporting discovery.
@item @code{scan-window-discovery} (default: @code{#f})
LE scanning window used for active scanning supporting discovery.
@item @code{scan-interval-adv-monitor} (default: @code{#f})
LE scanning interval used for passive scanning supporting the advertisement monitor APIs.
@item @code{scan-window-adv-monitor} (default: @code{#f})
LE scanning window used for passive scanning supporting the advertisement monitor APIs.
@item @code{scan-interval-connect} (default: @code{#f})
LE scanning interval used for connection establishment.
@item @code{scan-window-connect} (default: @code{#f})
LE scanning window used for connection establishment.
@item @code{min-connection-interval} (default: @code{#f})
LE default minimum connection interval. This value is superceeded by any specific
value provided via the Load Connection Parameters interface.
@item @code{max-connection-interval} (default: @code{#f})
LE default maximum connection interval. This value is superceeded by any specific
value provided via the Load Connection Parameters interface.
@item @code{connection-latency} (default: @code{#f})
LE default connection latency. This value is superceeded by any specific
value provided via the Load Connection Parameters interface.
@item @code{connection-supervision-timeout} (default: @code{#f})
LE default connection supervision timeout. This value is superceeded by any specific
value provided via the Load Connection Parameters interface.
@item @code{autoconnect-timeout} (default: @code{#f})
LE default autoconnect timeout. This value is superceeded by any specific
value provided via the Load Connection Parameters interface.
@item @code{adv-mon-allowlist-scan-duration} (default: @code{300})
Allowlist scan duration during interleaving scan. Only used when scanning for ADV
monitors. The units are msec.
@item @code{adv-mon-no-filter-scan-duration} (default: @code{500})
No filter scan duration during interleaving scan. Only used when scanning for ADV
monitors. The units are msec.
@item @code{enable-adv-mon-interleave-scan?} (default: @code{#t})
Enable/Disable Advertisement Monitor interleave scan for power saving.
@item @code{cache} (default: @code{'always})
GATT attribute cache.
Possible values are:
@itemize @bullet
@item
@code{'always}: Always cache attributes even for devices not paired, this is
recommended as it is best for interoperability, with more consistent
reconnection times and enables proper tracking of notifications for all
devices
@item
@code{'yes}: Only cache attributes of paired devices
@item
@code{'no}: Never cache attributes.
@end itemize
@item @code{key-size} (default: @code{0})
Minimum required Encryption Key Size for accessing secured characteristics.
Possible values are:
@itemize @bullet
@item
@code{0}: Don't care
@item
@code{7 <= N <= 16}
@end itemize
@item @code{exchange-mtu} (default: @code{517})
Exchange MTU size. Possible values are:
@itemize @bullet
@item
@code{23 <= N <= 517}
@end itemize
@item @code{att-channels} (default: @code{3})
Number of ATT channels. Possible values are:
@itemize @bullet
@item
@code{1}: Disables EATT
@item
@code{2 <= N <= 5}
@end itemize
@item @code{session-mode} (default: @code{'basic})
AVDTP L2CAP signalling channel mode.
Possible values are:
@itemize @bullet
@item
@code{'basic}: Use L2CAP basic mode
@item
@code{'ertm}: Use L2CAP enhanced retransmission mode.
@end itemize
@item @code{stream-mode} (default: @code{'basic})
AVDTP L2CAP transport channel mode.
Possible values are:
@itemize @bullet
@item
@code{'basic}: Use L2CAP basic mode
@item
@code{'streaming}: Use L2CAP streaming mode.
@end itemize
@item @code{reconnect-uuids} (default: @code{'()})
The ReconnectUUIDs defines the set of remote services that should try
to be reconnected to in case of a link loss (link supervision
timeout). The policy plugin should contain a sane set of values by
default, but this list can be overridden here. By setting the list to
empty the reconnection feature gets disabled.
Possible values:
@itemize @bullet
@item
@code{'()}
@item
@code{(list (uuid <uuid-1>) (uuid <uuid-2>) ...)}.
@end itemize
@item @code{reconnect-attempts} (default: @code{7})
Defines the number of attempts to reconnect after a link lost. Setting
the value to 0 disables reconnecting feature.
@item @code{reconnect-intervals} (default: @code{'(1 2 4 8 16 32 64)})
Defines a list of intervals in seconds to use in between attempts. If
the number of attempts defined in @var{reconnect-attempts} is bigger than
the list of intervals the last interval is repeated until the last attempt.
@item @code{auto-enable?} (default: @code{#f})
Defines option to enable all controllers when they are found. This includes
adapters present on start as well as adapters that are plugged in later on.
@item @code{resume-delay} (default: @code{2})
Audio devices that were disconnected due to suspend will be reconnected on
resume. @var{resume-delay} determines the delay between when the controller
resumes from suspend and a connection attempt is made. A longer delay is
better for better co-existence with Wi-Fi. The value is in seconds.
@item @code{rssi-sampling-period} (default: @code{#xFF})
Default RSSI Sampling Period. This is used when a client registers an
advertisement monitor and leaves the RSSISamplingPeriod unset.
Possible values are:
@itemize @bullet
@item
@code{#x0}: Report all advertisements
@item
@code{N = #xXX}: Report advertisements every N x 100 msec (range: #x01 to #xFE)
@item
@code{#xFF}: Report only one advertisement per device during monitoring period.
@end itemize
@end table
@end deftp
@defvr {Scheme Variable} gnome-keyring-service-type
This is the type of the service that adds the
@uref{https://wiki.gnome.org/Projects/GnomeKeyring, GNOME Keyring}. Its
@ -21412,7 +21854,6 @@ and ``passwd'' is with the value @code{passwd}.
@end table
@end deftp
@node Sound Services
@subsection Sound Services

View File

@ -44,6 +44,7 @@
#:use-module (gnu system)
#:use-module (gnu system setuid)
#:use-module (gnu system shadow)
#:use-module (gnu system uuid)
#:use-module (gnu system pam)
#:use-module (gnu packages glib)
#:use-module (gnu packages admin)
@ -68,6 +69,7 @@
#:use-module (guix utils)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
#:use-module (ice-9 format)
#:use-module (ice-9 match)
#:export (<upower-configuration>
upower-configuration
@ -403,14 +405,380 @@ site} for more information."
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 #x000000))
(discoverable-timeout
bluetooth-configuration-discoverable-timeout (default 180))
(always-pairable? bluetooth-configuration-always-pairable? (default #f))
(pairable-timeout bluetooth-configuration-pairable-timeout (default 0))
;;; MAYBE: Exclude into separate <device-id> record-type?
(device-id bluetooth-configuration-device-id (default #f))
(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: #t, #f, (uuid <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 #f))
(remote-name-request-retry-delay
bluetooth-configuration-remote-name-request-retry-delay (default 300))
;;; [BR]
(page-scan-type bluetooth-configuration-page-scan-type (default #f))
(page-scan-interval bluetooth-configuration-page-scan-interval (default #f))
(page-scan-window bluetooth-configuration-page-scan-window (default #f))
(inquiry-scan-type bluetooth-configuration-inquiry-scan-type (default #f))
(inquiry-scan-interval bluetooth-configuration-inquiry-scan-interval (default #f))
(inquiry-scan-window bluetooth-configuration-inquiry-scan-window (default #f))
(link-supervision-timeout bluetooth-configuration-link-supervision-timeout (default #f))
(page-timeout bluetooth-configuration-page-timeout (default #f))
(min-sniff-interval bluetooth-configuration-min-sniff-interval (default #f))
(max-sniff-interval bluetooth-configuration-max-sniff-interval (default #f))
;;; [LE]
(min-advertisement-interval
bluetooth-configuration-min-advertisement-interval (default #f))
(max-advertisement-interval
bluetooth-configuration-max-advertisement-interval (default #f))
(multi-advertisement-rotation-interval
bluetooth-configuration-multi-advertisement-rotation-interval (default #f))
(scan-interval-auto-connect
bluetooth-configuration-scan-interval-auto-connect (default #f))
(scan-window-auto-connect
bluetooth-configuration-scan-window-auto-connect (default #f))
(scan-interval-suspend
bluetooth-configuration-scan-interval-suspend (default #f))
(scan-window-suspend
bluetooth-configuration-scan-window-suspend (default #f))
(scan-interval-discovery
bluetooth-configuration-scan-interval-discovery (default #f))
(scan-window-discovery
bluetooth-configuration-scan-window-discovery (default #f))
(scan-interval-adv-monitor
bluetooth-configuration-scan-interval-adv-monitor (default #f))
(scan-window-adv-monitor
bluetooth-configuration-scan-window-adv-monitor (default #f))
(scan-interval-connect
bluetooth-configuration-scan-interval-connect (default #f))
(scan-window-connect
bluetooth-configuration-scan-window-connect (default #f))
(min-connection-interval
bluetooth-configuration-min-connection-interval (default #f))
(max-connection-interval
bluetooth-configuration-max-connection-interval (default #f))
(connection-latency
bluetooth-configuration-connection-latency (default #f))
(connection-supervision-timeout
bluetooth-configuration-connection-supervision-timeout (default #f))
(autoconnect-timeout
bluetooth-configuration-autoconnect-timeout (default #f))
(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 #t))
;;; [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 #xFF)))
(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 = " (string-append
"0x"
(format #f "~6,'0x" (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 (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 = " (let ((experimental (bluetooth-configuration-experimental config)))
(cond ((or (eq? experimental #t)
(eq? experimental #f)) (bool experimental))
((list? experimental)
(string-join (map uuid->string experimental) ","))))
"\nRemoteNameRequestRetryDelay = " (number->string
(bluetooth-configuration-remote-name-request-retry-delay
config))
"\n[BR]"
(if (bluetooth-configuration-page-scan-type config)
(string-append
"\nPageScanType = "
(number->string (bluetooth-configuration-page-scan-type config)))
"")
(if (bluetooth-configuration-page-scan-interval config)
(string-append
"\nPageScanInterval = "
(number->string (bluetooth-configuration-page-scan-interval config)))
"")
(if (bluetooth-configuration-page-scan-window config)
(string-append
"\nPageScanWindow = "
(number->string (bluetooth-configuration-page-scan-window config)))
"")
(if (bluetooth-configuration-inquiry-scan-type config)
(string-append
"\nInquiryScanType = "
(number->string (bluetooth-configuration-inquiry-scan-type config)))
"")
(if (bluetooth-configuration-inquiry-scan-interval config)
(string-append
"\nInquiryScanInterval = "
(number->string (bluetooth-configuration-inquiry-scan-interval config)))
"")
(if (bluetooth-configuration-inquiry-scan-window config)
(string-append
"\nInquiryScanWindow = "
(number->string (bluetooth-configuration-inquiry-scan-window config)))
"")
(if (bluetooth-configuration-link-supervision-timeout config)
(string-append
"\nLinkSupervisionTimeout = "
(number->string (bluetooth-configuration-link-supervision-timeout config)))
"")
(if (bluetooth-configuration-page-timeout config)
(string-append
"\nPageTimeout = "
(number->string (bluetooth-configuration-page-timeout config)))
"")
(if (bluetooth-configuration-min-sniff-interval config)
(string-append
"\nMinSniffInterval = "
(number->string (bluetooth-configuration-min-sniff-interval config)))
"")
(if (bluetooth-configuration-max-sniff-interval config)
(string-append
"\nMaxSniffInterval = "
(number->string (bluetooth-configuration-max-sniff-interval config)))
"")
"\n[LE]"
(if (bluetooth-configuration-min-advertisement-interval config)
(string-append
"\nMinAdvertisementInterval = "
(number->string (bluetooth-configuration-min-advertisement-interval config)))
"")
(if (bluetooth-configuration-max-advertisement-interval config)
(string-append
"\nMaxAdvertisementInterval = "
(number->string (bluetooth-configuration-max-advertisement-interval config)))
"")
(if (bluetooth-configuration-multi-advertisement-rotation-interval config)
(string-append
"\nMultiAdvertisementRotationInterval = "
(number->string
(bluetooth-configuration-multi-advertisement-rotation-interval config)))
"")
(if (bluetooth-configuration-scan-interval-auto-connect config)
(string-append
"\nScanIntervalAutoConnect = "
(number->string (bluetooth-configuration-scan-interval-auto-connect config)))
"")
(if (bluetooth-configuration-scan-window-auto-connect config)
(string-append
"\nScanWindowAutoConnect = "
(number->string (bluetooth-configuration-scan-window-auto-connect config)))
"")
(if (bluetooth-configuration-scan-interval-suspend config)
(string-append
"\nScanIntervalSuspend = "
(number->string (bluetooth-configuration-scan-interval-suspend config)))
"")
(if (bluetooth-configuration-scan-window-suspend config)
(string-append
"\nScanWindowSuspend = "
(number->string (bluetooth-configuration-scan-window-suspend config)))
"")
(if (bluetooth-configuration-scan-interval-discovery config)
(string-append
"\nScanIntervalDiscovery = "
(number->string (bluetooth-configuration-scan-interval-discovery config)))
"")
(if (bluetooth-configuration-scan-window-discovery config)
(string-append
"\nScanWindowDiscovery = "
(number->string (bluetooth-configuration-scan-window-discovery config)))
"")
(if (bluetooth-configuration-scan-interval-adv-monitor config)
(string-append
"\nScanIntervalAdvMonitor = "
(number->string (bluetooth-configuration-scan-interval-adv-monitor config)))
"")
(if (bluetooth-configuration-scan-window-adv-monitor config)
(string-append
"\nScanWindowAdvMonitor = "
(number->string (bluetooth-configuration-scan-window-adv-monitor config)))
"")
(if (bluetooth-configuration-scan-interval-connect config)
(string-append
"\nScanIntervalConnect = "
(number->string (bluetooth-configuration-scan-interval-connect config)))
"")
(if (bluetooth-configuration-scan-window-connect config)
(string-append
"\nScanWindowConnect = "
(number->string (bluetooth-configuration-scan-window-connect config)))
"")
(if (bluetooth-configuration-min-connection-interval config)
(string-append
"\nMinConnectionInterval = "
(number->string (bluetooth-configuration-min-connection-interval config)))
"")
(if (bluetooth-configuration-max-connection-interval config)
(string-append
"\nMaxConnectionInterval = "
(number->string (bluetooth-configuration-max-connection-interval config)))
"")
(if (bluetooth-configuration-connection-latency config)
(string-append
"\nConnectionLatency = "
(number->string (bluetooth-configuration-connection-latency config)))
"")
(if (bluetooth-configuration-connection-supervision-timeout config)
(string-append
"\nConnectionSupervisionTimeout = "
(number->string (bluetooth-configuration-connection-supervision-timeout config)))
"")
(if (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
(if (eq? #t
(bluetooth-configuration-enable-adv-mon-interleave-scan
config))
1 0))
"\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]"
(let ((uuids (bluetooth-configuration-reconnect-uuids config)))
(if (not (eq? '() uuids))
(string-append
"\nReconnectUUIDs = "
(string-join (map uuid->string uuids) ","))
""))
"\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 = " (string-append
"0x"
(format #f "~2,'0x"
(bluetooth-configuration-rssi-sampling-period config)))))
(define (bluetooth-directory config)
(computed-file "etc-bluetooth"