Ignore:
File:
1 edited

Legend:

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

    r1a5b252 re72fb34  
    11/*
    22 * Copyright (c) 2007 Josef Cejka
    3  * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2009 Jiri Svoboda
    44 * Copyright (c) 2010 Lenka Trochtova
    55 * All rights reserved.
     
    3535 */
    3636
    37 #include <adt/list.h>
    3837#include <str.h>
     38#include <stdio.h>
    3939#include <ipc/services.h>
    40 #include <ns.h>
    4140#include <ipc/devman.h>
    4241#include <devman.h>
     42#include <async.h>
    4343#include <fibril_synch.h>
    44 #include <async.h>
    4544#include <errno.h>
    4645#include <malloc.h>
    4746#include <bool.h>
    48 
    49 static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
    50 static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
    51 
    52 static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
    53 static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
    54 
    55 static async_sess_t *devman_driver_block_sess = NULL;
    56 static async_sess_t *devman_client_block_sess = NULL;
    57 
    58 static async_sess_t *devman_driver_sess = NULL;
    59 static async_sess_t *devman_client_sess = NULL;
    60 
    61 static 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  */
    79 async_exch_t *devman_exchange_begin_blocking(devman_interface_t iface)
     47#include <adt/list.h>
     48
     49static int devman_phone_driver = -1;
     50static int devman_phone_client = -1;
     51
     52static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
     53
     54int devman_get_phone(devman_interface_t iface, unsigned int flags)
    8055{
    8156        switch (iface) {
    8257        case DEVMAN_DRIVER:
    83                 fibril_mutex_lock(&devman_driver_block_mutex);
     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;
     62                }
    8463               
    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);
    93                 }
     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);
    9470               
    95                 fibril_mutex_unlock(&devman_driver_block_mutex);
     71                fibril_mutex_unlock(&devman_phone_mutex);
     72                return devman_phone_driver;
     73        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;
     78                }
    9679               
    97                 clone_session(&devman_driver_mutex, devman_driver_block_sess,
    98                     &devman_driver_sess);
     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                }
    9987               
    100                 return async_exchange_begin(devman_driver_block_sess);
    101         case DEVMAN_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);
    112                 }
    113                
    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);
     88                fibril_mutex_unlock(&devman_phone_mutex);
     89                return devman_phone_client;
    12090        default:
    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  */
    132 async_exch_t *devman_exchange_begin(devman_interface_t iface)
     91                return -1;
     92        }
     93}
     94
     95/** Register running driver with device manager. */
     96int devman_driver_register(const char *name, async_client_conn_t conn)
     97{
     98        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     99       
     100        if (phone < 0)
     101                return phone;
     102       
     103        async_serialize_start();
     104       
     105        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));
     109        if (retval != EOK) {
     110                async_wait_for(req, NULL);
     111                async_serialize_end();
     112                return -1;
     113        }
     114       
     115        async_set_client_connection(conn);
     116       
     117        async_connect_to_me(phone, 0, 0, 0, NULL);
     118        async_wait_for(req, &retval);
     119       
     120        async_serialize_end();
     121       
     122        return retval;
     123}
     124
     125static 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
     139static 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;
     156}
     157
     158/** Add function to a device.
     159 *
     160 * Request devman to add a new function to the specified device owned by
     161 * this driver task.
     162 *
     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.
     170 */
     171int devman_add_function(const char *name, fun_type_t ftype,
     172    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
     173{
     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       
     182        int match_count = list_count(&match_ids->ids);
     183        ipc_call_t answer;
     184
     185        aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
     186            devh, match_count, &answer);
     187
     188        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     189        if (retval != EOK) {
     190                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);
     196       
     197        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);
     208        else
     209                fun_handle = -1;
     210       
     211        *funh = fun_handle;
     212
     213        return retval;
     214}
     215
     216int 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();
     225        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));
     231        if (retval != EOK) {
     232                async_wait_for(req, NULL);
     233                async_serialize_end();
     234                return retval;
     235        }
     236       
     237        async_wait_for(req, &retval);
     238        async_serialize_end();
     239       
     240        return retval;
     241}
     242
     243void devman_hangup_phone(devman_interface_t iface)
    133244{
    134245        switch (iface) {
    135246        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);
     247                if (devman_phone_driver >= 0) {
     248                        async_hangup(devman_phone_driver);
     249                        devman_phone_driver = -1;
     250                }
     251                break;
    149252        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);
     253                if (devman_phone_client >= 0) {
     254                        async_hangup(devman_phone_client);
     255                        devman_phone_client = -1;
     256                }
     257                break;
    163258        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  */
    173 void devman_exchange_end(async_exch_t *exch)
    174 {
    175         async_exchange_end(exch);
    176 }
    177 
    178 /** Register running driver with device manager. */
    179 int devman_driver_register(const char *name, async_client_conn_t conn)
    180 {
    181         async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    182        
    183         ipc_call_t answer;
    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        
    189         if (retval != EOK) {
    190                 async_wait_for(req, NULL);
    191                 return retval;
    192         }
    193        
    194         async_set_client_connection(conn);
    195        
    196         exch = devman_exchange_begin(DEVMAN_DRIVER);
    197         async_connect_to_me(exch, 0, 0, 0, conn, NULL);
    198         devman_exchange_end(exch);
    199        
    200         async_wait_for(req, &retval);
    201         return retval;
    202 }
    203 
    204 /** Add function to a device.
    205  *
    206  * Request devman to add a new function to the specified device owned by
    207  * this driver task.
    208  *
    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  *
    217  */
    218 int devman_add_function(const char *name, fun_type_t ftype,
    219     match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
    220 {
    221         int match_count = list_count(&match_ids->ids);
    222         async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
    223        
    224         ipc_call_t answer;
    225         aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
    226             devh, match_count, &answer);
    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);
     259                break;
     260        }
     261}
     262
     263int 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);
    265270        } else {
    266                 if (funh != NULL)
    267                         *funh = -1;
    268         }
    269        
    270         return retval;
    271 }
    272 
    273 int 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        
    286         if (retval != EOK) {
    287                 async_wait_for(req, NULL);
    288                 return retval;
    289         }
    290        
    291         async_wait_for(req, &retval);
    292         return retval;
    293 }
    294 
    295 async_sess_t *devman_device_connect(exch_mgmt_t mgmt, devman_handle_t handle,
     271                phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
     272                    DEVMAN_CONNECT_TO_DEVICE, handle);
     273        }
     274       
     275        return phone;
     276}
     277
     278int 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
     293int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
    296294    unsigned int flags)
    297295{
    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);
    303         else
    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  */
    317 int 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 
    329 int 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 
    341 int 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 
    353 async_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 
    368 int 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        
    381         ipc_call_t answer;
    382         aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
     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,
    383305            &answer);
    384         sysarg_t retval = async_data_write_start(exch, pathname,
     306       
     307        sysarg_t retval = async_data_write_start(phone, pathname,
    385308            str_size(pathname));
    386        
    387         devman_exchange_end(exch);
    388        
    389         if (retval != EOK) {
    390                 async_wait_for(req, NULL);
    391                 return retval;
    392         }
    393        
    394         async_wait_for(req, &retval);
     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();
    395318       
    396319        if (retval != EOK) {
    397320                if (handle != NULL)
    398321                        *handle = (devman_handle_t) -1;
    399                
    400322                return retval;
    401323        }
     
    407329}
    408330
    409 static 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        
    419         ipc_call_t answer;
    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 
    444 int 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 
    450 int 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 
    456 int 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 
    468 int 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 
    480 static 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        
    499         if (retval != EOK) {
    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  */
    517 static 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 
    560 int 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 
    573 int 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 
    580 int 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 }
     331int 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
     341        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));
     347        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
    592376
    593377/** @}
Note: See TracChangeset for help on using the changeset viewer.