blob: bd925b9c4238c427d02d60827f02b6b3f5795d4d [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 Behrda55e6c2017-02-28 18:12:10 -080031#define FLAG_ENABLE_OSC '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 Behrda55e6c2017-02-28 18:12:10 -080055 { "enable-gfx", no_argument, NULL, FLAG_ENABLE_OSC },
56 { "enable-osc", no_argument, NULL, FLAG_ENABLE_OSC },
Dominik Behr0bb51772016-07-26 18:04:53 -070057 { "enable-vt1", no_argument, NULL, FLAG_ENABLE_VT1 },
Dominik Behr46c567f2016-03-08 15:11:48 -080058 { "enable-vts", no_argument, NULL, FLAG_ENABLE_VTS },
David Sodmanbbcb0522014-09-19 10:34:07 -070059 { "frame-interval", required_argument, NULL, FLAG_FRAME_INTERVAL },
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.",
Dominik Behrda55e6c2017-02-28 18:12:10 -080079 "Force dev mode behavior (deprecated, use --enable-vts).",
80 "Enable image and box drawing OSC escape codes (deprecated, use --enable-osc).",
81 "Enable OSC escape codes for graphics and input control.",
Mike Frysingerfbc52f32016-08-31 16:11:25 -040082 "Enable switching to VT1 and keep a terminal on it.",
83 "Enable additional terminals beyond VT1.",
84 "Default time (in msecs) between splash animation frames.",
Mike Frysingerfbc52f32016-08-31 16:11:25 -040085 "This help screen!",
86 "Image (low res) to use for splash animation.",
87 "Image (hi res) to use for splash animation.",
Pat Erley199d0442017-09-29 11:35:54 -070088 "Number of times to loop splash animations (unset = forever).",
Mike Frysingerfbc52f32016-08-31 16:11:25 -040089 "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
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800260static void main_on_login_prompt_visible(void)
Dominik Behr46c567f2016-03-08 15:11:48 -0800261{
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);
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800265 } else {
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 }
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;
Dominik Behr09f2b722016-10-05 12:02:04 -0700299 unsigned vt;
David Sodman8ef20062015-01-06 09:23:40 -0800300 int32_t x, y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800301 splash_t* splash;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700302 drm_t* drm;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700303
Dominik Behrda6df412016-08-02 12:56:42 -0700304 legacy_print_resolution(argc, argv);
305
Dominik Behr2b9f1232016-08-02 01:11:12 -0700306 fix_stdio();
Dominik Behrda6df412016-08-02 12:56:42 -0700307 pts_fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
Dominik Behr2b9f1232016-08-02 01:11:12 -0700308
Dominik Behrb1abcba2016-04-14 14:57:21 -0700309 optind = 1;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400310 opterr = 1;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700311 for (;;) {
312 c = getopt_long(argc, argv, "", command_options, NULL);
Dominik Behr0bb51772016-07-26 18:04:53 -0700313
314 if (c == -1)
Dominik Behrb1abcba2016-04-14 14:57:21 -0700315 break;
Dominik Behr0bb51772016-07-26 18:04:53 -0700316
317 switch (c) {
318 case FLAG_DAEMON:
319 command_flags.daemon = true;
320 break;
321
Dominik Behrda55e6c2017-02-28 18:12:10 -0800322 case FLAG_ENABLE_OSC:
323 command_flags.enable_osc = true;
Dominik Behr0bb51772016-07-26 18:04:53 -0700324 break;
325
326 case FLAG_ENABLE_VT1:
327 command_flags.enable_vt1 = true;
328 break;
329
330 case FLAG_ENABLE_VTS:
331 command_flags.enable_vts = true;;
332 break;
333
334 case FLAG_NO_LOGIN:
335 command_flags.no_login = true;
336 break;
337
Dominik Behrda6df412016-08-02 12:56:42 -0700338 case FLAG_NUM_VTS:
339 term_set_num_terminals(strtoul(optarg, NULL, 0));
340 break;
341
342 case FLAG_PRE_CREATE_VTS:
343 command_flags.pre_create_vts = true;
344 break;
345
Dominik Behr0bb51772016-07-26 18:04:53 -0700346 case FLAG_SPLASH_ONLY:
347 command_flags.splash_only = true;
348 break;
Mike Frysingerfbc52f32016-08-31 16:11:25 -0400349
350 case FLAG_HELP:
351 usage(0);
352 break;
353
354 case '?':
355 usage(1);
356 break;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700357 }
358 }
359
Dominik Behr09f2b722016-10-05 12:02:04 -0700360 /* Remove all stale VT links. */
361 for (vt = 0; vt < TERM_MAX_TERMINALS; vt++) {
362 char path[32];
363 snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
364 unlink(path);
365 }
366 /* And PID file. */
367 unlink(FRECON_PID_FILE);
368
Dominik Behrb1abcba2016-04-14 14:57:21 -0700369 if (command_flags.daemon) {
Dominik Behrda6df412016-08-02 12:56:42 -0700370 int status;
Dominik Behr09f2b722016-10-05 12:02:04 -0700371
Dominik Behr09f2b722016-10-05 12:02:04 -0700372 daemonize(command_flags.pre_create_vts);
Dominik Behrda6df412016-08-02 12:56:42 -0700373 status = mkdir(FRECON_RUN_DIR, S_IRWXU);
374 if (status == 0 || (status < 0 && errno == EEXIST)) {
375 char pids[32];
376
377 sprintf(pids, "%u", getpid());
378 write_string_to_file(FRECON_PID_FILE, pids);
379 }
Dominik Behrb1abcba2016-04-14 14:57:21 -0700380 }
Douglas Anderson4da95cd2015-10-05 15:04:30 -0700381
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700382 ret = input_init();
383 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700384 LOG(ERROR, "Input init failed.");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700385 return EXIT_FAILURE;
386 }
387
Dominik Behr5239cca2016-01-21 18:22:04 -0800388 ret = dev_init();
389 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700390 LOG(ERROR, "Device management init failed.");
Dominik Behr5239cca2016-01-21 18:22:04 -0800391 return EXIT_FAILURE;
392 }
393
Dominik Behrb1abcba2016-04-14 14:57:21 -0700394 drm_set(drm = drm_scan());
Dominik Behrda6df412016-08-02 12:56:42 -0700395
396 splash = splash_init(pts_fd);
397 if (splash == NULL) {
398 LOG(ERROR, "Splash init failed.");
399 return EXIT_FAILURE;
400 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700401
Dominik Behr06c5b932016-10-24 16:12:48 -0700402 if (command_flags.pre_create_vts) {
403 for (unsigned vt = command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1;
404 vt < (command_flags.enable_vts ? term_num_terminals : 1); vt++) {
Dominik Behr09f2b722016-10-05 12:02:04 -0700405 terminal_t *terminal = term_get_terminal(vt);
406 if (!terminal) {
407 terminal = term_init(vt, -1);
408 term_set_terminal(vt, terminal);
409 }
410 }
411 }
412
413 if (command_flags.daemon && command_flags.pre_create_vts)
414 daemon_exit_code(EXIT_SUCCESS);
415
Dominik Behr0bb51772016-07-26 18:04:53 -0700416 /* These flags can be only processed after splash object has been created. */
Dominik Behrb1abcba2016-04-14 14:57:21 -0700417 optind = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700418 for (;;) {
419 c = getopt_long(argc, argv, "", command_options, NULL);
420
421 if (c == -1)
422 break;
423
424 switch (c) {
425 case FLAG_CLEAR:
426 splash_set_clear(splash, strtoul(optarg, NULL, 0));
427 break;
428
David Sodman8ef20062015-01-06 09:23:40 -0800429 case FLAG_FRAME_INTERVAL:
430 splash_set_default_duration(splash, strtoul(optarg, NULL, 0));
431 break;
432
Dominik Behr32a7c892015-10-09 15:47:53 -0700433 case FLAG_IMAGE:
434 if (!splash_is_hires(splash))
435 splash_add_image(splash, optarg);
436 break;
437
438 case FLAG_IMAGE_HIRES:
439 if (splash_is_hires(splash))
440 splash_add_image(splash, optarg);
441 break;
442
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700443 case FLAG_LOOP_COUNT:
444 splash_set_loop_count(splash, strtoul(optarg, NULL, 0));
445 break;
446
David Sodman8ef20062015-01-06 09:23:40 -0800447 case FLAG_LOOP_START:
448 splash_set_loop_start(splash, strtoul(optarg, NULL, 0));
449 break;
450
451 case FLAG_LOOP_INTERVAL:
452 splash_set_loop_duration(splash, strtoul(optarg, NULL, 0));
453 break;
454
455 case FLAG_LOOP_OFFSET:
456 parse_offset(optarg, &x, &y);
457 splash_set_loop_offset(splash, x, y);
458 break;
459
460 case FLAG_OFFSET:
461 parse_offset(optarg, &x, &y);
462 splash_set_offset(splash, x, y);
463 break;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700464
Dominik Behr92d9e312016-05-04 20:10:48 -0700465 case FLAG_SCALE:
466 splash_set_scale(splash, strtoul(optarg, NULL, 0));
467 break;
David Sodmanbbcb0522014-09-19 10:34:07 -0700468 }
469 }
470
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800471 for (int i = optind; i < argc; i++)
David Sodman8ef20062015-01-06 09:23:40 -0800472 splash_add_image(splash, argv[i]);
473
Dominik Behr03720a92017-07-12 18:23:42 -0700474 if (drm && splash_num_images(splash) > 0) {
Dominik Behr797a3832016-01-11 15:53:11 -0800475 ret = splash_run(splash);
David Sodmanbbcb0522014-09-19 10:34:07 -0700476 if (ret) {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700477 LOG(ERROR, "Splash_run failed: %d.", ret);
Dominik Behraad57ba2017-09-18 12:24:16 -0700478 if (!command_flags.daemon)
479 return EXIT_FAILURE;
David Sodmanbbcb0522014-09-19 10:34:07 -0700480 }
481 }
482
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800483 splash_destroy(splash);
484
485 if (command_flags.splash_only)
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700486 goto main_done;
487
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();
Dominik Behr46c567f2016-03-08 15:11:48 -0800495 /*
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800496 * Ask DBUS to call us back so we can quit when login prompt is visible.
Dominik Behr46c567f2016-03-08 15:11:48 -0800497 */
Dominik Behr6e0f6fd2016-12-02 17:54:08 -0800498 dbus_set_login_prompt_visible_callback(main_on_login_prompt_visible);
Dominik Behr1883c042016-04-27 12:31:02 -0700499 /*
500 * Ask DBUS to notify us when suspend has finished so monitors can be reprobed
501 * in case they changed during suspend.
502 */
503 dbus_set_suspend_done_callback(term_suspend_done, NULL);
504
Dominik Behr46c567f2016-03-08 15:11:48 -0800505 if (command_flags.daemon) {
506 if (command_flags.enable_vts)
Dominik Behra818a1e2016-10-26 19:46:22 -0700507 set_drm_master_relax();
Dominik Behrda6df412016-08-02 12:56:42 -0700508 if (command_flags.enable_vt1)
509 term_switch_to(TERM_SPLASH_TERMINAL);
510 else
Dominik Behr33847332016-12-12 17:27:56 -0800511 term_background(true);
Dominik Behr46c567f2016-03-08 15:11:48 -0800512 } else {
Dominik Behrb1abcba2016-04-14 14:57:21 -0700513 /* Create and switch to first term in interactve mode. */
Dominik Behra818a1e2016-10-26 19:46:22 -0700514 set_drm_master_relax();
Dominik Behrda6df412016-08-02 12:56:42 -0700515 term_switch_to(command_flags.enable_vt1 ? TERM_SPLASH_TERMINAL : 1);
Dominik Behr46c567f2016-03-08 15:11:48 -0800516 }
517
518 ret = main_loop();
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700519
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700520main_done:
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700521 input_close();
Dominik Behr5239cca2016-01-21 18:22:04 -0800522 dev_close();
Dominik Behr44e07e62016-01-13 19:43:57 -0800523 dbus_destroy();
Dominik Behr83010f82016-03-18 18:43:08 -0700524 drm_close();
Dominik Behrda6df412016-08-02 12:56:42 -0700525 if (command_flags.daemon)
526 unlink(FRECON_PID_FILE);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700527
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700528 return ret;
529}