Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/tbarcfg/src/tbarcfg.c

    re63e74a ree3b28a9  
    3434 */
    3535
     36#include <async.h>
    3637#include <errno.h>
    3738#include <sif.h>
     39#include <ipc/tbarcfg.h>
     40#include <loc.h>
     41#include <task.h>
    3842#include <tbarcfg/tbarcfg.h>
     43#include <stdio.h>
    3944#include <stdlib.h>
    4045#include <str.h>
    4146#include "../private/tbarcfg.h"
     47
     48static void tbarcfg_notify_conn(ipc_call_t *, void *);
    4249
    4350/** Create taskbar configuration.
     
    784791}
    785792
     793/** Create taskbar configuration listener.
     794 *
     795 * Listens for taskbar configuration change notifications.
     796 *
     797 * @param nchan Notification channel (TBARCFG_NOTIFY_DEFAULT)
     798 * @param rlst Place to store pointer to new listener
     799 * @return EOK on success or an error code
     800 */
     801errno_t tbarcfg_listener_create(const char *nchan, void (*cb)(void *),
     802    void *arg, tbarcfg_listener_t **rlst)
     803{
     804        tbarcfg_listener_t *lst;
     805        service_id_t svcid = 0;
     806        loc_srv_t *srv = NULL;
     807        task_id_t taskid;
     808        char *svcname = NULL;
     809        category_id_t catid;
     810        port_id_t port;
     811        int rv;
     812        errno_t rc;
     813
     814        lst = calloc(1, sizeof(tbarcfg_listener_t));
     815        if (lst == NULL)
     816                return ENOMEM;
     817
     818        lst->cb = cb;
     819        lst->arg = arg;
     820
     821        rc = async_create_port(INTERFACE_TBARCFG_NOTIFY,
     822            tbarcfg_notify_conn, (void *)lst, &port);
     823        if (rc != EOK)
     824                goto error;
     825
     826        rc = loc_server_register("tbarcfg-listener", &srv);
     827        if (rc != EOK)
     828                goto error;
     829
     830        taskid = task_get_id();
     831
     832        rv = asprintf(&svcname, "tbarcfg/%u", (unsigned)taskid);
     833        if (rv < 0) {
     834                rc = ENOMEM;
     835                goto error;
     836        }
     837
     838        rc = loc_service_register(srv, svcname, &svcid);
     839        if (rc != EOK)
     840                goto error;
     841
     842        rc = loc_category_get_id(nchan, &catid, 0);
     843        if (rc != EOK)
     844                goto error;
     845
     846        rc = loc_service_add_to_cat(srv, svcid, catid);
     847        if (rc != EOK)
     848                goto error;
     849
     850        *rlst = lst;
     851        return EOK;
     852error:
     853        if (svcid != 0)
     854                loc_service_unregister(srv, svcid);
     855        if (srv != NULL)
     856                loc_server_unregister(srv);
     857        if (svcname != NULL)
     858                free(svcname);
     859        return rc;
     860}
     861
     862/** Destroy taskbar configuration listener.
     863 *
     864 * @param lst Listener
     865 */
     866void tbarcfg_listener_destroy(tbarcfg_listener_t *lst)
     867{
     868        free(lst);
     869}
     870
     871/** Send taskbar configuration notification to a particular service ID.
     872 *
     873 * @param svcid Service ID
     874 * @return EOK on success or an error code
     875 */
     876static errno_t tbarcfg_notify_svc(service_id_t svcid)
     877{
     878        async_sess_t *sess;
     879        async_exch_t *exch;
     880        errno_t rc;
     881
     882        sess = loc_service_connect(svcid, INTERFACE_TBARCFG_NOTIFY, 0);
     883        if (sess == NULL)
     884                return EIO;
     885
     886        exch = async_exchange_begin(sess);
     887        rc = async_req_0_0(exch, TBARCFG_NOTIFY_NOTIFY);
     888        if (rc != EOK) {
     889                async_exchange_end(exch);
     890                async_hangup(sess);
     891                return rc;
     892        }
     893
     894        async_exchange_end(exch);
     895        async_hangup(sess);
     896        return EOK;
     897}
     898
     899/** Send taskbar configuration change notification.
     900 *
     901 * @param nchan Notification channel (TBARCFG_NOTIFY_DEFAULT)
     902 */
     903errno_t tbarcfg_notify(const char *nchan)
     904{
     905        errno_t rc;
     906        category_id_t catid;
     907        service_id_t *svcs = NULL;
     908        size_t count, i;
     909
     910        rc = loc_category_get_id(nchan, &catid, 0);
     911        if (rc != EOK)
     912                return rc;
     913
     914        rc = loc_category_get_svcs(catid, &svcs, &count);
     915        if (rc != EOK)
     916                return rc;
     917
     918        for (i = 0; i < count; i++) {
     919                rc = tbarcfg_notify_svc(svcs[i]);
     920                if (rc != EOK)
     921                        goto error;
     922        }
     923
     924        free(svcs);
     925        return EOK;
     926error:
     927        free(svcs);
     928        return rc;
     929}
     930
     931/** Taskbar configuration connection handler.
     932 *
     933 * @param icall Initial call
     934 * @param arg Argument (tbarcfg_listener_t *)
     935 */
     936static void tbarcfg_notify_conn(ipc_call_t *icall, void *arg)
     937{
     938        tbarcfg_listener_t *lst = (tbarcfg_listener_t *)arg;
     939
     940        /* Accept the connection */
     941        async_accept_0(icall);
     942
     943        while (true) {
     944                ipc_call_t call;
     945                async_get_call(&call);
     946                sysarg_t method = ipc_get_imethod(&call);
     947
     948                if (!method) {
     949                        /* The other side has hung up */
     950                        async_answer_0(&call, EOK);
     951                        return;
     952                }
     953
     954                switch (method) {
     955                case TBARCFG_NOTIFY_NOTIFY:
     956                        lst->cb(lst->arg);
     957                        async_answer_0(&call, EOK);
     958                        break;
     959                default:
     960                        async_answer_0(&call, EINVAL);
     961                }
     962        }
     963}
     964
    786965/** @}
    787966 */
Note: See TracChangeset for help on using the changeset viewer.