modified install path for auto start in emulator
[platform/adaptation/emulator/spice-vdagent.git] / src / vdagentd-xorg-conf.c
1 /*  vdagentd.c vdagentd xorg.conf writing code
2
3     Copyright 2011, 2012 Red Hat, Inc.
4     Copyright (c) 2014 Samsung Electronics Co., Ltd.
5
6     Red Hat Authors:
7     Hans de Goede <hdegoede@redhat.com>
8
9     This program is free software: you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation, either version 3 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22     * Modifications by Samsung Electronics Co., Ltd.
23     1. modified xorg_conf path
24 */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #ifdef HAVE_PCIACCESS
30 #include <pciaccess.h>
31 #endif
32
33 #include <string.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <syslog.h>
37 #include "vdagentd-xorg-conf.h"
38
39 #define FPRINTF(...) \
40     do { \
41         r = fprintf(f, __VA_ARGS__); \
42         if (r < 0) { \
43             syslog(LOG_ERR, "Error writing to %s: %m", xorg_conf); \
44             fclose(f); \
45             pci_system_cleanup(); \
46             return; \
47         } \
48     } while(0)
49
50 void vdagentd_write_xorg_conf(VDAgentMonitorsConfig *monitor_conf)
51 {
52 #ifdef HAVE_PCIACCESS
53     int i, r, count, min_x = INT_MAX, min_y = INT_MAX;
54     FILE *f;
55     struct pci_device_iterator *it;
56     struct pci_device *dev;
57     const struct pci_id_match qxl_id_match = {
58         .vendor_id = 0x1b36,
59         .device_id = 0x0100,
60         .subvendor_id = PCI_MATCH_ANY,
61         .subdevice_id = PCI_MATCH_ANY,
62     };
63     const char *xorg_conf = "/tmp/spice-vdagentd/xorg.conf.spice";
64     const char *xorg_conf_old = "/tmp/spice-vdagentd/xorg.conf.spice.old";
65
66     r = rename(xorg_conf, xorg_conf_old);
67     if (r && errno != ENOENT) {
68         syslog(LOG_ERR,
69                "Error renaming %s to %s: %m, not generating xorg.conf",
70                xorg_conf, xorg_conf_old);
71         return;
72     }
73
74     r = pci_system_init();
75     if (r) {
76         syslog(LOG_ERR, "Error initializing libpciaccess: %d, not generating xorg.conf", r);
77         return;
78     }
79
80     it = pci_id_match_iterator_create(&qxl_id_match);
81     if (!it) {
82         syslog(LOG_ERR, "Error could not create pci id iterator for QXL devices, not generating xorg.conf");
83         pci_system_cleanup();
84         return;
85     }
86
87     dev = pci_device_next(it);
88     if (!dev) {
89         syslog(LOG_ERR, "No QXL devices found, not generating xorg.conf");
90         pci_system_cleanup();
91         return;
92     }
93
94     f = fopen(xorg_conf, "w");
95     if (!f) {
96         syslog(LOG_ERR, "Error opening %s for writing: %m", xorg_conf);
97         pci_system_cleanup();
98         return;
99     }
100
101     FPRINTF("# xorg.conf generated by spice-vdagentd\n");
102     FPRINTF("# generated from monitor info provided by the client\n\n");
103
104     if (monitor_conf->num_of_monitors == 1) {
105         FPRINTF("# Client has only 1 monitor\n");
106         FPRINTF("# This works best with no xorg.conf, leaving xorg.conf empty\n");
107         fclose(f);
108         pci_system_cleanup();
109         return;
110     }
111
112     FPRINTF("Section \"ServerFlags\"\n");
113     FPRINTF("\tOption\t\t\"Xinerama\"\t\"true\"\n");
114     FPRINTF("EndSection\n\n");
115
116     i = 0;
117     do {
118         FPRINTF("Section \"Device\"\n");
119         FPRINTF("\tIdentifier\t\"qxl%d\"\n", i++);
120         FPRINTF("\tDriver\t\t\"qxl\"\n");
121         FPRINTF("\tBusID\t\t\"PCI:%02d:%02d:%d\"\n",
122                 dev->bus, dev->dev, dev->func);
123         FPRINTF("\tOption\t\t\"NumHeads\"\t\"1\"\n");
124         FPRINTF("EndSection\n\n");
125     } while ((dev = pci_device_next(it)));
126
127     if (i < monitor_conf->num_of_monitors) {
128         FPRINTF("# Client has %d monitors, but only %d qxl devices found\n",
129                 monitor_conf->num_of_monitors, i);
130         FPRINTF("# Only generation %d \"Screen\" sections\n\n", i);
131         count = i;
132     } else {
133         count = monitor_conf->num_of_monitors;
134     }
135
136     for (i = 0; i < count; i++) {
137         FPRINTF("Section \"Screen\"\n");
138         FPRINTF("\tIdentifier\t\"Screen%d\"\n", i);
139         FPRINTF("\tDevice\t\t\"qxl%d\"\n", i);
140         FPRINTF("\tDefaultDepth\t24\n");
141         FPRINTF("\tSubSection \"Display\"\n");
142         FPRINTF("\t\tViewport\t0 0\n");
143         FPRINTF("\t\tDepth\t\t24\n");
144         FPRINTF("\t\tModes\t\t\"%dx%d\"\n", monitor_conf->monitors[i].width,
145                 monitor_conf->monitors[i].height);
146         FPRINTF("\tEndSubSection\n");
147         FPRINTF("EndSection\n\n");
148     }
149
150     /* monitor_conf may contain negative values, convert these to 0 - # */
151     for (i = 0; i < count; i++) {
152         if (monitor_conf->monitors[i].x < min_x) {
153             min_x = monitor_conf->monitors[i].x;
154         }
155         if (monitor_conf->monitors[i].y < min_y) {
156             min_y = monitor_conf->monitors[i].y;
157         }
158     }
159
160     FPRINTF("Section \"ServerLayout\"\n");
161     FPRINTF("\tIdentifier\t\"layout\"\n");
162     for (i = 0; i < count; i++) {
163         FPRINTF("\tScreen\t\t\"Screen%d\" %d %d\n", i,
164                 monitor_conf->monitors[i].x - min_x,
165                 monitor_conf->monitors[i].y - min_y);
166     }
167     FPRINTF("EndSection\n");
168
169     fclose(f);
170     pci_system_cleanup();
171 #endif
172 }