source: mainline/uspace/lib/c/generic/devmap.c@ 4db1fbf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4db1fbf was 007e6efa, checked in by Martin Decky <martin@…>, 14 years ago
  • libc routines for registering services and connecting to services via NS
  • async_connect_to_me()
  • Property mode set to 100644
File size: 10.6 KB
RevLine 
[1090b8c]1/*
2 * Copyright (c) 2007 Josef Cejka
3 * Copyright (c) 2009 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
[19f857a]30#include <str.h>
[1090b8c]31#include <ipc/ipc.h>
32#include <ipc/services.h>
[007e6efa]33#include <ipc/ns.h>
[1090b8c]34#include <ipc/devmap.h>
35#include <devmap.h>
36#include <async.h>
37#include <errno.h>
[1313ee9]38#include <malloc.h>
39#include <bool.h>
[1090b8c]40
[cb41a5e]41static int devmap_phone_driver = -1;
42static int devmap_phone_client = -1;
[1090b8c]43
44/** Get phone to device mapper task. */
[cb41a5e]45int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
[1090b8c]46{
[cb41a5e]47 switch (iface) {
48 case DEVMAP_DRIVER:
49 if (devmap_phone_driver >= 0)
50 return devmap_phone_driver;
51
52 if (flags & IPC_FLAG_BLOCKING)
[007e6efa]53 devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
54 DEVMAP_DRIVER, 0);
[cb41a5e]55 else
[007e6efa]56 devmap_phone_driver = service_connect(SERVICE_DEVMAP,
57 DEVMAP_DRIVER, 0);
[cb41a5e]58
59 return devmap_phone_driver;
60 case DEVMAP_CLIENT:
61 if (devmap_phone_client >= 0)
62 return devmap_phone_client;
63
64 if (flags & IPC_FLAG_BLOCKING)
[007e6efa]65 devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
66 DEVMAP_CLIENT, 0);
[cb41a5e]67 else
[007e6efa]68 devmap_phone_client = service_connect(SERVICE_DEVMAP,
69 DEVMAP_CLIENT, 0);
[cb41a5e]70
71 return devmap_phone_client;
72 default:
73 return -1;
[1090b8c]74 }
[cb41a5e]75}
[1090b8c]76
[cb41a5e]77void devmap_hangup_phone(devmap_interface_t iface)
78{
79 switch (iface) {
80 case DEVMAP_DRIVER:
81 if (devmap_phone_driver >= 0) {
82 ipc_hangup(devmap_phone_driver);
83 devmap_phone_driver = -1;
84 }
85 break;
86 case DEVMAP_CLIENT:
87 if (devmap_phone_client >= 0) {
88 ipc_hangup(devmap_phone_client);
89 devmap_phone_client = -1;
90 }
91 break;
92 default:
93 break;
94 }
[1090b8c]95}
96
97/** Register new driver with devmap. */
98int devmap_driver_register(const char *name, async_client_conn_t conn)
99{
[cb41a5e]100 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
101
102 if (phone < 0)
[1090b8c]103 return phone;
104
[e77994dd]105 async_serialize_start();
106
[cb41a5e]107 ipc_call_t answer;
108 aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
109
[96b02eb9]110 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]111 if (retval != EOK) {
112 async_wait_for(req, NULL);
[e77994dd]113 async_serialize_end();
[1090b8c]114 return -1;
115 }
[cb41a5e]116
[1090b8c]117 async_set_client_connection(conn);
[cb41a5e]118
[124c061]119 ipc_connect_to_me(phone, 0, 0, 0, NULL, NULL);
[1090b8c]120 async_wait_for(req, &retval);
[cb41a5e]121
[e77994dd]122 async_serialize_end();
123
[cb41a5e]124 return retval;
[1090b8c]125}
126
[cb41a5e]127/** Register new device.
128 *
[47a7174f]129 * The @p interface is used when forwarding connection to the driver.
130 * If not 0, the first argument is the interface and the second argument
131 * is the devmap handle of the device.
132 * When the interface is zero (default), the first argument is directly
133 * the handle (to ensure backward compatibility).
134 *
135 * @param fqdn Fully qualified device name.
136 * @param[out] handle Handle to the created instance of device.
137 * @param interface Interface when forwarding.
[cb41a5e]138 *
139 */
[47a7174f]140int devmap_device_register_with_iface(const char *fqdn,
141 devmap_handle_t *handle, sysarg_t interface)
[1090b8c]142{
[cb41a5e]143 int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
144
145 if (phone < 0)
146 return phone;
147
[e77994dd]148 async_serialize_start();
149
[1090b8c]150 ipc_call_t answer;
[47a7174f]151 aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
[cb41a5e]152 &answer);
153
[96b02eb9]154 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[cb41a5e]155 if (retval != EOK) {
156 async_wait_for(req, NULL);
[e77994dd]157 async_serialize_end();
[cb41a5e]158 return retval;
159 }
160
161 async_wait_for(req, &retval);
162
[e77994dd]163 async_serialize_end();
164
[cb41a5e]165 if (retval != EOK) {
166 if (handle != NULL)
167 *handle = -1;
168 return retval;
169 }
170
171 if (handle != NULL)
[991f645]172 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]173
174 return retval;
175}
[1090b8c]176
[47a7174f]177/** Register new device.
178 *
179 * @param fqdn Fully qualified device name.
180 * @param handle Output: Handle to the created instance of device.
181 *
182 */
183int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
184{
185 return devmap_device_register_with_iface(fqdn, handle, 0);
186}
187
188
[991f645]189int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
[cb41a5e]190{
191 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
192
[1090b8c]193 if (phone < 0)
194 return phone;
[cb41a5e]195
[e77994dd]196 async_serialize_start();
197
[cb41a5e]198 ipc_call_t answer;
199 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
[1090b8c]200 &answer);
[cb41a5e]201
[96b02eb9]202 sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
[1313ee9]203 if (retval != EOK) {
204 async_wait_for(req, NULL);
205 async_serialize_end();
206 return retval;
207 }
208
209 async_wait_for(req, &retval);
210
211 async_serialize_end();
212
213 if (retval != EOK) {
214 if (handle != NULL)
[991f645]215 *handle = (devmap_handle_t) -1;
[1313ee9]216 return retval;
217 }
218
219 if (handle != NULL)
[991f645]220 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[1313ee9]221
222 return retval;
223}
224
[991f645]225int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
[1313ee9]226{
227 int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
228
229 if (phone < 0)
230 return phone;
[cb41a5e]231
[1313ee9]232 async_serialize_start();
233
234 ipc_call_t answer;
235 aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
236 &answer);
237
[96b02eb9]238 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
[1090b8c]239 if (retval != EOK) {
240 async_wait_for(req, NULL);
[e77994dd]241 async_serialize_end();
[1090b8c]242 return retval;
243 }
[cb41a5e]244
[1090b8c]245 async_wait_for(req, &retval);
[cb41a5e]246
[e77994dd]247 async_serialize_end();
248
[1090b8c]249 if (retval != EOK) {
250 if (handle != NULL)
[991f645]251 *handle = (devmap_handle_t) -1;
[1090b8c]252 return retval;
253 }
[cb41a5e]254
[1090b8c]255 if (handle != NULL)
[991f645]256 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
[cb41a5e]257
[1090b8c]258 return retval;
259}
260
[991f645]261devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
[1313ee9]262{
263 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
264
265 if (phone < 0)
266 return phone;
267
[96b02eb9]268 sysarg_t type;
[1313ee9]269 int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
270 if (retval != EOK)
271 return DEV_HANDLE_NONE;
272
273 return (devmap_handle_type_t) type;
274}
275
[991f645]276int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
[1090b8c]277{
278 int phone;
[cb41a5e]279
[1090b8c]280 if (flags & IPC_FLAG_BLOCKING) {
[9476f4f]281 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
[1090b8c]282 DEVMAP_CONNECT_TO_DEVICE, handle);
283 } else {
[9476f4f]284 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
[1090b8c]285 DEVMAP_CONNECT_TO_DEVICE, handle);
286 }
[cb41a5e]287
[1090b8c]288 return phone;
289}
290
[7fcb74c]291int devmap_null_create(void)
292{
293 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
294
295 if (phone < 0)
296 return -1;
297
[96b02eb9]298 sysarg_t null_id;
[1313ee9]299 int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
[7fcb74c]300 if (retval != EOK)
301 return -1;
302
303 return (int) null_id;
304}
305
306void devmap_null_destroy(int null_id)
307{
308 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
309
310 if (phone < 0)
311 return;
312
[96b02eb9]313 async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
[7fcb74c]314}
315
[1313ee9]316static size_t devmap_count_namespaces_internal(int phone)
[1090b8c]317{
[96b02eb9]318 sysarg_t count;
[1313ee9]319 int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
320 if (retval != EOK)
[cb41a5e]321 return 0;
322
[1313ee9]323 return count;
324}
325
[991f645]326static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
[1313ee9]327{
[96b02eb9]328 sysarg_t count;
[1313ee9]329 int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
[cb41a5e]330 if (retval != EOK)
331 return 0;
332
333 return count;
334}
[1090b8c]335
[1313ee9]336size_t devmap_count_namespaces(void)
[cb41a5e]337{
338 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
339
340 if (phone < 0)
341 return 0;
342
[1313ee9]343 return devmap_count_namespaces_internal(phone);
344}
345
[991f645]346size_t devmap_count_devices(devmap_handle_t ns_handle)
[1313ee9]347{
348 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]349
[1313ee9]350 if (phone < 0)
351 return 0;
[cb41a5e]352
[1313ee9]353 return devmap_count_devices_internal(phone, ns_handle);
354}
355
356size_t devmap_get_namespaces(dev_desc_t **data)
357{
358 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[cb41a5e]359
[1313ee9]360 if (phone < 0)
[cb41a5e]361 return 0;
362
[1313ee9]363 /* Loop until namespaces read succesful */
364 while (true) {
365 size_t count = devmap_count_namespaces_internal(phone);
366 if (count == 0)
367 return 0;
368
369 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
370 if (devs == NULL)
371 return 0;
372
373 async_serialize_start();
374
375 ipc_call_t answer;
376 aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
377
378 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
379 if (rc == EOVERFLOW) {
380 /*
381 * Number of namespaces has changed since
382 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
383 */
384 async_serialize_end();
385 free(devs);
386 continue;
387 }
388
389 if (rc != EOK) {
390 async_wait_for(req, NULL);
391 async_serialize_end();
392 free(devs);
393 return 0;
394 }
395
[96b02eb9]396 sysarg_t retval;
[1313ee9]397 async_wait_for(req, &retval);
398 async_serialize_end();
399
400 if (retval != EOK)
401 return 0;
402
403 *data = devs;
404 return count;
405 }
406}
407
[991f645]408size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
[1313ee9]409{
410 int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
[e77994dd]411
[1313ee9]412 if (phone < 0)
[cb41a5e]413 return 0;
414
[1313ee9]415 /* Loop until namespaces read succesful */
416 while (true) {
417 size_t count = devmap_count_devices_internal(phone, ns_handle);
418 if (count == 0)
419 return 0;
420
421 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
422 if (devs == NULL)
423 return 0;
424
425 async_serialize_start();
426
427 ipc_call_t answer;
428 aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
429
430 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
431 if (rc == EOVERFLOW) {
432 /*
433 * Number of devices has changed since
434 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
435 */
436 async_serialize_end();
437 free(devs);
438 continue;
439 }
440
441 if (rc != EOK) {
442 async_wait_for(req, NULL);
443 async_serialize_end();
444 free(devs);
445 return 0;
446 }
447
[96b02eb9]448 sysarg_t retval;
[1313ee9]449 async_wait_for(req, &retval);
450 async_serialize_end();
451
452 if (retval != EOK)
453 return 0;
454
455 *data = devs;
456 return count;
457 }
[1090b8c]458}
Note: See TracBrowser for help on using the repository browser.