Ignore:
File:
1 edited

Legend:

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

    r25a179e rdb51a6a6  
    11/*
    2  * Copyright (c) 2010-2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2017 Ondrej Hlavaty
    45 * All rights reserved.
    56 *
     
    3536
    3637#include <async.h>
     38#include <macros.h>
    3739#include <errno.h>
    38 #include <assert.h>
    39 #include <macros.h>
     40#include <devman.h>
    4041
    4142#include "usbhc_iface.h"
    4243#include "ddf/driver.h"
    4344
    44 #define USB_MAX_PAYLOAD_SIZE 1020
    45 
    46 /** IPC methods for communication with HC through DDF interface.
    47  *
    48  * Notes for async methods:
    49  *
    50  * Methods for sending data to device (OUT transactions)
    51  * - e.g. IPC_M_USBHC_INTERRUPT_OUT -
    52  * always use the same semantics:
    53  * - first, IPC call with given method is made
    54  *   - argument #1 is target address
    55  *   - argument #2 is target endpoint
    56  *   - argument #3 is max packet size of the endpoint
    57  * - this call is immediately followed by IPC data write (from caller)
    58  * - the initial call (and the whole transaction) is answer after the
    59  *   transaction is scheduled by the HC and acknowledged by the device
    60  *   or immediately after error is detected
    61  * - the answer carries only the error code
    62  *
    63  * Methods for retrieving data from device (IN transactions)
    64  * - e.g. IPC_M_USBHC_INTERRUPT_IN -
    65  * also use the same semantics:
    66  * - first, IPC call with given method is made
    67  *   - argument #1 is target address
    68  *   - argument #2 is target endpoint
    69  * - this call is immediately followed by IPC data read (async version)
    70  * - the call is not answered until the device returns some data (or until
    71  *   error occurs)
    72  *
    73  * Some special methods (NO-DATA transactions) do not send any data. These
    74  * might behave as both OUT or IN transactions because communication parts
    75  * where actual buffers are exchanged are omitted.
    76  **
    77  * For all these methods, wrap functions exists. Important rule: functions
    78  * for IN transactions have (as parameters) buffers where retrieved data
    79  * will be stored. These buffers must be already allocated and shall not be
    80  * touch until the transaction is completed
    81  * (e.g. not before calling usb_wait_for() with appropriate handle).
    82  * OUT transactions buffers can be freed immediately after call is dispatched
    83  * (i.e. after return from wrapping function).
    84  *
    85  */
     45
    8646typedef enum {
    87         /** Get data from device.
    88          * See explanation at usb_iface_funcs_t (IN transaction).
    89          */
    90         IPC_M_USBHC_READ,
    91 
    92         /** Send data to device.
    93          * See explanation at usb_iface_funcs_t (OUT transaction).
    94          */
    95         IPC_M_USBHC_WRITE,
     47        IPC_M_USB_DEFAULT_ADDRESS_RESERVATION,
     48        IPC_M_USB_DEVICE_ENUMERATE,
     49        IPC_M_USB_DEVICE_REMOVE,
     50        IPC_M_USB_REGISTER_ENDPOINT,
     51        IPC_M_USB_UNREGISTER_ENDPOINT,
     52        IPC_M_USB_READ,
     53        IPC_M_USB_WRITE,
    9654} usbhc_iface_funcs_t;
    9755
    98 int usbhc_read(async_exch_t *exch, usb_address_t address,
    99     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
    100     size_t *rec_size)
     56/** Reserve default USB address.
     57 * @param[in] exch IPC communication exchange
     58 * @return Error code.
     59 */
     60int usbhc_reserve_default_address(async_exch_t *exch)
     61{
     62        if (!exch)
     63                return EBADMEM;
     64        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, true);
     65}
     66
     67/** Release default USB address.
     68 *
     69 * @param[in] exch IPC communication exchange
     70 *
     71 * @return Error code.
     72 */
     73int usbhc_release_default_address(async_exch_t *exch)
     74{
     75        if (!exch)
     76                return EBADMEM;
     77        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_DEFAULT_ADDRESS_RESERVATION, false);
     78}
     79
     80/**
     81 * Trigger USB device enumeration
     82 *
     83 * @param[in] exch IPC communication exchange
     84 * @param[in] port Port number at which the device is attached
     85 * @param[in] speed Communication speed of the newly attached device
     86 *
     87 * @return Error code.
     88 */
     89int usbhc_device_enumerate(async_exch_t *exch, unsigned port, usb_speed_t speed)
     90{
     91        if (!exch)
     92                return EBADMEM;
     93        const int ret = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     94            IPC_M_USB_DEVICE_ENUMERATE, port, speed);
     95        return ret;
     96}
     97
     98/** Trigger USB device enumeration
     99 *
     100 * @param[in] exch   IPC communication exchange
     101 * @param[in] handle Identifier of the device
     102 *
     103 * @return Error code.
     104 *
     105 */
     106int usbhc_device_remove(async_exch_t *exch, unsigned port)
     107{
     108        if (!exch)
     109                return EBADMEM;
     110        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     111            IPC_M_USB_DEVICE_REMOVE, port);
     112}
     113
     114int usbhc_register_endpoint(async_exch_t *exch, usb_pipe_desc_t *pipe_desc,
     115    const usb_endpoint_descriptors_t *desc)
     116{
     117        if (!exch)
     118                return EBADMEM;
     119
     120        if (!desc)
     121                return EINVAL;
     122
     123        aid_t opening_request = async_send_1(exch,
     124            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL);
     125
     126        if (opening_request == 0) {
     127                return ENOMEM;
     128        }
     129
     130        int ret = async_data_write_start(exch, desc, sizeof(*desc));
     131        if (ret != EOK) {
     132                async_forget(opening_request);
     133                return ret;
     134        }
     135
     136        /* Wait for the answer. */
     137        sysarg_t opening_request_rc;
     138        async_wait_for(opening_request, &opening_request_rc);
     139
     140        if (opening_request_rc)
     141                return (int) opening_request_rc;
     142
     143        usb_pipe_desc_t dest;
     144        ret = async_data_read_start(exch, &dest, sizeof(dest));
     145        if (ret != EOK) {
     146                return ret;
     147        }
     148
     149        if (pipe_desc)
     150                *pipe_desc = dest;
     151
     152        return EOK;
     153}
     154
     155int usbhc_unregister_endpoint(async_exch_t *exch, const usb_pipe_desc_t *pipe_desc)
     156{
     157        if (!exch)
     158                return EBADMEM;
     159
     160        aid_t opening_request = async_send_1(exch,
     161                DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL);
     162
     163        if (opening_request == 0) {
     164                return ENOMEM;
     165        }
     166
     167        const int ret = async_data_write_start(exch, pipe_desc, sizeof(*pipe_desc));
     168        if (ret != EOK) {
     169                async_forget(opening_request);
     170                return ret;
     171        }
     172
     173        /* Wait for the answer. */
     174        sysarg_t opening_request_rc;
     175        async_wait_for(opening_request, &opening_request_rc);
     176
     177        return (int) opening_request_rc;
     178}
     179
     180int usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     181    void *data, size_t size, size_t *rec_size)
    101182{
    102183        if (!exch)
     
    106187                return EOK;
    107188
    108         const usb_target_t target =
    109             {{ .address = address, .endpoint = endpoint }};
    110 
    111189        /* Make call identifying target USB device and type of transfer. */
    112190        aid_t opening_request = async_send_4(exch,
    113             DEV_IFACE_ID(USBHC_DEV_IFACE),
    114             IPC_M_USBHC_READ, target.packed,
     191            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint,
    115192            (setup & UINT32_MAX), (setup >> 32), NULL);
    116193
     
    131208
    132209        /* Wait for the answer. */
    133         int data_request_rc;
    134         int opening_request_rc;
     210        sysarg_t data_request_rc;
     211        sysarg_t opening_request_rc;
    135212        async_wait_for(data_request, &data_request_rc);
    136213        async_wait_for(opening_request, &opening_request_rc);
     
    152229}
    153230
    154 int usbhc_write(async_exch_t *exch, usb_address_t address,
    155     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
     231int usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
     232    const void *data, size_t size)
    156233{
    157234        if (!exch)
     
    161238                return EOK;
    162239
    163         const usb_target_t target =
    164             {{ .address = address, .endpoint = endpoint }};
    165 
    166         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    167             IPC_M_USBHC_WRITE, target.packed, size,
     240        aid_t opening_request = async_send_5(exch,
     241            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
    168242            (setup & UINT32_MAX), (setup >> 32), NULL);
    169243
     
    182256
    183257        /* Wait for the answer. */
    184         int opening_request_rc;
     258        sysarg_t opening_request_rc;
    185259        async_wait_for(opening_request, &opening_request_rc);
    186260
     
    188262}
    189263
    190 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    191 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    192 
    193 /** Remote USB host controller interface operations. */
    194 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
    195         [IPC_M_USBHC_READ] = remote_usbhc_read,
    196         [IPC_M_USBHC_WRITE] = remote_usbhc_write,
     264static void remote_usbhc_default_address_reservation(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     265static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     266static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     267static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     268static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     269static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     270static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     271
     272/** Remote USB interface operations. */
     273static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     274        [IPC_M_USB_DEFAULT_ADDRESS_RESERVATION] = remote_usbhc_default_address_reservation,
     275        [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate,
     276        [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove,
     277        [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     278        [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
     279        [IPC_M_USB_READ] = remote_usbhc_read,
     280        [IPC_M_USB_WRITE] = remote_usbhc_write,
    197281};
    198282
    199 /** Remote USB host controller interface structure.
     283/** Remote USB interface structure.
    200284 */
    201285const remote_iface_t remote_usbhc_iface = {
    202286        .method_count = ARRAY_SIZE(remote_usbhc_iface_ops),
    203         .methods = remote_usbhc_iface_ops
     287        .methods = remote_usbhc_iface_ops,
    204288};
    205289
     
    210294} async_transaction_t;
    211295
     296void remote_usbhc_default_address_reservation(ddf_fun_t *fun, void *iface,
     297    ipc_callid_t callid, ipc_call_t *call)
     298{
     299        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     300
     301        if (usbhc_iface->default_address_reservation == NULL) {
     302                async_answer_0(callid, ENOTSUP);
     303                return;
     304        }
     305
     306        const bool reserve = IPC_GET_ARG2(*call);
     307        const int ret = usbhc_iface->default_address_reservation(fun, reserve);
     308        async_answer_0(callid, ret);
     309}
     310
     311
     312static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface,
     313    ipc_callid_t callid, ipc_call_t *call)
     314{
     315        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     316
     317        if (usbhc_iface->device_enumerate == NULL) {
     318                async_answer_0(callid, ENOTSUP);
     319                return;
     320        }
     321
     322        const unsigned port = DEV_IPC_GET_ARG1(*call);
     323        usb_speed_t speed = DEV_IPC_GET_ARG2(*call);
     324        const int ret = usbhc_iface->device_enumerate(fun, port, speed);
     325        async_answer_0(callid, ret);
     326}
     327
     328static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface,
     329    ipc_callid_t callid, ipc_call_t *call)
     330{
     331        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     332
     333        if (usbhc_iface->device_remove == NULL) {
     334                async_answer_0(callid, ENOTSUP);
     335                return;
     336        }
     337
     338        const unsigned port = DEV_IPC_GET_ARG1(*call);
     339        const int ret = usbhc_iface->device_remove(fun, port);
     340        async_answer_0(callid, ret);
     341}
     342
     343static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     344    ipc_callid_t callid, ipc_call_t *call)
     345{
     346        assert(fun);
     347        assert(iface);
     348        assert(call);
     349
     350        const usbhc_iface_t *usbhc_iface = iface;
     351
     352        if (!usbhc_iface->register_endpoint) {
     353                async_answer_0(callid, ENOTSUP);
     354                return;
     355        }
     356
     357        usb_endpoint_descriptors_t ep_desc;
     358        ipc_callid_t data_callid;
     359        size_t len;
     360
     361        if (!async_data_write_receive(&data_callid, &len)
     362            || len != sizeof(ep_desc)) {
     363                async_answer_0(callid, EINVAL);
     364                return;
     365        }
     366        async_data_write_finalize(data_callid, &ep_desc, sizeof(ep_desc));
     367
     368        usb_pipe_desc_t pipe_desc;
     369
     370        const int rc = usbhc_iface->register_endpoint(fun, &pipe_desc, &ep_desc);
     371        async_answer_0(callid, rc);
     372
     373        if (!async_data_read_receive(&data_callid, &len)
     374            || len != sizeof(pipe_desc)) {
     375                return;
     376        }
     377        async_data_read_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
     378}
     379
     380static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     381    ipc_callid_t callid, ipc_call_t *call)
     382{
     383        assert(fun);
     384        assert(iface);
     385        assert(call);
     386
     387        const usbhc_iface_t *usbhc_iface = iface;
     388
     389        if (!usbhc_iface->unregister_endpoint) {
     390                async_answer_0(callid, ENOTSUP);
     391                return;
     392        }
     393
     394        usb_pipe_desc_t pipe_desc;
     395        ipc_callid_t data_callid;
     396        size_t len;
     397
     398        if (!async_data_write_receive(&data_callid, &len)
     399            || len != sizeof(pipe_desc)) {
     400                async_answer_0(callid, EINVAL);
     401                return;
     402        }
     403        async_data_write_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
     404
     405        const int rc = usbhc_iface->unregister_endpoint(fun, &pipe_desc);
     406        async_answer_0(callid, rc);
     407}
     408
    212409static void async_transaction_destroy(async_transaction_t *trans)
    213410{
    214         if (trans == NULL)
    215                 return;
    216        
    217         if (trans->buffer != NULL)
     411        if (trans == NULL) {
     412                return;
     413        }
     414        if (trans->buffer != NULL) {
    218415                free(trans->buffer);
    219        
     416        }
     417
    220418        free(trans);
    221419}
     
    235433}
    236434
    237 static void callback_out(int outcome, void *arg)
     435static int callback_out(void *arg, int error, size_t transferred_size)
    238436{
    239437        async_transaction_t *trans = arg;
    240438
    241         async_answer_0(trans->caller, outcome);
     439        const int err = async_answer_0(trans->caller, error);
    242440
    243441        async_transaction_destroy(trans);
    244 }
    245 
    246 static void callback_in(int outcome, size_t actual_size, void *arg)
    247 {
    248         async_transaction_t *trans = (async_transaction_t *)arg;
    249 
    250         if (outcome != EOK) {
    251                 async_answer_0(trans->caller, outcome);
    252                 if (trans->data_caller) {
     442
     443        return err;
     444}
     445
     446static int callback_in(void *arg, int error, size_t transferred_size)
     447{
     448        async_transaction_t *trans = arg;
     449
     450        if (trans->data_caller) {
     451                if (error == EOK) {
     452                        error = async_data_read_finalize(trans->data_caller,
     453                            trans->buffer, transferred_size);
     454                } else {
    253455                        async_answer_0(trans->data_caller, EINTR);
    254456                }
    255                 async_transaction_destroy(trans);
    256                 return;
    257         }
    258 
    259         if (trans->data_caller) {
    260                 async_data_read_finalize(trans->data_caller,
    261                     trans->buffer, actual_size);
    262         }
    263 
    264         async_answer_0(trans->caller, EOK);
    265 
     457        }
     458
     459        const int err = async_answer_0(trans->caller, error);
    266460        async_transaction_destroy(trans);
     461        return err;
    267462}
    268463
     
    274469        assert(call);
    275470
    276         const usbhc_iface_t *hc_iface = iface;
    277 
    278         if (!hc_iface->read) {
    279                 async_answer_0(callid, ENOTSUP);
    280                 return;
    281         }
    282 
    283         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     471        const usbhc_iface_t *usbhc_iface = iface;
     472
     473        if (!usbhc_iface->read) {
     474                async_answer_0(callid, ENOTSUP);
     475                return;
     476        }
     477
     478        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    284479        const uint64_t setup =
    285480            ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
     
    295490        if (!async_data_read_receive(&trans->data_caller, &size)) {
    296491                async_answer_0(callid, EPARTY);
     492                async_transaction_destroy(trans);
    297493                return;
    298494        }
     
    306502        }
    307503
    308         const int rc = hc_iface->read(
     504        const usb_target_t target = {{
     505                /* .address is initialized by read itself */
     506                .endpoint = ep,
     507        }};
     508
     509        const int rc = usbhc_iface->read(
    309510            fun, target, setup, trans->buffer, size, callback_in, trans);
    310511
     
    323524        assert(call);
    324525
    325         const usbhc_iface_t *hc_iface = iface;
    326 
    327         if (!hc_iface->write) {
    328                 async_answer_0(callid, ENOTSUP);
    329                 return;
    330         }
    331 
    332         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     526        const usbhc_iface_t *usbhc_iface = iface;
     527
     528        if (!usbhc_iface->write) {
     529                async_answer_0(callid, ENOTSUP);
     530                return;
     531        }
     532
     533        const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    333534        const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    334535        const uint64_t setup =
     
    345546        if (data_buffer_len > 0) {
    346547                const int rc = async_data_write_accept(&trans->buffer, false,
    347                     1, USB_MAX_PAYLOAD_SIZE,
    348                     0, &size);
     548                    1, data_buffer_len, 0, &size);
    349549
    350550                if (rc != EOK) {
     
    355555        }
    356556
    357         const int rc = hc_iface->write(
     557        const usb_target_t target = {{
     558                /* .address is initialized by write itself */
     559                .endpoint = ep,
     560                /* streams are not given by the API call yet */
     561                .stream = 0,
     562        }};
     563
     564        const int rc = usbhc_iface->write(
    358565            fun, target, setup, trans->buffer, size, callback_out, trans);
    359566
Note: See TracChangeset for help on using the changeset viewer.