blob: 8be17065ef136dcac768b0e9d2fcdc3becca9f50 [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'
Mike Frysingerfbc52f32016-08-31 16:11:25 -040035#define FLAG_HELP 'h'
Dominik Behr32a7c892015-10-09 15:47:53 -070036#define FLAG_IMAGE 'i'
37#define FLAG_IMAGE_HIRES 'I'
Dominik Behrfd9fdda2016-03-28 17:16:45 -070038#define FLAG_LOOP_COUNT 'C'
David Sodman8ef20062015-01-06 09:23:40 -080039#define FLAG_LOOP_START 'l'
40#define FLAG_LOOP_INTERVAL 'L'
41#define FLAG_LOOP_OFFSET 'o'
Dominik Behrda6df412016-08-02 12:56:42 -070042#define FLAG_NUM_VTS 'N'
Dominik Behr222936d2016-05-05 13:50:50 -070043#define FLAG_NO_LOGIN 'n'
David Sodman8ef20062015-01-06 09:23:40 -080044#define FLAG_OFFSET 'O'
Dominik Behrda6df412016-08-02 12:56:42 -070045#define FLAG_PRE_CREATE_VTS 'P'
David Sodmanbbcb0522014-09-19 10:34:07 -070046#define FLAG_PRINT_RESOLUTION 'p'
Dominik Behr92d9e312016-05-04 20:10:48 -070047#define FLAG_SCALE 'S'
Dominik Behrfd9fdda2016-03-28 17:16:45 -070048#define FLAG_SPLASH_ONLY 's'
Dominik Behr09f2b722016-10-05 12:02:04 -070049#define FLAG_WAIT_CHILD 'w'
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 },
Mike Frysingerfbc52f32016-08-31 16:11:25 -040059 { "help", no_argument, NULL, FLAG_HELP },
Dominik Behr32a7c892015-10-09 15:47:53 -070060 { "image", required_argument, NULL, FLAG_IMAGE },
61 { "image-hires", required_argument, NULL, FLAG_IMAGE_HIRES },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070062 { "loop-count", required_argument, NULL, FLAG_LOOP_COUNT },
David Sodman8ef20062015-01-06 09:23:40 -080063 { "loop-start", required_argument, NULL, FLAG_LOOP_START },
64 { "loop-interval", required_argument, NULL, FLAG_LOOP_INTERVAL },
65 { "loop-offset", required_argument, NULL, FLAG_LOOP_OFFSET },
Dominik Behrda6df412016-08-02 12:56:42 -070066 { "num-vts", required_argument, NULL, FLAG_NUM_VTS },
Dominik Behr222936d2016-05-05 13:50:50 -070067 { "no-login", no_argument, NULL, FLAG_NO_LOGIN },
David Sodman8ef20062015-01-06 09:23:40 -080068 { "offset", required_argument, NULL, FLAG_OFFSET },
David Sodmanbbcb0522014-09-19 10:34:07 -070069 { "print-resolution", no_argument, NULL, FLAG_PRINT_RESOLUTION },
Dominik Behrda6df412016-08-02 12:56:42 -070070 { "pre-create-vts", no_argument, NULL, FLAG_PRE_CREATE_VTS },
Dominik Behr92d9e312016-05-04 20:10:48 -070071 { "scale", required_argument, NULL, FLAG_SCALE },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070072 { "splash-only", no_argument, NULL, FLAG_SPLASH_ONLY },
David Sodmanbbcb0522014-09-19 10:34:07 -070073 { NULL, 0, NULL, 0 }
74};
Mike Frysingerfbc52f32016-08-31 16:11:25 -040075static const char * const command_help[] = {
76 "Splash screen clear color.",
77 "Daemonize frecon.",
78 "Force dev mode behavior (same as --enable-vts).",
79 "Enable image and box drawing OSC escape codes.",
80 "Enable switching to VT1 and keep a terminal on it.",
81 "Enable additional terminals beyond VT1.",
82 "Default time (in msecs) between splash animation frames.",
Mike Frysingerfbc52f32016-08-31 16:11:25 -040083 "This help screen!",
84 "Image (low res) to use for splash animation.",
85 "Image (hi res) to use for splash animation.",
86 "Number of times to loop splash animations (0 = forever).",
87 "First frame to start the splash animation loop (and enable looping).",
88 "Pause time (in msecs) between splash animation frames.",
89 "Offset (as x,y) for centering looped image.",
90 "Number of enabled VTs. The default is 4, the maximum is 12.",
91 "Do not display login prompt on additional VTs.",
92 "Absolute location of the splash image on screen (as x,y).",
93 "(Deprecated) Print detected screen resolution and exit.",
94 "Create all VTs immediately instead of on-demand.",
95 "Default scale for splash screen images.",
96 "Exit immediately after finishing splash animation.",
97};
98
99static void usage(int status)
100{
101 FILE *out = status ? stderr : stdout;
102
103 static_assert(ARRAY_SIZE(command_help) == ARRAY_SIZE(command_options) - 1,
104 "The help & option arrays need resyncing");
105
106 fprintf(out,
107 "Frecon: The Freon based console daemon.\n"
108 "\n"
109 "Usage: frecon [options] [splash images]\n"
110 "\n"
111 "Options:\n"
112 );
113
114 /* Output all the options & help text, and auto-align them. */
115 int len;
116 for (int i = 0; command_options[i].name; ++i) {
117 len = fprintf(out, " -%c, --%s ",
118 command_options[i].val, command_options[i].name);
119 if (command_options[i].has_arg == required_argument)
120 len += fprintf(out, "<arg> ");
121 fprintf(out, "%*s %s\n", (30 - len), "", command_help[i]);
122 }
123
124 fprintf(out, "\nFor more detailed documentation, visit:\n"
125 "https://chromium.googlesource.com/chromiumos/platform/frecon/+/master\n");
126
127 exit(status);
128}
David Sodmanbbcb0522014-09-19 10:34:07 -0700129
Dominik Behr46c567f2016-03-08 15:11:48 -0800130commandflags_t command_flags = { 0 };
Dominik Behr580462b2014-11-20 13:50:05 -0800131
Stéphane Marchesin8fc13522015-12-14 17:02:28 -0800132static void parse_offset(char* param, int32_t* x, int32_t* y)
David Sodman8ef20062015-01-06 09:23:40 -0800133{
134 char* token;
135 char* saveptr;
136
137 token = strtok_r(param, ",", &saveptr);
138 if (token)
139 *x = strtol(token, NULL, 0);
140
141 token = strtok_r(NULL, ",", &saveptr);
142 if (token)
143 *y = strtol(token, NULL, 0);
144}
David Sodmanbbcb0522014-09-19 10:34:07 -0700145
Dominik Behr44e07e62016-01-13 19:43:57 -0800146int main_process_events(uint32_t usec)
147{
148 terminal_t* terminal;
149 terminal_t* new_terminal;
150 fd_set read_set, exception_set;
Dominik Behrd7112672016-01-20 16:59:34 -0800151 int maxfd = -1;
Dominik Behr44e07e62016-01-13 19:43:57 -0800152 int sstat;
153 struct timeval tm;
154 struct timeval* ptm;
155
156 terminal = term_get_current_terminal();
157
158 FD_ZERO(&read_set);
159 FD_ZERO(&exception_set);
160
Dominik Behrd7112672016-01-20 16:59:34 -0800161 dbus_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behrd7112672016-01-20 16:59:34 -0800162 input_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr5239cca2016-01-21 18:22:04 -0800163 dev_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800164
Dominik Behrda6df412016-08-02 12:56:42 -0700165 for (unsigned i = 0; i < term_num_terminals; i++) {
166 terminal_t* current_term = term_get_terminal(i);
167 if (term_is_valid(current_term))
Dominik Behrd7112672016-01-20 16:59:34 -0800168 term_add_fds(current_term, &read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800169 }
170
171 if (usec) {
172 ptm = &tm;
173 tm.tv_sec = 0;
174 tm.tv_usec = usec;
175 } else
176 ptm = NULL;
177
Dominik Behrd7112672016-01-20 16:59:34 -0800178 sstat = select(maxfd + 1, &read_set, NULL, &exception_set, ptm);
Dominik Behr44e07e62016-01-13 19:43:57 -0800179 if (sstat == 0)
180 return 0;
181
182 dbus_dispatch_io();
183
184 if (term_exception(terminal, &exception_set))
185 return -1;
186
Dominik Behr5239cca2016-01-21 18:22:04 -0800187 dev_dispatch_io(&read_set, &exception_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800188 input_dispatch_io(&read_set, &exception_set);
189
Dominik Behrda6df412016-08-02 12:56:42 -0700190 for (unsigned i = 0; i < term_num_terminals; i++) {
191 terminal_t* current_term = term_get_terminal(i);
192 if (term_is_valid(current_term))
Dominik Behr44e07e62016-01-13 19:43:57 -0800193 term_dispatch_io(current_term, &read_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800194 }
195
Dominik Behrda6df412016-08-02 12:56:42 -0700196 /* Could have changed in input dispatch. */
197 terminal = term_get_current_terminal();
198
199 /* 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 -0800200 if (term_is_valid(terminal)) {
201 if (term_is_child_done(terminal)) {
Dominik Behrda6df412016-08-02 12:56:42 -0700202 if (terminal == term_get_terminal(TERM_SPLASH_TERMINAL) && !command_flags.enable_vt1) {
203 /* Let the old term be, splash_destroy will clean it up. */
204 return 0;
Dominik Behr44e07e62016-01-13 19:43:57 -0800205 }
Dominik Behrda6df412016-08-02 12:56:42 -0700206 term_set_current_terminal(term_init(term_get_current(), -1));
Dominik Behr44e07e62016-01-13 19:43:57 -0800207 new_terminal = term_get_current_terminal();
208 if (!term_is_valid(new_terminal)) {
209 return -1;
210 }
211 term_activate(new_terminal);
212 term_close(terminal);
213 }
214 }
215
216 return 0;
217}
218
Dominik Behr46c567f2016-03-08 15:11:48 -0800219int main_loop(void)
Dominik Behr44e07e62016-01-13 19:43:57 -0800220{
Dominik Behr44e07e62016-01-13 19:43:57 -0800221 int status;
222
Dominik Behr44e07e62016-01-13 19:43:57 -0800223 while (1) {
224 status = main_process_events(0);
225 if (status != 0) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700226 LOG(ERROR, "Input process returned %d.", status);
Dominik Behr44e07e62016-01-13 19:43:57 -0800227 break;
228 }
229 }
230
231 return 0;
232}
233
Dominik Behr46c567f2016-03-08 15:11:48 -0800234bool set_drm_master_relax(void)
235{
236 int fd;
237 int num_written;
238
239 /*
240 * Setting drm_master_relax flag in kernel allows us to transfer DRM master
Dominik Behrb1abcba2016-04-14 14:57:21 -0700241 * between Chrome and frecon.
Dominik Behr46c567f2016-03-08 15:11:48 -0800242 */
243 fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
244 if (fd != -1) {
245 num_written = write(fd, "Y", 1);
246 close(fd);
247 if (num_written != 1) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700248 LOG(ERROR, "Unable to set drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800249 return false;
250 }
251 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700252 LOG(ERROR, "Unable to open drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800253 return false;
254 }
255 return true;
256}
257
258static void main_on_login_prompt_visible(void* ptr)
259{
260 if (command_flags.daemon && !command_flags.enable_vts) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700261 LOG(INFO, "Chrome started, our work is done, exiting.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800262 exit(EXIT_SUCCESS);
263 } else
264 if (ptr) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700265 LOG(INFO, "Chrome started, splash screen is not needed anymore.");
Dominik Behr0bb51772016-07-26 18:04:53 -0700266 if (command_flags.enable_vt1)
267 LOG(WARNING, "VT1 enabled and Chrome is active!");
Dominik Behrda6df412016-08-02 12:56:42 -0700268 splash_destroy((splash_t*)ptr);
269 }
270}
271
272static void legacy_print_resolution(int argc, char* argv[])
273{
274 int c;
275
276 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400277 opterr = 0;
Dominik Behrda6df412016-08-02 12:56:42 -0700278 for (;;) {
279 c = getopt_long(argc, argv, "", command_options, NULL);
280 if (c == -1) {
281 break;
282 } else if (c == FLAG_PRINT_RESOLUTION) {
283 drm_t *drm = drm_scan();
284 if (!drm)
285 exit(EXIT_FAILURE);
286
287 printf("%d %d", drm_gethres(drm),
288 drm_getvres(drm));
289 drm_delref(drm);
290 exit(EXIT_SUCCESS);
291 }
Dominik Behr46c567f2016-03-08 15:11:48 -0800292 }
293}
Dominik Behr44e07e62016-01-13 19:43:57 -0800294
David Sodmanbbcb0522014-09-19 10:34:07 -0700295int main(int argc, char* argv[])
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700296{
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700297 int ret;
David Sodmanbbcb0522014-09-19 10:34:07 -0700298 int c;
Dominik Behrda6df412016-08-02 12:56:42 -0700299 int pts_fd;
Dominik Behr09f2b722016-10-05 12:02:04 -0700300 unsigned vt;
David Sodman8ef20062015-01-06 09:23:40 -0800301 int32_t x, y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800302 splash_t* splash;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700303 drm_t* drm;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700304
Dominik Behrda6df412016-08-02 12:56:42 -0700305 legacy_print_resolution(argc, argv);
306
Dominik Behr2b9f1232016-08-02 01:11:12 -0700307 fix_stdio();
Dominik Behrda6df412016-08-02 12:56:42 -0700308 pts_fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
Dominik Behr2b9f1232016-08-02 01:11:12 -0700309
Dominik Behrb1abcba2016-04-14 14:57:21 -0700310 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400311 opterr = 1;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700312 for (;;) {
313 c = getopt_long(argc, argv, "", command_options, NULL);
Dominik Behr0bb51772016-07-26 18:04:53 -0700314
315 if (c == -1)
Dominik Behrb1abcba2016-04-14 14:57:21 -0700316 break;
Dominik Behr0bb51772016-07-26 18:04:53 -0700317
318 switch (c) {
319 case FLAG_DAEMON:
320 command_flags.daemon = true;
321 break;
322
323 case FLAG_ENABLE_GFX:
324 command_flags.enable_gfx = true;
325 break;
326
327 case FLAG_ENABLE_VT1:
328 command_flags.enable_vt1 = true;
329 break;
330
331 case FLAG_ENABLE_VTS:
332 command_flags.enable_vts = true;;
333 break;
334
335 case FLAG_NO_LOGIN:
336 command_flags.no_login = true;
337 break;
338
Dominik Behrda6df412016-08-02 12:56:42 -0700339 case FLAG_NUM_VTS:
340 term_set_num_terminals(strtoul(optarg, NULL, 0));
341 break;
342
343 case FLAG_PRE_CREATE_VTS:
344 command_flags.pre_create_vts = true;
345 break;
346
Dominik Behr0bb51772016-07-26 18:04:53 -0700347 case FLAG_SPLASH_ONLY:
348 command_flags.splash_only = true;
349 break;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400350
351 case FLAG_HELP:
352 usage(0);
353 break;
354
355 case '?':
356 usage(1);
357 break;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700358 }
359 }
360
Dominik Behr09f2b722016-10-05 12:02:04 -0700361 /* Remove all stale VT links. */
362 for (vt = 0; vt < TERM_MAX_TERMINALS; vt++) {
363 char path[32];
364 snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
365 unlink(path);
366 }
367 /* And PID file. */
368 unlink(FRECON_PID_FILE);
369
Dominik Behrb1abcba2016-04-14 14:57:21 -0700370 if (command_flags.daemon) {
Dominik Behrda6df412016-08-02 12:56:42 -0700371 int status;
Dominik Behr09f2b722016-10-05 12:02:04 -0700372
Dominik Behrda6df412016-08-02 12:56:42 -0700373 fprintf(stdout, "%s\n", ptsname(pts_fd));
Dominik Behr09f2b722016-10-05 12:02:04 -0700374 daemonize(command_flags.pre_create_vts);
Dominik Behrda6df412016-08-02 12:56:42 -0700375 status = mkdir(FRECON_RUN_DIR, S_IRWXU);
376 if (status == 0 || (status < 0 && errno == EEXIST)) {
377 char pids[32];
378
379 sprintf(pids, "%u", getpid());
380 write_string_to_file(FRECON_PID_FILE, pids);
381 }
Dominik Behrb1abcba2016-04-14 14:57:21 -0700382 }
Douglas Anderson4da95cd2015-10-05 15:04:30 -0700383
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700384 ret = input_init();
385 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700386 LOG(ERROR, "Input init failed.");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700387 return EXIT_FAILURE;
388 }
389
Dominik Behr5239cca2016-01-21 18:22:04 -0800390 ret = dev_init();
391 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700392 LOG(ERROR, "Device management init failed.");
Dominik Behr5239cca2016-01-21 18:22:04 -0800393 return EXIT_FAILURE;
394 }
395
Dominik Behrb1abcba2016-04-14 14:57:21 -0700396 drm_set(drm = drm_scan());
Dominik Behrda6df412016-08-02 12:56:42 -0700397
398 splash = splash_init(pts_fd);
399 if (splash == NULL) {
400 LOG(ERROR, "Splash init failed.");
401 return EXIT_FAILURE;
402 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700403
Dominik Behr09f2b722016-10-05 12:02:04 -0700404 if (command_flags.pre_create_vts && command_flags.enable_vts) {
405 for (unsigned vt = command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1; vt < term_num_terminals; vt++) {
406 terminal_t *terminal = term_get_terminal(vt);
407 if (!terminal) {
408 terminal = term_init(vt, -1);
409 term_set_terminal(vt, terminal);
410 }
411 }
412 }
413
414 if (command_flags.daemon && command_flags.pre_create_vts)
415 daemon_exit_code(EXIT_SUCCESS);
416
Dominik Behr0bb51772016-07-26 18:04:53 -0700417 /* These flags can be only processed after splash object has been created. */
Dominik Behrb1abcba2016-04-14 14:57:21 -0700418 optind = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700419 for (;;) {
420 c = getopt_long(argc, argv, "", command_options, NULL);
421
422 if (c == -1)
423 break;
424
425 switch (c) {
426 case FLAG_CLEAR:
427 splash_set_clear(splash, strtoul(optarg, NULL, 0));
428 break;
429
David Sodman8ef20062015-01-06 09:23:40 -0800430 case FLAG_FRAME_INTERVAL:
431 splash_set_default_duration(splash, strtoul(optarg, NULL, 0));
432 break;
433
Dominik Behr32a7c892015-10-09 15:47:53 -0700434 case FLAG_IMAGE:
435 if (!splash_is_hires(splash))
436 splash_add_image(splash, optarg);
437 break;
438
439 case FLAG_IMAGE_HIRES:
440 if (splash_is_hires(splash))
441 splash_add_image(splash, optarg);
442 break;
443
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700444 case FLAG_LOOP_COUNT:
445 splash_set_loop_count(splash, strtoul(optarg, NULL, 0));
446 break;
447
David Sodman8ef20062015-01-06 09:23:40 -0800448 case FLAG_LOOP_START:
449 splash_set_loop_start(splash, strtoul(optarg, NULL, 0));
450 break;
451
452 case FLAG_LOOP_INTERVAL:
453 splash_set_loop_duration(splash, strtoul(optarg, NULL, 0));
454 break;
455
456 case FLAG_LOOP_OFFSET:
457 parse_offset(optarg, &x, &y);
458 splash_set_loop_offset(splash, x, y);
459 break;
460
461 case FLAG_OFFSET:
462 parse_offset(optarg, &x, &y);
463 splash_set_offset(splash, x, y);
464 break;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700465
Dominik Behr92d9e312016-05-04 20:10:48 -0700466 case FLAG_SCALE:
467 splash_set_scale(splash, strtoul(optarg, NULL, 0));
468 break;
David Sodmanbbcb0522014-09-19 10:34:07 -0700469 }
470 }
471
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800472 for (int i = optind; i < argc; i++)
David Sodman8ef20062015-01-06 09:23:40 -0800473 splash_add_image(splash, argv[i]);
474
David Sodmanf0a925a2015-05-04 11:19:19 -0700475 if (splash_num_images(splash) > 0) {
Dominik Behr797a3832016-01-11 15:53:11 -0800476 ret = splash_run(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -0700477 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700478 LOG(ERROR, "Splash_run failed: %d.", ret);
Yuly Novikov945871e2015-05-23 00:00:41 -0400479 return EXIT_FAILURE;
David Sodmanbbcb0522014-09-19 10:34:07 -0700480 }
481 }
482
Dominik Behr0bb51772016-07-26 18:04:53 -0700483 if (command_flags.splash_only) {
Dominik Behrda6df412016-08-02 12:56:42 -0700484 splash_destroy(splash);
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700485 goto main_done;
Dominik Behr0bb51772016-07-26 18:04:53 -0700486 }
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700487
David Sodmanbbcb0522014-09-19 10:34:07 -0700488 /*
Dominik Behr46c567f2016-03-08 15:11:48 -0800489 * The DBUS service launches later than the boot-splash service, and
490 * as a result, when splash_run starts DBUS is not yet up, but, by
491 * the time splash_run completes, it is running.
Dominik Behrb1abcba2016-04-14 14:57:21 -0700492 * We really need DBUS now, so we can interact with Chrome.
David Sodmanbbcb0522014-09-19 10:34:07 -0700493 */
Dominik Behr5f6742f2016-03-10 18:03:54 -0800494 dbus_init_wait();
David Sodman8ef20062015-01-06 09:23:40 -0800495
Dominik Behr46c567f2016-03-08 15:11:48 -0800496 /*
497 * Ask DBUS to call us back so we can destroy splash (or quit) when login
Dominik Behrb1abcba2016-04-14 14:57:21 -0700498 * prompt is visible.
Dominik Behr46c567f2016-03-08 15:11:48 -0800499 */
500 dbus_set_login_prompt_visible_callback(main_on_login_prompt_visible,
501 (void*)splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700502#if !DBUS
Dominik Behrda6df412016-08-02 12:56:42 -0700503 splash_destroy(splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700504#endif
Dominik Behr1883c042016-04-27 12:31:02 -0700505 /*
506 * Ask DBUS to notify us when suspend has finished so monitors can be reprobed
507 * in case they changed during suspend.
508 */
509 dbus_set_suspend_done_callback(term_suspend_done, NULL);
510
Dominik Behr46c567f2016-03-08 15:11:48 -0800511 if (command_flags.daemon) {
512 if (command_flags.enable_vts)
Dominik Behr83864df2016-04-21 12:35:08 -0700513 set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to actually release master. */
Dominik Behrda6df412016-08-02 12:56:42 -0700514 if (command_flags.enable_vt1)
515 term_switch_to(TERM_SPLASH_TERMINAL);
516 else
Dominik Behr0bb51772016-07-26 18:04:53 -0700517 term_background();
Dominik Behr46c567f2016-03-08 15:11:48 -0800518 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700519 /* Create and switch to first term in interactve mode. */
Dominik Behr83864df2016-04-21 12:35:08 -0700520 set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to actually release master. */
Dominik Behrda6df412016-08-02 12:56:42 -0700521 term_switch_to(command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1);
Dominik Behr46c567f2016-03-08 15:11:48 -0800522 }
523
524 ret = main_loop();
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700525
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700526main_done:
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700527 input_close();
Dominik Behr5239cca2016-01-21 18:22:04 -0800528 dev_close();
Dominik Behr44e07e62016-01-13 19:43:57 -0800529 dbus_destroy();
Dominik Behr83010f82016-03-18 18:43:08 -0700530 drm_close();
Dominik Behrda6df412016-08-02 12:56:42 -0700531 if (command_flags.daemon)
532 unlink(FRECON_PID_FILE);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700533
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700534 return ret;
535}