Ignore:
File:
1 edited

Legend:

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

    re72fb34 r1a5b252  
    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_PARALLEL,
     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_PARALLEL, 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                         return ret;
    150                 }
    151 
    152                 link = link->next;
    153         }
    154 
    155         return ret;
    156202}
    157203
     
    161207 * this driver task.
    162208 *
    163  * @param name          Name of the new function
    164  * @param ftype         Function type, fun_inner or fun_exposed
    165  * @param match_ids     Match IDs (should be empty for fun_exposed)
    166  * @param devh          Devman handle of the device
    167  * @param funh          Place to store handle of the new function
    168  *
    169  * @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 *
    170217 */
    171218int devman_add_function(const char *name, fun_type_t ftype,
    172219    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
    173220{
    174         int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
    175         int fun_handle;
    176        
    177         if (phone < 0)
    178                 return phone;
    179        
    180         async_serialize_start();
    181        
    182221        int match_count = list_count(&match_ids->ids);
     222        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
     223       
    183224        ipc_call_t answer;
    184 
    185         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,
    186226            devh, match_count, &answer);
    187 
    188         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       
    189286        if (retval != EOK) {
    190287                async_wait_for(req, NULL);
    191                 async_serialize_end();
    192                 return retval;
    193         }
    194        
    195         int match_ids_rc = devman_send_match_ids(phone, match_ids);
     288                return retval;
     289        }
    196290       
    197291        async_wait_for(req, &retval);
    198        
    199         async_serialize_end();
    200        
    201         /* Prefer the answer to DEVMAN_ADD_FUNCTION in case of errors. */
    202         if ((match_ids_rc != EOK) && (retval == EOK)) {
    203                 retval = match_ids_rc;
    204         }
    205 
    206         if (retval == EOK)
    207                 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);
    208303        else
    209                 fun_handle = -1;
    210        
    211         *funh = fun_handle;
    212 
    213         return retval;
    214 }
    215 
    216 int devman_add_device_to_class(devman_handle_t devman_handle,
    217     const char *class_name)
    218 {
    219         int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
    220        
    221         if (phone < 0)
    222                 return phone;
    223        
    224         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
     329int devman_drv_fun_online(devman_handle_t funh)
     330{
     331        async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER);
     332        if (exch == NULL)
     333                return ENOMEM;
     334       
     335        sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_ONLINE, funh);
     336       
     337        devman_exchange_end(exch);
     338        return (int) retval;
     339}
     340
     341int devman_drv_fun_offline(devman_handle_t funh)
     342{
     343        async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER);
     344        if (exch == NULL)
     345                return ENOMEM;
     346       
     347        sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_OFFLINE, funh);
     348       
     349        devman_exchange_end(exch);
     350        return (int) retval;
     351}
     352
     353async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
     354    devman_handle_t handle, unsigned int flags)
     355{
     356        async_sess_t *sess;
     357       
     358        if (flags & IPC_FLAG_BLOCKING)
     359                sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
     360                            DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     361        else
     362                sess = service_connect(mgmt, SERVICE_DEVMAN,
     363                            DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
     364       
     365        return sess;
     366}
     367
     368int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
     369    unsigned int flags)
     370{
     371        async_exch_t *exch;
     372       
     373        if (flags & IPC_FLAG_BLOCKING)
     374                exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
     375        else {
     376                exch = devman_exchange_begin(DEVMAN_CLIENT);
     377                if (exch == NULL)
     378                        return ENOMEM;
     379        }
     380       
    225381        ipc_call_t answer;
    226         aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
    227             devman_handle, &answer);
    228        
    229         sysarg_t retval = async_data_write_start(phone, class_name,
    230             str_size(class_name));
     382        aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
     383            &answer);
     384        sysarg_t retval = async_data_write_start(exch, pathname,
     385            str_size(pathname));
     386       
     387        devman_exchange_end(exch);
     388       
    231389        if (retval != EOK) {
    232390                async_wait_for(req, NULL);
    233                 async_serialize_end();
    234391                return retval;
    235392        }
    236393       
    237394        async_wait_for(req, &retval);
    238         async_serialize_end();
    239        
    240         return retval;
    241 }
    242 
    243 void devman_hangup_phone(devman_interface_t iface)
    244 {
    245         switch (iface) {
    246         case DEVMAN_DRIVER:
    247                 if (devman_phone_driver >= 0) {
    248                         async_hangup(devman_phone_driver);
    249                         devman_phone_driver = -1;
    250                 }
    251                 break;
    252         case DEVMAN_CLIENT:
    253                 if (devman_phone_client >= 0) {
    254                         async_hangup(devman_phone_client);
    255                         devman_phone_client = -1;
    256                 }
    257                 break;
    258         default:
    259                 break;
    260         }
    261 }
    262 
    263 int devman_device_connect(devman_handle_t handle, unsigned int flags)
    264 {
    265         int phone;
    266        
    267         if (flags & IPC_FLAG_BLOCKING) {
    268                 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
    269                     DEVMAN_CONNECT_TO_DEVICE, handle);
    270         } else {
    271                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
    272                     DEVMAN_CONNECT_TO_DEVICE, handle);
    273         }
    274        
    275         return phone;
    276 }
    277 
    278 int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
    279 {
    280         int phone;
    281        
    282         if (flags & IPC_FLAG_BLOCKING) {
    283                 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
    284                     DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    285         } else {
    286                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
    287                     DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
    288         }
    289        
    290         return phone;
    291 }
    292 
    293 int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
    294     unsigned int flags)
    295 {
    296         int phone = devman_get_phone(DEVMAN_CLIENT, flags);
    297        
    298         if (phone < 0)
    299                 return phone;
    300        
    301         async_serialize_start();
    302        
    303         ipc_call_t answer;
    304         aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
    305             &answer);
    306        
    307         sysarg_t retval = async_data_write_start(phone, pathname,
    308             str_size(pathname));
    309         if (retval != EOK) {
    310                 async_wait_for(req, NULL);
    311                 async_serialize_end();
    312                 return retval;
    313         }
    314        
    315         async_wait_for(req, &retval);
    316        
    317         async_serialize_end();
    318395       
    319396        if (retval != EOK) {
    320397                if (handle != NULL)
    321398                        *handle = (devman_handle_t) -1;
     399               
    322400                return retval;
    323401        }
     
    329407}
    330408
    331 int devman_device_get_handle_by_class(const char *classname,
    332     const char *devname, devman_handle_t *handle, unsigned int flags)
    333 {
    334         int phone = devman_get_phone(DEVMAN_CLIENT, flags);
    335 
    336         if (phone < 0)
    337                 return phone;
    338 
    339         async_serialize_start();
    340 
     409static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
     410    size_t buf_size)
     411{
     412        async_exch_t *exch;
     413        ipc_call_t dreply;
     414        size_t act_size;
     415        sysarg_t dretval;
     416       
     417        exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
     418       
    341419        ipc_call_t answer;
    342         aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
    343             flags, &answer);
    344 
    345         sysarg_t retval = async_data_write_start(phone, classname,
    346             str_size(classname));
     420        aid_t req = async_send_1(exch, method, arg1, &answer);
     421        aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
     422        async_wait_for(dreq, &dretval);
     423       
     424        devman_exchange_end(exch);
     425       
     426        if (dretval != EOK) {
     427                async_wait_for(req, NULL);
     428                return dretval;
     429        }
     430       
     431        sysarg_t retval;
     432        async_wait_for(req, &retval);
     433       
     434        if (retval != EOK)
     435                return retval;
     436       
     437        act_size = IPC_GET_ARG2(dreply);
     438        assert(act_size <= buf_size - 1);
     439        buf[act_size] = '\0';
     440       
     441        return EOK;
     442}
     443
     444int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
     445{
     446        return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
     447            buf_size);
     448}
     449
     450int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
     451{
     452        return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
     453            buf_size);
     454}
     455
     456int devman_fun_online(devman_handle_t funh)
     457{
     458        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     459        if (exch == NULL)
     460                return ENOMEM;
     461       
     462        sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_ONLINE, funh);
     463       
     464        devman_exchange_end(exch);
     465        return (int) retval;
     466}
     467
     468int devman_fun_offline(devman_handle_t funh)
     469{
     470        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     471        if (exch == NULL)
     472                return ENOMEM;
     473       
     474        sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_OFFLINE, funh);
     475       
     476        devman_exchange_end(exch);
     477        return (int) retval;
     478}
     479
     480static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
     481    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
     482{
     483        async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
     484
     485        ipc_call_t answer;
     486        aid_t req = async_send_1(exch, method, arg1, &answer);
     487        int rc = async_data_read_start(exch, handle_buf, buf_size);
     488       
     489        devman_exchange_end(exch);
     490       
     491        if (rc != EOK) {
     492                async_wait_for(req, NULL);
     493                return rc;
     494        }
     495       
     496        sysarg_t retval;
     497        async_wait_for(req, &retval);
     498       
    347499        if (retval != EOK) {
    348                 async_wait_for(req, NULL);
    349                 async_serialize_end();
    350                 return retval;
    351         }
    352         retval = async_data_write_start(phone, devname,
    353             str_size(devname));
    354         if (retval != EOK) {
    355                 async_wait_for(req, NULL);
    356                 async_serialize_end();
    357                 return retval;
    358         }
    359 
    360         async_wait_for(req, &retval);
    361 
    362         async_serialize_end();
    363 
    364         if (retval != EOK) {
    365                 if (handle != NULL)
    366                         *handle = (devman_handle_t) -1;
    367                 return retval;
    368         }
    369 
    370         if (handle != NULL)
    371                 *handle = (devman_handle_t) IPC_GET_ARG1(answer);
    372 
    373         return retval;
    374 }
    375 
     500                return retval;
     501        }
     502       
     503        *act_size = IPC_GET_ARG1(answer);
     504        return EOK;
     505}
     506
     507/** Get list of handles.
     508 *
     509 * Returns an allocated array of handles.
     510 *
     511 * @param method        IPC method
     512 * @param arg1          IPC argument 1
     513 * @param data          Place to store pointer to array of handles
     514 * @param count         Place to store number of handles
     515 * @return              EOK on success or negative error code
     516 */
     517static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
     518    devman_handle_t **data, size_t *count)
     519{
     520        devman_handle_t *handles;
     521        size_t act_size;
     522        size_t alloc_size;
     523        int rc;
     524
     525        *data = NULL;
     526        act_size = 0;   /* silence warning */
     527
     528        rc = devman_get_handles_once(method, arg1, NULL, 0,
     529            &act_size);
     530        if (rc != EOK)
     531                return rc;
     532
     533        alloc_size = act_size;
     534        handles = malloc(alloc_size);
     535        if (handles == NULL)
     536                return ENOMEM;
     537
     538        while (true) {
     539                rc = devman_get_handles_once(method, arg1, handles, alloc_size,
     540                    &act_size);
     541                if (rc != EOK)
     542                        return rc;
     543
     544                if (act_size <= alloc_size)
     545                        break;
     546
     547                alloc_size *= 2;
     548                free(handles);
     549
     550                handles = malloc(alloc_size);
     551                if (handles == NULL)
     552                        return ENOMEM;
     553        }
     554
     555        *count = act_size / sizeof(devman_handle_t);
     556        *data = handles;
     557        return EOK;
     558}
     559
     560int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
     561{
     562        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     563        if (exch == NULL)
     564                return ENOMEM;
     565       
     566        sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
     567            funh, devh);
     568       
     569        devman_exchange_end(exch);
     570        return (int) retval;
     571}
     572
     573int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
     574    size_t *count)
     575{
     576        return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
     577            devh, funcs, count);
     578}
     579
     580int devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
     581{
     582        async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
     583        if (exch == NULL)
     584                return ENOMEM;
     585       
     586        sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_SID_TO_HANDLE,
     587            sid, handle);
     588       
     589        devman_exchange_end(exch);
     590        return (int) retval;
     591}
    376592
    377593/** @}
Note: See TracChangeset for help on using the changeset viewer.