Ignore:
File:
1 edited

Legend:

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

    rcc574511 rd0dd7b5  
    4545static FIBRIL_MUTEX_INITIALIZE(loc_consumer_mutex);
    4646
     47static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
     48static bool loc_callback_created = false;
     49
    4750static async_sess_t *loc_supp_block_sess = NULL;
    4851static async_sess_t *loc_cons_block_sess = NULL;
     
    5154static async_sess_t *loc_consumer_sess = NULL;
    5255
     56static loc_cat_change_cb_t cat_change_cb = NULL;
     57
     58static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     59{
     60        loc_cat_change_cb_t cb_fun;
     61       
     62        while (true) {
     63                ipc_call_t call;
     64                ipc_callid_t callid = async_get_call(&call);
     65               
     66                if (!IPC_GET_IMETHOD(call)) {
     67                        /* TODO: Handle hangup */
     68                        return;
     69                }
     70               
     71                int retval;
     72               
     73                switch (IPC_GET_IMETHOD(call)) {
     74                case LOC_EVENT_CAT_CHANGE:
     75                        fibril_mutex_lock(&loc_callback_mutex);
     76                        cb_fun = cat_change_cb;
     77                        if (cb_fun != NULL) {
     78                                (*cb_fun)();
     79                        }
     80                        fibril_mutex_unlock(&loc_callback_mutex);
     81                        retval = 0;
     82                        break;
     83                default:
     84                        retval = ENOTSUP;
     85                }
     86               
     87                async_answer_0(callid, retval);
     88        }
     89}
     90
     91
    5392static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
    5493    async_sess_t **dst)
     
    6099       
    61100        fibril_mutex_unlock(mtx);
     101}
     102
     103static int loc_callback_create(void)
     104{
     105        async_exch_t *exch;
     106        sysarg_t retval;
     107        int rc = EOK;
     108
     109        fibril_mutex_lock(&loc_callback_mutex);
     110       
     111        if (!loc_callback_created) {
     112                exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
     113               
     114                ipc_call_t answer;
     115                aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
     116                async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
     117                loc_exchange_end(exch);
     118               
     119                async_wait_for(req, &retval);
     120                if (rc != EOK)
     121                        goto done;
     122               
     123                if (retval != EOK) {
     124                        rc = retval;
     125                        goto done;
     126                }
     127               
     128                loc_callback_created = true;
     129        }
     130       
     131        rc = EOK;
     132done:
     133        fibril_mutex_unlock(&loc_callback_mutex);
     134        return rc;
    62135}
    63136
     
    194267}
    195268
    196 /** Register new device.
    197  *
    198  * The @p interface is used when forwarding connection to the driver.
     269/** Register new service.
     270 *
     271 * The @p interface is used when forwarding connection to the server.
    199272 * If not 0, the first argument is the interface and the second argument
    200273 * is the service ID.
     
    203276 * the handle (to ensure backward compatibility).
    204277 *
    205  * @param      fqdn      Fully qualified device name.
    206  * @param[out] handle    Handle to the created instance of device.
    207  * @param      interface Interface when forwarding.
    208  *
    209  */
    210 int loc_service_register_with_iface(const char *fqdn,
    211     service_id_t *handle, sysarg_t interface)
     278 * @param      fqsn      Fully qualified service name
     279 * @param[out] sid       Service ID of new service
     280 * @param      interface Interface when forwarding
     281 *
     282 */
     283int loc_service_register_with_iface(const char *fqsn,
     284    service_id_t *sid, sysarg_t interface)
    212285{
    213286        async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
     
    216289        aid_t req = async_send_2(exch, LOC_SERVICE_REGISTER, interface, 0,
    217290            &answer);
    218         sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
     291        sysarg_t retval = async_data_write_start(exch, fqsn, str_size(fqsn));
    219292       
    220293        loc_exchange_end(exch);
     
    228301       
    229302        if (retval != EOK) {
    230                 if (handle != NULL)
    231                         *handle = -1;
    232                
    233                 return retval;
    234         }
    235        
    236         if (handle != NULL)
    237                 *handle = (service_id_t) IPC_GET_ARG1(answer);
     303                if (sid != NULL)
     304                        *sid = -1;
     305               
     306                return retval;
     307        }
     308       
     309        if (sid != NULL)
     310                *sid = (service_id_t) IPC_GET_ARG1(answer);
    238311       
    239312        return retval;
    240313}
    241314
    242 /** Register new device.
    243  *
    244  * @param fqdn   Fully qualified device name.
    245  * @param handle Output: Handle to the created instance of device.
    246  *
    247  */
    248 int loc_service_register(const char *fqdn, service_id_t *handle)
    249 {
    250         return loc_service_register_with_iface(fqdn, handle, 0);
     315/** Register new service.
     316 *
     317 * @param fqsn  Fully qualified service name
     318 * @param sid   Output: ID of new service
     319 *
     320 */
     321int loc_service_register(const char *fqdn, service_id_t *sid)
     322{
     323        return loc_service_register_with_iface(fqdn, sid, 0);
     324}
     325
     326/** Unregister service.
     327 *
     328 * @param sid   Service ID
     329 */
     330int loc_service_unregister(service_id_t sid)
     331{
     332        async_exch_t *exch;
     333        sysarg_t retval;
     334       
     335        exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
     336        retval = async_req_1_0(exch, LOC_SERVICE_UNREGISTER, sid);
     337        loc_exchange_end(exch);
     338       
     339        return (int)retval;
    251340}
    252341
     
    289378       
    290379        return retval;
     380}
     381
     382/** Get object name.
     383 *
     384 * Provided ID of an object, return its name.
     385 *
     386 * @param method        IPC method
     387 * @param id            Object ID
     388 * @param name          Place to store pointer to new string. Caller should
     389 *                      free it using free().
     390 * @return              EOK on success or negative error code
     391 */
     392static int loc_get_name_internal(sysarg_t method, sysarg_t id, char **name)
     393{
     394        async_exch_t *exch;
     395        char name_buf[LOC_NAME_MAXLEN + 1];
     396        ipc_call_t dreply;
     397        size_t act_size;
     398        sysarg_t dretval;
     399       
     400        *name = NULL;
     401        exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
     402       
     403        ipc_call_t answer;
     404        aid_t req = async_send_1(exch, method, id, &answer);
     405        aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN,
     406            &dreply);
     407        async_wait_for(dreq, &dretval);
     408       
     409        loc_exchange_end(exch);
     410       
     411        if (dretval != EOK) {
     412                async_wait_for(req, NULL);
     413                return dretval;
     414        }
     415       
     416        sysarg_t retval;
     417        async_wait_for(req, &retval);
     418       
     419        if (retval != EOK)
     420                return retval;
     421       
     422        act_size = IPC_GET_ARG2(dreply);
     423        assert(act_size <= LOC_NAME_MAXLEN);
     424        name_buf[act_size] = '\0';
     425
     426        *name = str_dup(name_buf);
     427        if (*name == NULL)
     428                return ENOMEM;
     429       
     430        return EOK;
     431}
     432
     433/** Get category name.
     434 *
     435 * Provided ID of a service, return its name.
     436 *
     437 * @param cat_id        Category ID
     438 * @param name          Place to store pointer to new string. Caller should
     439 *                      free it using free().
     440 * @return              EOK on success or negative error code
     441 */
     442int loc_category_get_name(category_id_t cat_id, char **name)
     443{
     444        return loc_get_name_internal(LOC_CATEGORY_GET_NAME, cat_id, name);
     445}
     446
     447/** Get service name.
     448 *
     449 * Provided ID of a service, return its name.
     450 *
     451 * @param svc_id        Service ID
     452 * @param name          Place to store pointer to new string. Caller should
     453 *                      free it using free().
     454 * @return              EOK on success or negative error code
     455 */
     456int loc_service_get_name(service_id_t svc_id, char **name)
     457{
     458        return loc_get_name_internal(LOC_SERVICE_GET_NAME, svc_id, name);
    291459}
    292460
     
    589757}
    590758
    591 static int loc_category_get_svcs_internal(category_id_t cat_id,
    592     service_id_t *id_buf, size_t buf_size, size_t *act_size)
     759static int loc_category_get_ids_once(sysarg_t method, sysarg_t arg1,
     760    sysarg_t *id_buf, size_t buf_size, size_t *act_size)
    593761{
    594762        async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
    595763
    596764        ipc_call_t answer;
    597         aid_t req = async_send_1(exch, LOC_CATEGORY_GET_SVCS, cat_id,
    598             &answer);
     765        aid_t req = async_send_1(exch, method, arg1, &answer);
    599766        int rc = async_data_read_start(exch, id_buf, buf_size);
    600767       
     
    614781       
    615782        *act_size = IPC_GET_ARG1(answer);
     783        return EOK;
     784}
     785
     786/** Get list of IDs.
     787 *
     788 * Returns an allocated array of service IDs.
     789 *
     790 * @param method        IPC method
     791 * @param arg1          IPC argument 1
     792 * @param data          Place to store pointer to array of IDs
     793 * @param count         Place to store number of IDs
     794 * @return              EOK on success or negative error code
     795 */
     796static int loc_get_ids_internal(sysarg_t method, sysarg_t arg1,
     797    sysarg_t **data, size_t *count)
     798{
     799        service_id_t *ids;
     800        size_t act_size;
     801        size_t alloc_size;
     802        int rc;
     803
     804        *data = NULL;
     805        act_size = 0;   /* silence warning */
     806
     807        rc = loc_category_get_ids_once(method, arg1, NULL, 0,
     808            &act_size);
     809        if (rc != EOK)
     810                return rc;
     811
     812        alloc_size = act_size;
     813        ids = malloc(alloc_size);
     814        if (ids == NULL)
     815                return ENOMEM;
     816
     817        while (true) {
     818                rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
     819                    &act_size);
     820                if (rc != EOK)
     821                        return rc;
     822
     823                if (act_size <= alloc_size)
     824                        break;
     825
     826                alloc_size *= 2;
     827                free(ids);
     828
     829                ids = malloc(alloc_size);
     830                if (ids == NULL)
     831                        return ENOMEM;
     832        }
     833
     834        *count = act_size / sizeof(category_id_t);
     835        *data = ids;
    616836        return EOK;
    617837}
     
    626846 * @return              EOK on success or negative error code
    627847 */
    628 int loc_category_get_svcs(category_id_t cat_id, category_id_t **data,
     848int loc_category_get_svcs(category_id_t cat_id, service_id_t **data,
    629849    size_t *count)
    630850{
    631         service_id_t *ids;
    632         size_t act_size;
    633         size_t alloc_size;
    634         int rc;
    635 
    636         *data = NULL;
    637         act_size = 0;   /* silence warning */
    638 
    639         rc = loc_category_get_svcs_internal(cat_id, NULL, 0, &act_size);
    640         if (rc != EOK)
    641                 return rc;
    642 
    643         alloc_size = act_size;
    644         ids = malloc(alloc_size);
    645         if (ids == NULL)
    646                 return ENOMEM;
    647 
    648         while (true) {
    649                 rc = loc_category_get_svcs_internal(cat_id, ids, alloc_size,
    650                     &act_size);
    651                 if (rc != EOK)
    652                         return rc;
    653 
    654                 if (act_size <= alloc_size)
    655                         break;
    656 
    657                 alloc_size *= 2;
    658                 free(ids);
    659 
    660                 ids = malloc(alloc_size);
    661                 if (ids == NULL)
    662                         return ENOMEM;
    663         }
    664 
    665         *count = act_size / sizeof(category_id_t);
    666         *data = ids;
     851        return loc_get_ids_internal(LOC_CATEGORY_GET_SVCS, cat_id,
     852            data, count);
     853}
     854
     855/** Get list of categories.
     856 *
     857 * Returns an allocated array of category IDs.
     858 *
     859 * @param data          Place to store pointer to array of IDs
     860 * @param count         Place to store number of IDs
     861 * @return              EOK on success or negative error code
     862 */
     863int loc_get_categories(category_id_t **data, size_t *count)
     864{
     865        return loc_get_ids_internal(LOC_GET_CATEGORIES, 0,
     866            data, count);
     867}
     868
     869int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
     870{
     871        if (loc_callback_create() != EOK)
     872                return EIO;
     873
     874        cat_change_cb = cb_fun;
    667875        return EOK;
    668876}
Note: See TracChangeset for help on using the changeset viewer.