0,0 → 1,871 |
/* |
* Copyright (c) 2007 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
|
/** |
* @defgroup devmap Device mapper. |
* @brief HelenOS device mapper. |
* @{ |
*/ |
|
/** @file |
*/ |
|
#include <ipc/services.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <stdio.h> |
#include <errno.h> |
#include <bool.h> |
#include <fibril_sync.h> |
#include <stdlib.h> |
#include <string.h> |
#include <ipc/devmap.h> |
|
#define NAME "devmap" |
#define NULL_DEVICES 256 |
|
/** Representation of device driver. |
* |
* Each driver is responsible for a set of devices. |
* |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Fibril mutex for list of devices owned by this driver */ |
fibril_mutex_t devices_mutex; |
} devmap_driver_t; |
|
/** Info about registered device |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
dev_handle_t handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
|
LIST_INITIALIZE(devices_list); |
LIST_INITIALIZE(drivers_list); |
|
/* Locking order: |
* drivers_list_mutex |
* devices_list_mutex |
* (devmap_driver_t *)->devices_mutex |
* create_handle_mutex |
**/ |
|
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex); |
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv); |
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex); |
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex); |
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex); |
|
static dev_handle_t last_handle = 0; |
static devmap_device_t *null_devices[NULL_DEVICES]; |
|
static dev_handle_t devmap_create_handle(void) |
{ |
/* TODO: allow reusing old handles after their unregistration |
* and implement some version of LRU algorithm, avoid overflow |
*/ |
|
fibril_mutex_lock(&create_handle_mutex); |
last_handle++; |
fibril_mutex_unlock(&create_handle_mutex); |
|
return last_handle; |
} |
|
/** Find device with given name. |
* |
*/ |
static devmap_device_t *devmap_device_find_name(const char *name) |
{ |
link_t *item = devices_list.next; |
devmap_device_t *device = NULL; |
|
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (str_cmp(device->name, name) == 0) |
break; |
item = item->next; |
} |
|
if (item == &devices_list) |
return NULL; |
|
device = list_get_instance(item, devmap_device_t, devices); |
return device; |
} |
|
/** Find device with given handle. |
* |
* @todo: use hash table |
* |
*/ |
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
|
link_t *item = (&devices_list)->next; |
devmap_device_t *device = NULL; |
|
while (item != &devices_list) { |
device = list_get_instance(item, devmap_device_t, devices); |
if (device->handle == handle) |
break; |
item = item->next; |
} |
|
if (item == &devices_list) { |
fibril_mutex_unlock(&devices_list_mutex); |
return NULL; |
} |
|
device = list_get_instance(item, devmap_device_t, devices); |
|
fibril_mutex_unlock(&devices_list_mutex); |
|
return device; |
} |
|
/** |
* Unregister device and free it. It's assumed that driver's device list is |
* already locked. |
*/ |
static int devmap_device_unregister_core(devmap_device_t *device) |
{ |
list_remove(&(device->devices)); |
list_remove(&(device->driver_devices)); |
|
free(device->name); |
free(device); |
|
return EOK; |
} |
|
/** |
* Read info about new driver and add it into linked list of registered |
* drivers. |
*/ |
static void devmap_driver_register(devmap_driver_t **odriver) |
{ |
*odriver = NULL; |
|
ipc_call_t icall; |
ipc_callid_t iid = async_get_call(&icall); |
|
if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t)); |
|
if (driver == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
|
/* |
* Get driver name |
*/ |
ipc_callid_t callid; |
size_t name_size; |
if (!ipc_data_write_receive(&callid, &name_size)) { |
free(driver); |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
if (name_size > DEVMAP_NAME_MAXLEN) { |
free(driver); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* |
* Allocate buffer for device name. |
*/ |
driver->name = (char *) malloc(name_size + 1); |
if (driver->name == NULL) { |
free(driver); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) { |
free(driver->name); |
free(driver); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
driver->name[name_size] = 0; |
|
/* Initialize mutex for list of devices owned by this driver */ |
fibril_mutex_initialize(&driver->devices_mutex); |
|
/* |
* Initialize list of asociated devices |
*/ |
list_initialize(&driver->devices); |
|
/* |
* Create connection to the driver |
*/ |
ipc_call_t call; |
callid = async_get_call(&call); |
|
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) { |
ipc_answer_0(callid, ENOTSUP); |
|
free(driver->name); |
free(driver); |
ipc_answer_0(iid, ENOTSUP); |
return; |
} |
|
driver->phone = IPC_GET_ARG5(call); |
|
ipc_answer_0(callid, EOK); |
|
list_initialize(&(driver->drivers)); |
|
fibril_mutex_lock(&drivers_list_mutex); |
|
/* TODO: |
* check that no driver with name equal to driver->name is registered |
*/ |
|
/* |
* Insert new driver into list of registered drivers |
*/ |
list_append(&(driver->drivers), &drivers_list); |
fibril_mutex_unlock(&drivers_list_mutex); |
|
ipc_answer_0(iid, EOK); |
|
*odriver = driver; |
} |
|
/** |
* Unregister device driver, unregister all its devices and free driver |
* structure. |
* |
*/ |
static int devmap_driver_unregister(devmap_driver_t *driver) |
{ |
if (driver == NULL) |
return EEXISTS; |
|
fibril_mutex_lock(&drivers_list_mutex); |
|
if (driver->phone != 0) |
ipc_hangup(driver->phone); |
|
/* Remove it from list of drivers */ |
list_remove(&(driver->drivers)); |
|
/* Unregister all its devices */ |
fibril_mutex_lock(&devices_list_mutex); |
fibril_mutex_lock(&driver->devices_mutex); |
|
while (!list_empty(&(driver->devices))) { |
devmap_device_t *device = list_get_instance(driver->devices.next, |
devmap_device_t, driver_devices); |
devmap_device_unregister_core(device); |
} |
|
fibril_mutex_unlock(&driver->devices_mutex); |
fibril_mutex_unlock(&devices_list_mutex); |
fibril_mutex_unlock(&drivers_list_mutex); |
|
/* free name and driver */ |
if (driver->name != NULL) |
free(driver->name); |
|
free(driver); |
|
return EOK; |
} |
|
/** Register instance of device |
* |
*/ |
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall, |
devmap_driver_t *driver) |
{ |
if (driver == NULL) { |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* Create new device entry */ |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) { |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
|
/* Get device name */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
free(device); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
if (size > DEVMAP_NAME_MAXLEN) { |
free(device); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* +1 for terminating \0 */ |
device->name = (char *) malloc(size + 1); |
|
if (device->name == NULL) { |
free(device); |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
ipc_data_write_finalize(callid, device->name, size); |
device->name[size] = 0; |
|
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
|
fibril_mutex_lock(&devices_list_mutex); |
|
/* Check that device with such name is not already registered */ |
if (NULL != devmap_device_find_name(device->name)) { |
printf(NAME ": Device '%s' already registered\n", device->name); |
fibril_mutex_unlock(&devices_list_mutex); |
free(device->name); |
free(device); |
ipc_answer_0(iid, EEXISTS); |
return; |
} |
|
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
|
device->driver = driver; |
|
/* Insert device into list of all devices */ |
list_append(&device->devices, &devices_list); |
|
/* Insert device into list of devices that belog to one driver */ |
fibril_mutex_lock(&device->driver->devices_mutex); |
|
list_append(&device->driver_devices, &device->driver->devices); |
|
fibril_mutex_unlock(&device->driver->devices_mutex); |
fibril_condvar_broadcast(&devices_list_cv); |
fibril_mutex_unlock(&devices_list_mutex); |
|
ipc_answer_1(iid, EOK, device->handle); |
} |
|
/** |
* |
*/ |
static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall, |
devmap_driver_t *driver) |
{ |
/* TODO */ |
return EOK; |
} |
|
/** Connect client to the device. |
* |
* Find device driver owning requested device and forward |
* the message to it. |
* |
*/ |
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) |
{ |
/* |
* Get handle from request |
*/ |
dev_handle_t handle = IPC_GET_ARG2(*call); |
devmap_device_t *dev = devmap_device_find_handle(handle); |
|
if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
|
ipc_forward_fast(callid, dev->driver->phone, dev->handle, |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
} |
|
/** Find handle for device instance identified by name. |
* |
* In answer will be send EOK and device handle in arg1 or a error |
* code from errno.h. |
* |
*/ |
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall) |
{ |
/* |
* Wait for incoming message with device name (but do not |
* read the name itself until the buffer is allocated). |
*/ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* |
* Allocate buffer for device name. |
*/ |
char *name = (char *) malloc(size + 1); |
if (name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
/* |
* Send confirmation to sender and get data into buffer. |
*/ |
ipcarg_t retval = ipc_data_write_finalize(callid, name, size); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(name); |
return; |
} |
name[size] = '\0'; |
|
fibril_mutex_lock(&devices_list_mutex); |
const devmap_device_t *dev; |
recheck: |
|
/* |
* Find device name in the list of known devices. |
*/ |
dev = devmap_device_find_name(name); |
|
/* |
* Device was not found. |
*/ |
if (dev == NULL) { |
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) { |
/* Blocking lookup */ |
fibril_condvar_wait(&devices_list_cv, |
&devices_list_mutex); |
goto recheck; |
} |
|
ipc_answer_0(iid, ENOENT); |
free(name); |
fibril_mutex_unlock(&devices_list_mutex); |
return; |
} |
fibril_mutex_unlock(&devices_list_mutex); |
|
ipc_answer_1(iid, EOK, dev->handle); |
free(name); |
} |
|
/** Find name of device identified by id and send it to caller. |
* |
*/ |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
{ |
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
|
/* |
* Device not found. |
*/ |
if (device == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
|
ipc_answer_0(iid, EOK); |
|
/* FIXME: |
* We have no channel from DEVMAP to client, therefore |
* sending must be initiated by client. |
* |
* size_t name_size = str_size(device->name); |
* |
* int rc = ipc_data_write_send(phone, device->name, name_size); |
* if (rc != EOK) { |
* async_wait_for(req, NULL); |
* return rc; |
* } |
*/ |
|
/* TODO: send name in response */ |
} |
|
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
ipc_answer_1(iid, EOK, list_count(&devices_list)); |
fibril_mutex_unlock(&devices_list_mutex); |
} |
|
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&devices_list_mutex); |
|
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
if ((size % sizeof(dev_desc_t)) != 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
size_t count = size / sizeof(dev_desc_t); |
dev_desc_t *desc = (dev_desc_t *) malloc(size); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
|
size_t pos = 0; |
link_t *item = devices_list.next; |
|
while ((item != &devices_list) && (pos < count)) { |
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices); |
|
desc[pos].handle = device->handle; |
str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name); |
pos++; |
item = item->next; |
} |
|
ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t)); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(desc); |
return; |
} |
|
free(desc); |
|
fibril_mutex_unlock(&devices_list_mutex); |
|
ipc_answer_1(iid, EOK, pos); |
} |
|
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
|
unsigned int i; |
bool fnd = false; |
|
for (i = 0; i < NULL_DEVICES; i++) { |
if (null_devices[i] == NULL) { |
fnd = true; |
break; |
} |
} |
|
if (!fnd) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
|
/* Create NULL device entry */ |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
|
char null[DEVMAP_NAME_MAXLEN]; |
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i); |
|
device->name = str_dup(null); |
if (device->name == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
free(device); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
|
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
|
fibril_mutex_lock(&devices_list_mutex); |
|
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
device->driver = NULL; |
|
/* Insert device into list of all devices |
and into null devices array */ |
list_append(&device->devices, &devices_list); |
null_devices[i] = device; |
|
fibril_mutex_unlock(&devices_list_mutex); |
fibril_mutex_unlock(&null_devices_mutex); |
|
ipc_answer_1(iid, EOK, (ipcarg_t) i); |
} |
|
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
|
ipcarg_t i = IPC_GET_ARG1(*icall); |
|
if (null_devices[i] == NULL) { |
ipc_answer_0(iid, ENOENT); |
return; |
} |
|
devmap_device_unregister_core(null_devices[i]); |
null_devices[i] = NULL; |
|
fibril_mutex_unlock(&null_devices_mutex); |
|
ipc_answer_0(iid, EOK); |
} |
|
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init(void) |
{ |
fibril_mutex_lock(&null_devices_mutex); |
|
unsigned int i; |
for (i = 0; i < NULL_DEVICES; i++) |
null_devices[i] = NULL; |
|
fibril_mutex_unlock(&null_devices_mutex); |
|
return true; |
} |
|
/** Handle connection with device driver. |
* |
*/ |
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
{ |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
|
devmap_driver_t *driver = NULL; |
devmap_driver_register(&driver); |
|
if (NULL == driver) |
return; |
|
bool cont = true; |
while (cont) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
|
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
cont = false; |
continue; |
case DEVMAP_DRIVER_UNREGISTER: |
if (NULL == driver) |
ipc_answer_0(callid, ENOENT); |
else |
ipc_answer_0(callid, EOK); |
break; |
case DEVMAP_DEVICE_REGISTER: |
/* Register one instance of device */ |
devmap_device_register(callid, &call, driver); |
break; |
case DEVMAP_DEVICE_UNREGISTER: |
/* Remove instance of device identified by handler */ |
devmap_device_unregister(callid, &call, driver); |
break; |
case DEVMAP_DEVICE_GET_HANDLE: |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
devmap_get_name(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
|
if (driver != NULL) { |
/* |
* Unregister the device driver and all its devices. |
*/ |
devmap_driver_unregister(driver); |
driver = NULL; |
} |
} |
|
/** Handle connection with device client. |
* |
*/ |
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
{ |
/* Accept connection */ |
ipc_answer_0(iid, EOK); |
|
bool cont = true; |
while (cont) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
|
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
cont = false; |
continue; |
case DEVMAP_DEVICE_GET_HANDLE: |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
devmap_get_name(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_CREATE: |
devmap_null_create(callid, &call); |
break; |
case DEVMAP_DEVICE_NULL_DESTROY: |
devmap_null_destroy(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_COUNT: |
devmap_get_count(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_DEVICES: |
devmap_get_devices(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
} |
} |
} |
|
/** Function for handling connections to devmap |
* |
*/ |
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
/* Select interface */ |
switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) { |
case DEVMAP_DRIVER: |
devmap_connection_driver(iid, icall); |
break; |
case DEVMAP_CLIENT: |
devmap_connection_client(iid, icall); |
break; |
case DEVMAP_CONNECT_TO_DEVICE: |
/* Connect client to selected device */ |
devmap_forward(iid, icall); |
break; |
default: |
/* No such interface */ |
ipc_answer_0(iid, ENOENT); |
} |
} |
|
/** |
* |
*/ |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Device Mapper\n"); |
|
if (!devmap_init()) { |
printf(NAME ": Error while initializing service\n"); |
return -1; |
} |
|
/* Set a handler of incomming connections */ |
async_set_client_connection(devmap_connection); |
|
/* Register device mapper at naming service */ |
ipcarg_t phonead; |
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) |
return -1; |
|
printf(NAME ": Accepting connections\n"); |
async_manager(); |
|
/* Never reached */ |
return 0; |
} |
|
/** |
* @} |
*/ |