blob: 881c678ac27adc831c1a49c824444da8ca1e661c [file] [log] [blame]
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07001/*
David Sodman8ef20062015-01-06 09:23:40 -08002 * Copyright 2014 The Chromium OS Authors. All rights reserved.
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07003 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
Mike Frysingerfbc52f32016-08-31 16:11:25 -04007#include <assert.h>
Dominik Behrda6df412016-08-02 12:56:42 -07008#include <errno.h>
Dominik Behr46c567f2016-03-08 15:11:48 -08009#include <fcntl.h>
Dominik Behr580462b2014-11-20 13:50:05 -080010#include <getopt.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070011#include <libtsm.h>
Dominik Behr580462b2014-11-20 13:50:05 -080012#include <memory.h>
13#include <stdbool.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070014#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
Dominik Behr46c567f2016-03-08 15:11:48 -080017#include <sys/stat.h>
18#include <sys/types.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070019
Dominik Behr580462b2014-11-20 13:50:05 -080020#include "dbus.h"
Dominik Behr44e07e62016-01-13 19:43:57 -080021#include "dbus_interface.h"
Dominik Behr5239cca2016-01-21 18:22:04 -080022#include "dev.h"
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070023#include "input.h"
Dominik Behr44e07e62016-01-13 19:43:57 -080024#include "main.h"
Dominik Behr580462b2014-11-20 13:50:05 -080025#include "splash.h"
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070026#include "term.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070027#include "util.h"
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070028
David Sodmanbbcb0522014-09-19 10:34:07 -070029#define FLAG_CLEAR 'c'
30#define FLAG_DAEMON 'd'
Dominik Behrd2530902016-05-05 14:01:06 -070031#define FLAG_ENABLE_GFX 'G'
Dominik Behr0bb51772016-07-26 18:04:53 -070032#define FLAG_ENABLE_VT1 '1'
Dominik Behr46c567f2016-03-08 15:11:48 -080033#define FLAG_ENABLE_VTS 'e'
David Sodmanbbcb0522014-09-19 10:34:07 -070034#define FLAG_FRAME_INTERVAL 'f'
35#define FLAG_GAMMA 'g'
Mike Frysingerfbc52f32016-08-31 16:11:25 -040036#define FLAG_HELP 'h'
Dominik Behr32a7c892015-10-09 15:47:53 -070037#define FLAG_IMAGE 'i'
38#define FLAG_IMAGE_HIRES 'I'
Dominik Behrfd9fdda2016-03-28 17:16:45 -070039#define FLAG_LOOP_COUNT 'C'
David Sodman8ef20062015-01-06 09:23:40 -080040#define FLAG_LOOP_START 'l'
41#define FLAG_LOOP_INTERVAL 'L'
42#define FLAG_LOOP_OFFSET 'o'
Dominik Behrda6df412016-08-02 12:56:42 -070043#define FLAG_NUM_VTS 'N'
Dominik Behr222936d2016-05-05 13:50:50 -070044#define FLAG_NO_LOGIN 'n'
David Sodman8ef20062015-01-06 09:23:40 -080045#define FLAG_OFFSET 'O'
Dominik Behrda6df412016-08-02 12:56:42 -070046#define FLAG_PRE_CREATE_VTS 'P'
David Sodmanbbcb0522014-09-19 10:34:07 -070047#define FLAG_PRINT_RESOLUTION 'p'
Dominik Behr92d9e312016-05-04 20:10:48 -070048#define FLAG_SCALE 'S'
Dominik Behrfd9fdda2016-03-28 17:16:45 -070049#define FLAG_SPLASH_ONLY 's'
David Sodmanbbcb0522014-09-19 10:34:07 -070050
Mike Frysingerfbc52f32016-08-31 16:11:25 -040051static const struct option command_options[] = {
David Sodmanbbcb0522014-09-19 10:34:07 -070052 { "clear", required_argument, NULL, FLAG_CLEAR },
53 { "daemon", no_argument, NULL, FLAG_DAEMON },
Dominik Behr46c567f2016-03-08 15:11:48 -080054 { "dev-mode", no_argument, NULL, FLAG_ENABLE_VTS },
Dominik Behrd2530902016-05-05 14:01:06 -070055 { "enable-gfx", no_argument, NULL, FLAG_ENABLE_GFX },
Dominik Behr0bb51772016-07-26 18:04:53 -070056 { "enable-vt1", no_argument, NULL, FLAG_ENABLE_VT1 },
Dominik Behr46c567f2016-03-08 15:11:48 -080057 { "enable-vts", no_argument, NULL, FLAG_ENABLE_VTS },
David Sodmanbbcb0522014-09-19 10:34:07 -070058 { "frame-interval", required_argument, NULL, FLAG_FRAME_INTERVAL },
59 { "gamma", required_argument, NULL, FLAG_GAMMA },
Mike Frysingerfbc52f32016-08-31 16:11:25 -040060 { "help", no_argument, NULL, FLAG_HELP },
Dominik Behr32a7c892015-10-09 15:47:53 -070061 { "image", required_argument, NULL, FLAG_IMAGE },
62 { "image-hires", required_argument, NULL, FLAG_IMAGE_HIRES },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070063 { "loop-count", required_argument, NULL, FLAG_LOOP_COUNT },
David Sodman8ef20062015-01-06 09:23:40 -080064 { "loop-start", required_argument, NULL, FLAG_LOOP_START },
65 { "loop-interval", required_argument, NULL, FLAG_LOOP_INTERVAL },
66 { "loop-offset", required_argument, NULL, FLAG_LOOP_OFFSET },
Dominik Behrda6df412016-08-02 12:56:42 -070067 { "num-vts", required_argument, NULL, FLAG_NUM_VTS },
Dominik Behr222936d2016-05-05 13:50:50 -070068 { "no-login", no_argument, NULL, FLAG_NO_LOGIN },
David Sodman8ef20062015-01-06 09:23:40 -080069 { "offset", required_argument, NULL, FLAG_OFFSET },
David Sodmanbbcb0522014-09-19 10:34:07 -070070 { "print-resolution", no_argument, NULL, FLAG_PRINT_RESOLUTION },
Dominik Behrda6df412016-08-02 12:56:42 -070071 { "pre-create-vts", no_argument, NULL, FLAG_PRE_CREATE_VTS },
Dominik Behr92d9e312016-05-04 20:10:48 -070072 { "scale", required_argument, NULL, FLAG_SCALE },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070073 { "splash-only", no_argument, NULL, FLAG_SPLASH_ONLY },
David Sodmanbbcb0522014-09-19 10:34:07 -070074 { NULL, 0, NULL, 0 }
75};
Mike Frysingerfbc52f32016-08-31 16:11:25 -040076static const char * const command_help[] = {
77 "Splash screen clear color.",
78 "Daemonize frecon.",
79 "Force dev mode behavior (same as --enable-vts).",
80 "Enable image and box drawing OSC escape codes.",
81 "Enable switching to VT1 and keep a terminal on it.",
82 "Enable additional terminals beyond VT1.",
83 "Default time (in msecs) between splash animation frames.",
84 "The gamma table to apply. (unimplemented)",
85 "This help screen!",
86 "Image (low res) to use for splash animation.",
87 "Image (hi res) to use for splash animation.",
88 "Number of times to loop splash animations (0 = forever).",
89 "First frame to start the splash animation loop (and enable looping).",
90 "Pause time (in msecs) between splash animation frames.",
91 "Offset (as x,y) for centering looped image.",
92 "Number of enabled VTs. The default is 4, the maximum is 12.",
93 "Do not display login prompt on additional VTs.",
94 "Absolute location of the splash image on screen (as x,y).",
95 "(Deprecated) Print detected screen resolution and exit.",
96 "Create all VTs immediately instead of on-demand.",
97 "Default scale for splash screen images.",
98 "Exit immediately after finishing splash animation.",
99};
100
101static void usage(int status)
102{
103 FILE *out = status ? stderr : stdout;
104
105 static_assert(ARRAY_SIZE(command_help) == ARRAY_SIZE(command_options) - 1,
106 "The help & option arrays need resyncing");
107
108 fprintf(out,
109 "Frecon: The Freon based console daemon.\n"
110 "\n"
111 "Usage: frecon [options] [splash images]\n"
112 "\n"
113 "Options:\n"
114 );
115
116 /* Output all the options & help text, and auto-align them. */
117 int len;
118 for (int i = 0; command_options[i].name; ++i) {
119 len = fprintf(out, " -%c, --%s ",
120 command_options[i].val, command_options[i].name);
121 if (command_options[i].has_arg == required_argument)
122 len += fprintf(out, "<arg> ");
123 fprintf(out, "%*s %s\n", (30 - len), "", command_help[i]);
124 }
125
126 fprintf(out, "\nFor more detailed documentation, visit:\n"
127 "https://chromium.googlesource.com/chromiumos/platform/frecon/+/master\n");
128
129 exit(status);
130}
David Sodmanbbcb0522014-09-19 10:34:07 -0700131
Dominik Behr46c567f2016-03-08 15:11:48 -0800132commandflags_t command_flags = { 0 };
Dominik Behr580462b2014-11-20 13:50:05 -0800133
Stéphane Marchesin8fc13522015-12-14 17:02:28 -0800134static void parse_offset(char* param, int32_t* x, int32_t* y)
David Sodman8ef20062015-01-06 09:23:40 -0800135{
136 char* token;
137 char* saveptr;
138
139 token = strtok_r(param, ",", &saveptr);
140 if (token)
141 *x = strtol(token, NULL, 0);
142
143 token = strtok_r(NULL, ",", &saveptr);
144 if (token)
145 *y = strtol(token, NULL, 0);
146}
David Sodmanbbcb0522014-09-19 10:34:07 -0700147
Dominik Behr44e07e62016-01-13 19:43:57 -0800148int main_process_events(uint32_t usec)
149{
150 terminal_t* terminal;
151 terminal_t* new_terminal;
152 fd_set read_set, exception_set;
Dominik Behrd7112672016-01-20 16:59:34 -0800153 int maxfd = -1;
Dominik Behr44e07e62016-01-13 19:43:57 -0800154 int sstat;
155 struct timeval tm;
156 struct timeval* ptm;
157
158 terminal = term_get_current_terminal();
159
160 FD_ZERO(&read_set);
161 FD_ZERO(&exception_set);
162
Dominik Behrd7112672016-01-20 16:59:34 -0800163 dbus_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behrd7112672016-01-20 16:59:34 -0800164 input_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr5239cca2016-01-21 18:22:04 -0800165 dev_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800166
Dominik Behrda6df412016-08-02 12:56:42 -0700167 for (unsigned i = 0; i < term_num_terminals; i++) {
168 terminal_t* current_term = term_get_terminal(i);
169 if (term_is_valid(current_term))
Dominik Behrd7112672016-01-20 16:59:34 -0800170 term_add_fds(current_term, &read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800171 }
172
173 if (usec) {
174 ptm = &tm;
175 tm.tv_sec = 0;
176 tm.tv_usec = usec;
177 } else
178 ptm = NULL;
179
Dominik Behrd7112672016-01-20 16:59:34 -0800180 sstat = select(maxfd + 1, &read_set, NULL, &exception_set, ptm);
Dominik Behr44e07e62016-01-13 19:43:57 -0800181 if (sstat == 0)
182 return 0;
183
184 dbus_dispatch_io();
185
186 if (term_exception(terminal, &exception_set))
187 return -1;
188
Dominik Behr5239cca2016-01-21 18:22:04 -0800189 dev_dispatch_io(&read_set, &exception_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800190 input_dispatch_io(&read_set, &exception_set);
191
Dominik Behrda6df412016-08-02 12:56:42 -0700192 for (unsigned i = 0; i < term_num_terminals; i++) {
193 terminal_t* current_term = term_get_terminal(i);
194 if (term_is_valid(current_term))
Dominik Behr44e07e62016-01-13 19:43:57 -0800195 term_dispatch_io(current_term, &read_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800196 }
197
Dominik Behrda6df412016-08-02 12:56:42 -0700198 /* Could have changed in input dispatch. */
199 terminal = term_get_current_terminal();
200
201 /* Restart terminal on which child has exited. We don't want possible garbage settings from previous session to remain. */
Dominik Behr44e07e62016-01-13 19:43:57 -0800202 if (term_is_valid(terminal)) {
203 if (term_is_child_done(terminal)) {
Dominik Behrda6df412016-08-02 12:56:42 -0700204 if (terminal == term_get_terminal(TERM_SPLASH_TERMINAL) && !command_flags.enable_vt1) {
205 /* Let the old term be, splash_destroy will clean it up. */
206 return 0;
Dominik Behr44e07e62016-01-13 19:43:57 -0800207 }
Dominik Behrda6df412016-08-02 12:56:42 -0700208 term_set_current_terminal(term_init(term_get_current(), -1));
Dominik Behr44e07e62016-01-13 19:43:57 -0800209 new_terminal = term_get_current_terminal();
210 if (!term_is_valid(new_terminal)) {
211 return -1;
212 }
213 term_activate(new_terminal);
214 term_close(terminal);
215 }
216 }
217
218 return 0;
219}
220
Dominik Behr46c567f2016-03-08 15:11:48 -0800221int main_loop(void)
Dominik Behr44e07e62016-01-13 19:43:57 -0800222{
Dominik Behr44e07e62016-01-13 19:43:57 -0800223 int status;
224
Dominik Behr44e07e62016-01-13 19:43:57 -0800225 while (1) {
226 status = main_process_events(0);
227 if (status != 0) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700228 LOG(ERROR, "Input process returned %d.", status);
Dominik Behr44e07e62016-01-13 19:43:57 -0800229 break;
230 }
231 }
232
233 return 0;
234}
235
Dominik Behr46c567f2016-03-08 15:11:48 -0800236bool set_drm_master_relax(void)
237{
238 int fd;
239 int num_written;
240
241 /*
242 * Setting drm_master_relax flag in kernel allows us to transfer DRM master
Dominik Behrb1abcba2016-04-14 14:57:21 -0700243 * between Chrome and frecon.
Dominik Behr46c567f2016-03-08 15:11:48 -0800244 */
245 fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
246 if (fd != -1) {
247 num_written = write(fd, "Y", 1);
248 close(fd);
249 if (num_written != 1) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700250 LOG(ERROR, "Unable to set drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800251 return false;
252 }
253 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700254 LOG(ERROR, "Unable to open drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800255 return false;
256 }
257 return true;
258}
259
260static void main_on_login_prompt_visible(void* ptr)
261{
262 if (command_flags.daemon && !command_flags.enable_vts) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700263 LOG(INFO, "Chrome started, our work is done, exiting.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800264 exit(EXIT_SUCCESS);
265 } else
266 if (ptr) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700267 LOG(INFO, "Chrome started, splash screen is not needed anymore.");
Dominik Behr0bb51772016-07-26 18:04:53 -0700268 if (command_flags.enable_vt1)
269 LOG(WARNING, "VT1 enabled and Chrome is active!");
Dominik Behrda6df412016-08-02 12:56:42 -0700270 splash_destroy((splash_t*)ptr);
271 }
272}
273
274static void legacy_print_resolution(int argc, char* argv[])
275{
276 int c;
277
278 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400279 opterr = 0;
Dominik Behrda6df412016-08-02 12:56:42 -0700280 for (;;) {
281 c = getopt_long(argc, argv, "", command_options, NULL);
282 if (c == -1) {
283 break;
284 } else if (c == FLAG_PRINT_RESOLUTION) {
285 drm_t *drm = drm_scan();
286 if (!drm)
287 exit(EXIT_FAILURE);
288
289 printf("%d %d", drm_gethres(drm),
290 drm_getvres(drm));
291 drm_delref(drm);
292 exit(EXIT_SUCCESS);
293 }
Dominik Behr46c567f2016-03-08 15:11:48 -0800294 }
295}
Dominik Behr44e07e62016-01-13 19:43:57 -0800296
David Sodmanbbcb0522014-09-19 10:34:07 -0700297int main(int argc, char* argv[])
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700298{
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700299 int ret;
David Sodmanbbcb0522014-09-19 10:34:07 -0700300 int c;
Dominik Behrda6df412016-08-02 12:56:42 -0700301 int pts_fd;
David Sodman8ef20062015-01-06 09:23:40 -0800302 int32_t x, y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800303 splash_t* splash;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700304 drm_t* drm;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700305
Dominik Behrda6df412016-08-02 12:56:42 -0700306 legacy_print_resolution(argc, argv);
307
Dominik Behr2b9f1232016-08-02 01:11:12 -0700308 fix_stdio();
Dominik Behrda6df412016-08-02 12:56:42 -0700309 pts_fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
Dominik Behr2b9f1232016-08-02 01:11:12 -0700310
Dominik Behrb1abcba2016-04-14 14:57:21 -0700311 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400312 opterr = 1;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700313 for (;;) {
314 c = getopt_long(argc, argv, "", command_options, NULL);
Dominik Behr0bb51772016-07-26 18:04:53 -0700315
316 if (c == -1)
Dominik Behrb1abcba2016-04-14 14:57:21 -0700317 break;
Dominik Behr0bb51772016-07-26 18:04:53 -0700318
319 switch (c) {
320 case FLAG_DAEMON:
321 command_flags.daemon = true;
322 break;
323
324 case FLAG_ENABLE_GFX:
325 command_flags.enable_gfx = true;
326 break;
327
328 case FLAG_ENABLE_VT1:
329 command_flags.enable_vt1 = true;
330 break;
331
332 case FLAG_ENABLE_VTS:
333 command_flags.enable_vts = true;;
334 break;
335
336 case FLAG_NO_LOGIN:
337 command_flags.no_login = true;
338 break;
339
Dominik Behrda6df412016-08-02 12:56:42 -0700340 case FLAG_NUM_VTS:
341 term_set_num_terminals(strtoul(optarg, NULL, 0));
342 break;
343
344 case FLAG_PRE_CREATE_VTS:
345 command_flags.pre_create_vts = true;
346 break;
347
Dominik Behr0bb51772016-07-26 18:04:53 -0700348 case FLAG_SPLASH_ONLY:
349 command_flags.splash_only = true;
350 break;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400351
352 case FLAG_HELP:
353 usage(0);
354 break;
355
356 case '?':
357 usage(1);
358 break;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700359 }
360 }
361
Dominik Behrb1abcba2016-04-14 14:57:21 -0700362 if (command_flags.daemon) {
Dominik Behrda6df412016-08-02 12:56:42 -0700363 int status;
Dominik Behrb23b05b2016-08-15 16:29:02 -0700364 unsigned vt;
Dominik Behrda6df412016-08-02 12:56:42 -0700365 fprintf(stdout, "%s\n", ptsname(pts_fd));
Dominik Behrb1abcba2016-04-14 14:57:21 -0700366 daemonize();
Dominik Behrda6df412016-08-02 12:56:42 -0700367 status = mkdir(FRECON_RUN_DIR, S_IRWXU);
368 if (status == 0 || (status < 0 && errno == EEXIST)) {
369 char pids[32];
370
371 sprintf(pids, "%u", getpid());
372 write_string_to_file(FRECON_PID_FILE, pids);
373 }
Dominik Behrb23b05b2016-08-15 16:29:02 -0700374
375 /* Remove all stale VT links. */
376 for (vt = 0; vt < TERM_MAX_TERMINALS; vt++) {
377 char path[32];
378 snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
379 unlink(path);
380 }
Dominik Behrb1abcba2016-04-14 14:57:21 -0700381 }
Douglas Anderson4da95cd2015-10-05 15:04:30 -0700382
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700383 ret = input_init();
384 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700385 LOG(ERROR, "Input init failed.");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700386 return EXIT_FAILURE;
387 }
388
Dominik Behr5239cca2016-01-21 18:22:04 -0800389 ret = dev_init();
390 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700391 LOG(ERROR, "Device management init failed.");
Dominik Behr5239cca2016-01-21 18:22:04 -0800392 return EXIT_FAILURE;
393 }
394
Dominik Behrb1abcba2016-04-14 14:57:21 -0700395 drm_set(drm = drm_scan());
Dominik Behrda6df412016-08-02 12:56:42 -0700396
397 splash = splash_init(pts_fd);
398 if (splash == NULL) {
399 LOG(ERROR, "Splash init failed.");
400 return EXIT_FAILURE;
401 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700402
Dominik Behr0bb51772016-07-26 18:04:53 -0700403 /* These flags can be only processed after splash object has been created. */
Dominik Behrb1abcba2016-04-14 14:57:21 -0700404 optind = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700405 for (;;) {
406 c = getopt_long(argc, argv, "", command_options, NULL);
407
408 if (c == -1)
409 break;
410
411 switch (c) {
412 case FLAG_CLEAR:
413 splash_set_clear(splash, strtoul(optarg, NULL, 0));
414 break;
415
David Sodman8ef20062015-01-06 09:23:40 -0800416 case FLAG_FRAME_INTERVAL:
417 splash_set_default_duration(splash, strtoul(optarg, NULL, 0));
418 break;
419
Dominik Behr32a7c892015-10-09 15:47:53 -0700420 case FLAG_IMAGE:
421 if (!splash_is_hires(splash))
422 splash_add_image(splash, optarg);
423 break;
424
425 case FLAG_IMAGE_HIRES:
426 if (splash_is_hires(splash))
427 splash_add_image(splash, optarg);
428 break;
429
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700430 case FLAG_LOOP_COUNT:
431 splash_set_loop_count(splash, strtoul(optarg, NULL, 0));
432 break;
433
David Sodman8ef20062015-01-06 09:23:40 -0800434 case FLAG_LOOP_START:
435 splash_set_loop_start(splash, strtoul(optarg, NULL, 0));
436 break;
437
438 case FLAG_LOOP_INTERVAL:
439 splash_set_loop_duration(splash, strtoul(optarg, NULL, 0));
440 break;
441
442 case FLAG_LOOP_OFFSET:
443 parse_offset(optarg, &x, &y);
444 splash_set_loop_offset(splash, x, y);
445 break;
446
447 case FLAG_OFFSET:
448 parse_offset(optarg, &x, &y);
449 splash_set_offset(splash, x, y);
450 break;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700451
Dominik Behr92d9e312016-05-04 20:10:48 -0700452 case FLAG_SCALE:
453 splash_set_scale(splash, strtoul(optarg, NULL, 0));
454 break;
David Sodmanbbcb0522014-09-19 10:34:07 -0700455 }
456 }
457
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800458 for (int i = optind; i < argc; i++)
David Sodman8ef20062015-01-06 09:23:40 -0800459 splash_add_image(splash, argv[i]);
460
David Sodmanf0a925a2015-05-04 11:19:19 -0700461 if (splash_num_images(splash) > 0) {
Dominik Behr797a3832016-01-11 15:53:11 -0800462 ret = splash_run(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -0700463 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700464 LOG(ERROR, "Splash_run failed: %d.", ret);
Yuly Novikov945871e2015-05-23 00:00:41 -0400465 return EXIT_FAILURE;
David Sodmanbbcb0522014-09-19 10:34:07 -0700466 }
467 }
468
Dominik Behr0bb51772016-07-26 18:04:53 -0700469 if (command_flags.splash_only) {
Dominik Behrda6df412016-08-02 12:56:42 -0700470 splash_destroy(splash);
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700471 goto main_done;
Dominik Behr0bb51772016-07-26 18:04:53 -0700472 }
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700473
David Sodmanbbcb0522014-09-19 10:34:07 -0700474 /*
Dominik Behr46c567f2016-03-08 15:11:48 -0800475 * The DBUS service launches later than the boot-splash service, and
476 * as a result, when splash_run starts DBUS is not yet up, but, by
477 * the time splash_run completes, it is running.
Dominik Behrb1abcba2016-04-14 14:57:21 -0700478 * We really need DBUS now, so we can interact with Chrome.
David Sodmanbbcb0522014-09-19 10:34:07 -0700479 */
Dominik Behr5f6742f2016-03-10 18:03:54 -0800480 dbus_init_wait();
David Sodman8ef20062015-01-06 09:23:40 -0800481
Dominik Behr46c567f2016-03-08 15:11:48 -0800482 /*
483 * Ask DBUS to call us back so we can destroy splash (or quit) when login
Dominik Behrb1abcba2016-04-14 14:57:21 -0700484 * prompt is visible.
Dominik Behr46c567f2016-03-08 15:11:48 -0800485 */
486 dbus_set_login_prompt_visible_callback(main_on_login_prompt_visible,
487 (void*)splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700488#if !DBUS
Dominik Behrda6df412016-08-02 12:56:42 -0700489 splash_destroy(splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700490#endif
Dominik Behr1883c042016-04-27 12:31:02 -0700491 /*
492 * Ask DBUS to notify us when suspend has finished so monitors can be reprobed
493 * in case they changed during suspend.
494 */
495 dbus_set_suspend_done_callback(term_suspend_done, NULL);
496
Dominik Behrda6df412016-08-02 12:56:42 -0700497 if (command_flags.pre_create_vts && command_flags.enable_vts) {
498 for (unsigned vt = command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1; vt < term_num_terminals; vt++) {
499 terminal_t *terminal = term_get_terminal(vt);
500 if (!terminal) {
501 terminal = term_init(vt, -1);
502 term_set_terminal(vt, terminal);
503 }
504 }
505 }
506
Dominik Behr46c567f2016-03-08 15:11:48 -0800507 if (command_flags.daemon) {
508 if (command_flags.enable_vts)
Dominik Behr83864df2016-04-21 12:35:08 -0700509 set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to actually release master. */
Dominik Behrda6df412016-08-02 12:56:42 -0700510 if (command_flags.enable_vt1)
511 term_switch_to(TERM_SPLASH_TERMINAL);
512 else
Dominik Behr0bb51772016-07-26 18:04:53 -0700513 term_background();
Dominik Behr46c567f2016-03-08 15:11:48 -0800514 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700515 /* Create and switch to first term in interactve mode. */
Dominik Behr83864df2016-04-21 12:35:08 -0700516 set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to actually release master. */
Dominik Behrda6df412016-08-02 12:56:42 -0700517 term_switch_to(command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1);
Dominik Behr46c567f2016-03-08 15:11:48 -0800518 }
519
520 ret = main_loop();
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700521
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700522main_done:
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700523 input_close();
Dominik Behr5239cca2016-01-21 18:22:04 -0800524 dev_close();
Dominik Behr44e07e62016-01-13 19:43:57 -0800525 dbus_destroy();
Dominik Behr83010f82016-03-18 18:43:08 -0700526 drm_close();
Dominik Behrda6df412016-08-02 12:56:42 -0700527 if (command_flags.daemon)
528 unlink(FRECON_PID_FILE);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700529
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700530 return ret;
531}