Changeset 64e1fb2 in mainline


Ignore:
Timestamp:
2013-08-02T14:57:26Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1845003
Parents:
1298a8fa
Message:

libdrv: Add data communication to usb iface.

Location:
uspace/lib/drv
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/remote_usb.c

    r1298a8fa r64e1fb2  
    7474        IPC_M_USB_REGISTER_ENDPOINT,
    7575        IPC_M_USB_UNREGISTER_ENDPOINT,
     76        IPC_M_USB_READ,
     77        IPC_M_USB_WRITE,
    7678} usb_iface_funcs_t;
    7779
     
    223225}
    224226
     227int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     228    void *data, size_t size, size_t *rec_size)
     229{
     230        if (!exch)
     231                return EBADMEM;
     232
     233        if (size == 0 && setup == 0)
     234                return EOK;
     235
     236        /* Make call identifying target USB device and type of transfer. */
     237        aid_t opening_request = async_send_4(exch,
     238            DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
     239            (setup & UINT32_MAX), (setup >> 32), NULL);
     240
     241        if (opening_request == 0) {
     242                return ENOMEM;
     243        }
     244
     245        /* Retrieve the data. */
     246        ipc_call_t data_request_call;
     247        aid_t data_request =
     248            async_data_read(exch, data, size, &data_request_call);
     249
     250        if (data_request == 0) {
     251                // FIXME: How to let the other side know that we want to abort?
     252                async_forget(opening_request);
     253                return ENOMEM;
     254        }
     255
     256        /* Wait for the answer. */
     257        sysarg_t data_request_rc;
     258        sysarg_t opening_request_rc;
     259        async_wait_for(data_request, &data_request_rc);
     260        async_wait_for(opening_request, &opening_request_rc);
     261
     262        if (data_request_rc != EOK) {
     263                /* Prefer the return code of the opening request. */
     264                if (opening_request_rc != EOK) {
     265                        return (int) opening_request_rc;
     266                } else {
     267                        return (int) data_request_rc;
     268                }
     269        }
     270        if (opening_request_rc != EOK) {
     271                return (int) opening_request_rc;
     272        }
     273
     274        *rec_size = IPC_GET_ARG2(data_request_call);
     275        return EOK;
     276}
     277
     278int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     279    const void *data, size_t size)
     280{
     281        if (!exch)
     282                return EBADMEM;
     283
     284        if (size == 0 && setup == 0)
     285                return EOK;
     286
     287        aid_t opening_request = async_send_5(exch,
     288            DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
     289            (setup & UINT32_MAX), (setup >> 32), NULL);
     290
     291        if (opening_request == 0) {
     292                return ENOMEM;
     293        }
     294
     295        /* Send the data if any. */
     296        if (size > 0) {
     297                const int ret = async_data_write_start(exch, data, size);
     298                if (ret != EOK) {
     299                        async_forget(opening_request);
     300                        return ret;
     301                }
     302        }
     303
     304        /* Wait for the answer. */
     305        sysarg_t opening_request_rc;
     306        async_wait_for(opening_request, &opening_request_rc);
     307
     308        return (int) opening_request_rc;
     309}
     310
    225311static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    226312static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    234320static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    235321static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     322static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     323
     324static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    236325
    237326/** Remote USB interface operations. */
     
    247336        [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
    248337        [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
     338        [IPC_M_USB_READ] = remote_usb_read,
     339        [IPC_M_USB_WRITE] = remote_usb_write,
    249340};
    250341
     
    445536        async_answer_0(callid, rc);
    446537}
     538
     539typedef struct {
     540        ipc_callid_t caller;
     541        ipc_callid_t data_caller;
     542        void *buffer;
     543} async_transaction_t;
     544
     545static void async_transaction_destroy(async_transaction_t *trans)
     546{
     547        if (trans == NULL) {
     548                return;
     549        }
     550        if (trans->buffer != NULL) {
     551                free(trans->buffer);
     552        }
     553
     554        free(trans);
     555}
     556
     557static async_transaction_t *async_transaction_create(ipc_callid_t caller)
     558{
     559        async_transaction_t *trans = malloc(sizeof(async_transaction_t));
     560        if (trans == NULL) {
     561                return NULL;
     562        }
     563
     564        trans->caller = caller;
     565        trans->data_caller = 0;
     566        trans->buffer = NULL;
     567
     568        return trans;
     569}
     570
     571static void callback_out(int outcome, void *arg)
     572{
     573        async_transaction_t *trans = arg;
     574
     575        async_answer_0(trans->caller, outcome);
     576
     577        async_transaction_destroy(trans);
     578}
     579
     580static void callback_in(int outcome, size_t actual_size, void *arg)
     581{
     582        async_transaction_t *trans = (async_transaction_t *)arg;
     583
     584        if (outcome != EOK) {
     585                async_answer_0(trans->caller, outcome);
     586                if (trans->data_caller) {
     587                        async_answer_0(trans->data_caller, EINTR);
     588                }
     589                async_transaction_destroy(trans);
     590                return;
     591        }
     592
     593        if (trans->data_caller) {
     594                async_data_read_finalize(trans->data_caller,
     595                    trans->buffer, actual_size);
     596        }
     597
     598        async_answer_0(trans->caller, EOK);
     599
     600        async_transaction_destroy(trans);
     601}
     602
     603void remote_usb_read(
     604    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     605{
     606        assert(fun);
     607        assert(iface);
     608        assert(call);
     609
     610        const usb_iface_t *usb_iface = iface;
     611
     612        if (!usb_iface->read) {
     613                async_answer_0(callid, ENOTSUP);
     614                return;
     615        }
     616
     617        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
     618        const uint64_t setup =
     619            ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
     620            (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
     621
     622        async_transaction_t *trans = async_transaction_create(callid);
     623        if (trans == NULL) {
     624                async_answer_0(callid, ENOMEM);
     625                return;
     626        }
     627
     628        size_t size = 0;
     629        if (!async_data_read_receive(&trans->data_caller, &size)) {
     630                async_answer_0(callid, EPARTY);
     631                return;
     632        }
     633
     634        trans->buffer = malloc(size);
     635        if (trans->buffer == NULL) {
     636                async_answer_0(trans->data_caller, ENOMEM);
     637                async_answer_0(callid, ENOMEM);
     638                async_transaction_destroy(trans);
     639        }
     640
     641        const int rc = usb_iface->read(
     642            fun, ep, setup, trans->buffer, size, callback_in, trans);
     643
     644        if (rc != EOK) {
     645                async_answer_0(trans->data_caller, rc);
     646                async_answer_0(callid, rc);
     647                async_transaction_destroy(trans);
     648        }
     649}
     650
     651void remote_usb_write(
     652    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     653{
     654        assert(fun);
     655        assert(iface);
     656        assert(call);
     657
     658        const usb_iface_t *usb_iface = iface;
     659
     660        if (!usb_iface->write) {
     661                async_answer_0(callid, ENOTSUP);
     662                return;
     663        }
     664
     665        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
     666        const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
     667        const uint64_t setup =
     668            ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
     669            (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
     670
     671        async_transaction_t *trans = async_transaction_create(callid);
     672        if (trans == NULL) {
     673                async_answer_0(callid, ENOMEM);
     674                return;
     675        }
     676
     677        size_t size = 0;
     678        if (data_buffer_len > 0) {
     679                const int rc = async_data_write_accept(&trans->buffer, false,
     680                    1, data_buffer_len, 0, &size);
     681
     682                if (rc != EOK) {
     683                        async_answer_0(callid, rc);
     684                        async_transaction_destroy(trans);
     685                        return;
     686                }
     687        }
     688
     689        const int rc = usb_iface->write(
     690            fun, ep, setup, trans->buffer, size, callback_out, trans);
     691
     692        if (rc != EOK) {
     693                async_answer_0(callid, rc);
     694                async_transaction_destroy(trans);
     695        }
     696}
    447697/**
    448698 * @}
  • uspace/lib/drv/include/usb_iface.h

    r1298a8fa r64e1fb2  
    6666    usb_direction_t, size_t, unsigned);
    6767int usb_unregister_endpoint(async_exch_t *, usb_endpoint_t, usb_direction_t);
     68int usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, size_t *);
     69int usb_write(async_exch_t *, usb_endpoint_t, uint64_t, const void *, size_t);
     70
     71/** Callback for outgoing transfer. */
     72typedef void (*usbhc_iface_transfer_out_callback_t)(int, void *);
     73
     74/** Callback for incoming transfer. */
     75typedef void (*usbhc_iface_transfer_in_callback_t)(int, size_t, void *);
    6876
    6977/** USB device communication interface. */
     
    8391        int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t,
    8492            usb_direction_t);
     93        int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t,
     94            usbhc_iface_transfer_in_callback_t, void *);
     95        int (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *,
     96            size_t, usbhc_iface_transfer_out_callback_t, void *);
    8597} usb_iface_t;
    8698
Note: See TracChangeset for help on using the changeset viewer.