blob: 98419a147f2df9ab5fc1017ce3c1ee7392d24350 [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
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800258static void main_on_login_prompt_visible(void)
Dominik Behr46c567f2016-03-08 15:11:48 -0800259{
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);
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800263 } else {
Dominik Behr0bb51772016-07-26 18:04:53 -0700264 if (command_flags.enable_vt1)
265 LOG(WARNING, "VT1 enabled and Chrome is active!");
Dominik Behrda6df412016-08-02 12:56:42 -0700266 }
267}
268
269static void legacy_print_resolution(int argc, char* argv[])
270{
271 int c;
272
273 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400274 opterr = 0;
Dominik Behrda6df412016-08-02 12:56:42 -0700275 for (;;) {
276 c = getopt_long(argc, argv, "", command_options, NULL);
277 if (c == -1) {
278 break;
279 } else if (c == FLAG_PRINT_RESOLUTION) {
280 drm_t *drm = drm_scan();
281 if (!drm)
282 exit(EXIT_FAILURE);
283
284 printf("%d %d", drm_gethres(drm),
285 drm_getvres(drm));
286 drm_delref(drm);
287 exit(EXIT_SUCCESS);
288 }
Dominik Behr46c567f2016-03-08 15:11:48 -0800289 }
290}
Dominik Behr44e07e62016-01-13 19:43:57 -0800291
David Sodmanbbcb0522014-09-19 10:34:07 -0700292int main(int argc, char* argv[])
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700293{
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700294 int ret;
David Sodmanbbcb0522014-09-19 10:34:07 -0700295 int c;
Dominik Behrda6df412016-08-02 12:56:42 -0700296 int pts_fd;
Dominik Behr09f2b722016-10-05 12:02:04 -0700297 unsigned vt;
David Sodman8ef20062015-01-06 09:23:40 -0800298 int32_t x, y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800299 splash_t* splash;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700300 drm_t* drm;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700301
Dominik Behrda6df412016-08-02 12:56:42 -0700302 legacy_print_resolution(argc, argv);
303
Dominik Behr2b9f1232016-08-02 01:11:12 -0700304 fix_stdio();
Dominik Behrda6df412016-08-02 12:56:42 -0700305 pts_fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
Dominik Behr2b9f1232016-08-02 01:11:12 -0700306
Dominik Behrb1abcba2016-04-14 14:57:21 -0700307 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400308 opterr = 1;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700309 for (;;) {
310 c = getopt_long(argc, argv, "", command_options, NULL);
Dominik Behr0bb51772016-07-26 18:04:53 -0700311
312 if (c == -1)
Dominik Behrb1abcba2016-04-14 14:57:21 -0700313 break;
Dominik Behr0bb51772016-07-26 18:04:53 -0700314
315 switch (c) {
316 case FLAG_DAEMON:
317 command_flags.daemon = true;
318 break;
319
320 case FLAG_ENABLE_GFX:
321 command_flags.enable_gfx = true;
322 break;
323
324 case FLAG_ENABLE_VT1:
325 command_flags.enable_vt1 = true;
326 break;
327
328 case FLAG_ENABLE_VTS:
329 command_flags.enable_vts = true;;
330 break;
331
332 case FLAG_NO_LOGIN:
333 command_flags.no_login = true;
334 break;
335
Dominik Behrda6df412016-08-02 12:56:42 -0700336 case FLAG_NUM_VTS:
337 term_set_num_terminals(strtoul(optarg, NULL, 0));
338 break;
339
340 case FLAG_PRE_CREATE_VTS:
341 command_flags.pre_create_vts = true;
342 break;
343
Dominik Behr0bb51772016-07-26 18:04:53 -0700344 case FLAG_SPLASH_ONLY:
345 command_flags.splash_only = true;
346 break;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400347
348 case FLAG_HELP:
349 usage(0);
350 break;
351
352 case '?':
353 usage(1);
354 break;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700355 }
356 }
357
Dominik Behr09f2b722016-10-05 12:02:04 -0700358 /* Remove all stale VT links. */
359 for (vt = 0; vt < TERM_MAX_TERMINALS; vt++) {
360 char path[32];
361 snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
362 unlink(path);
363 }
364 /* And PID file. */
365 unlink(FRECON_PID_FILE);
366
Dominik Behrb1abcba2016-04-14 14:57:21 -0700367 if (command_flags.daemon) {
Dominik Behrda6df412016-08-02 12:56:42 -0700368 int status;
Dominik Behr09f2b722016-10-05 12:02:04 -0700369
Dominik Behrda6df412016-08-02 12:56:42 -0700370 fprintf(stdout, "%s\n", ptsname(pts_fd));
Dominik Behr09f2b722016-10-05 12:02:04 -0700371 daemonize(command_flags.pre_create_vts);
Dominik Behrda6df412016-08-02 12:56:42 -0700372 status = mkdir(FRECON_RUN_DIR, S_IRWXU);
373 if (status == 0 || (status < 0 && errno == EEXIST)) {
374 char pids[32];
375
376 sprintf(pids, "%u", getpid());
377 write_string_to_file(FRECON_PID_FILE, pids);
378 }
Dominik Behrb1abcba2016-04-14 14:57:21 -0700379 }
Douglas Anderson4da95cd2015-10-05 15:04:30 -0700380
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700381 ret = input_init();
382 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700383 LOG(ERROR, "Input init failed.");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700384 return EXIT_FAILURE;
385 }
386
Dominik Behr5239cca2016-01-21 18:22:04 -0800387 ret = dev_init();
388 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700389 LOG(ERROR, "Device management init failed.");
Dominik Behr5239cca2016-01-21 18:22:04 -0800390 return EXIT_FAILURE;
391 }
392
Dominik Behrb1abcba2016-04-14 14:57:21 -0700393 drm_set(drm = drm_scan());
Dominik Behrda6df412016-08-02 12:56:42 -0700394
395 splash = splash_init(pts_fd);
396 if (splash == NULL) {
397 LOG(ERROR, "Splash init failed.");
398 return EXIT_FAILURE;
399 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700400
Dominik Behr06c5b932016-10-24 16:12:48 -0700401 if (command_flags.pre_create_vts) {
402 for (unsigned vt = command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1;
403 vt < (command_flags.enable_vts ? term_num_terminals : 1); vt++) {
Dominik Behr09f2b722016-10-05 12:02:04 -0700404 terminal_t *terminal = term_get_terminal(vt);
405 if (!terminal) {
406 terminal = term_init(vt, -1);
407 term_set_terminal(vt, terminal);
408 }
409 }
410 }
411
412 if (command_flags.daemon && command_flags.pre_create_vts)
413 daemon_exit_code(EXIT_SUCCESS);
414
Dominik Behr0bb51772016-07-26 18:04:53 -0700415 /* These flags can be only processed after splash object has been created. */
Dominik Behrb1abcba2016-04-14 14:57:21 -0700416 optind = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700417 for (;;) {
418 c = getopt_long(argc, argv, "", command_options, NULL);
419
420 if (c == -1)
421 break;
422
423 switch (c) {
424 case FLAG_CLEAR:
425 splash_set_clear(splash, strtoul(optarg, NULL, 0));
426 break;
427
David Sodman8ef20062015-01-06 09:23:40 -0800428 case FLAG_FRAME_INTERVAL:
429 splash_set_default_duration(splash, strtoul(optarg, NULL, 0));
430 break;
431
Dominik Behr32a7c892015-10-09 15:47:53 -0700432 case FLAG_IMAGE:
433 if (!splash_is_hires(splash))
434 splash_add_image(splash, optarg);
435 break;
436
437 case FLAG_IMAGE_HIRES:
438 if (splash_is_hires(splash))
439 splash_add_image(splash, optarg);
440 break;
441
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700442 case FLAG_LOOP_COUNT:
443 splash_set_loop_count(splash, strtoul(optarg, NULL, 0));
444 break;
445
David Sodman8ef20062015-01-06 09:23:40 -0800446 case FLAG_LOOP_START:
447 splash_set_loop_start(splash, strtoul(optarg, NULL, 0));
448 break;
449
450 case FLAG_LOOP_INTERVAL:
451 splash_set_loop_duration(splash, strtoul(optarg, NULL, 0));
452 break;
453
454 case FLAG_LOOP_OFFSET:
455 parse_offset(optarg, &x, &y);
456 splash_set_loop_offset(splash, x, y);
457 break;
458
459 case FLAG_OFFSET:
460 parse_offset(optarg, &x, &y);
461 splash_set_offset(splash, x, y);
462 break;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700463
Dominik Behr92d9e312016-05-04 20:10:48 -0700464 case FLAG_SCALE:
465 splash_set_scale(splash, strtoul(optarg, NULL, 0));
466 break;
David Sodmanbbcb0522014-09-19 10:34:07 -0700467 }
468 }
469
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800470 for (int i = optind; i < argc; i++)
David Sodman8ef20062015-01-06 09:23:40 -0800471 splash_add_image(splash, argv[i]);
472
David Sodmanf0a925a2015-05-04 11:19:19 -0700473 if (splash_num_images(splash) > 0) {
Dominik Behr797a3832016-01-11 15:53:11 -0800474 ret = splash_run(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -0700475 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700476 LOG(ERROR, "Splash_run failed: %d.", ret);
Yuly Novikov945871e2015-05-23 00:00:41 -0400477 return EXIT_FAILURE;
David Sodmanbbcb0522014-09-19 10:34:07 -0700478 }
479 }
480
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800481 splash_destroy(splash);
482
483 if (command_flags.splash_only)
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700484 goto main_done;
485
David Sodmanbbcb0522014-09-19 10:34:07 -0700486 /*
Dominik Behr46c567f2016-03-08 15:11:48 -0800487 * The DBUS service launches later than the boot-splash service, and
488 * as a result, when splash_run starts DBUS is not yet up, but, by
489 * the time splash_run completes, it is running.
Dominik Behrb1abcba2016-04-14 14:57:21 -0700490 * We really need DBUS now, so we can interact with Chrome.
David Sodmanbbcb0522014-09-19 10:34:07 -0700491 */
Dominik Behr5f6742f2016-03-10 18:03:54 -0800492 dbus_init_wait();
Dominik Behr46c567f2016-03-08 15:11:48 -0800493 /*
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800494 * Ask DBUS to call us back so we can quit when login prompt is visible.
Dominik Behr46c567f2016-03-08 15:11:48 -0800495 */
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800496 dbus_set_login_prompt_visible_callback(main_on_login_prompt_visible);
Dominik Behr1883c042016-04-27 12:31:02 -0700497 /*
498 * Ask DBUS to notify us when suspend has finished so monitors can be reprobed
499 * in case they changed during suspend.
500 */
501 dbus_set_suspend_done_callback(term_suspend_done, NULL);
502
Dominik Behr46c567f2016-03-08 15:11:48 -0800503 if (command_flags.daemon) {
504 if (command_flags.enable_vts)
Dominik Behra818a1e2016-10-26 19:46:22 -0700505 set_drm_master_relax();
Dominik Behrda6df412016-08-02 12:56:42 -0700506 if (command_flags.enable_vt1)
507 term_switch_to(TERM_SPLASH_TERMINAL);
508 else
Dominik Behr33847332016-12-12 17:27:56 -0800509 term_background(true);
Dominik Behr46c567f2016-03-08 15:11:48 -0800510 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700511 /* Create and switch to first term in interactve mode. */
Dominik Behra818a1e2016-10-26 19:46:22 -0700512 set_drm_master_relax();
Dominik Behrda6df412016-08-02 12:56:42 -0700513 term_switch_to(command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1);
Dominik Behr46c567f2016-03-08 15:11:48 -0800514 }
515
516 ret = main_loop();
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700517
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700518main_done:
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700519 input_close();
Dominik Behr5239cca2016-01-21 18:22:04 -0800520 dev_close();
Dominik Behr44e07e62016-01-13 19:43:57 -0800521 dbus_destroy();
Dominik Behr83010f82016-03-18 18:43:08 -0700522 drm_close();
Dominik Behrda6df412016-08-02 12:56:42 -0700523 if (command_flags.daemon)
524 unlink(FRECON_PID_FILE);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700525
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700526 return ret;
527}