Changeset df6ded8 in mainline for uspace/lib/drv


Ignore:
Timestamp:
2018-02-28T16:37:50Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
Location:
uspace/lib/drv
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/Makefile

    rf5e5f73 rdf6ded8  
    4747        generic/remote_usb.c \
    4848        generic/remote_pci.c \
     49        generic/remote_usbdiag.c \
    4950        generic/remote_usbhc.c \
    5051        generic/remote_usbhid.c \
  • uspace/lib/drv/generic/dev_iface.c

    rf5e5f73 rdf6ded8  
    4848#include "remote_ieee80211.h"
    4949#include "remote_usb.h"
     50#include "remote_usbdiag.h"
    5051#include "remote_usbhc.h"
    5152#include "remote_usbhid.h"
     
    6566                [PCI_DEV_IFACE] = &remote_pci_iface,
    6667                [USB_DEV_IFACE] = &remote_usb_iface,
     68                [USBDIAG_DEV_IFACE] = &remote_usbdiag_iface,
    6769                [USBHC_DEV_IFACE] = &remote_usbhc_iface,
    6870                [USBHID_DEV_IFACE] = &remote_usbhid_iface,
     
    8587        if (iface_method_idx >= rem_iface->method_count)
    8688                return NULL;
    87        
     89
    8890        return rem_iface->methods[iface_method_idx];
    8991}
  • uspace/lib/drv/generic/driver.c

    rf5e5f73 rdf6ded8  
    971971}
    972972
    973 int ddf_driver_main(const driver_t *drv)
     973errno_t ddf_driver_main(const driver_t *drv)
    974974{
    975975        /*
  • uspace/lib/drv/generic/private/remote_usbhc.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2017 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
  • uspace/lib/drv/generic/remote_usb.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2010 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Michal Staruch, Ondrej Hlavaty
    45 * All rights reserved.
    56 *
     
    5152usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev)
    5253{
    53         return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
     54        return devman_parent_device_connect(ddf_dev_get_handle(dev),
     55            IPC_FLAG_BLOCKING);
    5456}
    5557
     
    6163
    6264typedef enum {
    63         IPC_M_USB_GET_MY_INTERFACE,
    64         IPC_M_USB_GET_MY_DEVICE_HANDLE,
    65         IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
    66         IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
    67         IPC_M_USB_DEVICE_ENUMERATE,
    68         IPC_M_USB_DEVICE_REMOVE,
    69         IPC_M_USB_REGISTER_ENDPOINT,
    70         IPC_M_USB_UNREGISTER_ENDPOINT,
    71         IPC_M_USB_READ,
    72         IPC_M_USB_WRITE,
     65        IPC_M_USB_GET_MY_DESCRIPTION,
    7366} usb_iface_funcs_t;
    7467
     
    7972 * @return Error code.
    8073 */
    81 errno_t usb_get_my_interface(async_exch_t *exch, int *usb_iface)
    82 {
    83         if (!exch)
    84                 return EBADMEM;
    85         sysarg_t iface_no;
    86         const errno_t ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    87             IPC_M_USB_GET_MY_INTERFACE, &iface_no);
    88         if (ret == EOK && usb_iface)
    89                 *usb_iface = (int)iface_no;
    90         return ret;
    91 }
    92 
    93 /** Tell devman handle of the usb device function.
    94  *
    95  * @param[in]  exch   IPC communication exchange
    96  * @param[out] handle devman handle of the HC used by the target device.
    97  *
    98  * @return Error code.
    99  *
    100  */
    101 errno_t usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle)
    102 {
    103         devman_handle_t h = 0;
    104         const errno_t ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    105             IPC_M_USB_GET_MY_DEVICE_HANDLE, &h);
    106         if (ret == EOK && handle)
    107                 *handle = (devman_handle_t)h;
    108         return ret;
    109 }
    110 
    111 /** Reserve default USB address.
    112  * @param[in] exch IPC communication exchange
    113  * @param[in] speed Communication speed of the newly attached device
    114  * @return Error code.
    115  */
    116 errno_t usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
    117 {
    118         if (!exch)
    119                 return EBADMEM;
    120         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    121             IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
    122 }
    123 
    124 /** Release default USB address.
    125  *
    126  * @param[in] exch IPC communication exchange
    127  *
    128  * @return Error code.
    129  *
    130  */
    131 errno_t usb_release_default_address(async_exch_t *exch)
    132 {
    133         if (!exch)
    134                 return EBADMEM;
    135         return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    136             IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
    137 }
    138 
    139 /** Trigger USB device enumeration
    140  *
    141  * @param[in]  exch   IPC communication exchange
    142  * @param[out] handle Identifier of the newly added device (if successful)
    143  *
    144  * @return Error code.
    145  *
    146  */
    147 errno_t usb_device_enumerate(async_exch_t *exch, unsigned port)
    148 {
    149         if (!exch)
    150                 return EBADMEM;
    151         const errno_t ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    152             IPC_M_USB_DEVICE_ENUMERATE, port);
    153         return ret;
    154 }
    155 
    156 /** Trigger USB device enumeration
    157  *
    158  * @param[in] exch   IPC communication exchange
    159  * @param[in] handle Identifier of the device
    160  *
    161  * @return Error code.
    162  *
    163  */
    164 errno_t usb_device_remove(async_exch_t *exch, unsigned port)
    165 {
    166         if (!exch)
    167                 return EBADMEM;
    168         return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    169             IPC_M_USB_DEVICE_REMOVE, port);
    170 }
    171 
    172 static_assert(sizeof(sysarg_t) >= 4);
    173 
    174 typedef union {
    175         uint8_t arr[sizeof(sysarg_t)];
    176         sysarg_t arg;
    177 } pack8_t;
    178 
    179 errno_t usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    180     usb_transfer_type_t type, usb_direction_t direction,
    181     size_t mps, unsigned packets, unsigned interval)
    182 {
    183         if (!exch)
    184                 return EBADMEM;
    185         pack8_t pack;
    186         pack.arr[0] = type;
    187         pack.arr[1] = direction;
    188         pack.arr[2] = interval;
    189         pack.arr[3] = packets;
    190 
    191         return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    192             IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps);
    193 
    194 }
    195 
    196 errno_t usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
    197     usb_direction_t direction)
    198 {
    199         if (!exch)
    200                 return EBADMEM;
    201         return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    202             IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction);
    203 }
    204 
    205 errno_t usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    206     void *data, size_t size, size_t *rec_size)
     74errno_t usb_get_my_description(async_exch_t *exch, usb_device_desc_t *desc)
    20775{
    20876        if (!exch)
    20977                return EBADMEM;
    21078
    211         if (size == 0 && setup == 0)
    212                 return EOK;
     79        usb_device_desc_t tmp_desc;
    21380
    214         /* Make call identifying target USB device and type of transfer. */
    215         aid_t opening_request = async_send_4(exch,
    216             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
    217             (setup & UINT32_MAX), (setup >> 32), NULL);
    218 
    219         if (opening_request == 0) {
    220                 return ENOMEM;
    221         }
    222 
    223         /* Retrieve the data. */
    224         ipc_call_t data_request_call;
    225         aid_t data_request =
    226             async_data_read(exch, data, size, &data_request_call);
    227 
    228         if (data_request == 0) {
    229                 // FIXME: How to let the other side know that we want to abort?
    230                 async_forget(opening_request);
    231                 return ENOMEM;
    232         }
    233 
    234         /* Wait for the answer. */
    235         errno_t data_request_rc;
    236         errno_t opening_request_rc;
    237         async_wait_for(data_request, &data_request_rc);
    238         async_wait_for(opening_request, &opening_request_rc);
    239 
    240         if (data_request_rc != EOK) {
    241                 /* Prefer the return code of the opening request. */
    242                 if (opening_request_rc != EOK) {
    243                         return (errno_t) opening_request_rc;
    244                 } else {
    245                         return (errno_t) data_request_rc;
    246                 }
    247         }
    248         if (opening_request_rc != EOK) {
    249                 return (errno_t) opening_request_rc;
    250         }
    251 
    252         *rec_size = IPC_GET_ARG2(data_request_call);
    253         return EOK;
     81        const errno_t ret = async_req_1_5(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     82            IPC_M_USB_GET_MY_DESCRIPTION,
     83            (sysarg_t *) &tmp_desc.address,
     84            (sysarg_t *) &tmp_desc.depth,
     85            (sysarg_t *) &tmp_desc.speed,
     86            &tmp_desc.handle,
     87            (sysarg_t *) &tmp_desc.iface);
     88        if (ret == EOK && desc)
     89                *desc = tmp_desc;
     90        return ret;
    25491}
    25592
    256 errno_t usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
    257     const void *data, size_t size)
    258 {
    259         if (!exch)
    260                 return EBADMEM;
    261 
    262         if (size == 0 && setup == 0)
    263                 return EOK;
    264 
    265         aid_t opening_request = async_send_5(exch,
    266             DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
    267             (setup & UINT32_MAX), (setup >> 32), NULL);
    268 
    269         if (opening_request == 0) {
    270                 return ENOMEM;
    271         }
    272 
    273         /* Send the data if any. */
    274         if (size > 0) {
    275                 const errno_t ret = async_data_write_start(exch, data, size);
    276                 if (ret != EOK) {
    277                         async_forget(opening_request);
    278                         return ret;
    279                 }
    280         }
    281 
    282         /* Wait for the answer. */
    283         errno_t opening_request_rc;
    284         async_wait_for(opening_request, &opening_request_rc);
    285 
    286         return (errno_t) opening_request_rc;
    287 }
    288 
    289 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    290 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    291 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    292 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    293 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    294 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    295 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    296 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    297 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
    298 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     93static void remote_usb_get_my_description(ddf_fun_t *, void *,
     94    ipc_callid_t, ipc_call_t *);
    29995
    30096/** Remote USB interface operations. */
    30197static const remote_iface_func_ptr_t remote_usb_iface_ops [] = {
    302         [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
    303         [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle,
    304         [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
    305         [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
    306         [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
    307         [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
    308         [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
    309         [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
    310         [IPC_M_USB_READ] = remote_usb_read,
    311         [IPC_M_USB_WRITE] = remote_usb_write,
     98        [IPC_M_USB_GET_MY_DESCRIPTION] = remote_usb_get_my_description,
    31299};
    313100
     
    319106};
    320107
    321 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
     108void remote_usb_get_my_description(ddf_fun_t *fun, void *iface,
    322109    ipc_callid_t callid, ipc_call_t *call)
    323110{
    324111        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    325112
    326         if (usb_iface->get_my_interface == NULL) {
     113        if (usb_iface->get_my_description == NULL) {
    327114                async_answer_0(callid, ENOTSUP);
    328115                return;
    329116        }
    330117
    331         int iface_no;
    332         const errno_t ret = usb_iface->get_my_interface(fun, &iface_no);
     118        usb_device_desc_t desc;
     119        const errno_t ret = usb_iface->get_my_description(fun, &desc);
    333120        if (ret != EOK) {
    334121                async_answer_0(callid, ret);
    335122        } else {
    336                 async_answer_1(callid, EOK, iface_no);
     123                async_answer_5(callid, EOK,
     124                    (sysarg_t) desc.address,
     125                    (sysarg_t) desc.depth,
     126                    (sysarg_t) desc.speed,
     127                    desc.handle,
     128                    desc.iface);
    337129        }
    338130}
    339131
    340 void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface,
    341     ipc_callid_t callid, ipc_call_t *call)
    342 {
    343         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    344 
    345         if (usb_iface->get_my_device_handle == NULL) {
    346                 async_answer_0(callid, ENOTSUP);
    347                 return;
    348         }
    349 
    350         devman_handle_t handle;
    351         const errno_t ret = usb_iface->get_my_device_handle(fun, &handle);
    352         if (ret != EOK) {
    353                 async_answer_0(callid, ret);
    354         }
    355 
    356         async_answer_1(callid, EOK, (sysarg_t) handle);
    357 }
    358 
    359 void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
    360     ipc_callid_t callid, ipc_call_t *call)
    361 {
    362         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    363 
    364         if (usb_iface->reserve_default_address == NULL) {
    365                 async_answer_0(callid, ENOTSUP);
    366                 return;
    367         }
    368 
    369         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    370         const errno_t ret = usb_iface->reserve_default_address(fun, speed);
    371         async_answer_0(callid, ret);
    372 }
    373 
    374 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
    375     ipc_callid_t callid, ipc_call_t *call)
    376 {
    377         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    378 
    379         if (usb_iface->release_default_address == NULL) {
    380                 async_answer_0(callid, ENOTSUP);
    381                 return;
    382         }
    383 
    384         const errno_t ret = usb_iface->release_default_address(fun);
    385         async_answer_0(callid, ret);
    386 }
    387 
    388 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
    389     ipc_callid_t callid, ipc_call_t *call)
    390 {
    391         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    392 
    393         if (usb_iface->device_enumerate == NULL) {
    394                 async_answer_0(callid, ENOTSUP);
    395                 return;
    396         }
    397 
    398         const unsigned port = DEV_IPC_GET_ARG1(*call);
    399         const errno_t ret = usb_iface->device_enumerate(fun, port);
    400         async_answer_0(callid, ret);
    401 }
    402 
    403 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
    404     ipc_callid_t callid, ipc_call_t *call)
    405 {
    406         const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    407 
    408         if (usb_iface->device_remove == NULL) {
    409                 async_answer_0(callid, ENOTSUP);
    410                 return;
    411         }
    412 
    413         const unsigned port = DEV_IPC_GET_ARG1(*call);
    414         const errno_t ret = usb_iface->device_remove(fun, port);
    415         async_answer_0(callid, ret);
    416 }
    417 
    418 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,
    419     ipc_callid_t callid, ipc_call_t *call)
    420 {
    421         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    422 
    423         if (!usb_iface->register_endpoint) {
    424                 async_answer_0(callid, ENOTSUP);
    425                 return;
    426         }
    427 
    428         const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call);
    429         const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)};
    430         const size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    431 
    432         const usb_transfer_type_t transfer_type = pack.arr[0];
    433         const usb_direction_t direction = pack.arr[1];
    434         unsigned packets = pack.arr[2];
    435         unsigned interval = pack.arr[3];
    436 
    437         const errno_t ret = usb_iface->register_endpoint(fun, endpoint,
    438             transfer_type, direction, max_packet_size, packets, interval);
    439 
    440         async_answer_0(callid, ret);
    441 }
    442 
    443 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,
    444     ipc_callid_t callid, ipc_call_t *call)
    445 {
    446         usb_iface_t *usb_iface = (usb_iface_t *) iface;
    447 
    448         if (!usb_iface->unregister_endpoint) {
    449                 async_answer_0(callid, ENOTSUP);
    450                 return;
    451         }
    452 
    453         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call);
    454         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call);
    455 
    456         errno_t rc = usb_iface->unregister_endpoint(fun, endpoint, direction);
    457 
    458         async_answer_0(callid, rc);
    459 }
    460 
    461 typedef struct {
    462         ipc_callid_t caller;
    463         ipc_callid_t data_caller;
    464         void *buffer;
    465 } async_transaction_t;
    466 
    467 static void async_transaction_destroy(async_transaction_t *trans)
    468 {
    469         if (trans == NULL) {
    470                 return;
    471         }
    472         if (trans->buffer != NULL) {
    473                 free(trans->buffer);
    474         }
    475 
    476         free(trans);
    477 }
    478 
    479 static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    480 {
    481         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    482         if (trans == NULL) {
    483                 return NULL;
    484         }
    485 
    486         trans->caller = caller;
    487         trans->data_caller = 0;
    488         trans->buffer = NULL;
    489 
    490         return trans;
    491 }
    492 
    493 static void callback_out(errno_t outcome, void *arg)
    494 {
    495         async_transaction_t *trans = arg;
    496 
    497         async_answer_0(trans->caller, outcome);
    498 
    499         async_transaction_destroy(trans);
    500 }
    501 
    502 static void callback_in(errno_t outcome, size_t actual_size, void *arg)
    503 {
    504         async_transaction_t *trans = (async_transaction_t *)arg;
    505 
    506         if (outcome != EOK) {
    507                 async_answer_0(trans->caller, outcome);
    508                 if (trans->data_caller) {
    509                         async_answer_0(trans->data_caller, EINTR);
    510                 }
    511                 async_transaction_destroy(trans);
    512                 return;
    513         }
    514 
    515         if (trans->data_caller) {
    516                 async_data_read_finalize(trans->data_caller,
    517                     trans->buffer, actual_size);
    518         }
    519 
    520         async_answer_0(trans->caller, EOK);
    521 
    522         async_transaction_destroy(trans);
    523 }
    524 
    525 void remote_usb_read(
    526     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    527 {
    528         assert(fun);
    529         assert(iface);
    530         assert(call);
    531 
    532         const usb_iface_t *usb_iface = iface;
    533 
    534         if (!usb_iface->read) {
    535                 async_answer_0(callid, ENOTSUP);
    536                 return;
    537         }
    538 
    539         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    540         const uint64_t setup =
    541             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    542             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
    543 
    544         async_transaction_t *trans = async_transaction_create(callid);
    545         if (trans == NULL) {
    546                 async_answer_0(callid, ENOMEM);
    547                 return;
    548         }
    549 
    550         size_t size = 0;
    551         if (!async_data_read_receive(&trans->data_caller, &size)) {
    552                 async_answer_0(callid, EPARTY);
    553                 async_transaction_destroy(trans);
    554                 return;
    555         }
    556 
    557         trans->buffer = malloc(size);
    558         if (trans->buffer == NULL) {
    559                 async_answer_0(trans->data_caller, ENOMEM);
    560                 async_answer_0(callid, ENOMEM);
    561                 async_transaction_destroy(trans);
    562                 return;
    563         }
    564 
    565         const errno_t rc = usb_iface->read(
    566             fun, ep, setup, trans->buffer, size, callback_in, trans);
    567 
    568         if (rc != EOK) {
    569                 async_answer_0(trans->data_caller, rc);
    570                 async_answer_0(callid, rc);
    571                 async_transaction_destroy(trans);
    572         }
    573 }
    574 
    575 void remote_usb_write(
    576     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    577 {
    578         assert(fun);
    579         assert(iface);
    580         assert(call);
    581 
    582         const usb_iface_t *usb_iface = iface;
    583 
    584         if (!usb_iface->write) {
    585                 async_answer_0(callid, ENOTSUP);
    586                 return;
    587         }
    588 
    589         const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
    590         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    591         const uint64_t setup =
    592             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    593             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    594 
    595         async_transaction_t *trans = async_transaction_create(callid);
    596         if (trans == NULL) {
    597                 async_answer_0(callid, ENOMEM);
    598                 return;
    599         }
    600 
    601         size_t size = 0;
    602         if (data_buffer_len > 0) {
    603                 const errno_t rc = async_data_write_accept(&trans->buffer, false,
    604                     1, data_buffer_len, 0, &size);
    605 
    606                 if (rc != EOK) {
    607                         async_answer_0(callid, rc);
    608                         async_transaction_destroy(trans);
    609                         return;
    610                 }
    611         }
    612 
    613         const errno_t rc = usb_iface->write(
    614             fun, ep, setup, trans->buffer, size, callback_out, trans);
    615 
    616         if (rc != EOK) {
    617                 async_answer_0(callid, rc);
    618                 async_transaction_destroy(trans);
    619         }
    620 }
    621132/**
    622133 * @}
  • uspace/lib/drv/generic/remote_usbhc.c

    rf5e5f73 rdf6ded8  
    11/*
    2  * Copyright (c) 2010-2011 Vojtech Horky
     2 * Copyright (c) 2010 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek
    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>
     41#include <as.h>
    4042
    4143#include "usbhc_iface.h"
    4244#include "ddf/driver.h"
    4345
    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  */
     46
    8647typedef 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,
     48        IPC_M_USB_DEFAULT_ADDRESS_RESERVATION,
     49        IPC_M_USB_DEVICE_ENUMERATE,
     50        IPC_M_USB_DEVICE_REMOVE,
     51        IPC_M_USB_REGISTER_ENDPOINT,
     52        IPC_M_USB_UNREGISTER_ENDPOINT,
     53        IPC_M_USB_TRANSFER,
    9654} usbhc_iface_funcs_t;
    9755
    98 errno_t 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)
    101 {
    102         if (!exch)
    103                 return EBADMEM;
    104 
    105         if (size == 0 && setup == 0)
    106                 return EOK;
    107 
    108         const usb_target_t target =
    109             {{ .address = address, .endpoint = endpoint }};
    110 
    111         /* Make call identifying target USB device and type of transfer. */
    112         aid_t opening_request = async_send_4(exch,
    113             DEV_IFACE_ID(USBHC_DEV_IFACE),
    114             IPC_M_USBHC_READ, target.packed,
    115             (setup & UINT32_MAX), (setup >> 32), NULL);
     56/** Reserve default USB address.
     57 * @param[in] exch IPC communication exchange
     58 * @return Error code.
     59 */
     60errno_t 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 */
     73errno_t 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 */
     89errno_t usbhc_device_enumerate(async_exch_t *exch, unsigned port, usb_speed_t speed)
     90{
     91        if (!exch)
     92                return EBADMEM;
     93        const errno_t 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 */
     106errno_t 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
     114errno_t 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);
    116125
    117126        if (opening_request == 0) {
     
    119128        }
    120129
    121         /* Retrieve the data. */
    122         ipc_call_t data_request_call;
    123         aid_t data_request =
    124             async_data_read(exch, data, size, &data_request_call);
    125 
    126         if (data_request == 0) {
    127                 // FIXME: How to let the other side know that we want to abort?
     130        errno_t ret = async_data_write_start(exch, desc, sizeof(*desc));
     131        if (ret != EOK) {
    128132                async_forget(opening_request);
    129                 return ENOMEM;
     133                return ret;
    130134        }
    131135
    132136        /* Wait for the answer. */
    133         errno_t data_request_rc;
    134137        errno_t opening_request_rc;
    135         async_wait_for(data_request, &data_request_rc);
    136138        async_wait_for(opening_request, &opening_request_rc);
    137139
    138         if (data_request_rc != EOK) {
    139                 /* Prefer the return code of the opening request. */
    140                 if (opening_request_rc != EOK) {
    141                         return (errno_t) opening_request_rc;
    142                 } else {
    143                         return (errno_t) data_request_rc;
    144                 }
    145         }
    146         if (opening_request_rc != EOK) {
     140        if (opening_request_rc)
    147141                return (errno_t) opening_request_rc;
    148         }
    149 
    150         *rec_size = IPC_GET_ARG2(data_request_call);
     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
    151152        return EOK;
    152153}
    153154
    154 errno_t usbhc_write(async_exch_t *exch, usb_address_t address,
    155     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
    156 {
    157         if (!exch)
    158                 return EBADMEM;
    159 
    160         if (size == 0 && setup == 0)
    161                 return EOK;
    162 
    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,
    168             (setup & UINT32_MAX), (setup >> 32), NULL);
     155errno_t 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);
    169162
    170163        if (opening_request == 0) {
     
    172165        }
    173166
    174         /* Send the data if any. */
    175         if (size > 0) {
    176                 const errno_t ret = async_data_write_start(exch, data, size);
     167        const errno_t 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        errno_t opening_request_rc;
     175        async_wait_for(opening_request, &opening_request_rc);
     176
     177        return (errno_t) opening_request_rc;
     178}
     179
     180/**
     181 * Issue a USB transfer with a data contained in memory area. That area is
     182 * temporarily shared with the HC.
     183 */
     184errno_t usbhc_transfer(async_exch_t *exch,
     185    const usbhc_iface_transfer_request_t *req, size_t *transferred)
     186{
     187        if (transferred)
     188                *transferred = 0;
     189
     190        if (!exch)
     191                return EBADMEM;
     192
     193        ipc_call_t call;
     194
     195        aid_t opening_request = async_send_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     196            IPC_M_USB_TRANSFER, &call);
     197
     198        if (opening_request == 0)
     199                return ENOMEM;
     200
     201        const errno_t ret = async_data_write_start(exch, req, sizeof(*req));
     202        if (ret != EOK) {
     203                async_forget(opening_request);
     204                return ret;
     205        }
     206
     207        /* Share the data, if any. */
     208        if (req->size > 0) {
     209                unsigned flags = (req->dir == USB_DIRECTION_IN)
     210                        ? AS_AREA_WRITE : AS_AREA_READ;
     211
     212                const errno_t ret = async_share_out_start(exch, req->buffer.virt, flags);
    177213                if (ret != EOK) {
    178214                        async_forget(opening_request);
     
    185221        async_wait_for(opening_request, &opening_request_rc);
    186222
     223        if (transferred)
     224                *transferred = IPC_GET_ARG1(call);
     225
    187226        return (errno_t) opening_request_rc;
    188227}
    189228
    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,
     229static void remote_usbhc_default_address_reservation(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     230static void remote_usbhc_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     231static void remote_usbhc_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     232static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     233static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     234static void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
     235
     236/** Remote USB interface operations. */
     237static const remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     238        [IPC_M_USB_DEFAULT_ADDRESS_RESERVATION] = remote_usbhc_default_address_reservation,
     239        [IPC_M_USB_DEVICE_ENUMERATE] = remote_usbhc_device_enumerate,
     240        [IPC_M_USB_DEVICE_REMOVE] = remote_usbhc_device_remove,
     241        [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     242        [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
     243        [IPC_M_USB_TRANSFER] = remote_usbhc_transfer,
    197244};
    198245
    199 /** Remote USB host controller interface structure.
     246/** Remote USB interface structure.
    200247 */
    201248const remote_iface_t remote_usbhc_iface = {
    202249        .method_count = ARRAY_SIZE(remote_usbhc_iface_ops),
    203         .methods = remote_usbhc_iface_ops
     250        .methods = remote_usbhc_iface_ops,
    204251};
    205252
    206253typedef struct {
    207254        ipc_callid_t caller;
    208         ipc_callid_t data_caller;
    209         void *buffer;
     255        usbhc_iface_transfer_request_t request;
    210256} async_transaction_t;
    211257
    212 static void async_transaction_destroy(async_transaction_t *trans)
    213 {
    214         if (trans == NULL)
    215                 return;
    216        
    217         if (trans->buffer != NULL)
    218                 free(trans->buffer);
    219        
    220         free(trans);
    221 }
    222 
    223 static async_transaction_t *async_transaction_create(ipc_callid_t caller)
    224 {
    225         async_transaction_t *trans = malloc(sizeof(async_transaction_t));
    226         if (trans == NULL) {
    227                 return NULL;
    228         }
    229 
    230         trans->caller = caller;
    231         trans->data_caller = 0;
    232         trans->buffer = NULL;
    233 
    234         return trans;
    235 }
    236 
    237 static void callback_out(errno_t outcome, void *arg)
    238 {
    239         async_transaction_t *trans = arg;
    240 
    241         async_answer_0(trans->caller, outcome);
    242 
    243         async_transaction_destroy(trans);
    244 }
    245 
    246 static void callback_in(errno_t 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) {
    253                         async_answer_0(trans->data_caller, EINTR);
    254                 }
    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 
    266         async_transaction_destroy(trans);
    267 }
    268 
    269 void remote_usbhc_read(
    270     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     258void remote_usbhc_default_address_reservation(ddf_fun_t *fun, void *iface,
     259    ipc_callid_t callid, ipc_call_t *call)
     260{
     261        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     262
     263        if (usbhc_iface->default_address_reservation == NULL) {
     264                async_answer_0(callid, ENOTSUP);
     265                return;
     266        }
     267
     268        const bool reserve = IPC_GET_ARG2(*call);
     269        const errno_t ret = usbhc_iface->default_address_reservation(fun, reserve);
     270        async_answer_0(callid, ret);
     271}
     272
     273
     274static void remote_usbhc_device_enumerate(ddf_fun_t *fun, void *iface,
     275    ipc_callid_t callid, ipc_call_t *call)
     276{
     277        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     278
     279        if (usbhc_iface->device_enumerate == NULL) {
     280                async_answer_0(callid, ENOTSUP);
     281                return;
     282        }
     283
     284        const unsigned port = DEV_IPC_GET_ARG1(*call);
     285        usb_speed_t speed = DEV_IPC_GET_ARG2(*call);
     286        const errno_t ret = usbhc_iface->device_enumerate(fun, port, speed);
     287        async_answer_0(callid, ret);
     288}
     289
     290static void remote_usbhc_device_remove(ddf_fun_t *fun, void *iface,
     291    ipc_callid_t callid, ipc_call_t *call)
     292{
     293        const usbhc_iface_t *usbhc_iface = (usbhc_iface_t *) iface;
     294
     295        if (usbhc_iface->device_remove == NULL) {
     296                async_answer_0(callid, ENOTSUP);
     297                return;
     298        }
     299
     300        const unsigned port = DEV_IPC_GET_ARG1(*call);
     301        const errno_t ret = usbhc_iface->device_remove(fun, port);
     302        async_answer_0(callid, ret);
     303}
     304
     305static void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     306    ipc_callid_t callid, ipc_call_t *call)
    271307{
    272308        assert(fun);
     
    274310        assert(call);
    275311
    276         const usbhc_iface_t *hc_iface = iface;
    277 
    278         if (!hc_iface->read) {
     312        const usbhc_iface_t *usbhc_iface = iface;
     313
     314        if (!usbhc_iface->register_endpoint) {
    279315                async_answer_0(callid, ENOTSUP);
    280316                return;
    281317        }
    282318
    283         const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    284         const uint64_t setup =
    285             ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
    286             (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
     319        usb_endpoint_descriptors_t ep_desc;
     320        ipc_callid_t data_callid;
     321        size_t len;
     322
     323        if (!async_data_write_receive(&data_callid, &len)
     324            || len != sizeof(ep_desc)) {
     325                async_answer_0(callid, EINVAL);
     326                return;
     327        }
     328        async_data_write_finalize(data_callid, &ep_desc, sizeof(ep_desc));
     329
     330        usb_pipe_desc_t pipe_desc;
     331
     332        const errno_t rc = usbhc_iface->register_endpoint(fun, &pipe_desc, &ep_desc);
     333        async_answer_0(callid, rc);
     334
     335        if (!async_data_read_receive(&data_callid, &len)
     336            || len != sizeof(pipe_desc)) {
     337                return;
     338        }
     339        async_data_read_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
     340}
     341
     342static void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     343    ipc_callid_t callid, ipc_call_t *call)
     344{
     345        assert(fun);
     346        assert(iface);
     347        assert(call);
     348
     349        const usbhc_iface_t *usbhc_iface = iface;
     350
     351        if (!usbhc_iface->unregister_endpoint) {
     352                async_answer_0(callid, ENOTSUP);
     353                return;
     354        }
     355
     356        usb_pipe_desc_t pipe_desc;
     357        ipc_callid_t data_callid;
     358        size_t len;
     359
     360        if (!async_data_write_receive(&data_callid, &len)
     361            || len != sizeof(pipe_desc)) {
     362                async_answer_0(callid, EINVAL);
     363                return;
     364        }
     365        async_data_write_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
     366
     367        const errno_t rc = usbhc_iface->unregister_endpoint(fun, &pipe_desc);
     368        async_answer_0(callid, rc);
     369}
     370
     371static void async_transaction_destroy(async_transaction_t *trans)
     372{
     373        if (trans == NULL) {
     374                return;
     375        }
     376        if (trans->request.buffer.virt != NULL) {
     377                as_area_destroy(trans->request.buffer.virt);
     378        }
     379
     380        free(trans);
     381}
     382
     383static async_transaction_t *async_transaction_create(ipc_callid_t caller)
     384{
     385        async_transaction_t *trans = calloc(1, sizeof(async_transaction_t));
     386
     387        if (trans != NULL)
     388                trans->caller = caller;
     389
     390        return trans;
     391}
     392
     393static errno_t transfer_finished(void *arg, errno_t error, size_t transferred_size)
     394{
     395        async_transaction_t *trans = arg;
     396        const errno_t err = async_answer_1(trans->caller, error, transferred_size);
     397        async_transaction_destroy(trans);
     398        return err;
     399}
     400
     401static errno_t receive_memory_buffer(async_transaction_t *trans)
     402{
     403        assert(trans);
     404        assert(trans->request.size > 0);
     405
     406        const size_t required_size = trans->request.offset + trans->request.size;
     407        const unsigned required_flags =
     408                (trans->request.dir == USB_DIRECTION_IN)
     409                ? AS_AREA_WRITE : AS_AREA_READ;
     410
     411        errno_t err;
     412        ipc_callid_t data_callid;
     413        size_t size;
     414        unsigned flags;
     415
     416        if (!async_share_out_receive(&data_callid, &size, &flags))
     417                return EPARTY;
     418
     419        if (size < required_size || (flags & required_flags) != required_flags) {
     420                async_answer_0(data_callid, EINVAL);
     421                return EINVAL;
     422        }
     423
     424        if ((err = async_share_out_finalize(data_callid, &trans->request.buffer.virt)))
     425                return err;
     426
     427        /*
     428         * As we're going to get physical addresses of the mapping, we must make
     429         * sure the memory is actually mapped. We must do it right now, because
     430         * the area might be read-only or write-only, and we may be unsure
     431         * later.
     432         */
     433        if (flags & AS_AREA_READ) {
     434                char foo = 0;
     435                volatile const char *buf = trans->request.buffer.virt + trans->request.offset;
     436                for (size_t i = 0; i < size; i += PAGE_SIZE)
     437                        foo += buf[i];
     438        } else {
     439                volatile char *buf = trans->request.buffer.virt + trans->request.offset;
     440                for (size_t i = 0; i < size; i += PAGE_SIZE)
     441                        buf[i] = 0xff;
     442        }
     443
     444        return EOK;
     445}
     446
     447void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     448{
     449        assert(fun);
     450        assert(iface);
     451        assert(call);
     452
     453        const usbhc_iface_t *usbhc_iface = iface;
     454
     455        if (!usbhc_iface->transfer) {
     456                async_answer_0(callid, ENOTSUP);
     457                return;
     458        }
    287459
    288460        async_transaction_t *trans = async_transaction_create(callid);
     
    292464        }
    293465
    294         size_t size = 0;
    295         if (!async_data_read_receive(&trans->data_caller, &size)) {
    296                 async_answer_0(callid, EPARTY);
    297                 return;
    298         }
    299 
    300         trans->buffer = malloc(size);
    301         if (trans->buffer == NULL) {
    302                 async_answer_0(trans->data_caller, ENOMEM);
    303                 async_answer_0(callid, ENOMEM);
    304                 async_transaction_destroy(trans);
    305                 return;
    306         }
    307 
    308         const errno_t rc = hc_iface->read(
    309             fun, target, setup, trans->buffer, size, callback_in, trans);
    310 
    311         if (rc != EOK) {
    312                 async_answer_0(trans->data_caller, rc);
    313                 async_answer_0(callid, rc);
    314                 async_transaction_destroy(trans);
    315         }
    316 }
    317 
    318 void remote_usbhc_write(
    319     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    320 {
    321         assert(fun);
    322         assert(iface);
    323         assert(call);
    324 
    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) };
    333         const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
    334         const uint64_t setup =
    335             ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
    336             (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
    337 
    338         async_transaction_t *trans = async_transaction_create(callid);
    339         if (trans == NULL) {
    340                 async_answer_0(callid, ENOMEM);
    341                 return;
    342         }
    343 
    344         size_t size = 0;
    345         if (data_buffer_len > 0) {
    346                 const errno_t rc = async_data_write_accept(&trans->buffer, false,
    347                     1, USB_MAX_PAYLOAD_SIZE,
    348                     0, &size);
    349 
    350                 if (rc != EOK) {
    351                         async_answer_0(callid, rc);
    352                         async_transaction_destroy(trans);
    353                         return;
    354                 }
    355         }
    356 
    357         const errno_t rc = hc_iface->write(
    358             fun, target, setup, trans->buffer, size, callback_out, trans);
    359 
    360         if (rc != EOK) {
    361                 async_answer_0(callid, rc);
    362                 async_transaction_destroy(trans);
    363         }
    364 }
     466        errno_t err = EPARTY;
     467
     468        ipc_callid_t data_callid;
     469        size_t len;
     470        if (!async_data_write_receive(&data_callid, &len)
     471            || len != sizeof(trans->request)) {
     472                async_answer_0(data_callid, EINVAL);
     473                goto err;
     474        }
     475
     476        if ((err = async_data_write_finalize(data_callid,
     477                            &trans->request, sizeof(trans->request))))
     478                goto err;
     479
     480        if (trans->request.size > 0) {
     481                if ((err = receive_memory_buffer(trans)))
     482                        goto err;
     483        } else {
     484                /* The value was valid on the other side, for us, its garbage. */
     485                trans->request.buffer.virt = NULL;
     486        }
     487
     488        if ((err = usbhc_iface->transfer(fun, &trans->request,
     489            &transfer_finished, trans)))
     490                goto err;
     491
     492        /* The call will be answered asynchronously by the callback. */
     493        return;
     494
     495err:
     496        async_answer_0(callid, err);
     497        async_transaction_destroy(trans);
     498}
     499
    365500/**
    366501 * @}
  • uspace/lib/drv/include/usb_iface.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    34 * All rights reserved.
    45 *
     
    3233 */
    3334/** @file
    34  * @brief USB interface definition.
     35 * @brief USB device interface definition.
    3536 */
    3637
     
    4041#include "ddf/driver.h"
    4142#include <async.h>
     43#include <usbhc_iface.h>
    4244
    4345typedef async_sess_t usb_dev_session_t;
    4446
    45 /** USB speeds. */
    46 typedef enum {
    47         /** USB 1.1 low speed (1.5Mbits/s). */
    48         USB_SPEED_LOW,
    49         /** USB 1.1 full speed (12Mbits/s). */
    50         USB_SPEED_FULL,
    51         /** USB 2.0 high speed (480Mbits/s). */
    52         USB_SPEED_HIGH,
    53         /** Psuedo-speed serving as a boundary. */
    54         USB_SPEED_MAX
    55 } usb_speed_t;
    56 
    57 /** USB endpoint number type.
    58  * Negative values could be used to indicate error.
    59  */
    60 typedef int16_t usb_endpoint_t;
    61 
    62 /** USB address type.
    63  * Negative values could be used to indicate error.
    64  */
    65 typedef int16_t usb_address_t;
    66 
    67 /** USB transfer type. */
    68 typedef enum {
    69         USB_TRANSFER_CONTROL = 0,
    70         USB_TRANSFER_ISOCHRONOUS = 1,
    71         USB_TRANSFER_BULK = 2,
    72         USB_TRANSFER_INTERRUPT = 3
    73 } usb_transfer_type_t;
    74 
    75 /** USB data transfer direction. */
    76 typedef enum {
    77         USB_DIRECTION_IN,
    78         USB_DIRECTION_OUT,
    79         USB_DIRECTION_BOTH
    80 } usb_direction_t;
    81 
    82 /** USB complete address type.
    83  * Pair address + endpoint is identification of transaction recipient.
    84  */
    85 typedef union {
    86         struct {
    87                 usb_address_t address;
    88                 usb_endpoint_t endpoint;
    89         } __attribute__((packed));
    90         uint32_t packed;
    91 } usb_target_t;
     47typedef struct {
     48        usb_address_t address;  /**< Current USB address */
     49        uint8_t depth;          /**< Depth in the hub hiearchy */
     50        usb_speed_t speed;      /**< Speed of the device */
     51        devman_handle_t handle; /**< Handle to DDF function of the HC driver */
     52        /** Interface set by multi interface driver,  -1 if none */
     53        int iface;
     54} usb_device_desc_t;
    9255
    9356extern usb_dev_session_t *usb_dev_connect(devman_handle_t);
     
    9558extern void usb_dev_disconnect(usb_dev_session_t *);
    9659
    97 extern errno_t usb_get_my_interface(async_exch_t *, int *);
    98 extern errno_t usb_get_my_device_handle(async_exch_t *, devman_handle_t *);
    99 
    100 extern errno_t usb_reserve_default_address(async_exch_t *, usb_speed_t);
    101 extern errno_t usb_release_default_address(async_exch_t *);
    102 
    103 extern errno_t usb_device_enumerate(async_exch_t *, unsigned port);
    104 extern errno_t usb_device_remove(async_exch_t *, unsigned port);
    105 
    106 extern errno_t usb_register_endpoint(async_exch_t *, usb_endpoint_t,
    107     usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned);
    108 extern errno_t usb_unregister_endpoint(async_exch_t *, usb_endpoint_t,
    109     usb_direction_t);
    110 extern errno_t usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t,
    111     size_t *);
    112 extern errno_t usb_write(async_exch_t *, usb_endpoint_t, uint64_t, const void *,
    113     size_t);
    114 
    115 /** Callback for outgoing transfer. */
    116 typedef void (*usb_iface_transfer_out_callback_t)(errno_t, void *);
    117 
    118 /** Callback for incoming transfer. */
    119 typedef void (*usb_iface_transfer_in_callback_t)(errno_t, size_t, void *);
     60extern errno_t usb_get_my_description(async_exch_t *, usb_device_desc_t *);
    12061
    12162/** USB device communication interface. */
    12263typedef struct {
    123         errno_t (*get_my_interface)(ddf_fun_t *, int *);
    124         errno_t (*get_my_device_handle)(ddf_fun_t *, devman_handle_t *);
    125 
    126         errno_t (*reserve_default_address)(ddf_fun_t *, usb_speed_t);
    127         errno_t (*release_default_address)(ddf_fun_t *);
    128 
    129         errno_t (*device_enumerate)(ddf_fun_t *, unsigned);
    130         errno_t (*device_remove)(ddf_fun_t *, unsigned);
    131 
    132         errno_t (*register_endpoint)(ddf_fun_t *, usb_endpoint_t,
    133             usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned);
    134         errno_t (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t,
    135             usb_direction_t);
    136 
    137         errno_t (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t,
    138             usb_iface_transfer_in_callback_t, void *);
    139         errno_t (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *,
    140             size_t, usb_iface_transfer_out_callback_t, void *);
     64        errno_t (*get_my_description)(ddf_fun_t *, usb_device_desc_t *);
    14165} usb_iface_t;
    14266
  • uspace/lib/drv/include/usbhc_iface.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2017 Ondrej Hlavaty
    44 * All rights reserved.
    55 *
     
    3232 * @{
    3333 */
    34 
    3534/** @file
    36  * @brief USB host controller interface definition.
     35 * @brief USB host controler interface definition. This is the interface of
     36 * USB host controller function, which can be used by usb device drivers.
    3737 */
    3838
     
    4141
    4242#include "ddf/driver.h"
    43 #include <usb_iface.h>
    44 #include <stdbool.h>
    45 
    46 extern errno_t usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t,
    47     uint64_t, void *, size_t, size_t *);
    48 extern errno_t usbhc_write(async_exch_t *, usb_address_t, usb_endpoint_t,
    49     uint64_t, const void *, size_t);
    50 
    51 /** Callback for outgoing transfer. */
    52 typedef void (*usbhc_iface_transfer_out_callback_t)(errno_t, void *);
    53 
    54 /** Callback for incoming transfer. */
    55 typedef void (*usbhc_iface_transfer_in_callback_t)(errno_t, size_t, void *);
    56 
    57 /** USB host controller communication interface. */
     43#include <async.h>
     44
     45/** USB speeds. */
     46typedef enum {
     47        /** USB 1.1 low speed (1.5Mbits/s). */
     48        USB_SPEED_LOW,
     49        /** USB 1.1 full speed (12Mbits/s). */
     50        USB_SPEED_FULL,
     51        /** USB 2.0 high speed (480Mbits/s). */
     52        USB_SPEED_HIGH,
     53        /** USB 3.0 super speed (5Gbits/s). */
     54        USB_SPEED_SUPER,
     55        /** Psuedo-speed serving as a boundary. */
     56        USB_SPEED_MAX
     57} usb_speed_t;
     58
     59/** USB endpoint number type.
     60 * Negative values could be used to indicate error.
     61 */
     62typedef uint16_t usb_endpoint_t;
     63
     64/** USB address type.
     65 * Negative values could be used to indicate error.
     66 */
     67typedef uint16_t usb_address_t;
     68
     69/**
     70 * USB Stream ID type.
     71 */
     72typedef uint16_t usb_stream_t;
     73
     74/** USB transfer type. */
     75typedef enum {
     76        USB_TRANSFER_CONTROL = 0,
     77        USB_TRANSFER_ISOCHRONOUS = 1,
     78        USB_TRANSFER_BULK = 2,
     79        USB_TRANSFER_INTERRUPT = 3,
     80} usb_transfer_type_t;
     81
     82#define USB_TRANSFER_COUNT  (USB_TRANSFER_INTERRUPT + 1)
     83
     84/** USB data transfer direction. */
     85typedef enum {
     86        USB_DIRECTION_IN,
     87        USB_DIRECTION_OUT,
     88        USB_DIRECTION_BOTH,
     89} usb_direction_t;
     90
     91#define USB_DIRECTION_COUNT  (USB_DIRECTION_BOTH + 1)
     92
     93/** USB complete address type.
     94 * Pair address + endpoint is identification of transaction recipient.
     95 */
     96typedef union {
     97        struct {
     98                usb_address_t address;
     99                usb_endpoint_t endpoint;
     100                usb_stream_t stream;
     101        } __attribute__((packed));
     102        uint64_t packed;
     103} usb_target_t;
     104
     105// FIXME: DMA buffers shall be part of libdrv anyway.
     106typedef uintptr_t dma_policy_t;
     107
     108typedef struct dma_buffer {
     109        void *virt;
     110        dma_policy_t policy;
     111} dma_buffer_t;
     112
     113typedef struct usb_pipe_desc {
     114        /** Endpoint number. */
     115        usb_endpoint_t endpoint_no;
     116
     117        /** Endpoint transfer type. */
     118        usb_transfer_type_t transfer_type;
     119
     120        /** Endpoint direction. */
     121        usb_direction_t direction;
     122
     123        /**
     124         * Maximum size of one transfer. Non-periodic endpoints may handle
     125         * bigger transfers, but those can be split into multiple USB transfers.
     126         */
     127        size_t max_transfer_size;
     128
     129        /** Constraints on buffers to be transferred without copying */
     130        dma_policy_t transfer_buffer_policy;
     131} usb_pipe_desc_t;
     132
     133typedef struct usb_pipe_transfer_request {
     134        usb_direction_t dir;
     135        usb_endpoint_t endpoint;
     136        usb_stream_t stream;
     137
     138        uint64_t setup;                 /**< Valid iff the transfer is of control type */
     139
     140        /**
     141         * The DMA buffer to share. Must be at least offset + size large. Is
     142         * patched after being transmitted over IPC, so the pointer is still
     143         * valid.
     144         */
     145        dma_buffer_t buffer;
     146        size_t offset;                  /**< Offset to the buffer */
     147        size_t size;                    /**< Requested size. */
     148} usbhc_iface_transfer_request_t;
     149
     150/** This structure follows standard endpoint descriptor + superspeed companion
     151 * descriptor, and exists to avoid dependency of libdrv on libusb. Keep the
     152 * internal fields named exactly like their source (because we want to use the
     153 * same macros to access them).
     154 * Callers shall fill it with bare contents of respective descriptors (in usb endianity).
     155 */
     156typedef struct usb_endpoint_descriptors {
     157        struct {
     158                uint8_t endpoint_address;
     159                uint8_t attributes;
     160                uint16_t max_packet_size;
     161                uint8_t poll_interval;
     162        } endpoint;
     163
     164        /* Superspeed companion descriptor */
     165        struct companion_desc_t {
     166                uint8_t max_burst;
     167                uint8_t attributes;
     168                uint16_t bytes_per_interval;
     169        } companion;
     170} usb_endpoint_descriptors_t;
     171
     172extern errno_t usbhc_reserve_default_address(async_exch_t *);
     173extern errno_t usbhc_release_default_address(async_exch_t *);
     174
     175extern errno_t usbhc_device_enumerate(async_exch_t *, unsigned, usb_speed_t);
     176extern errno_t usbhc_device_remove(async_exch_t *, unsigned);
     177
     178extern errno_t usbhc_register_endpoint(async_exch_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *);
     179extern errno_t usbhc_unregister_endpoint(async_exch_t *, const usb_pipe_desc_t *);
     180
     181extern errno_t usbhc_transfer(async_exch_t *, const usbhc_iface_transfer_request_t *, size_t *);
     182
     183/** Callback for outgoing transfer */
     184typedef errno_t (*usbhc_iface_transfer_callback_t)(void *, int, size_t);
     185
     186/** USB device communication interface. */
    58187typedef struct {
    59         errno_t (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t,
    60             usbhc_iface_transfer_in_callback_t, void *);
    61         errno_t (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *,
    62             size_t, usbhc_iface_transfer_out_callback_t, void *);
     188        errno_t (*default_address_reservation)(ddf_fun_t *, bool);
     189
     190        errno_t (*device_enumerate)(ddf_fun_t *, unsigned, usb_speed_t);
     191        errno_t (*device_remove)(ddf_fun_t *, unsigned);
     192
     193        errno_t (*register_endpoint)(ddf_fun_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *);
     194        errno_t (*unregister_endpoint)(ddf_fun_t *, const usb_pipe_desc_t *);
     195
     196        errno_t (*transfer)(ddf_fun_t *, const usbhc_iface_transfer_request_t *,
     197            usbhc_iface_transfer_callback_t, void *);
    63198} usbhc_iface_t;
    64 
    65199
    66200#endif
Note: See TracChangeset for help on using the changeset viewer.