-
Notifications
You must be signed in to change notification settings - Fork 1
/
ddcutil-service.1
745 lines (606 loc) · 21.4 KB
/
ddcutil-service.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
.TH ddcutil-service 1 "ddcutil-service" "MH" \" -*- nroff -*-
.SH NAME
ddcutil-service \- D-Bus service for libddcutil VESA DDC Monitor Virtual Control Panel
.SH SYNOPSIS
.B ddcutil-service
.I --help
|
.I --version
|
.I --introspect
.br
.B ddcutil-service
[
.B --emit-connectivity-signals
]
|
[
.B --prefer-polling
]
|
[
.B --prefer-drm
]
|
[
.B --polling-interval \fIseconds\fP
]
|
[
.B --return-raw-values
]
|
[
.B --lock
]
|
[
.B --log-info
]
[
.B --ddca-syslog-level \fIN\fP
]
|
[
.B --ddca-init-options \fIM\fP
]
[
.B -- \fIlibddcutil ddc_init options...\fP
]
.SH DESCRIPTION
.B ddcutil-service
is D-Bus service wrapper for libddcutil which
implements the VESA DDC Monitor Control Command Set.
Most things that can be controlled using a monitor's on-screen
display can be controlled by this service.
The
service
is registered as a
.B session-service
with the
.B dbus-daemon.
The daemon starts the service on demand.
If the service terminates for any reason, the daemon will be restart
it when it is next accessed.
Client connections with the service are stateless, each request
is handled atomically.
\fBWhen using this service, avoid excessively writing VCP values because each VDU's NVRAM
likely has a write-cycle limit/lifespan. The suggested guideline is to limit updates
to rates comparable to those observed when using the VDU's onboard controls. Avoid coding
that might rapidly or infinitely loop, including when recovering from errors and bugs.\fP
\fBNon-standard manufacturer specific features should only be experimented with caution,
some may have irreversible consequences, including bricking the hardware.\fP
.SS OPTIONS
Depending on the version of
.B libddcutil
in use, not all options may be available.
.TP
.B "--help"
Outputs options-help and exits.
.TP
.B "--version"
Outputs the service interface version and the
.B libddcutil
version and exits.
.TP
.B "--introspect"
Outputs the XML introspection text for the service and exits.
.TP
.B "--emit-connectivity-signals"
Enable the
.B ConnectedDisplaysChanged signal
sent to clients and also enable any monitoring for changes.
Once the service is running, this setting can be toggled by altering the
.B ServiceEmitConnectivitySignals
property.
See \fBSERVICE SIGNALS\fP.
.TP
.B "--prefer-polling"
Set polling to be the preferred method for detecting display connectivity changes
for the \fBConnectedDisplaysChanged signal\fP. This is the default.
.TP
.B "--prefer-drm"
Use
.B libddcutil DRM-lookups
as the preferred method for detecting display connectivity changes
for the \fBConnectedDisplaysChanged signal\fP. This option should detect changes sooner
with less overheads, but may fail to detect changes for some combinations or drivers and hardware.
.TP
.B "--poll-interval" \fIseconds\fP
If polling is enabled, this option defines how often to check for display
connectivity changes. Default 30 seconds, minimum 10 seconds, zero to disable polling.
.TP
.B "--poll-cascade-interval" \fIseconds\fP
If polling is enabled, this option defines the minimum interval between
events within a cascade of events. For example, a cascade of events will
occur when a session is locked and all displays are put into DPMS sleep.
Default 0.5 seconds, minimum 0.1 seconds.
.TP
.B "--return-raw-values"
Return high-byte and low-byte for all values, including for
\fBSimple Non-Continuous\fP values. Normally SMC (single-byte) values are
masked to remove the high-byte value (see \fBLIMITATIONS\fP
for an explanation).
.TP
.B "--lock"
Lock the configuration. Disable the \fBSetSleepMultiplier\fP
and \fBRestart\fP methods. Make all properties read-only.
This option provides a way to
lockdown the service to the configuration passed on the command line.
The lock is provided to assist with avoiding conflicts
when more than one ddcutil-service client is in use at the same time.
.TP
.B "--log-info"
Enabling log-info will produce info and debug level output. When the
service is run from \fBdbus-daemon\fP, the diagnostic output will be
captured in the journal logs, otherwise it is directed to standard-error.
This option can also be toggled after startup by using B-Bus
to alter the
service's
.B ServiceInfoLogging
property (see
.B EXAMPLES
below).
.TP
.B "--ddca-syslog-level" \fIN\fP
The DDCA syslog level numerical value is passed to
.B libddcutil ddca_init()
function at startup to enable logging from within the library.
It's only available for
.B libddcutil version 2.1.0
and up.
Values for
.I N
are 0:never, 2:error:, 6:warning, 9:notice, 12:info, 15:verbose, and 18:debug.
.TP
.B "--ddca-init-options" \fIN\fP
The DDCA init option is a numerical value is passed to
.B libddcutil ddca_init()
function at startup to enable/disable various options with the library.
It's only available for
.B libddcutil 2.1.0+.
.TP
.B -- \fIlibddcutil ddc_init options...\fP
The
.B libddcutil
library also supports its own extensive set of init options, any arguments following
.B --
will be passed as to
.B libddcutil ddca_init()
function at service startup.
.SH SERVICE METHODS
The following is a brief summary of the methods provided by the service.
Full API documentation can be found in \fBddcutil_service(7)\fP.
.TP
.B Detect
Return a list of monitors detected along with their properties.
.TP
.B GetVcp
Query a display settings by VCP code, for example, brightness is VCP code 0x10.
The method's \fBflags\fP bit-string parameter can be set to \fB2\fP (\fBRETURN_RAW_VALUES\fP),
see \fBLIMITATIONS\fP for an explanation.
.TP
.B GetMultipleVcp
Query multiple VCP codes for a single display.
The method's \fBflags\fP bit-string parameter can be set to \fB2\fP (\fBRETURN_RAW_VALUES\fP),
see \fBLIMITATIONS\fP for an explanation.
.TP
.B SetVcp
Set a display setting, specified by VCP code, to a new value.
If the method succeeds, it will also emit a D-Bus \fBVcpValueChanged\fP signal.
Set the method's \fBflags\fP to \fB4\fP (\fBNO_VERIFY\fP) to disable libddcutil
verification and retry.
.TP
.B SetVcpWithContext
As with \fBSetVcp\fP, but also accept a client supplied context string
to be returned with the emitted D-Bus \fBVcpValueChanged\fP signal.
The client-context may be of use to signal recipients for interpreting the
origin of the change.
.TP
.B GetCapabilitiesMetadata
Query a displays capabilities returning a parsed data-structure describing the
features and permitted values.
.TP
.B GetCapabilitiesString
Query a displays capabilities returning a unparsed capabilities string.
.TP
.B GetVcpMetadata
Query the metadata describing a specific VCP code for a specific display.
.TP
.B GetSleepMultiplier
Get the display specific
.B ddcutil
sleep multiplier.
.TP
.B SetSleepMultiplier
Set a display specific
.B ddcutil
sleep multiplier.
.TP
.B Restart
Restart the service with specific arguments.
.PP
If a method requires a display-argument, either an integer
.I display-number
or a
.I base64-encoded EDID
can be supplied. Base64-encoded EDIDs are obtained from the
.B Detect
method.
When passing an EDID, pass -1 for display_number, otherwise both are tied with the display_number
having precedence.
If a EDID is supplied, a method's
.B flags
bit-string parameter can be set to
.B 1
(EDID_PREFIX),
this indicates a unique prefix of an EDID has been passed rather than
the entire string (this makes using EDIDs from the command line a little easier).
Run
.B ddcutil-service --introspect
for details on each method's in/out parameters. For even more
information, the
.B d-feet
graphical D-Bus debugger provides a very readable
way to browse and experiment with the service interface, simply start
.B d-feet,
select the
.B Session Bus
and search for
.B ddcutil-service.
.SH SERVICE SIGNALS
.TP
.B ServiceInitialized
At startup the service emits the
.B ServiceInitialized
D-Bus signal. This signal provides clients with a way to detect a
service restart and reinstate any custom service properties or settings.
.TP
.B ConnectedDisplaysChanged
The service may optionally emit a
.B ConnectedDisplaysChanged
D-Bus signal when a display undergoes a connectivity status change
due to hot-plug and DPMS events.
This feature is optional because the manual
experimentation required to configure it is unnecessary for display
configurations that remain static.
Change-detection can be enabled by passing
.B --emit-connectivity-signals
on the command line, or by setting the
.B ServiceEmitConnectivitySignals
property.
To permanently enable change-detection, the
.B --emit-connectivity-signals
option can be appended to the
.B Exec
line of the
system or user D-Bus
.B com.ddcutil.DdcutilService.service
file (see \fBFILES\fP).
Changes are detected in one of two ways.
The service defaults to periodic polling by
issuing \fBlibddcutil DDCA detects\fP. Polling is
likely to work for a wide variety of drivers and hardware.
Polling for changes will be subject to delays because
the polling interval defaults to 30 seconds (with a minimum of 10 seconds).
Alternatively the service can use \fBlibddcutil DRM access \fP to provide
a more efficient method for change detection,
this requires \fBddcutil/libddcutil version 2.1.0+\fP, a GPU configured for \fBDRM\fP, and
the \fB--enable-watch-displays\fP to be added to \fI[libddcutil] options\fP
in \fB$HOME/.config/ddcutil/ddcutilrc\fP.
Not all displays, GPUs, GPU-drivers, or cabling, provide the necessary support
for detecting connection status changes. Results may vary
depending on the mix of desktop components, such as KDE, Gnome, X11, and Wayland.
DisplayPort behaves differently to DVI and HDMI when
a display is turned off but remains connected. Some drivers that
support DRM don't properly support the necessary change detection features.
.TP
.B VcpValueChanged
The service will emit a
.B VcpValueChanged
D-Bus signal whenever a SetVcp or SetVcpWithContext method call succeeds in
changing a VCP's value. \fBOnly changes made by service methods are detected,
changes made externally to the service are not detected and will not trigger
this signal\fP.
.SH SERVICE PROPERTIES
.TP
.B AttributesReturnedByDetect
Query the fieldnames returned from the
.B Detect
method. Lists the names of the fields in the order they are
found in each struct returned from
.B Detect.
.TP
.B StatusValues
Query the list of status values returned by
.B libddcutil
along with their text names.
.TP
.B DisplayEventTypes
List the event-types sent by the
.B ConnectedDisplaysChanged
signal along with their text names.
Events are included for display connection/disconnection (hot-plug), DPMS-sleep, and DPMS-wake.
If the list is empty, the GPU, GPU-driver, or
.B libddcutil
version doesn't support display event detection.
.TP
.B DdcutilDynamicSleep
Enable/disable
.B libddcutil
dynamic-sleep adjustment of DDC timings.
.TP
.B DdcutilOutputLevel
Read/write the
.B libddcutil
output level.
.TP
.B DdcutilVerifySetVcp
Obsolete as of version 1.0.5+,
replaced by the \fBSetVcp\fP method's \fBNO_VERIFY\fP flag.
.TP
.B DdcutilVersion
Query the
.B libddcutil
version string.
.TP
.B ServiceEmitConnectivitySignals
Set this property to \fBtrue\fP or \fBfalse\fP to enable or disable the
.B ConnectedDisplaysChanged
dbus-signal and associated monitoring.
.TP
.B ServiceInfoLogging
Enable/disable the service's diagnostic level output to include info and debug messages.
Note that
.B libddcutil
also has a logging mechanism (see \fBlibddcutil ddc_init options\fP).
.TP
.B ServiceInterfaceVersion
Query the service interface version.
.TP
.B ServiceFlagOptions
List the available flag option values that can be passed to service methods.
Not all options are applicable to all methods.
.TP
.B ServiceParametersLocked
Returns whether the
.B --lock
command line argument has been used.
.TP
.B ServicePollInterval
Query or set the display change detection poll-interval (minimum 10 seconds, zero to disable polling).
.TP
.B ServicePollCascadeInterval
Query or set the display change detection poll-cascade-interval (minimum 0.1 seconds).
When dealing with a cascade of events, for example, when a desktop-session is locked
and sets all VDUs to DPMS sleep, polling occurs more frequently until the cascade is
cleared.
.PP
Properties can be queried and set using utilities such as
.B busctl,
.B d-bus-send,
and
.B d-feet,
see
.B EXAMPLES.
.SH SERVICE ERRORS
.SS Errors forwarded from libddcutil
Status codes and error messages from \fBlibddcutil\fP are passed back to clients as part of the data
returned by each method call.
.SS Exceptions
The service may also issue the following exceptions when attempting to set properties or call methods:
.TP
.B com.ddcutil.DdcutilService.Error.ConfigurationLocked
The \fB--lock\fP option has prevented a client from altering a configuration
settings. This includes using the \fBSetSleepMultiplier\fP method, \fBRestart\fP method,
or setting any property value.
.TP
.B com.ddcutil.DdcutilService.Error.InvalidPollSeconds
An attempt was made to set \fBServicePollInterval\fP to a value outside its accepted range.
.TP
.B com.ddcutil.DdcutilService.Error.InvalidPollCascadeSeconds
An attempt was made to set \fBServicePollCascadeInterval\fP to a value outside its accepted range.
.TP
.B com.ddcutil.DdcutilService.Error.I2cDevNoModule
At startup no \fB/dev/i2c\fP devices are present and an attempt to verify communications via i2c failed.
.TP
.B com.ddcutil.DdcutilService.Error.I2cDevNoPermissions
At startup it was found that the user/service lacked read/write access to the \fB/dev/i2c\fP devices.
.SH FILES
.TP
.B /usr/share/dbus-1/services/com.ddcutil.DdcutilService.service
If running via the dbus-daemon, this config file is read when the
service is requested. Typically the contents would be as follows
.nf
[D-BUS Service]
Name=com.ddcutil.DdcutilService
Exec=/usr/bin/ddcutil-service
.fi
Service options, such as \fB--emit-connectivity-signals\fP or \fB--prefer-drm\fP,
should be appended to the end of \fBExec=\fP line.
.TP
.B $HOME/.local/share/dbus-1/services/com.ddcutil.DdcutilService.service
If you do not have root access or wish to set options
for a specific user, the dbus-daemon first looks for in
.B $HOME/.local/share
before looking in
.B /usr/share.
.TP
.B $HOME/.config/ddcutil/ddcutilrc
When initialised at service startup,
.B libddcutil
loads options from its rc file. See
.I https://www.ddcutil.com/config_file/
for details.
.TP
.B /usr/share/ddcutil-service/examples/
The service is packaged with several example scripts, including
.B dbus-send
bash-scripts
and
.B python3
clients for D-Bus
.B dasbus
and
.B QtDBus
APIs.
.SH EXECUTION ENVIRONMENT
The service relies on \fBlibddcutil\fP which
requires read/write access to the
.B /dev/i2c
devices. See
.I http://www.ddcutil.com/i2c_permissions
for details.
At startup
.B ddcutil-service
will attempt to verify that
.B i2c-dev
module is loaded and that the permissions for
.B /dev/i2c
are set appropriately. If these checks fail, method calls will error until
the problem is resolved.
.SH NVIDIA PROPRIETARY DRIVER
Some Nvidia cards using the proprietary Nvidia driver require special settings to properly enable I2C support.
See
.I http://www.ddcutil.com/nvidia
for details.
.SH VIRTUAL MACHINES
Virtualized video drivers in VMWare and VirtualBox do not provide I2C emulation.
It may be possible to forward D-BUS over \fBssh\fP to side step this issue.
.SH EXAMPLES
.PP
The commonly available command line utilities systemd \fBbustctl\fP and
dbus-tools \fBdbus-send\fP command
can be used to interact with the service.
.B Summarise the service methods and properties:
.nf
busctl --user introspect com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject
dbus-send --session --dest=com.ddcutil.DdcutilService --print-reply \\
/com/ddcutil/DdcutilObject \\
org.freedesktop.DBus.Introspectable.Introspect
.fi
.B Detect the connected displays:
.nf
busctl --user call com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject \\
com.ddcutil.DdcutilInterface Detect u 0
dbus-send --dest=com.ddcutil.DdcutilService --print-reply --type=method_call \\
/com/ddcutil/DdcutilObject com.ddcutil.DdcutilInterface.Detect uint32:0
.fi
.B Get the brightness of display-1 (VCP 0x10):
.nf
busctl --user call com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject \\
com.ddcutil.DdcutilInterface GetVcp isyu 1 "" 0x10 0
dbus-send --dest=com.ddcutil.DdcutilService --print-reply --type=method_call \\
/com/ddcutil/DdcutilObject com.ddcutil.DdcutilInterface.GetVcp \\
int32:1 string: byte:0x10 uint32:0
.fi
.B Set brightness of display-1 (VCP 0x10):
.nf
busctl --user call com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject \\
com.ddcutil.DdcutilInterface SetVcp isyqu 1 "" 16 50 0
dbus-send --session --dest=com.ddcutil.DdcutilService --print-reply --type=method_call \\
/com/ddcutil/DdcutilObject com.ddcutil.DdcutilInterface.SetVcp \\
int32:1 string:"" byte:0x10 uint16:10 uint32:0
.fi
.B Query or set the service logging level property:
.nf
busctl --user get-property com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject \\
com.ddcutil.DdcutilInterface ServiceInfoLogging
busctl --user set-property com.ddcutil.DdcutilService /com/ddcutil/DdcutilObject \\
com.ddcutil.DdcutilInterface ServiceInfoLogging b true
dbus-send --session --dest=com.ddcutil.DdcutilService --print-reply \\
--type=method_call /com/ddcutil/DdcutilObject \\
org.freedesktop.DBus.Properties.Get \\
string:com.ddcutil.DdcutilInterface \\
string:ServiceInfoLogging
dbus-send --dest=com.ddcutil.DdcutilService --print-reply \\
--type=method_call /com/ddcutil/DdcutilObject \\
org.freedesktop.DBus.Properties.Set \\
string:com.ddcutil.DdcutilInterface \\
string:ServiceInfoLogging variant:boolean:true
.fi
.SH LIMITATIONS
Some VDUs are not fully DDC compliant. In some cases issues raised
by non-compliance can only be resolved at the client-level,
often by requiring the user to provide additional metadata.
For example, the \fBvdu_controls\fP client allows the user to
edit/override the service supplied capabilities-metadata.
Some VDUs differ in how they treat the data-type for
\fBSimple-Non-Continuous\fP values. SNC values are used for
features such as the \fIInput-Source\fP or \fIOSD-language\fP. According
to the DDC specification, SNC values
should be 8-bit values passed in the low-byte of a 16-bit value.
Some VDUs don't zero the SNC high-byte. This may cause a mismatch with
the values specified in the VDU metadata.
The service handles this by defaulting to masking off the high-byte of SNC values.
Some VDUs return SNC values
where both the low and high byte are significant.
The \fBGetVcp\fP and \fBGetMultipleVcp\fP methods support the
\fBRETURN_RAW_VALUES\fP flag to force the return of unmasked 16-bit values.
This allows clients to apply heuristics or use additional
metadata to handle such cases. The \fBSetVcp\fP counterpart always accepts
full 16-bit values and passes them unaltered to the VDU.
Some mixes of VPUs and GPUs don't consistently update
DRM metadata for hot-plug events. If \fBConnectedDisplaysChanged\fP
signals are not being raised, try manually adding \fB--prefer-polling\fP
option, to force the service to poll for changes. Polling is less responsive,
but it doesn't require DRM, and is likely to always work.
Some GPU drivers and VDUs have buggy implementations of DDC.
If you have the choice, a
.B DisplayPort to DisplayPort
connection may work more reliably than
.B DVI,
.B HDMI
or mixed connectors.
In some cases GPU driver editions, such as production, beta, and development, may
vary in the state of their DDC support.
Some
.libddcutil
parameters can only be changed at process startup. The service can be
restarted either by killing it with a UNIX signal, or by invoking the
service's
.B Restart
method.
The service is a relatively thin wrapper around \fBlibddcutil\fP,
in order to resolve VDU compatibility/compliance issues, the user may need to
become familiar with the \fBlibddcutil\fP configuration options normally
stored in $HOME/.config/ddcutil/ddcutilrc and documented at
\fIhttps://www.ddcutil.com/config_file/\fP.
In some cases \fBlibddcutil\fP has been found to
perform differently from the \fBddcutil\fP command. If the service has
problems with a VDU, it's worth trying the ddcutil command to see if
it differs in result and to include those details in any issue raised.
.SH SEE ALSO
.TP
ddcutil-service(7), vdu_controls(1), ddcutil(1), dbus-daemon(1), dbus-send(1), busctl(1)
.SH REPORTING BUGS
Before raising a new issue, please read through \fBLIMITATIONS\fP.
Issues can be raised at
.I https://github.com/digitaltrails/ddcutil-service/issues
(requires a github login).
.SH AUTHOR
Michael Hamilton
.SH ACKNOWLEDGEMENTS
Thanks go out to
.B Sanford Rockowitz
for
.B libddcutil,
.B ddcutil
and all the assistance and advice provided during the development of this service.
Thanks also go out to all those who assisted with development and packaging.
An up-to-date list of contributors can be found at
\fBhttps://github.com/digitaltrails/vdu_controls#acknowledgements\fP.
.SH COPYRIGHT
Copyright (C) 2023,2024 Michael Hamilton.
.B ddcutil-service
is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.