source: mainline/uspace/srv/devman/client_conn.c@ fc0b2a8

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

Fix block comment formatting (ccheck).

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/*
2 * Copyright (c) 2010 Lenka Trochtova
3 * Copyright (c) 2013 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @defgroup devman Device manager.
32 * @brief HelenOS device manager.
33 * @{
34 */
35
36/** @file
37 */
38
39#include <inttypes.h>
40#include <assert.h>
41#include <ns.h>
42#include <async.h>
43#include <stdio.h>
44#include <errno.h>
45#include <str_error.h>
46#include <stdbool.h>
47#include <fibril_synch.h>
48#include <stdlib.h>
49#include <str.h>
50#include <ctype.h>
51#include <ipc/devman.h>
52
53#include "client_conn.h"
54#include "dev.h"
55#include "devman.h"
56#include "driver.h"
57#include "fun.h"
58#include "loc.h"
59#include "main.h"
60
61/** Find handle for the device instance identified by the device's path in the
62 * device tree.
63 */
64static void devman_function_get_handle(cap_call_handle_t icall_handle, ipc_call_t *icall)
65{
66 char *pathname;
67 devman_handle_t handle;
68
69 errno_t rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
70 if (rc != EOK) {
71 async_answer_0(icall_handle, rc);
72 return;
73 }
74
75 fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
76
77 free(pathname);
78
79 if (fun == NULL) {
80 async_answer_0(icall_handle, ENOENT);
81 return;
82 }
83
84 fibril_rwlock_read_lock(&device_tree.rwlock);
85
86 /* Check function state */
87 if (fun->state == FUN_REMOVED) {
88 fibril_rwlock_read_unlock(&device_tree.rwlock);
89 async_answer_0(icall_handle, ENOENT);
90 return;
91 }
92 handle = fun->handle;
93
94 fibril_rwlock_read_unlock(&device_tree.rwlock);
95
96 /* Delete reference created above by find_fun_node_by_path() */
97 fun_del_ref(fun);
98
99 async_answer_1(icall_handle, EOK, handle);
100}
101
102/** Get device match ID. */
103static void devman_fun_get_match_id(cap_call_handle_t icall_handle, ipc_call_t *icall)
104{
105 devman_handle_t handle = IPC_GET_ARG1(*icall);
106 size_t index = IPC_GET_ARG2(*icall);
107 void *buffer = NULL;
108
109 fun_node_t *fun = find_fun_node(&device_tree, handle);
110 if (fun == NULL) {
111 async_answer_0(icall_handle, ENOMEM);
112 return;
113 }
114
115 cap_call_handle_t data_chandle;
116 size_t data_len;
117 if (!async_data_read_receive(&data_chandle, &data_len)) {
118 async_answer_0(icall_handle, EINVAL);
119 fun_del_ref(fun);
120 return;
121 }
122
123 buffer = malloc(data_len);
124 if (buffer == NULL) {
125 async_answer_0(data_chandle, ENOMEM);
126 async_answer_0(icall_handle, ENOMEM);
127 fun_del_ref(fun);
128 return;
129 }
130
131 fibril_rwlock_read_lock(&device_tree.rwlock);
132
133 /* Check function state */
134 if (fun->state == FUN_REMOVED)
135 goto error;
136
137 link_t *link = list_nth(&fun->match_ids.ids, index);
138 if (link == NULL)
139 goto error;
140
141 match_id_t *mid = list_get_instance(link, match_id_t, link);
142
143 size_t sent_length = str_size(mid->id);
144 if (sent_length > data_len) {
145 sent_length = data_len;
146 }
147
148 async_data_read_finalize(data_chandle, mid->id, sent_length);
149 async_answer_1(icall_handle, EOK, mid->score);
150
151 fibril_rwlock_read_unlock(&device_tree.rwlock);
152 fun_del_ref(fun);
153 free(buffer);
154
155 return;
156error:
157 fibril_rwlock_read_unlock(&device_tree.rwlock);
158 free(buffer);
159
160 async_answer_0(data_chandle, ENOENT);
161 async_answer_0(icall_handle, ENOENT);
162 fun_del_ref(fun);
163}
164
165/** Get device name. */
166static void devman_fun_get_name(cap_call_handle_t icall_handle, ipc_call_t *icall)
167{
168 devman_handle_t handle = IPC_GET_ARG1(*icall);
169
170 fun_node_t *fun = find_fun_node(&device_tree, handle);
171 if (fun == NULL) {
172 async_answer_0(icall_handle, ENOMEM);
173 return;
174 }
175
176 cap_call_handle_t data_chandle;
177 size_t data_len;
178 if (!async_data_read_receive(&data_chandle, &data_len)) {
179 async_answer_0(icall_handle, EINVAL);
180 fun_del_ref(fun);
181 return;
182 }
183
184 void *buffer = malloc(data_len);
185 if (buffer == NULL) {
186 async_answer_0(data_chandle, ENOMEM);
187 async_answer_0(icall_handle, ENOMEM);
188 fun_del_ref(fun);
189 return;
190 }
191
192 fibril_rwlock_read_lock(&device_tree.rwlock);
193
194 /* Check function state */
195 if (fun->state == FUN_REMOVED) {
196 fibril_rwlock_read_unlock(&device_tree.rwlock);
197 free(buffer);
198
199 async_answer_0(data_chandle, ENOENT);
200 async_answer_0(icall_handle, ENOENT);
201 fun_del_ref(fun);
202 return;
203 }
204
205 size_t sent_length = str_size(fun->name);
206 if (sent_length > data_len) {
207 sent_length = data_len;
208 }
209
210 async_data_read_finalize(data_chandle, fun->name, sent_length);
211 async_answer_0(icall_handle, EOK);
212
213 fibril_rwlock_read_unlock(&device_tree.rwlock);
214 fun_del_ref(fun);
215 free(buffer);
216}
217
218/** Get function driver name. */
219static void devman_fun_get_driver_name(cap_call_handle_t icall_handle, ipc_call_t *icall)
220{
221 devman_handle_t handle = IPC_GET_ARG1(*icall);
222
223 fun_node_t *fun = find_fun_node(&device_tree, handle);
224 if (fun == NULL) {
225 async_answer_0(icall_handle, ENOMEM);
226 return;
227 }
228
229 cap_call_handle_t data_chandle;
230 size_t data_len;
231 if (!async_data_read_receive(&data_chandle, &data_len)) {
232 async_answer_0(icall_handle, EINVAL);
233 fun_del_ref(fun);
234 return;
235 }
236
237 void *buffer = malloc(data_len);
238 if (buffer == NULL) {
239 async_answer_0(data_chandle, ENOMEM);
240 async_answer_0(icall_handle, ENOMEM);
241 fun_del_ref(fun);
242 return;
243 }
244
245 fibril_rwlock_read_lock(&device_tree.rwlock);
246
247 /* Check function state */
248 if (fun->state == FUN_REMOVED) {
249 fibril_rwlock_read_unlock(&device_tree.rwlock);
250 free(buffer);
251
252 async_answer_0(data_chandle, ENOENT);
253 async_answer_0(icall_handle, ENOENT);
254 fun_del_ref(fun);
255 return;
256 }
257
258 /* Check whether function has a driver */
259 if (fun->child == NULL || fun->child->drv == NULL) {
260 fibril_rwlock_read_unlock(&device_tree.rwlock);
261 free(buffer);
262
263 async_answer_0(data_chandle, EINVAL);
264 async_answer_0(icall_handle, EINVAL);
265 fun_del_ref(fun);
266 return;
267 }
268
269 size_t sent_length = str_size(fun->child->drv->name);
270 if (sent_length > data_len) {
271 sent_length = data_len;
272 }
273
274 async_data_read_finalize(data_chandle, fun->child->drv->name,
275 sent_length);
276 async_answer_0(icall_handle, EOK);
277
278 fibril_rwlock_read_unlock(&device_tree.rwlock);
279 fun_del_ref(fun);
280 free(buffer);
281}
282
283/** Get device path. */
284static void devman_fun_get_path(cap_call_handle_t icall_handle, ipc_call_t *icall)
285{
286 devman_handle_t handle = IPC_GET_ARG1(*icall);
287
288 fun_node_t *fun = find_fun_node(&device_tree, handle);
289 if (fun == NULL) {
290 async_answer_0(icall_handle, ENOMEM);
291 return;
292 }
293
294 cap_call_handle_t data_chandle;
295 size_t data_len;
296 if (!async_data_read_receive(&data_chandle, &data_len)) {
297 async_answer_0(icall_handle, EINVAL);
298 fun_del_ref(fun);
299 return;
300 }
301
302 void *buffer = malloc(data_len);
303 if (buffer == NULL) {
304 async_answer_0(data_chandle, ENOMEM);
305 async_answer_0(icall_handle, ENOMEM);
306 fun_del_ref(fun);
307 return;
308 }
309
310 fibril_rwlock_read_lock(&device_tree.rwlock);
311
312 /* Check function state */
313 if (fun->state == FUN_REMOVED) {
314 fibril_rwlock_read_unlock(&device_tree.rwlock);
315 free(buffer);
316
317 async_answer_0(data_chandle, ENOENT);
318 async_answer_0(icall_handle, ENOENT);
319 fun_del_ref(fun);
320 return;
321 }
322
323 size_t sent_length = str_size(fun->pathname);
324 if (sent_length > data_len) {
325 sent_length = data_len;
326 }
327
328 async_data_read_finalize(data_chandle, fun->pathname, sent_length);
329 async_answer_0(icall_handle, EOK);
330
331 fibril_rwlock_read_unlock(&device_tree.rwlock);
332 fun_del_ref(fun);
333 free(buffer);
334}
335
336/** Get handle for parent function of a device. */
337static void devman_dev_get_parent(cap_call_handle_t icall_handle, ipc_call_t *icall)
338{
339 dev_node_t *dev;
340
341 fibril_rwlock_read_lock(&device_tree.rwlock);
342
343 dev = find_dev_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
344 if (dev == NULL || dev->state == DEVICE_REMOVED) {
345 fibril_rwlock_read_unlock(&device_tree.rwlock);
346 async_answer_0(icall_handle, ENOENT);
347 return;
348 }
349
350 if (dev->pfun == NULL) {
351 fibril_rwlock_read_unlock(&device_tree.rwlock);
352 async_answer_0(icall_handle, ENOENT);
353 return;
354 }
355
356 async_answer_1(icall_handle, EOK, dev->pfun->handle);
357
358 fibril_rwlock_read_unlock(&device_tree.rwlock);
359}
360
361static void devman_dev_get_functions(cap_call_handle_t icall_handle, ipc_call_t *icall)
362{
363 cap_call_handle_t chandle;
364 size_t size;
365 size_t act_size;
366 errno_t rc;
367
368 if (!async_data_read_receive(&chandle, &size)) {
369 async_answer_0(chandle, EREFUSED);
370 async_answer_0(icall_handle, EREFUSED);
371 return;
372 }
373
374 fibril_rwlock_read_lock(&device_tree.rwlock);
375
376 dev_node_t *dev = find_dev_node_no_lock(&device_tree,
377 IPC_GET_ARG1(*icall));
378 if (dev == NULL || dev->state == DEVICE_REMOVED) {
379 fibril_rwlock_read_unlock(&device_tree.rwlock);
380 async_answer_0(chandle, ENOENT);
381 async_answer_0(icall_handle, ENOENT);
382 return;
383 }
384
385 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
386 if (hdl_buf == NULL) {
387 fibril_rwlock_read_unlock(&device_tree.rwlock);
388 async_answer_0(chandle, ENOMEM);
389 async_answer_0(icall_handle, ENOMEM);
390 return;
391 }
392
393 rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
394 if (rc != EOK) {
395 fibril_rwlock_read_unlock(&device_tree.rwlock);
396 async_answer_0(chandle, rc);
397 async_answer_0(icall_handle, rc);
398 return;
399 }
400
401 fibril_rwlock_read_unlock(&device_tree.rwlock);
402
403 errno_t retval = async_data_read_finalize(chandle, hdl_buf, size);
404 free(hdl_buf);
405
406 async_answer_1(icall_handle, retval, act_size);
407}
408
409/** Get handle for child device of a function. */
410static void devman_fun_get_child(cap_call_handle_t icall_handle, ipc_call_t *icall)
411{
412 fun_node_t *fun;
413
414 fibril_rwlock_read_lock(&device_tree.rwlock);
415
416 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
417 if (fun == NULL || fun->state == FUN_REMOVED) {
418 fibril_rwlock_read_unlock(&device_tree.rwlock);
419 async_answer_0(icall_handle, ENOENT);
420 return;
421 }
422
423 if (fun->child == NULL) {
424 fibril_rwlock_read_unlock(&device_tree.rwlock);
425 async_answer_0(icall_handle, ENOENT);
426 return;
427 }
428
429 async_answer_1(icall_handle, EOK, fun->child->handle);
430
431 fibril_rwlock_read_unlock(&device_tree.rwlock);
432}
433
434/** Online function.
435 *
436 * Send a request to online a function to the responsible driver.
437 * The driver may offline other functions if necessary (i.e. if the state
438 * of this function is linked to state of another function somehow).
439 */
440static void devman_fun_online(cap_call_handle_t icall_handle, ipc_call_t *icall)
441{
442 fun_node_t *fun;
443 errno_t rc;
444
445 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
446 if (fun == NULL) {
447 async_answer_0(icall_handle, ENOENT);
448 return;
449 }
450
451 rc = driver_fun_online(&device_tree, fun);
452 fun_del_ref(fun);
453
454 async_answer_0(icall_handle, rc);
455}
456
457/** Offline function.
458 *
459 * Send a request to offline a function to the responsible driver. As
460 * a result the subtree rooted at that function should be cleanly
461 * detatched. The driver may offline other functions if necessary
462 * (i.e. if the state of this function is linked to state of another
463 * function somehow).
464 */
465static void devman_fun_offline(cap_call_handle_t icall_handle, ipc_call_t *icall)
466{
467 fun_node_t *fun;
468 errno_t rc;
469
470 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
471 if (fun == NULL) {
472 async_answer_0(icall_handle, ENOENT);
473 return;
474 }
475
476 rc = driver_fun_offline(&device_tree, fun);
477 fun_del_ref(fun);
478
479 async_answer_0(icall_handle, rc);
480}
481
482/** Find handle for the function instance identified by its service ID. */
483static void devman_fun_sid_to_handle(cap_call_handle_t icall_handle, ipc_call_t *icall)
484{
485 fun_node_t *fun;
486
487 fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
488
489 if (fun == NULL) {
490 async_answer_0(icall_handle, ENOENT);
491 return;
492 }
493
494 fibril_rwlock_read_lock(&device_tree.rwlock);
495
496 /* Check function state */
497 if (fun->state == FUN_REMOVED) {
498 fibril_rwlock_read_unlock(&device_tree.rwlock);
499 async_answer_0(icall_handle, ENOENT);
500 return;
501 }
502
503 async_answer_1(icall_handle, EOK, fun->handle);
504 fibril_rwlock_read_unlock(&device_tree.rwlock);
505 fun_del_ref(fun);
506}
507
508/** Get list of all registered drivers. */
509static void devman_get_drivers(cap_call_handle_t icall_handle, ipc_call_t *icall)
510{
511 cap_call_handle_t chandle;
512 size_t size;
513 size_t act_size;
514 errno_t rc;
515
516 if (!async_data_read_receive(&chandle, &size)) {
517 async_answer_0(icall_handle, EREFUSED);
518 return;
519 }
520
521 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
522 if (hdl_buf == NULL) {
523 async_answer_0(chandle, ENOMEM);
524 async_answer_0(icall_handle, ENOMEM);
525 return;
526 }
527
528 rc = driver_get_list(&drivers_list, hdl_buf, size, &act_size);
529 if (rc != EOK) {
530 async_answer_0(chandle, rc);
531 async_answer_0(icall_handle, rc);
532 return;
533 }
534
535 errno_t retval = async_data_read_finalize(chandle, hdl_buf, size);
536 free(hdl_buf);
537
538 async_answer_1(icall_handle, retval, act_size);
539}
540
541static void devman_driver_get_devices(cap_call_handle_t icall_handle, ipc_call_t *icall)
542{
543 cap_call_handle_t chandle;
544 size_t size;
545 size_t act_size;
546 errno_t rc;
547
548 if (!async_data_read_receive(&chandle, &size)) {
549 async_answer_0(icall_handle, EREFUSED);
550 return;
551 }
552
553 driver_t *drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
554 if (drv == NULL) {
555 async_answer_0(chandle, ENOENT);
556 async_answer_0(icall_handle, ENOENT);
557 return;
558 }
559
560 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
561 if (hdl_buf == NULL) {
562 async_answer_0(chandle, ENOMEM);
563 async_answer_0(icall_handle, ENOMEM);
564 return;
565 }
566
567 rc = driver_get_devices(drv, hdl_buf, size, &act_size);
568 if (rc != EOK) {
569 fibril_rwlock_read_unlock(&device_tree.rwlock);
570 async_answer_0(chandle, rc);
571 async_answer_0(icall_handle, rc);
572 return;
573 }
574
575 errno_t retval = async_data_read_finalize(chandle, hdl_buf, size);
576 free(hdl_buf);
577
578 async_answer_1(icall_handle, retval, act_size);
579}
580
581
582/** Find driver by name. */
583static void devman_driver_get_handle(cap_call_handle_t icall_handle, ipc_call_t *icall)
584{
585 char *drvname;
586
587 errno_t rc = async_data_write_accept((void **) &drvname, true, 0, 0, 0, 0);
588 if (rc != EOK) {
589 async_answer_0(icall_handle, rc);
590 return;
591 }
592
593 driver_t *driver = driver_find_by_name(&drivers_list, drvname);
594
595 free(drvname);
596
597 if (driver == NULL) {
598 async_answer_0(icall_handle, ENOENT);
599 return;
600 }
601
602 async_answer_1(icall_handle, EOK, driver->handle);
603}
604
605/** Get driver match ID. */
606static void devman_driver_get_match_id(cap_call_handle_t icall_handle, ipc_call_t *icall)
607{
608 devman_handle_t handle = IPC_GET_ARG1(*icall);
609 size_t index = IPC_GET_ARG2(*icall);
610
611 driver_t *drv = driver_find(&drivers_list, handle);
612 if (drv == NULL) {
613 async_answer_0(icall_handle, ENOMEM);
614 return;
615 }
616
617 cap_call_handle_t data_chandle;
618 size_t data_len;
619 if (!async_data_read_receive(&data_chandle, &data_len)) {
620 async_answer_0(icall_handle, EINVAL);
621 return;
622 }
623
624 void *buffer = malloc(data_len);
625 if (buffer == NULL) {
626 async_answer_0(data_chandle, ENOMEM);
627 async_answer_0(icall_handle, ENOMEM);
628 return;
629 }
630
631 fibril_mutex_lock(&drv->driver_mutex);
632 link_t *link = list_nth(&drv->match_ids.ids, index);
633 if (link == NULL) {
634 fibril_mutex_unlock(&drv->driver_mutex);
635 free(buffer);
636 async_answer_0(data_chandle, ENOMEM);
637 async_answer_0(icall_handle, ENOMEM);
638 return;
639 }
640
641 match_id_t *mid = list_get_instance(link, match_id_t, link);
642
643 size_t sent_length = str_size(mid->id);
644 if (sent_length > data_len) {
645 sent_length = data_len;
646 }
647
648 async_data_read_finalize(data_chandle, mid->id, sent_length);
649 async_answer_1(icall_handle, EOK, mid->score);
650
651 fibril_mutex_unlock(&drv->driver_mutex);
652
653 free(buffer);
654}
655
656/** Get driver name. */
657static void devman_driver_get_name(cap_call_handle_t icall_handle, ipc_call_t *icall)
658{
659 devman_handle_t handle = IPC_GET_ARG1(*icall);
660
661 driver_t *drv = driver_find(&drivers_list, handle);
662 if (drv == NULL) {
663 async_answer_0(icall_handle, ENOMEM);
664 return;
665 }
666
667 cap_call_handle_t data_chandle;
668 size_t data_len;
669 if (!async_data_read_receive(&data_chandle, &data_len)) {
670 async_answer_0(icall_handle, EINVAL);
671 return;
672 }
673
674 void *buffer = malloc(data_len);
675 if (buffer == NULL) {
676 async_answer_0(data_chandle, ENOMEM);
677 async_answer_0(icall_handle, ENOMEM);
678 return;
679 }
680
681 fibril_mutex_lock(&drv->driver_mutex);
682
683 size_t sent_length = str_size(drv->name);
684 if (sent_length > data_len) {
685 sent_length = data_len;
686 }
687
688 async_data_read_finalize(data_chandle, drv->name, sent_length);
689 async_answer_0(icall_handle, EOK);
690
691 fibril_mutex_unlock(&drv->driver_mutex);
692
693 free(buffer);
694}
695
696/** Get driver state. */
697static void devman_driver_get_state(cap_call_handle_t icall_handle, ipc_call_t *icall)
698{
699 driver_t *drv;
700
701 drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
702 if (drv == NULL) {
703 async_answer_0(icall_handle, ENOENT);
704 return;
705 }
706
707 async_answer_1(icall_handle, EOK, (sysarg_t) drv->state);
708}
709
710/** Forcibly load a driver. */
711static void devman_driver_load(cap_call_handle_t icall_handle, ipc_call_t *icall)
712{
713 driver_t *drv;
714 errno_t rc;
715
716 drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
717 if (drv == NULL) {
718 async_answer_0(icall_handle, ENOENT);
719 return;
720 }
721
722 fibril_mutex_lock(&drv->driver_mutex);
723 rc = start_driver(drv) ? EOK : EIO;
724 fibril_mutex_unlock(&drv->driver_mutex);
725
726 async_answer_0(icall_handle, rc);
727}
728
729/** Unload a driver by user request. */
730static void devman_driver_unload(cap_call_handle_t icall_handle, ipc_call_t *icall)
731{
732 driver_t *drv;
733 errno_t rc;
734
735 drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
736 if (drv == NULL) {
737 async_answer_0(icall_handle, ENOENT);
738 return;
739 }
740
741 fibril_mutex_lock(&drv->driver_mutex);
742 rc = stop_driver(drv);
743 fibril_mutex_unlock(&drv->driver_mutex);
744
745 async_answer_0(icall_handle, rc);
746}
747
748/** Function for handling connections from a client to the device manager. */
749void devman_connection_client(cap_call_handle_t icall_handle, ipc_call_t *icall, void *arg)
750{
751 /* Accept connection. */
752 async_answer_0(icall_handle, EOK);
753
754 while (true) {
755 ipc_call_t call;
756 cap_call_handle_t chandle = async_get_call(&call);
757
758 if (!IPC_GET_IMETHOD(call))
759 break;
760
761 switch (IPC_GET_IMETHOD(call)) {
762 case DEVMAN_DEVICE_GET_HANDLE:
763 devman_function_get_handle(chandle, &call);
764 break;
765 case DEVMAN_DEV_GET_PARENT:
766 devman_dev_get_parent(chandle, &call);
767 break;
768 case DEVMAN_DEV_GET_FUNCTIONS:
769 devman_dev_get_functions(chandle, &call);
770 break;
771 case DEVMAN_FUN_GET_CHILD:
772 devman_fun_get_child(chandle, &call);
773 break;
774 case DEVMAN_FUN_GET_MATCH_ID:
775 devman_fun_get_match_id(chandle, &call);
776 break;
777 case DEVMAN_FUN_GET_NAME:
778 devman_fun_get_name(chandle, &call);
779 break;
780 case DEVMAN_FUN_GET_DRIVER_NAME:
781 devman_fun_get_driver_name(chandle, &call);
782 break;
783 case DEVMAN_FUN_GET_PATH:
784 devman_fun_get_path(chandle, &call);
785 break;
786 case DEVMAN_FUN_ONLINE:
787 devman_fun_online(chandle, &call);
788 break;
789 case DEVMAN_FUN_OFFLINE:
790 devman_fun_offline(chandle, &call);
791 break;
792 case DEVMAN_FUN_SID_TO_HANDLE:
793 devman_fun_sid_to_handle(chandle, &call);
794 break;
795 case DEVMAN_GET_DRIVERS:
796 devman_get_drivers(chandle, &call);
797 break;
798 case DEVMAN_DRIVER_GET_DEVICES:
799 devman_driver_get_devices(chandle, &call);
800 break;
801 case DEVMAN_DRIVER_GET_HANDLE:
802 devman_driver_get_handle(chandle, &call);
803 break;
804 case DEVMAN_DRIVER_GET_MATCH_ID:
805 devman_driver_get_match_id(chandle, &call);
806 break;
807 case DEVMAN_DRIVER_GET_NAME:
808 devman_driver_get_name(chandle, &call);
809 break;
810 case DEVMAN_DRIVER_GET_STATE:
811 devman_driver_get_state(chandle, &call);
812 break;
813 case DEVMAN_DRIVER_LOAD:
814 devman_driver_load(chandle, &call);
815 break;
816 case DEVMAN_DRIVER_UNLOAD:
817 devman_driver_unload(chandle, &call);
818 break;
819 default:
820 async_answer_0(chandle, ENOENT);
821 }
822 }
823}
824
825
826/** @}
827 */
Note: See TracBrowser for help on using the repository browser.