source: mainline/uspace/srv/devman/main.c@ a087f2e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a087f2e was a087f2e, checked in by Lenka Trochtova <trochtova.lenka@…>, 15 years ago

copy drivers to the ramdisk including their configuration files (ia32)

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 * Copyright (c) 2010 Lenka Trochtova
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 * - Redistributions 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/**
30 * @defgroup devman Device manager.
31 * @brief HelenOS device manager.
32 * @{
33 */
34
35/** @file
36 */
37
38#include <assert.h>
39#include <ipc/services.h>
40#include <ipc/ns.h>
41#include <async.h>
42#include <stdio.h>
43#include <errno.h>
44#include <bool.h>
45#include <fibril_synch.h>
46#include <stdlib.h>
47#include <string.h>
48#include <dirent.h>
49#include <fcntl.h>
50#include <sys/stat.h>
51#include <ctype.h>
52#include <ipc/devman.h>
53#include <thread.h>
54
55#include "devman.h"
56
57#define DRIVER_DEFAULT_STORE "/srv/drivers"
58
59static driver_list_t drivers_list;
60static dev_tree_t device_tree;
61
62/**
63 * Register running driver.
64 */
65static driver_t * devman_driver_register(void)
66{
67 printf(NAME ": devman_driver_register \n");
68
69 ipc_call_t icall;
70 ipc_callid_t iid = async_get_call(&icall);
71 driver_t *driver = NULL;
72
73 if (IPC_GET_METHOD(icall) != DEVMAN_DRIVER_REGISTER) {
74 ipc_answer_0(iid, EREFUSED);
75 return NULL;
76 }
77
78 char *drv_name = NULL;
79
80 // Get driver name
81 int rc = async_string_receive(&drv_name, DEVMAN_NAME_MAXLEN, NULL);
82 if (rc != EOK) {
83 ipc_answer_0(iid, rc);
84 return NULL;
85 }
86 printf(NAME ": the %s driver is trying to register by the service.\n", drv_name);
87
88 // Find driver structure
89 driver = find_driver(&drivers_list, drv_name);
90
91 free(drv_name);
92 drv_name = NULL;
93
94 if (NULL == driver) {
95 printf(NAME ": no driver named %s was found.\n", drv_name);
96 ipc_answer_0(iid, ENOENT);
97 return NULL;
98 }
99
100 // Create connection to the driver
101 printf(NAME ": creating connection to the %s driver.\n", driver->name);
102 ipc_call_t call;
103 ipc_callid_t callid = async_get_call(&call);
104 if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
105 ipc_answer_0(callid, ENOTSUP);
106 ipc_answer_0(iid, ENOTSUP);
107 return NULL;
108 }
109
110 // remember driver's phone
111 set_driver_phone(driver, IPC_GET_ARG5(call));
112
113 printf(NAME ": the %s driver was successfully registered as running.\n", driver->name);
114
115 ipc_answer_0(callid, EOK);
116
117 ipc_answer_0(iid, EOK);
118
119 return driver;
120}
121
122static int devman_receive_match_id(match_id_list_t *match_ids) {
123
124 match_id_t *match_id = create_match_id();
125 ipc_callid_t callid;
126 ipc_call_t call;
127 int rc = 0;
128
129 callid = async_get_call(&call);
130 if (DEVMAN_ADD_MATCH_ID != IPC_GET_METHOD(call)) {
131 printf(NAME ": ERROR: devman_receive_match_id - invalid protocol.\n");
132 ipc_answer_0(callid, EINVAL);
133 delete_match_id(match_id);
134 return EINVAL;
135 }
136
137 if (NULL == match_id) {
138 printf(NAME ": ERROR: devman_receive_match_id - failed to allocate match id.\n");
139 ipc_answer_0(callid, ENOMEM);
140 return ENOMEM;
141 }
142
143 match_id->score = IPC_GET_ARG1(call);
144
145 rc = async_string_receive(&match_id->id, DEVMAN_NAME_MAXLEN, NULL);
146 if (EOK != rc) {
147 delete_match_id(match_id);
148 return rc;
149 }
150
151 list_append(&match_id->link, &match_ids->ids);
152
153 printf(NAME ": received match id '%s', score = %d \n", match_id->id, match_id->score);
154 return rc;
155}
156
157static int devman_receive_match_ids(ipcarg_t match_count, match_id_list_t *match_ids)
158{
159 int ret = EOK;
160 int i;
161 for (i = 0; i < match_count; i++) {
162 if (EOK != (ret = devman_receive_match_id(match_ids))) {
163 return ret;
164 }
165 }
166 return ret;
167}
168
169static void devman_add_child(ipc_callid_t callid, ipc_call_t *call, driver_t *driver)
170{
171 printf(NAME ": devman_add_child\n");
172
173 device_handle_t parent_handle = IPC_GET_ARG1(*call);
174 ipcarg_t match_count = IPC_GET_ARG2(*call);
175
176 node_t *parent = find_dev_node(&device_tree, parent_handle);
177
178 if (NULL == parent) {
179 ipc_answer_0(callid, ENOENT);
180 return;
181 }
182
183 char *dev_name = NULL;
184 int rc = async_string_receive(&dev_name, DEVMAN_NAME_MAXLEN, NULL);
185 if (EOK != rc) {
186 ipc_answer_0(callid, rc);
187 return;
188 }
189 printf(NAME ": newly added child device's name is '%s'.\n", dev_name);
190
191 node_t *node = create_dev_node();
192 if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
193 delete_dev_node(node);
194 ipc_answer_0(callid, ENOMEM);
195 return;
196 }
197
198 devman_receive_match_ids(match_count, &node->match_ids);
199
200 // return device handle to parent's driver
201 ipc_answer_1(callid, EOK, node->handle);
202
203 // try to find suitable driver and assign it to the device
204 assign_driver(node, &drivers_list);
205}
206
207static int init_running_drv(void *drv)
208{
209 driver_t *driver = (driver_t *)drv;
210 initialize_running_driver(driver);
211 printf(NAME ": the %s driver was successfully initialized. \n", driver->name);
212 return 0;
213}
214
215/** Function for handling connections to device manager.
216 *
217 */
218static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
219{
220 /* Accept the connection */
221 ipc_answer_0(iid, EOK);
222
223 driver_t *driver = devman_driver_register();
224 if (NULL == driver)
225 return;
226
227 fid_t fid = fibril_create(init_running_drv, driver);
228 if (fid == 0) {
229 printf(NAME ": Error creating fibril for the initialization of the newly registered running driver.\n");
230 exit(1);
231 }
232 fibril_add_ready(fid);
233
234 /*thread_id_t tid;
235 if (0 != thread_create(init_running_drv, driver, "init_running_drv", &tid)) {
236 printf(NAME ": failed to start the initialization of the newly registered running driver.\n");
237 }*/
238
239 ipc_callid_t callid;
240 ipc_call_t call;
241 bool cont = true;
242 while (cont) {
243 callid = async_get_call(&call);
244
245 switch (IPC_GET_METHOD(call)) {
246 case IPC_M_PHONE_HUNGUP:
247 cont = false;
248 continue;
249 case DEVMAN_ADD_CHILD_DEVICE:
250 devman_add_child(callid, &call, driver);
251 break;
252 default:
253 ipc_answer_0(callid, EINVAL);
254 break;
255 }
256 }
257}
258
259/** Function for handling connections to device manager.
260 *
261 */
262static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
263{
264 // Select interface
265 switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
266 case DEVMAN_DRIVER:
267 devman_connection_driver(iid, icall);
268 break;
269 /*case DEVMAN_CLIENT:
270 devmap_connection_client(iid, icall);
271 break;
272 case DEVMAN_CONNECT_TO_DEVICE:
273 // Connect client to selected device
274 devmap_forward(iid, icall);
275 break;*/
276 default:
277 /* No such interface */
278 ipc_answer_0(iid, ENOENT);
279 }
280}
281
282/** Initialize device manager internal structures.
283 */
284static bool devman_init()
285{
286 printf(NAME ": devman_init - looking for available drivers. \n");
287
288 // initialize list of available drivers
289 init_driver_list(&drivers_list);
290 if (0 == lookup_available_drivers(&drivers_list, DRIVER_DEFAULT_STORE)) {
291 printf(NAME " no drivers found.");
292 return false;
293 }
294 printf(NAME ": devman_init - list of drivers has been initialized. \n");
295
296 // create root device node
297 if (!init_device_tree(&device_tree, &drivers_list)) {
298 printf(NAME " failed to initialize device tree.");
299 return false;
300 }
301
302 return true;
303}
304
305int main(int argc, char *argv[])
306{
307 printf(NAME ": HelenOS Device Manager\n");
308
309 if (!devman_init()) {
310 printf(NAME ": Error while initializing service\n");
311 return -1;
312 }
313
314 // Set a handler of incomming connections
315 async_set_client_connection(devman_connection);
316
317 // Register device manager at naming service
318 ipcarg_t phonead;
319 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAN, 0, 0, &phonead) != 0)
320 return -1;
321
322 printf(NAME ": Accepting connections\n");
323 async_manager();
324
325 // Never reached
326 return 0;
327}
328
329/** @}
330 */
Note: See TracBrowser for help on using the repository browser.