blob: 07c363be3a5f6c4c46ca0b02be792c5632a523d3 [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'
David Sodmanbbcb0522014-09-19 10:34:07 -070049
Mike Frysingerfbc52f32016-08-31 16:11:25 -040050static const struct option command_options[] = {
David Sodmanbbcb0522014-09-19 10:34:07 -070051 { "clear", required_argument, NULL, FLAG_CLEAR },
52 { "daemon", no_argument, NULL, FLAG_DAEMON },
Dominik Behr46c567f2016-03-08 15:11:48 -080053 { "dev-mode", no_argument, NULL, FLAG_ENABLE_VTS },
Dominik Behrd2530902016-05-05 14:01:06 -070054 { "enable-gfx", no_argument, NULL, FLAG_ENABLE_GFX },
Dominik Behr0bb51772016-07-26 18:04:53 -070055 { "enable-vt1", no_argument, NULL, FLAG_ENABLE_VT1 },
Dominik Behr46c567f2016-03-08 15:11:48 -080056 { "enable-vts", no_argument, NULL, FLAG_ENABLE_VTS },
David Sodmanbbcb0522014-09-19 10:34:07 -070057 { "frame-interval", required_argument, NULL, FLAG_FRAME_INTERVAL },
Mike Frysingerfbc52f32016-08-31 16:11:25 -040058 { "help", no_argument, NULL, FLAG_HELP },
Dominik Behr32a7c892015-10-09 15:47:53 -070059 { "image", required_argument, NULL, FLAG_IMAGE },
60 { "image-hires", required_argument, NULL, FLAG_IMAGE_HIRES },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070061 { "loop-count", required_argument, NULL, FLAG_LOOP_COUNT },
David Sodman8ef20062015-01-06 09:23:40 -080062 { "loop-start", required_argument, NULL, FLAG_LOOP_START },
63 { "loop-interval", required_argument, NULL, FLAG_LOOP_INTERVAL },
64 { "loop-offset", required_argument, NULL, FLAG_LOOP_OFFSET },
Dominik Behrda6df412016-08-02 12:56:42 -070065 { "num-vts", required_argument, NULL, FLAG_NUM_VTS },
Dominik Behr222936d2016-05-05 13:50:50 -070066 { "no-login", no_argument, NULL, FLAG_NO_LOGIN },
David Sodman8ef20062015-01-06 09:23:40 -080067 { "offset", required_argument, NULL, FLAG_OFFSET },
David Sodmanbbcb0522014-09-19 10:34:07 -070068 { "print-resolution", no_argument, NULL, FLAG_PRINT_RESOLUTION },
Dominik Behrda6df412016-08-02 12:56:42 -070069 { "pre-create-vts", no_argument, NULL, FLAG_PRE_CREATE_VTS },
Dominik Behr92d9e312016-05-04 20:10:48 -070070 { "scale", required_argument, NULL, FLAG_SCALE },
Dominik Behrfd9fdda2016-03-28 17:16:45 -070071 { "splash-only", no_argument, NULL, FLAG_SPLASH_ONLY },
David Sodmanbbcb0522014-09-19 10:34:07 -070072 { NULL, 0, NULL, 0 }
73};
Mike Frysingerfbc52f32016-08-31 16:11:25 -040074static const char * const command_help[] = {
75 "Splash screen clear color.",
76 "Daemonize frecon.",
77 "Force dev mode behavior (same as --enable-vts).",
78 "Enable image and box drawing OSC escape codes.",
79 "Enable switching to VT1 and keep a terminal on it.",
80 "Enable additional terminals beyond VT1.",
81 "Default time (in msecs) between splash animation frames.",
Mike Frysingerfbc52f32016-08-31 16:11:25 -040082 "This help screen!",
83 "Image (low res) to use for splash animation.",
84 "Image (hi res) to use for splash animation.",
85 "Number of times to loop splash animations (0 = forever).",
86 "First frame to start the splash animation loop (and enable looping).",
87 "Pause time (in msecs) between splash animation frames.",
88 "Offset (as x,y) for centering looped image.",
89 "Number of enabled VTs. The default is 4, the maximum is 12.",
90 "Do not display login prompt on additional VTs.",
91 "Absolute location of the splash image on screen (as x,y).",
92 "(Deprecated) Print detected screen resolution and exit.",
93 "Create all VTs immediately instead of on-demand.",
94 "Default scale for splash screen images.",
95 "Exit immediately after finishing splash animation.",
96};
97
98static void usage(int status)
99{
100 FILE *out = status ? stderr : stdout;
101
102 static_assert(ARRAY_SIZE(command_help) == ARRAY_SIZE(command_options) - 1,
103 "The help & option arrays need resyncing");
104
105 fprintf(out,
106 "Frecon: The Freon based console daemon.\n"
107 "\n"
108 "Usage: frecon [options] [splash images]\n"
109 "\n"
110 "Options:\n"
111 );
112
113 /* Output all the options & help text, and auto-align them. */
114 int len;
115 for (int i = 0; command_options[i].name; ++i) {
116 len = fprintf(out, " -%c, --%s ",
117 command_options[i].val, command_options[i].name);
118 if (command_options[i].has_arg == required_argument)
119 len += fprintf(out, "<arg> ");
120 fprintf(out, "%*s %s\n", (30 - len), "", command_help[i]);
121 }
122
123 fprintf(out, "\nFor more detailed documentation, visit:\n"
124 "https://chromium.googlesource.com/chromiumos/platform/frecon/+/master\n");
125
126 exit(status);
127}
David Sodmanbbcb0522014-09-19 10:34:07 -0700128
Dominik Behr46c567f2016-03-08 15:11:48 -0800129commandflags_t command_flags = { 0 };
Dominik Behr580462b2014-11-20 13:50:05 -0800130
Stéphane Marchesin8fc13522015-12-14 17:02:28 -0800131static void parse_offset(char* param, int32_t* x, int32_t* y)
David Sodman8ef20062015-01-06 09:23:40 -0800132{
133 char* token;
134 char* saveptr;
135
136 token = strtok_r(param, ",", &saveptr);
137 if (token)
138 *x = strtol(token, NULL, 0);
139
140 token = strtok_r(NULL, ",", &saveptr);
141 if (token)
142 *y = strtol(token, NULL, 0);
143}
David Sodmanbbcb0522014-09-19 10:34:07 -0700144
Dominik Behr44e07e62016-01-13 19:43:57 -0800145int main_process_events(uint32_t usec)
146{
147 terminal_t* terminal;
148 terminal_t* new_terminal;
149 fd_set read_set, exception_set;
Dominik Behrd7112672016-01-20 16:59:34 -0800150 int maxfd = -1;
Dominik Behr44e07e62016-01-13 19:43:57 -0800151 int sstat;
152 struct timeval tm;
153 struct timeval* ptm;
154
155 terminal = term_get_current_terminal();
156
157 FD_ZERO(&read_set);
158 FD_ZERO(&exception_set);
159
Dominik Behrd7112672016-01-20 16:59:34 -0800160 dbus_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behrd7112672016-01-20 16:59:34 -0800161 input_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr5239cca2016-01-21 18:22:04 -0800162 dev_add_fds(&read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800163
Dominik Behrda6df412016-08-02 12:56:42 -0700164 for (unsigned i = 0; i < term_num_terminals; i++) {
165 terminal_t* current_term = term_get_terminal(i);
166 if (term_is_valid(current_term))
Dominik Behrd7112672016-01-20 16:59:34 -0800167 term_add_fds(current_term, &read_set, &exception_set, &maxfd);
Dominik Behr44e07e62016-01-13 19:43:57 -0800168 }
169
170 if (usec) {
171 ptm = &tm;
172 tm.tv_sec = 0;
173 tm.tv_usec = usec;
174 } else
175 ptm = NULL;
176
Dominik Behrd7112672016-01-20 16:59:34 -0800177 sstat = select(maxfd + 1, &read_set, NULL, &exception_set, ptm);
Dominik Behr44e07e62016-01-13 19:43:57 -0800178 if (sstat == 0)
179 return 0;
180
181 dbus_dispatch_io();
182
183 if (term_exception(terminal, &exception_set))
184 return -1;
185
Dominik Behr5239cca2016-01-21 18:22:04 -0800186 dev_dispatch_io(&read_set, &exception_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800187 input_dispatch_io(&read_set, &exception_set);
188
Dominik Behrda6df412016-08-02 12:56:42 -0700189 for (unsigned i = 0; i < term_num_terminals; i++) {
190 terminal_t* current_term = term_get_terminal(i);
191 if (term_is_valid(current_term))
Dominik Behr44e07e62016-01-13 19:43:57 -0800192 term_dispatch_io(current_term, &read_set);
Dominik Behr44e07e62016-01-13 19:43:57 -0800193 }
194
Dominik Behrda6df412016-08-02 12:56:42 -0700195 /* Could have changed in input dispatch. */
196 terminal = term_get_current_terminal();
197
198 /* 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 -0800199 if (term_is_valid(terminal)) {
200 if (term_is_child_done(terminal)) {
Dominik Behrda6df412016-08-02 12:56:42 -0700201 if (terminal == term_get_terminal(TERM_SPLASH_TERMINAL) && !command_flags.enable_vt1) {
202 /* Let the old term be, splash_destroy will clean it up. */
203 return 0;
Dominik Behr44e07e62016-01-13 19:43:57 -0800204 }
Dominik Behrda6df412016-08-02 12:56:42 -0700205 term_set_current_terminal(term_init(term_get_current(), -1));
Dominik Behr44e07e62016-01-13 19:43:57 -0800206 new_terminal = term_get_current_terminal();
207 if (!term_is_valid(new_terminal)) {
208 return -1;
209 }
210 term_activate(new_terminal);
211 term_close(terminal);
212 }
213 }
214
215 return 0;
216}
217
Dominik Behr46c567f2016-03-08 15:11:48 -0800218int main_loop(void)
Dominik Behr44e07e62016-01-13 19:43:57 -0800219{
Dominik Behr44e07e62016-01-13 19:43:57 -0800220 int status;
221
Dominik Behr44e07e62016-01-13 19:43:57 -0800222 while (1) {
223 status = main_process_events(0);
224 if (status != 0) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700225 LOG(ERROR, "Input process returned %d.", status);
Dominik Behr44e07e62016-01-13 19:43:57 -0800226 break;
227 }
228 }
229
230 return 0;
231}
232
Dominik Behr46c567f2016-03-08 15:11:48 -0800233bool set_drm_master_relax(void)
234{
235 int fd;
236 int num_written;
237
238 /*
239 * Setting drm_master_relax flag in kernel allows us to transfer DRM master
Dominik Behrb1abcba2016-04-14 14:57:21 -0700240 * between Chrome and frecon.
Dominik Behr46c567f2016-03-08 15:11:48 -0800241 */
242 fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
243 if (fd != -1) {
244 num_written = write(fd, "Y", 1);
245 close(fd);
246 if (num_written != 1) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700247 LOG(ERROR, "Unable to set drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800248 return false;
249 }
250 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700251 LOG(ERROR, "Unable to open drm_master_relax.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800252 return false;
253 }
254 return true;
255}
256
257static void main_on_login_prompt_visible(void* ptr)
258{
259 if (command_flags.daemon && !command_flags.enable_vts) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700260 LOG(INFO, "Chrome started, our work is done, exiting.");
Dominik Behr46c567f2016-03-08 15:11:48 -0800261 exit(EXIT_SUCCESS);
262 } else
263 if (ptr) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700264 LOG(INFO, "Chrome started, splash screen is not needed anymore.");
Dominik Behr0bb51772016-07-26 18:04:53 -0700265 if (command_flags.enable_vt1)
266 LOG(WARNING, "VT1 enabled and Chrome is active!");
Dominik Behrda6df412016-08-02 12:56:42 -0700267 splash_destroy((splash_t*)ptr);
268 }
269}
270
271static void legacy_print_resolution(int argc, char* argv[])
272{
273 int c;
274
275 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400276 opterr = 0;
Dominik Behrda6df412016-08-02 12:56:42 -0700277 for (;;) {
278 c = getopt_long(argc, argv, "", command_options, NULL);
279 if (c == -1) {
280 break;
281 } else if (c == FLAG_PRINT_RESOLUTION) {
282 drm_t *drm = drm_scan();
283 if (!drm)
284 exit(EXIT_FAILURE);
285
286 printf("%d %d", drm_gethres(drm),
287 drm_getvres(drm));
288 drm_delref(drm);
289 exit(EXIT_SUCCESS);
290 }
Dominik Behr46c567f2016-03-08 15:11:48 -0800291 }
292}
Dominik Behr44e07e62016-01-13 19:43:57 -0800293
David Sodmanbbcb0522014-09-19 10:34:07 -0700294int main(int argc, char* argv[])
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700295{
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700296 int ret;
David Sodmanbbcb0522014-09-19 10:34:07 -0700297 int c;
Dominik Behrda6df412016-08-02 12:56:42 -0700298 int pts_fd;
David Sodman8ef20062015-01-06 09:23:40 -0800299 int32_t x, y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800300 splash_t* splash;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700301 drm_t* drm;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700302
Dominik Behrda6df412016-08-02 12:56:42 -0700303 legacy_print_resolution(argc, argv);
304
Dominik Behr2b9f1232016-08-02 01:11:12 -0700305 fix_stdio();
Dominik Behrda6df412016-08-02 12:56:42 -0700306 pts_fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
Dominik Behr2b9f1232016-08-02 01:11:12 -0700307
Dominik Behrb1abcba2016-04-14 14:57:21 -0700308 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400309 opterr = 1;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700310 for (;;) {
311 c = getopt_long(argc, argv, "", command_options, NULL);
Dominik Behr0bb51772016-07-26 18:04:53 -0700312
313 if (c == -1)
Dominik Behrb1abcba2016-04-14 14:57:21 -0700314 break;
Dominik Behr0bb51772016-07-26 18:04:53 -0700315
316 switch (c) {
317 case FLAG_DAEMON:
318 command_flags.daemon = true;
319 break;
320
321 case FLAG_ENABLE_GFX:
322 command_flags.enable_gfx = true;
323 break;
324
325 case FLAG_ENABLE_VT1:
326 command_flags.enable_vt1 = true;
327 break;
328
329 case FLAG_ENABLE_VTS:
330 command_flags.enable_vts = true;;
331 break;
332
333 case FLAG_NO_LOGIN:
334 command_flags.no_login = true;
335 break;
336
Dominik Behrda6df412016-08-02 12:56:42 -0700337 case FLAG_NUM_VTS:
338 term_set_num_terminals(strtoul(optarg, NULL, 0));
339 break;
340
341 case FLAG_PRE_CREATE_VTS:
342 command_flags.pre_create_vts = true;
343 break;
344
Dominik Behr0bb51772016-07-26 18:04:53 -0700345 case FLAG_SPLASH_ONLY:
346 command_flags.splash_only = true;
347 break;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400348
349 case FLAG_HELP:
350 usage(0);
351 break;
352
353 case '?':
354 usage(1);
355 break;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700356 }
357 }
358
Dominik Behrb1abcba2016-04-14 14:57:21 -0700359 if (command_flags.daemon) {
Dominik Behrda6df412016-08-02 12:56:42 -0700360 int status;
Dominik Behrb23b05b2016-08-15 16:29:02 -0700361 unsigned vt;
Dominik Behrda6df412016-08-02 12:56:42 -0700362 fprintf(stdout, "%s\n", ptsname(pts_fd));
Dominik Behrb1abcba2016-04-14 14:57:21 -0700363 daemonize();
Dominik Behrda6df412016-08-02 12:56:42 -0700364 status = mkdir(FRECON_RUN_DIR, S_IRWXU);
365 if (status == 0 || (status < 0 && errno == EEXIST)) {
366 char pids[32];
367
368 sprintf(pids, "%u", getpid());
369 write_string_to_file(FRECON_PID_FILE, pids);
370 }
Dominik Behrb23b05b2016-08-15 16:29:02 -0700371
372 /* Remove all stale VT links. */
373 for (vt = 0; vt < TERM_MAX_TERMINALS; vt++) {
374 char path[32];
375 snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
376 unlink(path);
377 }
Dominik Behrb1abcba2016-04-14 14:57:21 -0700378 }
Douglas Anderson4da95cd2015-10-05 15:04:30 -0700379
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700380 ret = input_init();
381 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700382 LOG(ERROR, "Input init failed.");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700383 return EXIT_FAILURE;
384 }
385
Dominik Behr5239cca2016-01-21 18:22:04 -0800386 ret = dev_init();
387 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700388 LOG(ERROR, "Device management init failed.");
Dominik Behr5239cca2016-01-21 18:22:04 -0800389 return EXIT_FAILURE;
390 }
391
Dominik Behrb1abcba2016-04-14 14:57:21 -0700392 drm_set(drm = drm_scan());
Dominik Behrda6df412016-08-02 12:56:42 -0700393
394 splash = splash_init(pts_fd);
395 if (splash == NULL) {
396 LOG(ERROR, "Splash init failed.");
397 return EXIT_FAILURE;
398 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700399
Dominik Behr0bb51772016-07-26 18:04:53 -0700400 /* These flags can be only processed after splash object has been created. */
Dominik Behrb1abcba2016-04-14 14:57:21 -0700401 optind = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700402 for (;;) {
403 c = getopt_long(argc, argv, "", command_options, NULL);
404
405 if (c == -1)
406 break;
407
408 switch (c) {
409 case FLAG_CLEAR:
410 splash_set_clear(splash, strtoul(optarg, NULL, 0));
411 break;
412
David Sodman8ef20062015-01-06 09:23:40 -0800413 case FLAG_FRAME_INTERVAL:
414 splash_set_default_duration(splash, strtoul(optarg, NULL, 0));
415 break;
416
Dominik Behr32a7c892015-10-09 15:47:53 -0700417 case FLAG_IMAGE:
418 if (!splash_is_hires(splash))
419 splash_add_image(splash, optarg);
420 break;
421
422 case FLAG_IMAGE_HIRES:
423 if (splash_is_hires(splash))
424 splash_add_image(splash, optarg);
425 break;
426
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700427 case FLAG_LOOP_COUNT:
428 splash_set_loop_count(splash, strtoul(optarg, NULL, 0));
429 break;
430
David Sodman8ef20062015-01-06 09:23:40 -0800431 case FLAG_LOOP_START:
432 splash_set_loop_start(splash, strtoul(optarg, NULL, 0));
433 break;
434
435 case FLAG_LOOP_INTERVAL:
436 splash_set_loop_duration(splash, strtoul(optarg, NULL, 0));
437 break;
438
439 case FLAG_LOOP_OFFSET:
440 parse_offset(optarg, &x, &y);
441 splash_set_loop_offset(splash, x, y);
442 break;
443
444 case FLAG_OFFSET:
445 parse_offset(optarg, &x, &y);
446 splash_set_offset(splash, x, y);
447 break;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700448
Dominik Behr92d9e312016-05-04 20:10:48 -0700449 case FLAG_SCALE:
450 splash_set_scale(splash, strtoul(optarg, NULL, 0));
451 break;
David Sodmanbbcb0522014-09-19 10:34:07 -0700452 }
453 }
454
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800455 for (int i = optind; i < argc; i++)
David Sodman8ef20062015-01-06 09:23:40 -0800456 splash_add_image(splash, argv[i]);
457
David Sodmanf0a925a2015-05-04 11:19:19 -0700458 if (splash_num_images(splash) > 0) {
Dominik Behr797a3832016-01-11 15:53:11 -0800459 ret = splash_run(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -0700460 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700461 LOG(ERROR, "Splash_run failed: %d.", ret);
Yuly Novikov945871e2015-05-23 00:00:41 -0400462 return EXIT_FAILURE;
David Sodmanbbcb0522014-09-19 10:34:07 -0700463 }
464 }
465
Dominik Behr0bb51772016-07-26 18:04:53 -0700466 if (command_flags.splash_only) {
Dominik Behrda6df412016-08-02 12:56:42 -0700467 splash_destroy(splash);
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700468 goto main_done;
Dominik Behr0bb51772016-07-26 18:04:53 -0700469 }
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700470
David Sodmanbbcb0522014-09-19 10:34:07 -0700471 /*
Dominik Behr46c567f2016-03-08 15:11:48 -0800472 * The DBUS service launches later than the boot-splash service, and
473 * as a result, when splash_run starts DBUS is not yet up, but, by
474 * the time splash_run completes, it is running.
Dominik Behrb1abcba2016-04-14 14:57:21 -0700475 * We really need DBUS now, so we can interact with Chrome.
David Sodmanbbcb0522014-09-19 10:34:07 -0700476 */
Dominik Behr5f6742f2016-03-10 18:03:54 -0800477 dbus_init_wait();
David Sodman8ef20062015-01-06 09:23:40 -0800478
Dominik Behr46c567f2016-03-08 15:11:48 -0800479 /*
480 * Ask DBUS to call us back so we can destroy splash (or quit) when login
Dominik Behrb1abcba2016-04-14 14:57:21 -0700481 * prompt is visible.
Dominik Behr46c567f2016-03-08 15:11:48 -0800482 */
483 dbus_set_login_prompt_visible_callback(main_on_login_prompt_visible,
484 (void*)splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700485#if !DBUS
Dominik Behrda6df412016-08-02 12:56:42 -0700486 splash_destroy(splash);
Dominik Behr0bb51772016-07-26 18:04:53 -0700487#endif
Dominik Behr1883c042016-04-27 12:31:02 -0700488 /*
489 * Ask DBUS to notify us when suspend has finished so monitors can be reprobed
490 * in case they changed during suspend.
491 */
492 dbus_set_suspend_done_callback(term_suspend_done, NULL);
493
Dominik Behrda6df412016-08-02 12:56:42 -0700494 if (command_flags.pre_create_vts && command_flags.enable_vts) {
495 for (unsigned vt = command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1; vt < term_num_terminals; vt++) {
496 terminal_t *terminal = term_get_terminal(vt);
497 if (!terminal) {
498 terminal = term_init(vt, -1);
499 term_set_terminal(vt, terminal);
500 }
501 }
502 }
503
Dominik Behr46c567f2016-03-08 15:11:48 -0800504 if (command_flags.daemon) {
505 if (command_flags.enable_vts)
Dominik Behr83864df2016-04-21 12:35:08 -0700506 set_drm_master_relax(); /* TODO(dbehr) Remove when Chrome is fixed to actually release master. */
Dominik Behrda6df412016-08-02 12:56:42 -0700507 if (command_flags.enable_vt1)
508 term_switch_to(TERM_SPLASH_TERMINAL);
509 else
Dominik Behr0bb51772016-07-26 18:04:53 -0700510 term_background();
Dominik Behr46c567f2016-03-08 15:11:48 -0800511 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700512 /* Create and switch to first term in interactve mode. */
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 term_switch_to(command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1);
Dominik Behr46c567f2016-03-08 15:11:48 -0800515 }
516
517 ret = main_loop();
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700518
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700519main_done:
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700520 input_close();
Dominik Behr5239cca2016-01-21 18:22:04 -0800521 dev_close();
Dominik Behr44e07e62016-01-13 19:43:57 -0800522 dbus_destroy();
Dominik Behr83010f82016-03-18 18:43:08 -0700523 drm_close();
Dominik Behrda6df412016-08-02 12:56:42 -0700524 if (command_flags.daemon)
525 unlink(FRECON_PID_FILE);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700526
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700527 return ret;
528}