Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/devman.c

    r8b1e15ac r45059d6b  
    11/*
    22 * Copyright (c) 2007 Josef Cejka
    3  * Copyright (c) 2009 Jiri Svoboda
     3 * Copyright (c) 2011 Jiri Svoboda
    44 * Copyright (c) 2010 Lenka Trochtova
    55 * All rights reserved.
     
    3535 */
    3636
     37#include <adt/list.h>
    3738#include <str.h>
    38 #include <stdio.h>
    3939#include <ipc/services.h>
     40#include <ns.h>
    4041#include <ipc/devman.h>
    4142#include <devman.h>
     43#include <fibril_synch.h>
    4244#include <async.h>
    43 #include <fibril_synch.h>
    4445#include <errno.h>
    4546#include <malloc.h>
    4647#include <bool.h>
    47 #include <adt/list.h>
    48 
    49 static int devman_phone_driver = -1;
    50 static int devman_phone_client = -1;
    51 
    52 static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
    53 
    54 int devman_get_phone(devman_interface_t iface, unsigned int flags)
     48
     49static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
     50static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
     51
     52static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
     53static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
     54
     55static async_sess_t *devman_driver_block_sess = NULL;
     56static async_sess_t *devman_client_block_sess = NULL;
     57
     58static async_sess_t *devman_driver_sess = NULL;
     59static async_sess_t *devman_client_sess = NULL;
     60
     61static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
     62    async_sess_t **dst)
     63{
     64        fibril_mutex_lock(mtx);
     65       
     66        if ((*dst == NULL) && (src != NULL))
     67                *dst = src;
     68       
     69        fibril_mutex_unlock(mtx);
     70}
     71
     72/** Start an async exchange on the devman session (blocking).
     73 *
     74 * @param iface Device manager interface to choose
     75 *
     76 * @return New exchange.
     77 *
     78 */
     79async_exch_t *devman_exchange_begin_blocking(devman_interface_t iface)
    5580{
    5681        switch (iface) {
    5782        case DEVMAN_DRIVER:
    58                 fibril_mutex_lock(&devman_phone_mutex);
    59                 if (devman_phone_driver >= 0) {
    60                         fibril_mutex_unlock(&devman_phone_mutex);
    61                         return devman_phone_driver;
     83                fibril_mutex_lock(&devman_driver_block_mutex);
     84               
     85                while (devman_driver_block_sess == NULL) {
     86                        clone_session(&devman_driver_mutex, devman_driver_sess,
     87                            &devman_driver_block_sess);
     88                       
     89                        if (devman_driver_block_sess == NULL)
     90                                devman_driver_block_sess =
     91                                    service_connect_blocking(EXCHANGE_SERIALIZE,
     92                                    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    6293                }
    6394               
    64                 if (flags & IPC_FLAG_BLOCKING)
    65                         devman_phone_driver = async_connect_me_to_blocking(
    66                             PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    67                 else
    68                         devman_phone_driver = async_connect_me_to(PHONE_NS,
    69                             SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
    70                
    71                 fibril_mutex_unlock(&devman_phone_mutex);
    72                 return devman_phone_driver;
     95                fibril_mutex_unlock(&devman_driver_block_mutex);
     96               
     97                clone_session(&devman_driver_mutex, devman_driver_block_sess,
     98                    &devman_driver_sess);
     99               
     100                return async_exchange_begin(devman_driver_block_sess);
    73101        case DEVMAN_CLIENT:
    74                 fibril_mutex_lock(&devman_phone_mutex);
    75                 if (devman_phone_client >= 0) {
    76                         fibril_mutex_unlock(&devman_phone_mutex);
    77                         return devman_phone_client;
     102                fibril_mutex_lock(&devman_client_block_mutex);
     103               
     104                while (devman_client_block_sess == NULL) {
     105                        clone_session(&devman_client_mutex, devman_client_sess,
     106                            &devman_client_block_sess);
     107                       
     108                        if (devman_client_block_sess == NULL)
     109                                devman_client_block_sess =
     110                                    service_connect_blocking(EXCHANGE_SERIALIZE,
     111                                    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
    78112                }
    79113               
    80                 if (flags & IPC_FLAG_BLOCKING) {
    81                         devman_phone_client = async_connect_me_to_blocking(
    82                             PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
    83                 } else {
    84                         devman_phone_client = async_connect_me_to(PHONE_NS,
    85                             SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
    86                 }
    87                
    88                 fibril_mutex_unlock(&devman_phone_mutex);
    89                 return devman_phone_client;
     114                fibril_mutex_unlock(&devman_client_block_mutex);
     115               
     116                clone_session(&devman_client_mutex, devman_client_block_sess,
     117                    &devman_client_sess);
     118               
     119                return async_exchange_begin(devman_client_block_sess);
    90120        default:
    91                 return -1;
    92         }
     121                return NULL;
     122        }
     123}
     124
     125/** Start an async exchange on the devman session.
     126 *
     127 * @param iface Device manager interface to choose
     128 *
     129 * @return New exchange.
     130 *
     131 */
     132async_exch_t *devman_exchange_begin(devman_interface_t iface)
     133{
     134        switch (iface) {
     135        case DEVMAN_DRIVER:
     136                fibril_mutex_lock(&devman_driver_mutex);
     137               
     138                if (devman_driver_sess == NULL)
     139                        devman_driver_sess =
     140                            service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
     141                            DEVMAN_DRIVER, 0);
     142               
     143                fibril_mutex_unlock(&devman_driver_mutex);
     144               
     145                if (devman_driver_sess == NULL)
     146                        return NULL;
     147               
     148                return async_exchange_begin(devman_driver_sess);
     149        case DEVMAN_CLIENT:
     150                fibril_mutex_lock(&devman_client_mutex);
     151               
     152                if (devman_client_sess == NULL)
     153                        devman_client_sess =
     154                            service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
     155                            DEVMAN_CLIENT, 0);
     156               
     157                fibril_mutex_unlock(&devman_client_mutex);
     158               
     159                if (devman_client_sess == NULL)
     160                        return NULL;
     161               
     162                return async_exchange_begin(devman_client_sess);
     163        default:
     164                return NULL;
     165        }
     166}
     167
     168/** Finish an async exchange on the devman session.
     169 *
     170 * @param exch Exchange to be finished.
     171 *
     172 */
     173void devman_exchange_end(async_exch_t *exch)
     174{
     175        async_exchange_end(exch);
    93176}
    94177
     
    96179int devman_driver_register(const char *name, async_client_conn_t conn)
    97180{
    98         int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
    99        
    100         if (phone < 0)
    101                 return phone;
    102        
    103         async_serialize_start();
     181        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    104182       
    105183        ipc_call_t answer;
    106         aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
    107        
    108         sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     184        aid_t req = async_send_2(exch, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
     185        sysarg_t retval = async_data_write_start(exch, name, str_size(name));
     186       
     187        devman_exchange_end(exch);
     188       
    109189        if (retval != EOK) {
    110190                async_wait_for(req, NULL);
    111                 async_serialize_end();
    112                 return -1;
     191                return retval;
    113192        }
    114193       
    115194        async_set_client_connection(conn);
    116195       
    117         async_connect_to_me(phone, 0, 0, 0, NULL);
     196        exch = devman_exchange_begin(DEVMAN_DRIVER);
     197        async_connect_to_me(exch, 0, 0, 0, conn, NULL);
     198        devman_exchange_end(exch);
     199       
    118200        async_wait_for(req, &retval);
    119        
    120         async_serialize_end();
    121        
    122201        return retval;
    123 }
    124 
    125 static int devman_send_match_id(int phone, match_id_t *match_id)
    126 {
    127         ipc_call_t answer;
    128 
    129         aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
    130             &answer);
    131         int retval = async_data_write_start(phone, match_id->id,
    132             str_size(match_id->id));
    133 
    134         async_wait_for(req, NULL);
    135         return retval;
    136 }
    137 
    138 
    139 static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
    140 {
    141         link_t *link = match_ids->ids.next;
    142         match_id_t *match_id = NULL;
    143         int ret = EOK;
    144 
    145         while (link != &match_ids->ids) {
    146                 match_id = list_get_instance(link, match_id_t, link);
    147                 ret = devman_send_match_id(phone, match_id);
    148                 if (ret != EOK) {
    149                         printf("Driver failed to send match id, error %d\n",
    150                             ret);
    151                         return ret;
    152                 }
    153 
    154                 link = link->next;
    155         }
    156 
    157         return ret;
    158202}
    159203
     
    163207 * this driver task.
    164208 *
    165  * @param name          Name of the new function
    166  * @param ftype         Function type, fun_inner or fun_exposed
    167  * @param match_ids     Match IDs (should be empty for fun_exposed)
    168  * @param devh          Devman handle of the device
    169  * @param funh          Place to store handle of the new function
    170  *
    171  * @return              EOK on success or negative error code.
     209 * @param name      Name of the new function
     210 * @param ftype     Function type, fun_inner or fun_exposed
     211 * @param match_ids Match IDs (should be empty for fun_exposed)
     212 * @param devh      Devman handle of the device
     213 * @param funh      Place to store handle of the new function
     214 *
     215 * @return EOK on success or negative error code.
     216 *
    172217 */
    173218int devman_add_function(const char *name, fun_type_t ftype,
    174219    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
    175220{
    176         int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
    177         int fun_handle;
    178        
    179         if (phone < 0)
    180                 return phone;
    181        
    182         async_serialize_start();
    183        
    184221        int match_count = list_count(&match_ids->ids);
     222        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
     223       
    185224        ipc_call_t answer;
    186 
    187         aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
     225        aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
    188226            devh, match_count, &answer);
    189 
    190         sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     227        sysarg_t retval = async_data_write_start(exch, name, str_size(name));
     228        if (retval != EOK) {
     229                devman_exchange_end(exch);
     230                async_wait_for(req, NULL);
     231                return retval;
     232        }
     233       
     234        match_id_t *match_id = NULL;
     235       
     236        list_foreach(match_ids->ids, link) {
     237                match_id = list_get_instance(link, match_id_t, link);
     238               
     239                ipc_call_t answer2;
     240                aid_t req2 = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
     241                    match_id->score, &answer2);
     242                retval = async_data_write_start(exch, match_id->id,
     243                    str_size(match_id->id));
     244                if (retval != EOK) {
     245                        devman_exchange_end(exch);
     246                        async_wait_for(req2, NULL);
     247                        async_wait_for(req, NULL);
     248                        return retval;
     249                }
     250               
     251                async_wait_for(req2, &retval);
     252                if (retval != EOK) {
     253                        devman_exchange_end(exch);
     254                        async_wait_for(req, NULL);
     255                        return retval;
     256                }
     257        }
     258       
     259        devman_exchange_end(exch);
     260       
     261        async_wait_for(req, &retval);
     262        if (retval == EOK) {
     263                if (funh != NULL)
     264                        *funh = (int) IPC_GET_ARG1(answer);
     265        } else {
     266                if (funh != NULL)
     267                        *funh = -1;
     268        }
     269       
     270        return retval;
     271}
     272
     273int devman_add_device_to_category(devman_handle_t devman_handle,
     274    const char *cat_name)
     275{
     276        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
     277       
     278        ipc_call_t answer;
     279        aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CATEGORY,
     280            devman_handle, &answer);
     281        sysarg_t retval = async_data_write_start(exch, cat_name,
     282            str_size(cat_name));
     283       
     284        devman_exchange_end(exch);
     285       
    191286        if (retval != EOK) {
    192287                async_wait_for(req, NULL);
    193                 async_serialize_end();
    194                 return retval;
    195         }
    196        
    197         devman_send_match_ids(phone, match_ids);
     288                return retval;
     289        }
    198290       
    199291        async_wait_for(req, &retval);
    200        
    201         async_serialize_end();
    202        
    203         if (retval == EOK)
    204                 fun_handle = (int) IPC_GET_ARG1(answer);
     292        return retval;
     293}
     294
     295async_sess_t *devman_device_connect(exch_mgmt_t mgmt, devman_handle_t handle,
     296    unsigned int flags)
     297{
     298        async_sess_t *sess;
     299       
     300        if (flags & IPC_FLAG_BLOCKING)
     301                sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
     302                            DEVMAN_CONNECT_TO_DEVICE, handle);
    205303        else
    206                 fun_handle = -1;
    207        
    208         *funh = fun_handle;
    209 
    210         return retval;
    211 }
    212 
    213 int devman_add_device_to_class(devman_handle_t devman_handle,
    214     const char *class_name)
    215 {
    216         int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
    217        
    218         if (phone < 0)
    219                 return phone;
    220        
    221         async_serialize_start();
     304                sess = service_connect(mgmt, SERVICE_DEVMAN,
     305                            DEVMAN_CONNECT_TO_DEVICE, handle);
     306       
     307        return sess;
     308}
     309
     310/** Remove function from device.
     311 *
     312 * Request devman to remove function owned by this driver task.
     313 * @param funh      Devman handle of the function
     314 *
     315 * @return EOK on success or negative error code.
     316 */
     317int devman_remove_function(devman_handle_t funh)
     318{
     319        async_exch_t *exch;
     320        sysarg_t retval;
     321       
     322        exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
     323        retval = async_req_1_0(exch, DEVMAN_REMOVE_FUNCTION, (sysarg_t) funh);
     324        devman_exchange_end(exch);
     325       
     326        return (int) retval;
     327}
     328
     329async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
     330    devman_handle_t handle, unsigned int flags)
     331{
     332        async_sess_t *sess;
     333       
     334        if (flags & IPC_FLAG_BLOCKING)
     335                sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
     336                            DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     337        else
     338                sess = service_connect(mgmt, SERVICE_DEVMAN,
     339                            DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     340       
     341        return sess;
     342}
     343
     344int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
     345    unsigned int flags)
     346{
     347        async_exch_t *exch;
     348       
     349        if (flags & IPC_FLAG_BLOCKING)
     350                exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
     351        else {
     352                exch = devman_exchange_begin(DEVMAN_CLIENT);
     353                if (exch == NULL)
     354                        return ENOMEM;
     355        }
     356       
    222357        ipc_call_t answer;
    223         aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
    224             devman_handle, &answer);
    225        
    226         sysarg_t retval = async_data_write_start(phone, class_name,
    227             str_size(class_name));
     358        aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
     359            &answer);
     360        sysarg_t retval = async_data_write_start(exch, pathname,
     361            str_size(pathname));
     362       
     363        devman_exchange_end(exch);
     364       
    228365        if (retval != EOK) {
    229366                async_wait_for(req, NULL);
    230                 async_serialize_end();
    231367                return retval;
    232368        }
    233369       
    234370        async_wait_for(req, &retval);
    235         async_serialize_end();
    236        
    237         return retval;
    238 }
    239 
    240 void devman_hangup_phone(devman_interface_t iface)
    241 {
    242         switch (iface) {
    243         case DEVMAN_DRIVER:
    244                 if (devman_phone_driver >= 0) {
    245                         async_hangup(devman_phone_driver);
    246                         devman_phone_driver = -1;
    247                 }
    248                 break;
    249         case DEVMAN_CLIENT:
    250                 if (devman_phone_client >= 0) {
    251                         async_hangup(devman_phone_client);
    252                         devman_phone_client = -1;
    253                 }
    254                 break;
    255         default:
    256                 break;
    257         }
    258 }
    259 
    260 int devman_device_connect(devman_handle_t handle, unsigned int flags)
    261 {
    262         int phone;
    263        
    264         if (flags & IPC_FLAG_BLOCKING) {
    265                 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
    266                     DEVMAN_CONNECT_TO_DEVICE, handle);
    267         } else {
    268                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
    269                     DEVMAN_CONNECT_TO_DEVICE, handle);
    270         }
    271        
    272         return phone;
    273 }
    274 
    275 int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
    276 {
    277         int phone;
    278        
    279         if (flags & IPC_FLAG_BLOCKING) {
    280                 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
    281                     DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    282         } else {
    283                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
    284                     DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    285         }
    286        
    287         return phone;
    288 }
    289 
    290 int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
    291     unsigned int flags)
    292 {
    293         int phone = devman_get_phone(DEVMAN_CLIENT, flags);
    294        
    295         if (phone < 0)
    296                 return phone;
    297        
    298         async_serialize_start();
    299        
    300         ipc_call_t answer;
    301         aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
    302             &answer);
    303        
    304         sysarg_t retval = async_data_write_start(phone, pathname,
    305             str_size(pathname));
    306         if (retval != EOK) {
    307                 async_wait_for(req, NULL);
    308                 async_serialize_end();
    309                 return retval;
    310         }
    311        
    312         async_wait_for(req, &retval);
    313        
    314         async_serialize_end();
    315371       
    316372        if (retval != EOK) {
    317373                if (handle != NULL)
    318374                        *handle = (devman_handle_t) -1;
     375               
    319376                return retval;
    320377        }
     
    326383}
    327384
     385static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
     386    size_t buf_size)
     387{
     388        async_exch_t *exch;
     389        ipc_call_t dreply;
     390        size_t act_size;
     391        sysarg_t dretval;
     392       
     393        exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
     394       
     395        ipc_call_t answer;
     396        aid_t req = async_send_1(exch, method, arg1, &answer);
     397        aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
     398        async_wait_for(dreq, &dretval);
     399       
     400        devman_exchange_end(exch);
     401       
     402        if (dretval != EOK) {
     403                async_wait_for(req, NULL);
     404                return dretval;
     405        }
     406       
     407        sysarg_t retval;
     408        async_wait_for(req, &retval);
     409       
     410        if (retval != EOK)
     411                return retval;
     412       
     413        act_size = IPC_GET_ARG2(dreply);
     414        assert(act_size <= buf_size - 1);
     415        buf[act_size] = '\0';
     416       
     417        return EOK;
     418}
     419
     420int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
     421{
     422        return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
     423            buf_size);
     424}
     425
     426int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
     427{
     428        return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
     429            buf_size);
     430}
     431
     432static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
     433    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
     434{
     435        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
     436
     437        ipc_call_t answer;
     438        aid_t req = async_send_1(exch, method, arg1, &answer);
     439        int rc = async_data_read_start(exch, handle_buf, buf_size);
     440       
     441        devman_exchange_end(exch);
     442       
     443        if (rc != EOK) {
     444                async_wait_for(req, NULL);
     445                return rc;
     446        }
     447       
     448        sysarg_t retval;
     449        async_wait_for(req, &retval);
     450       
     451        if (retval != EOK) {
     452                return retval;
     453        }
     454       
     455        *act_size = IPC_GET_ARG1(answer);
     456        return EOK;
     457}
     458
     459/** Get list of handles.
     460 *
     461 * Returns an allocated array of handles.
     462 *
     463 * @param method        IPC method
     464 * @param arg1          IPC argument 1
     465 * @param data          Place to store pointer to array of handles
     466 * @param count         Place to store number of handles
     467 * @return              EOK on success or negative error code
     468 */
     469static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
     470    devman_handle_t **data, size_t *count)
     471{
     472        devman_handle_t *handles;
     473        size_t act_size;
     474        size_t alloc_size;
     475        int rc;
     476
     477        *data = NULL;
     478        act_size = 0;   /* silence warning */
     479
     480        rc = devman_get_handles_once(method, arg1, NULL, 0,
     481            &act_size);
     482        if (rc != EOK)
     483                return rc;
     484
     485        alloc_size = act_size;
     486        handles = malloc(alloc_size);
     487        if (handles == NULL)
     488                return ENOMEM;
     489
     490        while (true) {
     491                rc = devman_get_handles_once(method, arg1, handles, alloc_size,
     492                    &act_size);
     493                if (rc != EOK)
     494                        return rc;
     495
     496                if (act_size <= alloc_size)
     497                        break;
     498
     499                alloc_size *= 2;
     500                free(handles);
     501
     502                handles = malloc(alloc_size);
     503                if (handles == NULL)
     504                        return ENOMEM;
     505        }
     506
     507        *count = act_size / sizeof(devman_handle_t);
     508        *data = handles;
     509        return EOK;
     510}
     511
     512int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
     513{
     514        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     515        if (exch == NULL)
     516                return ENOMEM;
     517       
     518        sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
     519            funh, devh);
     520       
     521        devman_exchange_end(exch);
     522        return (int) retval;
     523}
     524
     525int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
     526    size_t *count)
     527{
     528        return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
     529            devh, funcs, count);
     530}
     531
     532int devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
     533{
     534        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     535        if (exch == NULL)
     536                return ENOMEM;
     537       
     538        sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_SID_TO_HANDLE,
     539            sid, handle);
     540       
     541        devman_exchange_end(exch);
     542        return (int) retval;
     543}
    328544
    329545/** @}
Note: See TracChangeset for help on using the changeset viewer.