1 /* vdagentd.c vdagentd xorg.conf writing code
3 Copyright 2011 Red Hat, Inc.
6 Hans de Goede <hdegoede@redhat.com>
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <pciaccess.h>
32 #include "vdagentd-xorg-conf.h"
34 #define FPRINTF(...) \
36 r = fprintf(f, __VA_ARGS__); \
38 fprintf(logfile, "Error writing to %s: %s\n", \
39 xorg_conf, strerror(errno)); \
41 pci_system_cleanup(); \
46 void vdagentd_write_xorg_conf(VDAgentMonitorsConfig
*monitor_conf
,
50 int i
, r
, count
, min_x
= INT_MAX
, min_y
= INT_MAX
;
52 struct pci_device_iterator
*it
;
53 struct pci_device
*dev
;
54 const struct pci_id_match qxl_id_match
= {
57 .subvendor_id
= PCI_MATCH_ANY
,
58 .subdevice_id
= PCI_MATCH_ANY
,
60 const char *xorg_conf
= "/var/run/spice-vdagentd/xorg.conf.spice";
61 const char *xorg_conf_old
= "/var/run/spice-vdagentd/xorg.conf.spice.old";
63 r
= rename(xorg_conf
, xorg_conf_old
);
64 if (r
&& errno
!= ENOENT
) {
66 "Error renaming %s to %s: %s, not generating xorg.conf\n",
67 xorg_conf
, xorg_conf_old
, strerror(errno
));
71 r
= pci_system_init();
73 fprintf(logfile
, "Error initializing libpciaccess: %d, not generating xorg.conf\n", r
);
77 it
= pci_id_match_iterator_create(&qxl_id_match
);
79 fprintf(logfile
, "Error could not create pci id iterator for QXL devices, not generating xorg.conf\n");
84 dev
= pci_device_next(it
);
86 fprintf(logfile
, "No QXL devices found, not generating xorg.conf\n");
91 f
= fopen(xorg_conf
, "w");
93 fprintf(logfile
, "Error opening %s for writing: %s\n",
94 xorg_conf
, strerror(errno
));
99 FPRINTF("# xorg.conf generated by spice-vdagentd\n");
100 FPRINTF("# generated from monitor info provided by the client\n\n");
102 if (monitor_conf
->num_of_monitors
== 1) {
103 FPRINTF("# Client has only 1 monitor\n");
104 FPRINTF("# This works best with no xorg.conf, leaving xorg.conf empty\n");
106 pci_system_cleanup();
110 FPRINTF("Section \"ServerFlags\"\n");
111 FPRINTF("\tOption\t\t\"Xinerama\"\t\"true\"\n");
112 FPRINTF("EndSection\n\n");
116 FPRINTF("Section \"Device\"\n");
117 FPRINTF("\tIdentifier\t\"qxl%d\"\n", i
++);
118 FPRINTF("\tDriver\t\t\"qxl\"\n");
119 FPRINTF("\tBusID\t\t\"PCI:%02d:%02d:%d\"\n",
120 dev
->bus
, dev
->dev
, dev
->func
);
121 FPRINTF("EndSection\n\n");
122 } while ((dev
= pci_device_next(it
)));
124 if (i
< monitor_conf
->num_of_monitors
) {
125 fprintf(logfile
, "Client has %d monitors, but only %d qxl devices found\n",
126 monitor_conf
->num_of_monitors
, i
);
127 FPRINTF("# Client has %d monitors, but only %d qxl devices found\n",
128 monitor_conf
->num_of_monitors
, i
);
129 FPRINTF("# Only generation %d \"Screen\" sections\n\n", i
);
132 count
= monitor_conf
->num_of_monitors
;
135 for (i
= 0; i
< count
; i
++) {
136 FPRINTF("Section \"Screen\"\n");
137 FPRINTF("\tIdentifier\t\"Screen%d\"\n", i
);
138 FPRINTF("\tDevice\t\t\"qxl%d\"\n", i
);
139 FPRINTF("\tDefaultDepth\t24\n");
140 FPRINTF("\tSubSection \"Display\"\n");
141 FPRINTF("\t\tViewport\t0 0\n");
142 FPRINTF("\t\tDepth\t\t24\n");
143 FPRINTF("\t\tModes\t\t\"%dx%d\"\n", monitor_conf
->monitors
[i
].width
,
144 monitor_conf
->monitors
[i
].height
);
145 FPRINTF("\tEndSubSection\n");
146 FPRINTF("EndSection\n\n");
149 /* monitor_conf may contain negative values, convert these to 0 - # */
150 for (i
= 0; i
< count
; i
++) {
151 if (monitor_conf
->monitors
[i
].x
< min_x
) {
152 min_x
= monitor_conf
->monitors
[i
].x
;
154 if (monitor_conf
->monitors
[i
].y
< min_y
) {
155 min_y
= monitor_conf
->monitors
[i
].y
;
159 FPRINTF("Section \"ServerLayout\"\n");
160 FPRINTF("\tIdentifier\t\"layout\"\n");
161 for (i
= 0; i
< count
; i
++) {
162 FPRINTF("\tScreen\t\t\"Screen%d\" %d %d\n", i
,
163 monitor_conf
->monitors
[i
].x
- min_x
,
164 monitor_conf
->monitors
[i
].y
- min_y
);
166 FPRINTF("EndSection\n");
169 pci_system_cleanup();