source: mainline/uspace/srv/hid/display/main.c@ dbf5d7c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dbf5d7c was dbf5d7c, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Only initialize input after we have probed for display devices

Avoids null pointer dereference (null GC) that could occur if an input event
arrived earlier than we could initialize a display device.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistribution1s of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup display
30 * @{
31 */
32/**
33 * @file Display server main
34 */
35
36#include <async.h>
37#include <disp_srv.h>
38#include <errno.h>
39#include <gfx/context.h>
40#include <str_error.h>
41#include <io/log.h>
42#include <io/kbd_event.h>
43#include <io/pos_event.h>
44#include <ipc/services.h>
45#include <ipcgfx/server.h>
46#include <loc.h>
47#include <stdio.h>
48#include <task.h>
49#include "client.h"
50#include "display.h"
51#include "dsops.h"
52#include "input.h"
53#include "main.h"
54#include "output.h"
55#include "seat.h"
56#include "window.h"
57
58static void display_client_conn(ipc_call_t *, void *);
59static void display_client_ev_pending(void *);
60
61#ifdef CONFIG_DISP_DOUBLE_BUF
62/*
63 * Double buffering is one way to provide flicker-free display.
64 */
65static ds_display_flags_t disp_flags = df_disp_double_buf;
66#else
67/*
68 * With double buffering disabled, wet screen flicker since front-to-back
69 * rendering is not implemented.
70 */
71static ds_display_flags_t disp_flags = df_none;
72#endif
73
74static ds_client_cb_t display_client_cb = {
75 .ev_pending = display_client_ev_pending
76};
77
78static void display_client_ev_pending(void *arg)
79{
80 display_srv_t *srv = (display_srv_t *) arg;
81
82 display_srv_ev_pending(srv);
83}
84
85/** Initialize display server */
86static errno_t display_srv_init(ds_output_t **routput)
87{
88 ds_display_t *disp = NULL;
89 ds_seat_t *seat = NULL;
90 ds_output_t *output = NULL;
91 gfx_context_t *gc = NULL;
92 errno_t rc;
93
94 log_msg(LOG_DEFAULT, LVL_DEBUG, "display_srv_init()");
95
96 rc = ds_display_create(NULL, disp_flags, &disp);
97 if (rc != EOK)
98 goto error;
99
100 rc = ds_seat_create(disp, &seat);
101 if (rc != EOK)
102 goto error;
103
104 rc = ds_output_create(&output);
105 if (rc != EOK)
106 goto error;
107
108 output->def_display = disp;
109 rc = ds_output_start_discovery(output);
110 if (rc != EOK)
111 goto error;
112
113 rc = ds_input_open(disp);
114 if (rc != EOK)
115 goto error;
116
117 async_set_fallback_port_handler(display_client_conn, disp);
118
119 rc = loc_server_register(NAME);
120 if (rc != EOK) {
121 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server: %s.", str_error(rc));
122 rc = EEXIST;
123 }
124
125 service_id_t sid;
126 rc = loc_service_register(SERVICE_NAME_DISPLAY, &sid);
127 if (rc != EOK) {
128 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service: %s.", str_error(rc));
129 rc = EEXIST;
130 goto error;
131 }
132
133 *routput = output;
134 return EOK;
135error:
136#if 0
137 if (disp->input != NULL)
138 ds_input_close(disp);
139#endif
140 if (output != NULL)
141 ds_output_destroy(output);
142 if (gc != NULL)
143 gfx_context_delete(gc);
144 if (seat != NULL)
145 ds_seat_destroy(seat);
146 if (disp != NULL)
147 ds_display_destroy(disp);
148 return rc;
149}
150
151/** Handle client connection to display server */
152static void display_client_conn(ipc_call_t *icall, void *arg)
153{
154 display_srv_t srv;
155 sysarg_t wnd_id;
156 sysarg_t svc_id;
157 ds_client_t *client = NULL;
158 ds_window_t *wnd;
159 ds_display_t *disp = (ds_display_t *) arg;
160 gfx_context_t *gc;
161 errno_t rc;
162
163 log_msg(LOG_DEFAULT, LVL_DEBUG, "display_client_conn arg1=%zu arg2=%zu arg3=%zu arg4=%zu.",
164 ipc_get_arg1(icall), ipc_get_arg2(icall), ipc_get_arg3(icall),
165 ipc_get_arg4(icall));
166
167 (void) icall;
168 (void) arg;
169
170 svc_id = ipc_get_arg2(icall);
171 wnd_id = ipc_get_arg3(icall);
172
173 if (svc_id != 0) {
174 /* Create client object */
175 rc = ds_client_create(disp, &display_client_cb, &srv, &client);
176 if (rc != EOK) {
177 async_answer_0(icall, ENOMEM);
178 return;
179 }
180
181 /* Set up protocol structure */
182 display_srv_initialize(&srv);
183 srv.ops = &display_srv_ops;
184 srv.arg = client;
185
186 /* Handle connection */
187 display_conn(icall, &srv);
188
189 ds_client_destroy(client);
190 } else {
191 /* Window GC connection */
192
193 wnd = ds_display_find_window(disp, wnd_id);
194 if (wnd == NULL) {
195 async_answer_0(icall, ENOENT);
196 return;
197 }
198
199 /*
200 * XXX We need a way to make sure that the connection does
201 * not stay active after the window had been destroyed
202 */
203 gc = ds_window_get_ctx(wnd);
204 gc_conn(icall, gc);
205 }
206}
207
208int main(int argc, char *argv[])
209{
210 errno_t rc;
211 ds_output_t *output;
212
213 printf("%s: Display server\n", NAME);
214
215 if (log_init(NAME) != EOK) {
216 printf(NAME ": Failed to initialize logging.\n");
217 return 1;
218 }
219
220 rc = display_srv_init(&output);
221 if (rc != EOK)
222 return 1;
223
224 printf(NAME ": Accepting connections.\n");
225 task_retval(0);
226 async_manager();
227
228 return 0;
229}
230
231/** @}
232 */
Note: See TracBrowser for help on using the repository browser.