Changeset df6ded8 in mainline for uspace/lib


Ignore:
Timestamp:
2018-02-28T16:37:50Z (8 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
Files:
15 added
2 deleted
48 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/bitops.h

    rf5e5f73 rdf6ded8  
    5454#define BIT_RANGE_EXTRACT(type, hi, lo, value) \
    5555    (((value) >> (lo)) & BIT_RRANGE(type, (hi) - (lo) + 1))
     56
     57/** Insert @a value between bits @a hi .. @a lo. */
     58#define BIT_RANGE_INSERT(type, hi, lo, value) \
     59    (((value) & BIT_RRANGE(type, (hi) - (lo) + 1)) << (lo))
    5660
    5761/** Return position of first non-zero bit from left (i.e. [log_2(arg)]).
  • uspace/lib/c/include/byteorder.h

    rf5e5f73 rdf6ded8  
    8585#define ntohl(n)  uint32_t_be2host((n))
    8686
     87#define uint8_t_be2host(n)  (n)
     88#define uint8_t_le2host(n)  (n)
     89#define host2uint8_t_be(n)  (n)
     90#define host2uint8_t_le(n)  (n)
     91#define host2uint8_t_le(n)  (n)
     92
     93#define  int8_t_le2host(n)  uint8_t_le2host(n)
     94#define int16_t_le2host(n) uint16_t_le2host(n)
     95#define int32_t_le2host(n) uint32_t_le2host(n)
     96#define int64_t_le2host(n) uint64_t_le2host(n)
     97
     98#define  int8_t_be2host(n)  uint8_t_be2host(n)
     99#define int16_t_be2host(n) uint16_t_be2host(n)
     100#define int32_t_be2host(n) uint32_t_be2host(n)
     101#define int64_t_be2host(n) uint64_t_be2host(n)
     102
     103#define  host2int8_t_le(n)  host2uint8_t_le(n)
     104#define host2int16_t_le(n) host2uint16_t_le(n)
     105#define host2int32_t_le(n) host2uint32_t_le(n)
     106#define host2int64_t_le(n) host2uint64_t_le(n)
     107
     108#define  host2int8_t_be(n)  host2uint8_t_be(n)
     109#define host2int16_t_be(n) host2uint16_t_be(n)
     110#define host2int32_t_be(n) host2uint32_t_be(n)
     111#define host2int64_t_be(n) host2uint64_t_be(n)
     112
    87113static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
    88114{
  • uspace/lib/c/include/ipc/dev_iface.h

    rf5e5f73 rdf6ded8  
    4444        /** Audio device pcm buffer interface */
    4545        AUDIO_PCM_BUFFER_IFACE,
    46        
     46
    4747        /** Network interface controller interface */
    4848        NIC_DEV_IFACE,
    49                
     49
    5050        /** IEEE 802.11 interface controller interface */
    5151        IEEE80211_DEV_IFACE,
    52        
     52
    5353        /** Interface provided by any PCI device. */
    5454        PCI_DEV_IFACE,
     
    5656        /** Interface provided by any USB device. */
    5757        USB_DEV_IFACE,
    58         /** Interface provided by USB host controller. */
     58        /** Interface provided by USB diagnostic devices. */
     59        USBDIAG_DEV_IFACE,
     60        /** Interface provided by USB host controller to USB device. */
    5961        USBHC_DEV_IFACE,
    6062        /** Interface provided by USB HID devices. */
  • 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
  • uspace/lib/pcm/src/format.c

    rf5e5f73 rdf6ded8  
    4141
    4242#include "format.h"
    43 
    44 #define uint8_t_le2host(x) (x)
    45 #define host2uint8_t_le(x) (x)
    46 #define uint8_t_be2host(x) (x)
    47 #define host2uint8_t_be(x) (x)
    48 
    49 #define int8_t_le2host(x) (x)
    50 #define host2int8_t_le(x) (x)
    51 
    52 #define int16_t_le2host(x) uint16_t_le2host(x)
    53 #define host2int16_t_le(x) host2uint16_t_le(x)
    54 
    55 #define int32_t_le2host(x) uint32_t_le2host(x)
    56 #define host2int32_t_le(x) host2uint32_t_le(x)
    57 
    58 #define int8_t_be2host(x) (x)
    59 #define host2int8_t_be(x) (x)
    60 
    61 #define int16_t_be2host(x) uint16_t_be2host(x)
    62 #define host2int16_t_be(x) host2uint16_t_be(x)
    63 
    64 #define int32_t_be2host(x) uint32_t_be2host(x)
    65 #define host2int32_t_be(x) host2uint32_t_be(x)
    6643
    6744// TODO float endian?
  • uspace/lib/usb/Makefile

    rf5e5f73 rdf6ded8  
    3535        src/dev.c \
    3636        src/debug.c \
     37        src/dma_buffer.c \
    3738        src/dump.c \
     39        src/port.c \
    3840        src/usb.c
    3941
  • uspace/lib/usb/include/usb/classes/hub.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Matus Dekanek
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4849        USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4950        USB_HUB_FEATURE_PORT_CONNECTION = 0,
    50         USB_HUB_FEATURE_PORT_ENABLE = 1,
    51         USB_HUB_FEATURE_PORT_SUSPEND = 2,
     51        USB2_HUB_FEATURE_PORT_ENABLE = 1,
     52        USB2_HUB_FEATURE_PORT_SUSPEND = 2,
    5253        USB_HUB_FEATURE_PORT_OVER_CURRENT = 3,
    5354        USB_HUB_FEATURE_PORT_RESET = 4,
     55        USB3_HUB_FEATURE_PORT_LINK_STATE = 5,
    5456        USB_HUB_FEATURE_PORT_POWER = 8,
    55         USB_HUB_FEATURE_PORT_LOW_SPEED = 9,
    56         USB_HUB_FEATURE_PORT_HIGH_SPEED = 10,
     57        USB2_HUB_FEATURE_PORT_LOW_SPEED = 9,
    5758        USB_HUB_FEATURE_C_PORT_CONNECTION = 16,
    58         USB_HUB_FEATURE_C_PORT_ENABLE = 17,
    59         USB_HUB_FEATURE_C_PORT_SUSPEND = 18,
     59        USB2_HUB_FEATURE_C_PORT_ENABLE = 17,
     60        USB2_HUB_FEATURE_C_PORT_SUSPEND = 18,
    6061        USB_HUB_FEATURE_C_PORT_OVER_CURRENT = 19,
    6162        USB_HUB_FEATURE_C_PORT_RESET = 20,
    62         USB_HUB_FEATURE_PORT_TEST = 21,
    63         USB_HUB_FEATURE_PORT_INDICATOR = 22
     63        USB2_HUB_FEATURE_PORT_TEST = 21,
     64        USB2_HUB_FEATURE_PORT_INDICATOR = 22,
     65        USB3_HUB_FEATURE_C_PORT_LINK_STATE = 25,
     66        USB3_HUB_FEATURE_BH_PORT_RESET = 28,
     67        USB3_HUB_FEATURE_C_BH_PORT_RESET = 29,
    6468        /* USB_HUB_FEATURE_ = , */
    6569} usb_hub_class_feature_t;
    6670
     71/**
     72 * Dword holding port status and changes flags.
     73 *
     74 * For more information refer to tables 11-15 and 11-16 in
     75 * "Universal Serial Bus Specification Revision 1.1" pages 274 and 277
     76 * (290 and 293 in pdf)
     77 *
     78 * Beware that definition of bits changed between USB 2 and 3,
     79 * so some fields are prefixed with USB2 or USB3 instead.
     80 */
     81typedef uint32_t usb_port_status_t;
     82
     83#define USB_HUB_PORT_STATUS_BIT(bit)  (uint32_usb2host(1 << (bit)))
     84#define USB_HUB_PORT_STATUS_CONNECTION          USB_HUB_PORT_STATUS_BIT(0)
     85#define USB_HUB_PORT_STATUS_ENABLE              USB_HUB_PORT_STATUS_BIT(1)
     86#define USB2_HUB_PORT_STATUS_SUSPEND            USB_HUB_PORT_STATUS_BIT(2)
     87#define USB_HUB_PORT_STATUS_OC                  USB_HUB_PORT_STATUS_BIT(3)
     88#define USB_HUB_PORT_STATUS_RESET               USB_HUB_PORT_STATUS_BIT(4)
     89
     90#define USB2_HUB_PORT_STATUS_POWER              USB_HUB_PORT_STATUS_BIT(8)
     91#define USB2_HUB_PORT_STATUS_LOW_SPEED          USB_HUB_PORT_STATUS_BIT(9)
     92#define USB3_HUB_PORT_STATUS_POWER              USB_HUB_PORT_STATUS_BIT(9)
     93#define USB2_HUB_PORT_STATUS_HIGH_SPEED         USB_HUB_PORT_STATUS_BIT(10)
     94#define USB2_HUB_PORT_STATUS_TEST               USB_HUB_PORT_STATUS_BIT(11)
     95#define USB2_HUB_PORT_STATUS_INDICATOR          USB_HUB_PORT_STATUS_BIT(12)
     96
     97#define USB_HUB_PORT_STATUS_C_CONNECTION        USB_HUB_PORT_STATUS_BIT(16)
     98#define USB2_HUB_PORT_STATUS_C_ENABLE           USB_HUB_PORT_STATUS_BIT(17)
     99#define USB2_HUB_PORT_STATUS_C_SUSPEND          USB_HUB_PORT_STATUS_BIT(18)
     100#define USB_HUB_PORT_STATUS_C_OC                USB_HUB_PORT_STATUS_BIT(19)
     101#define USB_HUB_PORT_STATUS_C_RESET             USB_HUB_PORT_STATUS_BIT(20)
     102#define USB3_HUB_PORT_STATUS_C_BH_RESET         USB_HUB_PORT_STATUS_BIT(21)
     103#define USB3_HUB_PORT_STATUS_C_LINK_STATE       USB_HUB_PORT_STATUS_BIT(22)
     104#define USB3_HUB_PORT_STATUS_C_CONFIG_ERROR     USB_HUB_PORT_STATUS_BIT(23)
    67105
    68106/** Header of standard hub descriptor without the "variadic" part. */
     
    71109        uint8_t length;
    72110
    73         /** Descriptor type (0x29). */
     111        /** Descriptor type (0x29 or 0x2a for superspeed hub). */
    74112        uint8_t descriptor_type;
    75113
     
    116154#define HUB_CHAR_OC_PER_PORT_FLAG       (1 << 3)
    117155#define HUB_CHAR_NO_OC_FLAG             (1 << 4)
     156
     157/* These are invalid for superspeed hub */
    118158#define HUB_CHAR_TT_THINK_16            (1 << 5)
    119159#define HUB_CHAR_TT_THINK_8             (1 << 6)
     
    138178         */
    139179        uint8_t max_current;
    140 } __attribute__ ((packed)) usb_hub_descriptor_header_t;
     180} __attribute__((packed)) usb_hub_descriptor_header_t;
    141181
    142182/** One bit for the device and one bit for every port */
    143183#define STATUS_BYTES(ports) ((1 + ports + 7) / 8)
    144184
    145 /**     @brief usb hub specific request types.
    146  *
    147  *      For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
     185/**
     186 * @brief usb hub specific request types.
    148187 */
    149188typedef enum {
    150     /** This request resets a value reported in the hub status. */
    151     USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE = 0x20,
    152     /** This request resets a value reported in the port status. */
    153     USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE = 0x23,
    154     /** This is an optional per-port diagnostic request that returns the bus state value, as sampled at the last EOF2 point. */
    155     USB_HUB_REQ_TYPE_GET_STATE = 0xA3,
    156     /** This request returns the hub descriptor. */
    157     USB_HUB_REQ_TYPE_GET_DESCRIPTOR = 0xA0,
    158     /** This request returns the current hub status and the states that have changed since the previous acknowledgment. */
    159     USB_HUB_REQ_TYPE_GET_HUB_STATUS = 0xA0,
    160     /** This request returns the current port status and the current value of the port status change bits. */
    161     USB_HUB_REQ_TYPE_GET_PORT_STATUS = 0xA3,
    162     /** This request overwrites the hub descriptor. */
    163     USB_HUB_REQ_TYPE_SET_DESCRIPTOR = 0x20,
    164     /** This request sets a value reported in the hub status. */
    165     USB_HUB_REQ_TYPE_SET_HUB_FEATURE = 0x20,
    166     /** This request sets a value reported in the port status. */
    167     USB_HUB_REQ_TYPE_SET_PORT_FEATURE = 0x23
     189        /** This request resets a value reported in the hub status. */
     190        USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE = 0x20,
     191        /** This request resets a value reported in the port status. */
     192        USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE = 0x23,
     193        /**
     194         * This is an optional per-port diagnostic request that returns the bus
     195         * state value, as sampled at the last EOF2 point.
     196         */
     197        USB_HUB_REQ_TYPE_GET_STATE = 0xA3,
     198        /** This request returns the hub descriptor. */
     199        USB_HUB_REQ_TYPE_GET_DESCRIPTOR = 0xA0,
     200        /**
     201         * This request returns the current hub status and the states that have
     202         * changed since the previous acknowledgment.
     203         */
     204        USB_HUB_REQ_TYPE_GET_HUB_STATUS = 0xA0,
     205        /**
     206         * This request returns the current port status and the current value of the
     207         * port status change bits.
     208         */
     209        USB_HUB_REQ_TYPE_GET_PORT_STATUS = 0xA3,
     210        /** This request overwrites the hub descriptor. */
     211        USB_HUB_REQ_TYPE_SET_DESCRIPTOR = 0x20,
     212        /** This request sets a value reported in the hub status. */
     213        USB_HUB_REQ_TYPE_SET_HUB_FEATURE = 0x20,
     214        /**
     215         * This request sets the value that the hub uses to determine the index
     216         * into the Route String Index for the hub.
     217         */
     218        USB_HUB_REQ_TYPE_SET_HUB_DEPTH = 0x20,
     219        /** This request sets a value reported in the port status. */
     220        USB_HUB_REQ_TYPE_SET_PORT_FEATURE = 0x23,
    168221} usb_hub_bm_request_type_t;
    169222
    170 /** @brief hub class request codes*/
    171 /// \TODO these are duplicit to standart descriptors
     223/**
     224 * @brief hub class request codes
     225 */
    172226typedef enum {
    173     /**  */
    174     USB_HUB_REQUEST_GET_STATUS = 0,
    175     /** */
    176     USB_HUB_REQUEST_CLEAR_FEATURE = 1,
    177     /** USB 1.0 only */
    178     USB_HUB_REQUEST_GET_STATE = 2,
    179     /** */
    180     USB_HUB_REQUEST_SET_FEATURE = 3,
    181     /** */
    182     USB_HUB_REQUEST_GET_DESCRIPTOR = 6,
    183     /** */
    184     USB_HUB_REQUEST_SET_DESCRIPTOR = 7,
    185     /** */
    186     USB_HUB_REQUEST_CLEAR_TT_BUFFER = 8,
    187     /** */
    188     USB_HUB_REQUEST_RESET_TT = 9,
    189     /** */
    190     USB_HUB_GET_TT_STATE = 10,
    191     /** */
    192     USB_HUB_STOP_TT = 11,
     227        USB_HUB_REQUEST_GET_STATUS = 0,
     228        USB_HUB_REQUEST_CLEAR_FEATURE = 1,
     229        /** USB 1.0 only */
     230        USB_HUB_REQUEST_GET_STATE = 2,
     231        USB_HUB_REQUEST_SET_FEATURE = 3,
     232        USB_HUB_REQUEST_GET_DESCRIPTOR = 6,
     233        USB_HUB_REQUEST_SET_DESCRIPTOR = 7,
     234        USB_HUB_REQUEST_CLEAR_TT_BUFFER = 8,
     235        USB_HUB_REQUEST_RESET_TT = 9,
     236        USB_HUB_GET_TT_STATE = 10,
     237        USB_HUB_STOP_TT = 11,
     238        /** USB 3+ only */
     239        USB_HUB_REQUEST_SET_HUB_DEPTH = 12,
    193240} usb_hub_request_t;
    194241
    195242/**
    196  *      Maximum size of usb hub descriptor in bytes
     243 * Maximum size of usb hub descriptor in bytes
    197244 */
    198245/* 7 (basic size) + 2*32 (port bitmasks) */
  • uspace/lib/usb/include/usb/descriptor.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2018 Michal Staruch, Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4950        USB_DESCTYPE_OTHER_SPEED_CONFIGURATION = 7,
    5051        USB_DESCTYPE_INTERFACE_POWER = 8,
     52        /* USB 3.0 types */
     53        USB_DESCTYPE_OTG = 9,
     54        USB_DESCTYPE_DEBUG = 0xa,
     55        USB_DESCTYPE_IFACE_ASSOC = 0xb,
     56        USB_DESCTYPE_BOS = 0xf,
     57        USB_DESCTYPE_DEVICE_CAP = 0x10,
    5158        /* Class specific */
    5259        USB_DESCTYPE_HID = 0x21,
     
    5461        USB_DESCTYPE_HID_PHYSICAL = 0x23,
    5562        USB_DESCTYPE_HUB = 0x29,
     63        USB_DESCTYPE_SSPEED_HUB = 0x2a,
     64        USB_DESCTYPE_SSPEED_EP_COMPANION = 0x30
    5665        /* USB_DESCTYPE_ = */
    5766} usb_descriptor_type_t;
     
    92101        /** Number of possible configurations. */
    93102        uint8_t configuration_count;
    94 } __attribute__ ((packed)) usb_standard_device_descriptor_t;
     103} __attribute__((packed)) usb_standard_device_descriptor_t;
    95104
    96105/** USB device qualifier decriptor is basically a cut down version of the device
     
    120129        uint8_t configuration_count;
    121130        uint8_t reserved;
    122 } __attribute__ ((packed)) usb_standard_device_qualifier_descriptor_t;
     131} __attribute__((packed)) usb_standard_device_qualifier_descriptor_t;
    123132
    124133/** Standard USB configuration descriptor.
     
    147156         */
    148157        uint8_t max_power;
    149 } __attribute__ ((packed)) usb_standard_configuration_descriptor_t;
     158} __attribute__((packed)) usb_standard_configuration_descriptor_t;
    150159
    151160/** USB Other Speed Configuration descriptor shows values that would change
     
    182191        /** String descriptor describing this interface. */
    183192        uint8_t str_interface;
    184 } __attribute__ ((packed)) usb_standard_interface_descriptor_t;
     193} __attribute__((packed)) usb_standard_interface_descriptor_t;
    185194
    186195/** Standard USB endpoint descriptor.
     
    193202        /** Endpoint address together with data flow direction. */
    194203        uint8_t endpoint_address;
     204#define USB_ED_GET_EP(ed)       ((ed).endpoint_address & 0xf)
     205#define USB_ED_GET_DIR(ed)      (!(((ed).endpoint_address >> 7) & 0x1))
     206
    195207        /** Endpoint attributes.
    196208         * Includes transfer type (usb_transfer_type_t).
    197209         */
    198210        uint8_t attributes;
     211#define USB_ED_GET_TRANSFER_TYPE(ed)    ((ed).attributes & 0x3)
    199212        /** Maximum packet size.
    200213         * Lower 10 bits represent the actuall size
     
    202215         * HS INT and ISO transfers. */
    203216        uint16_t max_packet_size;
    204 
    205 #define ED_MPS_PACKET_SIZE_MASK  0x3ff
    206 #define ED_MPS_PACKET_SIZE_GET(value) \
    207         ((value) & ED_MPS_PACKET_SIZE_MASK)
    208 #define ED_MPS_TRANS_OPPORTUNITIES_GET(value) \
    209         ((((value) >> 10) & 0x3) + 1)
    210 
    211         /** Polling interval in milliseconds.
    212          * Ignored for bulk and control endpoints.
    213          * Isochronous endpoints must use value 1.
    214          * Interrupt endpoints any value from 1 to 255.
     217#define USB_ED_GET_MPS(ed) \
     218        (uint16_usb2host((ed).max_packet_size) & 0x7ff)
     219#define USB_ED_GET_ADD_OPPS(ed) \
     220        ((uint16_usb2host((ed).max_packet_size) >> 11) & 0x3)
     221        /** Polling interval. Different semantics for various (speed, type)
     222         * pairs.
    215223         */
    216224        uint8_t poll_interval;
    217 } __attribute__ ((packed)) usb_standard_endpoint_descriptor_t;
     225} __attribute__((packed)) usb_standard_endpoint_descriptor_t;
     226
     227/** Superspeed USB endpoint companion descriptor.
     228 * See USB 3 specification, section 9.6.7.
     229 */
     230typedef struct {
     231        /** Size of this descriptor in bytes */
     232        uint8_t length;
     233        /** Descriptor type (USB_DESCTYPE_SSPEED_EP_COMPANION). */
     234        uint8_t descriptor_type;
     235        /** The maximum number of packets the endpoint can send
     236         * or receive as part of a burst. Valid values are from 0 to 15.
     237         * The endpoint can only burst max_burst + 1 packets at a time.
     238         */
     239        uint8_t max_burst;
     240        /** Valid only for bulk and isochronous endpoints.
     241         * For bulk endpoints, this field contains the amount of streams
     242         * supported by the endpoint.
     243         * For isochronous endpoints, this field contains maximum
     244         * number of packets supported within a service interval.
     245         * Warning: the values returned by macros may not make any sense
     246         * for specific endpoint types.
     247         */
     248        uint8_t attributes;
     249#define USB_SSC_MAX_STREAMS(sscd) ((sscd).attributes & 0x1f)
     250#define USB_SSC_MULT(sscd) ((sscd).attributes & 0x3)
     251        /** The total number of bytes this endpoint will transfer
     252         * every service interval (SI).
     253         * This field is only valid for periodic endpoints.
     254         */
     255        uint16_t bytes_per_interval;
     256} __attribute__((packed)) usb_superspeed_endpoint_companion_descriptor_t;
    218257
    219258/** Part of standard USB HID descriptor specifying one class descriptor.
     
    226265        /** Length of class-specific descriptor in bytes. */
    227266        uint16_t length;
    228 } __attribute__ ((packed)) usb_standard_hid_class_descriptor_info_t;
     267} __attribute__((packed)) usb_standard_hid_class_descriptor_info_t;
    229268
    230269/** Standard USB HID descriptor.
     
    257296        /** First mandatory class descriptor (Report) info. */
    258297        usb_standard_hid_class_descriptor_info_t report_desc_info;
    259 } __attribute__ ((packed)) usb_standard_hid_descriptor_t;
     298} __attribute__((packed)) usb_standard_hid_descriptor_t;
    260299
    261300#endif
  • uspace/lib/usb/include/usb/request.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2012 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    7172#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
    7273
     74/** Size of the USB setup packet */
     75#define USB_SETUP_PACKET_SIZE 8
     76
    7377/** Device request setup packet.
    7478 * The setup packet describes the request.
     
    8286#define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7)
    8387#define SETUP_REQUEST_TYPE_HOST_TO_DEVICE (0 << 7)
     88#define SETUP_REQUEST_TYPE_IS_DEVICE_TO_HOST(rt) ((rt) & (1 << 7))
    8489#define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3)
    8590#define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f)
     
    108113} __attribute__ ((packed)) usb_device_request_setup_packet_t;
    109114
    110 static_assert(sizeof(usb_device_request_setup_packet_t) == 8);
     115static_assert(sizeof(usb_device_request_setup_packet_t) == USB_SETUP_PACKET_SIZE);
    111116
    112 int usb_request_needs_toggle_reset(
    113     const usb_device_request_setup_packet_t *request);
     117#define GET_DEVICE_DESC(size) \
     118{ \
     119        .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
     120            | (USB_REQUEST_TYPE_STANDARD << 5) \
     121            | USB_REQUEST_RECIPIENT_DEVICE, \
     122        .request = USB_DEVREQ_GET_DESCRIPTOR, \
     123        .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
     124        .index = uint16_host2usb(0), \
     125        .length = uint16_host2usb(size), \
     126};
     127
     128#define SET_ADDRESS(address) \
     129{ \
     130        .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
     131            | (USB_REQUEST_TYPE_STANDARD << 5) \
     132            | USB_REQUEST_RECIPIENT_DEVICE, \
     133        .request = USB_DEVREQ_SET_ADDRESS, \
     134        .value = uint16_host2usb(address), \
     135        .index = uint16_host2usb(0), \
     136        .length = uint16_host2usb(0), \
     137};
     138
     139#define CTRL_PIPE_MIN_PACKET_SIZE 8
    114140
    115141#endif
  • uspace/lib/usb/include/usb/usb.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    34 * All rights reserved.
    45 *
     
    3940#include <stdint.h>
    4041#include <types/common.h>
    41 #include <usb_iface.h>
     42#include <usbhc_iface.h>
    4243
    4344/** Convert 16bit value from native (host) endianness to USB endianness. */
     
    5354#define uint32_usb2host(n) uint32_t_le2host((n))
    5455
    55 const char * usb_str_transfer_type(usb_transfer_type_t t);
    56 const char * usb_str_transfer_type_short(usb_transfer_type_t t);
     56const char *usb_str_transfer_type(usb_transfer_type_t);
     57const char *usb_str_transfer_type_short(usb_transfer_type_t);
    5758
    5859const char *usb_str_direction(usb_direction_t);
     
    6162{
    6263        return (s == USB_SPEED_FULL) || (s == USB_SPEED_LOW);
     64}
     65
     66static inline bool usb_speed_is_valid(const usb_speed_t s)
     67{
     68        return (s >= USB_SPEED_LOW) && (s < USB_SPEED_MAX);
    6369}
    6470
     
    97103static inline bool usb_address_is_valid(usb_address_t a)
    98104{
    99         return (a >= USB_ADDRESS_DEFAULT) && (a <= USB11_ADDRESS_MAX);
     105        return a <= USB11_ADDRESS_MAX;
    100106}
    101107
     
    103109#define USB_ENDPOINT_DEFAULT_CONTROL 0
    104110
    105 /** Maximum endpoint number in USB 1.1. */
    106 #define USB11_ENDPOINT_MAX 16
     111/** Maximum endpoint number in USB */
     112#define USB_ENDPOINT_MAX 16
     113
     114/** There might be two directions for every endpoint number (except 0) */
     115#define USB_ENDPOINT_COUNT (2 * USB_ENDPOINT_MAX)
    107116
    108117/** Check USB endpoint for allowed values.
     
    115124static inline bool usb_endpoint_is_valid(usb_endpoint_t ep)
    116125{
    117         return (ep >= USB_ENDPOINT_DEFAULT_CONTROL) &&
    118             (ep < USB11_ENDPOINT_MAX);
     126        return ep < USB_ENDPOINT_MAX;
    119127}
    120128
    121 /** Check USB target for allowed values (address and endpoint).
     129/**
     130 * Check USB target for allowed values (address, endpoint, stream).
    122131 *
    123132 * @param target.
    124133 * @return True, if values are wihtin limits, false otherwise.
    125134 */
    126 static inline bool usb_target_is_valid(usb_target_t target)
     135static inline bool usb_target_is_valid(const usb_target_t *target)
    127136{
    128         return usb_address_is_valid(target.address) &&
    129             usb_endpoint_is_valid(target.endpoint);
     137        return usb_address_is_valid(target->address) &&
     138            usb_endpoint_is_valid(target->endpoint);
     139
     140        // A 16-bit Stream ID is always valid.
    130141}
    131142
     
    136147 * @return Whether @p a and @p b points to the same pipe on the same device.
    137148 */
    138 static inline int usb_target_same(usb_target_t a, usb_target_t b)
     149static inline bool usb_target_same(usb_target_t a, usb_target_t b)
    139150{
    140         return (a.address == b.address)
    141             && (a.endpoint == b.endpoint);
     151        return (a.address == b.address) && (a.endpoint == b.endpoint);
    142152}
    143 
    144 /** General handle type.
    145  * Used by various USB functions as opaque handle.
    146  */
    147 typedef sysarg_t usb_handle_t;
    148153
    149154/** USB packet identifier. */
     
    161166        USB_PID_SETUP = _MAKE_PID(3, 1),
    162167
    163         USB_PID_DATA0 = _MAKE_PID(0 ,3),
    164         USB_PID_DATA1 = _MAKE_PID(2 ,3),
     168        USB_PID_DATA0 = _MAKE_PID(0, 3),
     169        USB_PID_DATA1 = _MAKE_PID(2, 3),
    165170
    166         USB_PID_ACK = _MAKE_PID(0 ,2),
    167         USB_PID_NAK = _MAKE_PID(2 ,2),
    168         USB_PID_STALL = _MAKE_PID(3 ,2),
     171        USB_PID_ACK = _MAKE_PID(0, 2),
     172        USB_PID_NAK = _MAKE_PID(2, 2),
     173        USB_PID_STALL = _MAKE_PID(3, 2),
    169174
    170         USB_PID_PRE = _MAKE_PID(3 ,0),
     175        USB_PID_PRE = _MAKE_PID(3, 0),
    171176        /* USB_PID_ = _MAKE_PID( ,), */
    172177#undef _MAKE_PID
  • uspace/lib/usb/src/dump.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    6162static void usb_dump_descriptor_endpoint(FILE *, const char *, const char *,
    6263    const uint8_t *, size_t);
     64static void usb_dump_descriptor_superspeed_endpoint_companion(FILE *, const char *, const char *,
     65    const uint8_t *, size_t);
    6366static void usb_dump_descriptor_hid(FILE *, const char *, const char *,
    6467    const uint8_t *, size_t);
     
    7578        { USB_DESCTYPE_INTERFACE, usb_dump_descriptor_interface },
    7679        { USB_DESCTYPE_ENDPOINT, usb_dump_descriptor_endpoint },
     80        { USB_DESCTYPE_SSPEED_EP_COMPANION, usb_dump_descriptor_superspeed_endpoint_companion },
    7781        { USB_DESCTYPE_HID, usb_dump_descriptor_hid },
    7882        { USB_DESCTYPE_HUB, usb_dump_descriptor_hub },
     
    238242        PRINTLINE("wMaxPacketSize = %d", d->max_packet_size);
    239243        PRINTLINE("bInterval = %dms", d->poll_interval);
     244}
     245
     246static void usb_dump_descriptor_superspeed_endpoint_companion(FILE *output,
     247    const char *line_prefix, const char *line_suffix,
     248    const uint8_t *descriptor, size_t descriptor_length)
     249{
     250        usb_superspeed_endpoint_companion_descriptor_t *d
     251           = (usb_superspeed_endpoint_companion_descriptor_t *) descriptor;
     252        if (descriptor_length < sizeof(*d)) {
     253                return;
     254        }
     255
     256        PRINTLINE("bLength = %u", d->length);
     257        PRINTLINE("bDescriptorType = 0x%02X", d->descriptor_type);
     258        PRINTLINE("bMaxBurst = %u", d->max_burst);
     259        PRINTLINE("bmAttributes = %d", d->attributes);
     260        PRINTLINE("wBytesPerInterval = %u", d->bytes_per_interval);
    240261}
    241262
  • uspace/lib/usb/src/usb.c

    rf5e5f73 rdf6ded8  
    4444        [USB_SPEED_FULL] = "full",
    4545        [USB_SPEED_HIGH] = "high",
     46        [USB_SPEED_SUPER] = "super",
    4647};
    4748
     
    118119}
    119120
    120 /** Check setup packet data for signs of toggle reset.
    121  *
    122  * @param[in] requst Setup requst data.
    123  *
    124  * @retval -1 No endpoints need reset.
    125  * @retval 0 All endpoints need reset.
    126  * @retval >0 Specified endpoint needs reset.
    127  *
    128  */
    129 int usb_request_needs_toggle_reset(
    130     const usb_device_request_setup_packet_t *request)
    131 {
    132         assert(request);
    133         switch (request->request)
    134         {
    135         /* Clear Feature ENPOINT_STALL */
    136         case USB_DEVREQ_CLEAR_FEATURE: /*resets only cleared ep */
    137                 /* 0x2 ( HOST to device | STANDART | TO ENPOINT) */
    138                 if ((request->request_type == 0x2) &&
    139                     (request->value == USB_FEATURE_ENDPOINT_HALT))
    140                         return uint16_usb2host(request->index);
    141                 break;
    142         case USB_DEVREQ_SET_CONFIGURATION:
    143         case USB_DEVREQ_SET_INTERFACE:
    144                 /* Recipient must be device, this resets all endpoints,
    145                  * In fact there should be no endpoints but EP 0 registered
    146                  * as different interfaces use different endpoints,
    147                  * unless you're changing configuration or alternative
    148                  * interface of an already setup device. */
    149                 if (!(request->request_type & SETUP_REQUEST_TYPE_DEVICE_TO_HOST))
    150                         return 0;
    151                 break;
    152         default:
    153                 break;
    154         }
    155         return -1;
    156 }
    157 
    158121/**
    159122 * @}
  • uspace/lib/usbdev/include/usb/dev/device.h

    rf5e5f73 rdf6ded8  
    4242#include <usb/dev/alternate_ifaces.h>
    4343#include <usb/dev/pipes.h>
     44#include <usbhc_iface.h>
    4445
    4546#include <assert.h>
     
    5859
    5960/* DDF parts */
    60 errno_t usb_device_create_ddf(ddf_dev_t *, const usb_endpoint_description_t **, const char **);
     61errno_t usb_device_create_ddf(ddf_dev_t *,
     62    const usb_endpoint_description_t **, const char **);
    6163void usb_device_destroy_ddf(ddf_dev_t *);
    6264
     
    6769}
    6870
    69 usb_device_t * usb_device_create(devman_handle_t);
     71usb_device_t *usb_device_create(devman_handle_t);
    7072void usb_device_destroy(usb_device_t *);
    7173
    72 const char * usb_device_get_name(usb_device_t *);
     74const char *usb_device_get_name(usb_device_t *);
    7375ddf_fun_t *usb_device_ddf_fun_create(usb_device_t *, fun_type_t, const char *);
    7476
    75 async_exch_t * usb_device_bus_exchange_begin(usb_device_t *);
     77async_exch_t *usb_device_bus_exchange_begin(usb_device_t *);
    7678void usb_device_bus_exchange_end(async_exch_t *);
    7779
     
    8688usb_endpoint_mapping_t * usb_device_get_mapped_ep_desc(usb_device_t *,
    8789    const usb_endpoint_description_t *);
    88 usb_endpoint_mapping_t * usb_device_get_mapped_ep(usb_device_t *,
    89     usb_endpoint_t);
     90int usb_device_unmap_ep(usb_endpoint_mapping_t *);
    9091
    91 int usb_device_get_iface_number(usb_device_t *);
    92 devman_handle_t usb_device_get_devman_handle(usb_device_t *);
     92usb_address_t usb_device_get_address(const usb_device_t *);
     93usb_speed_t usb_device_get_depth(const usb_device_t *);
     94usb_speed_t usb_device_get_speed(const usb_device_t *);
     95int usb_device_get_iface_number(const usb_device_t *);
     96devman_handle_t usb_device_get_devman_handle(const usb_device_t *);
    9397
    94 const usb_device_descriptors_t * usb_device_descriptors(usb_device_t *);
     98const usb_device_descriptors_t *usb_device_descriptors(usb_device_t *);
    9599
    96 const usb_alternate_interfaces_t * usb_device_get_alternative_ifaces(
     100const usb_alternate_interfaces_t *usb_device_get_alternative_ifaces(
    97101    usb_device_t *);
    98102
    99 void * usb_device_data_alloc(usb_device_t *, size_t);
    100 void * usb_device_data_get(usb_device_t *);
     103void *usb_device_data_alloc(usb_device_t *, size_t);
     104void *usb_device_data_get(usb_device_t *);
    101105
    102106#endif
  • uspace/lib/usbdev/include/usb/dev/driver.h

    rf5e5f73 rdf6ded8  
    4545        errno_t (*device_add)(usb_device_t *);
    4646        /** Callback when a device is about to be removed from the system. */
    47         errno_t (*device_rem)(usb_device_t *);
     47        errno_t (*device_remove)(usb_device_t *);
    4848        /** Callback when a device was removed from the system. */
    4949        errno_t (*device_gone)(usb_device_t *);
     50        /** Callback asking the driver to online a specific function. */
     51        errno_t (*function_online)(ddf_fun_t *);
     52        /** Callback asking the driver to offline a specific function. */
     53        errno_t (*function_offline)(ddf_fun_t *);
    5054} usb_driver_ops_t;
    5155
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4445
    4546#define CTRL_PIPE_MIN_PACKET_SIZE 8
     47
    4648/** Abstraction of a logical connection to USB device endpoint.
    47  * It encapsulates endpoint attributes (transfer type etc.).
     49 * It contains some vital information about the pipe.
    4850 * This endpoint must be bound with existing usb_device_connection_t
    4951 * (i.e. the wire to send data over).
    5052 */
    5153typedef struct {
    52         /** Endpoint number. */
    53         usb_endpoint_t endpoint_no;
    54 
    55         /** Endpoint transfer type. */
    56         usb_transfer_type_t transfer_type;
    57 
    58         /** Endpoint direction. */
    59         usb_direction_t direction;
    60 
    61         /** Maximum packet size for the endpoint. */
    62         size_t max_packet_size;
    63 
    64         /** Number of packets per frame/uframe.
    65          * Only valid for HS INT and ISO transfers. All others should set to 1*/
    66         unsigned packets;
     54        /** Pipe description received from HC */
     55        usb_pipe_desc_t desc;
    6756
    6857        /** Whether to automatically reset halt on the endpoint.
     
    7059         */
    7160        bool auto_reset_halt;
    72 
    7361        /** The connection used for sending the data. */
    7462        usb_dev_session_t *bus_session;
     
    10391        /** Found descriptor fitting the description. */
    10492        const usb_standard_endpoint_descriptor_t *descriptor;
     93        /** Relevant superspeed companion descriptor. */
     94        const usb_superspeed_endpoint_companion_descriptor_t
     95            *companion_descriptor;
    10596        /** Interface descriptor the endpoint belongs to. */
    10697        const usb_standard_interface_descriptor_t *interface;
     
    109100} usb_endpoint_mapping_t;
    110101
    111 errno_t usb_pipe_initialize(usb_pipe_t *, usb_endpoint_t, usb_transfer_type_t,
    112     size_t, usb_direction_t, unsigned, usb_dev_session_t *);
     102errno_t usb_pipe_initialize(usb_pipe_t *, usb_dev_session_t *);
    113103errno_t usb_pipe_initialize_default_control(usb_pipe_t *, usb_dev_session_t *);
    114104
    115 errno_t usb_pipe_probe_default_control(usb_pipe_t *);
    116105errno_t usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    117106    size_t, const uint8_t *, size_t, usb_dev_session_t *);
    118107
    119 errno_t usb_pipe_register(usb_pipe_t *, unsigned);
     108errno_t usb_pipe_register(usb_pipe_t *,
     109    const usb_standard_endpoint_descriptor_t *,
     110    const usb_superspeed_endpoint_companion_descriptor_t *);
    120111errno_t usb_pipe_unregister(usb_pipe_t *);
    121112
    122113errno_t usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
    123114errno_t usb_pipe_write(usb_pipe_t *, const void *, size_t);
     115
     116errno_t usb_pipe_read_dma(usb_pipe_t *, void *, void *, size_t, size_t *);
     117errno_t usb_pipe_write_dma(usb_pipe_t *, void *, void *, size_t);
    124118
    125119errno_t usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
     
    128122    const void *, size_t);
    129123
     124void *usb_pipe_alloc_buffer(usb_pipe_t *, size_t);
     125void usb_pipe_free_buffer(usb_pipe_t *, void *);
    130126#endif
    131127/**
  • uspace/lib/usbdev/include/usb/dev/poll.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2017 Petr Manek
    34 * All rights reserved.
    45 *
     
    4344#include <stddef.h>
    4445#include <stdint.h>
     46#include <fibril_synch.h>
    4547
    46 /** Parameters and callbacks for automated polling. */
    47 typedef struct {
    48         /** Level of debugging messages from auto polling.
    49          * 0 - nothing
    50          * 1 - inform about errors and polling start/end
    51          * 2 - also dump every retrieved buffer
     48
     49/** USB automated polling. */
     50typedef struct usb_polling {
     51        /** Mandatory parameters - user is expected to configure these. */
     52
     53        /** USB device to poll. */
     54        usb_device_t *device;
     55
     56        /** Device enpoint mapping to use for polling. */
     57        usb_endpoint_mapping_t *ep_mapping;
     58
     59        /** Size of the recieved data. */
     60        size_t request_size;
     61
     62        /**
     63         * Data buffer of at least `request_size`. User is responsible for its
     64         * allocation.
    5265         */
    53         int debug;
    54         /** Maximum number of consecutive errors before polling termination. */
    55         size_t max_failures;
    56         /** Delay between poll requests in milliseconds.
    57          * Set to negative value to use value from endpoint descriptor.
    58          */
    59         int delay;
    60         /** Whether to automatically try to clear the HALT feature after
    61          * the endpoint stalls.
    62          */
    63         bool auto_clear_halt;
     66        uint8_t *buffer;
     67
    6468        /** Callback when data arrives.
    6569         *
     
    7276        bool (*on_data)(usb_device_t *dev, uint8_t *data, size_t data_size,
    7377            void *arg);
     78
     79
     80        /**
     81         * Optional parameters - user can customize them, but they are
     82         * defaulted to  some reasonable values.
     83         */
     84
     85        /** Level of debugging messages from auto polling.
     86         * 0 - nothing (default)
     87         * 1 - inform about errors and polling start/end
     88         * 2 - also dump every retrieved buffer
     89         */
     90        int debug;
     91
     92        /**
     93         * Maximum number of consecutive errors before polling termination
     94         * (default 3).
     95         */
     96        size_t max_failures;
     97
     98        /** Delay between poll requests in milliseconds.
     99         * By default, value from endpoint descriptor used.
     100         */
     101        int delay;
     102
     103        /** Whether to automatically try to clear the HALT feature after
     104         * the endpoint stalls (true by default).
     105         */
     106        bool auto_clear_halt;
     107
     108        /** Argument to pass to callbacks (default NULL). */
     109        void *arg;
     110
    74111        /** Callback when polling is terminated.
    75112         *
     
    80117        void (*on_polling_end)(usb_device_t *dev, bool due_to_errors,
    81118            void *arg);
     119
    82120        /** Callback when error occurs.
    83121         *
     
    88126         */
    89127        bool (*on_error)(usb_device_t *dev, errno_t err_code, void *arg);
    90         /** Argument to pass to callbacks. */
    91         void *arg;
    92 } usb_device_auto_polling_t;
    93128
    94 typedef bool (*usb_polling_callback_t)(usb_device_t *, uint8_t *, size_t, void *);
    95 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
    96129
    97 extern errno_t usb_device_auto_polling(usb_device_t *, usb_endpoint_t,
    98     const usb_device_auto_polling_t *, size_t);
     130        /**
     131         * Internal parameters - user is not expected to set them. Messing with
     132         * them can result in unexpected behavior if you do not know what you
     133         * are doing.
     134         */
    99135
    100 extern errno_t usb_device_auto_poll(usb_device_t *, usb_endpoint_t,
    101     usb_polling_callback_t, size_t, int, usb_polling_terminted_callback_t, void *);
     136        /** Fibril used for polling. */
     137        fid_t fibril;
    102138
    103 extern errno_t usb_device_auto_polling_desc(usb_device_t *,
    104     const usb_endpoint_description_t *, const usb_device_auto_polling_t *,
    105     size_t);
     139        /** True if polling is currently in operation. */
     140        volatile bool running;
    106141
    107 extern errno_t usb_device_auto_poll_desc(usb_device_t *,
    108     const usb_endpoint_description_t *, usb_polling_callback_t, size_t, int,
    109     usb_polling_terminted_callback_t, void *);
     142        /** True if polling should terminate as soon as possible. */
     143        volatile bool joining;
     144
     145        /** Synchronization primitives for joining polling end. */
     146        fibril_mutex_t guard;
     147        fibril_condvar_t cv;
     148} usb_polling_t;
     149
     150errno_t usb_polling_init(usb_polling_t *);
     151void usb_polling_fini(usb_polling_t *);
     152
     153errno_t usb_polling_start(usb_polling_t *);
     154errno_t usb_polling_join(usb_polling_t *);
    110155
    111156#endif
  • uspace/lib/usbdev/include/usb/dev/request.h

    rf5e5f73 rdf6ded8  
    8585    char **);
    8686
    87 errno_t usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
    8887errno_t usb_pipe_clear_halt(usb_pipe_t *, usb_pipe_t *);
    8988errno_t usb_request_get_endpoint_status(usb_pipe_t *, usb_pipe_t *, uint16_t *);
  • uspace/lib/usbdev/src/devdrv.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek, Michal Staruch
    45 * All rights reserved.
    56 *
     
    4849#include <devman.h>
    4950#include <errno.h>
     51#include <str_error.h>
    5052#include <stdlib.h>
    5153
     
    5658        /** Connection to device on USB bus */
    5759        usb_dev_session_t *bus_session;
    58        
     60
    5961        /** devman handle */
    6062        devman_handle_t handle;
    61        
     63
    6264        /** The default control pipe. */
    6365        usb_pipe_t ctrl_pipe;
    64        
     66
    6567        /** Other endpoint pipes.
    6668         *
     
    6971         */
    7072        usb_endpoint_mapping_t *pipes;
    71        
     73
    7274        /** Number of other endpoint pipes. */
    7375        size_t pipes_count;
    74        
     76
     77        /** USB address of this device */
     78        usb_address_t address;
     79
     80        /** Depth in the USB hub hiearchy */
     81        unsigned depth;
     82
     83        /** USB speed of this device */
     84        usb_speed_t speed;
     85
    7586        /** Current interface.
    7687         *
     
    7990         */
    8091        int interface_no;
    81        
     92
    8293        /** Alternative interfaces. */
    8394        usb_alternate_interfaces_t alternate_interfaces;
    84        
     95
    8596        /** Some useful descriptors for USB device. */
    8697        usb_device_descriptors_t descriptors;
    87        
     98
    8899        /** Generic DDF device backing this one. DO NOT TOUCH! */
    89100        ddf_dev_t *ddf_dev;
    90        
     101
    91102        /** Custom driver data.
    92103         *
     
    146157                return rc;
    147158        }
    148        
     159
    149160        /* Change current alternative */
    150161        usb_dev->alternate_interfaces.current = alternate_setting;
     
    255266
    256267        /* Register created pipes. */
     268        unsigned pipes_registered = 0;
    257269        for (size_t i = 0; i < pipe_count; i++) {
    258270                if (pipes[i].present) {
    259                         rc = usb_pipe_register(&pipes[i].pipe,
    260                             pipes[i].descriptor->poll_interval);
     271                        rc = usb_pipe_register(&pipes[i].pipe, pipes[i].descriptor, pipes[i].companion_descriptor);
    261272                        if (rc != EOK) {
    262273                                goto rollback_unregister_endpoints;
    263274                        }
    264275                }
     276                pipes_registered++;
    265277        }
    266278
     
    277289         */
    278290rollback_unregister_endpoints:
    279         for (size_t i = 0; i < pipe_count; i++) {
     291        for (size_t i = 0; i < pipes_registered; i++) {
    280292                if (pipes[i].present) {
    281293                        usb_pipe_unregister(&pipes[i].pipe);
     
    296308        assert(usb_dev);
    297309        assert(usb_dev->pipes || usb_dev->pipes_count == 0);
    298        
     310
    299311        /* Destroy the pipes. */
     312        int rc;
    300313        for (size_t i = 0; i < usb_dev->pipes_count; ++i) {
    301                 usb_log_debug2("Unregistering pipe %zu: %spresent.\n",
     314                usb_log_debug2("Unregistering pipe %zu: %spresent.",
    302315                    i, usb_dev->pipes[i].present ? "" : "not ");
    303                 if (usb_dev->pipes[i].present)
    304                         usb_pipe_unregister(&usb_dev->pipes[i].pipe);
    305         }
    306        
     316
     317                rc = usb_device_unmap_ep(usb_dev->pipes + i);
     318                if (rc != EOK && rc != ENOENT)
     319                        usb_log_warning("Unregistering pipe %zu failed: %s", i, str_error(rc));
     320        }
     321
    307322        free(usb_dev->pipes);
    308323        usb_dev->pipes = NULL;
     
    327342}
    328343
    329 usb_endpoint_mapping_t * usb_device_get_mapped_ep(
    330     usb_device_t *usb_dev, usb_endpoint_t ep)
    331 {
    332         assert(usb_dev);
    333         for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
    334                 if (usb_dev->pipes[i].pipe.endpoint_no == ep)
    335                         return &usb_dev->pipes[i];
    336         }
    337         return NULL;
    338 }
    339 
    340 int usb_device_get_iface_number(usb_device_t *usb_dev)
     344int usb_device_unmap_ep(usb_endpoint_mapping_t *epm)
     345{
     346        assert(epm);
     347
     348        if (!epm->present)
     349                return ENOENT;
     350
     351        const int rc = usb_pipe_unregister(&epm->pipe);
     352        if (rc != EOK)
     353                return rc;
     354
     355        epm->present = false;
     356        return EOK;
     357}
     358
     359usb_address_t usb_device_get_address(const usb_device_t *usb_dev)
     360{
     361        assert(usb_dev);
     362        return usb_dev->depth;
     363}
     364
     365unsigned usb_device_get_depth(const usb_device_t *usb_dev)
     366{
     367        assert(usb_dev);
     368        return usb_dev->depth;
     369}
     370
     371usb_speed_t usb_device_get_speed(const usb_device_t *usb_dev)
     372{
     373        assert(usb_dev);
     374        return usb_dev->speed;
     375}
     376
     377int usb_device_get_iface_number(const usb_device_t *usb_dev)
    341378{
    342379        assert(usb_dev);
     
    344381}
    345382
    346 devman_handle_t usb_device_get_devman_handle(usb_device_t *usb_dev)
     383devman_handle_t usb_device_get_devman_handle(const usb_device_t *usb_dev)
    347384{
    348385        assert(usb_dev);
     
    394431 */
    395432static errno_t usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
    396     const usb_endpoint_description_t **endpoints, const char **errstr_ptr,
    397     devman_handle_t handle, int interface_no)
     433    const usb_endpoint_description_t **endpoints, const char **errstr_ptr)
    398434{
    399435        assert(usb_dev != NULL);
     
    403439
    404440        usb_dev->ddf_dev = ddf_dev;
    405         usb_dev->handle = handle;
    406         usb_dev->interface_no = interface_no;
    407441        usb_dev->driver_data = NULL;
    408442        usb_dev->descriptors.full_config = NULL;
     
    411445        usb_dev->pipes = NULL;
    412446
    413         usb_dev->bus_session = usb_dev_connect(handle);
     447        usb_dev->bus_session = usb_dev_connect(usb_dev->handle);
    414448
    415449        if (!usb_dev->bus_session) {
     
    420454        /* This pipe was registered by the hub driver,
    421455         * during device initialization. */
    422         errno_t rc = usb_pipe_initialize_default_control(
    423             &usb_dev->ctrl_pipe, usb_dev->bus_session);
     456        errno_t rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, usb_dev->bus_session);
    424457        if (rc != EOK) {
    425458                usb_dev_disconnect(usb_dev->bus_session);
     
    440473         * it makes no sense to speak about alternate interfaces when
    441474         * controlling a device. */
    442         rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
     475        usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
    443476            usb_dev->descriptors.full_config,
    444477            usb_dev->descriptors.full_config_size, usb_dev->interface_no);
     
    457490}
    458491
    459 static errno_t usb_device_get_info(async_sess_t *sess, devman_handle_t *handle,
    460         int *iface_no)
    461 {
    462         assert(handle);
    463         assert(iface_no);
    464        
     492static errno_t usb_device_get_info(async_sess_t *sess, usb_device_t *dev)
     493{
     494        assert(dev);
     495
    465496        async_exch_t *exch = async_exchange_begin(sess);
    466497        if (!exch)
    467498                return EPARTY;
    468        
    469         errno_t ret = usb_get_my_device_handle(exch, handle);
     499
     500        usb_device_desc_t dev_desc;
     501        const errno_t ret = usb_get_my_description(exch, &dev_desc);
     502
    470503        if (ret == EOK) {
    471                 ret = usb_get_my_interface(exch, iface_no);
    472                 if (ret == ENOTSUP) {
    473                         *iface_no = -1;
    474                         ret = EOK;
    475                 }
    476         }
    477        
     504                dev->address = dev_desc.address;
     505                dev->depth = dev_desc.depth;
     506                dev->speed = dev_desc.speed;
     507                dev->handle = dev_desc.handle;
     508                dev->interface_no = dev_desc.iface;
     509        }
     510
    478511        async_exchange_end(exch);
    479512        return ret;
     
    485518        assert(ddf_dev);
    486519        assert(err);
    487 
    488         devman_handle_t h = 0;
    489         int iface_no = -1;
    490520
    491521        async_sess_t *sess = ddf_dev_parent_sess_get(ddf_dev);
    492522        if (sess == NULL)
    493523                return ENOMEM;
    494         const errno_t ret = usb_device_get_info(sess, &h, &iface_no);
    495         if (ret != EOK)
    496                 return ret;
    497524
    498525        usb_device_t *usb_dev =
     
    502529                return ENOMEM;
    503530        }
    504        
    505         return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no);
     531
     532        const errno_t ret = usb_device_get_info(sess, usb_dev);
     533        if (ret != EOK)
     534                return ret;
     535
     536        return usb_device_init(usb_dev, ddf_dev, desc, err);
    506537}
    507538
     
    517548usb_device_t * usb_device_create(devman_handle_t handle)
    518549{
    519         devman_handle_t h = 0;
    520         int iface_no = -1;
    521 
    522         async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
    523         errno_t ret = usb_device_get_info(sess, &h, &iface_no);
    524         if (sess)
    525                 async_hangup(sess);
    526         if (ret != EOK)
    527                 return NULL;
    528 
    529550        usb_device_t *usb_dev = malloc(sizeof(usb_device_t));
    530551        if (!usb_dev)
    531552                return NULL;
    532553
     554        async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
     555        errno_t ret = usb_device_get_info(sess, usb_dev);
     556        if (sess)
     557                async_hangup(sess);
     558        if (ret != EOK) {
     559                free(usb_dev);
     560                return NULL;
     561        }
     562
    533563        const char* dummy = NULL;
    534         ret = usb_device_init(usb_dev, NULL, NULL, &dummy, handle, iface_no);
     564        ret = usb_device_init(usb_dev, NULL, NULL, &dummy);
    535565        if (ret != EOK) {
    536566                free(usb_dev);
  • uspace/lib/usbdev/src/devpoll.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2017 Petr Manek
    34 * All rights reserved.
    45 *
     
    4748#include <errno.h>
    4849#include <fibril.h>
     50#include <fibril_synch.h>
    4951#include <stdbool.h>
    5052#include <stdlib.h>
     
    5355#include <stdint.h>
    5456
    55 /** Maximum number of failed consecutive requests before announcing failure. */
    56 #define MAX_FAILED_ATTEMPTS 3
    57 
    58 /** Data needed for polling. */
    59 typedef struct {
    60         /** Parameters for automated polling. */
    61         usb_device_auto_polling_t auto_polling;
    62 
    63         /** USB device to poll. */
    64         usb_device_t *dev;
    65         /** Device enpoint mapping to use for polling. */
    66         usb_endpoint_mapping_t *polling_mapping;
    67         /** Size of the recieved data. */
    68         size_t request_size;
    69         /** Data buffer. */
    70         uint8_t *buffer;
    71 } polling_data_t;
     57
     58/** Initialize the polling data structure, its internals and configuration
     59 *  with default values.
     60 *
     61 * @param polling Valid polling data structure.
     62 * @return Error code.
     63 * @retval EOK Polling data structure is ready to be used.
     64 */
     65int usb_polling_init(usb_polling_t *polling)
     66{
     67        if (!polling)
     68                return EBADMEM;
     69
     70        /* Zero out everything */
     71        memset(polling, 0, sizeof(usb_polling_t));
     72
     73        /* Internal initializers. */
     74        fibril_mutex_initialize(&polling->guard);
     75        fibril_condvar_initialize(&polling->cv);
     76
     77        /* Default configuration. */
     78        polling->auto_clear_halt = true;
     79        polling->delay = -1;
     80        polling->max_failures = 3;
     81
     82        return EOK;
     83}
     84
     85
     86/** Destroy the polling data structure.
     87 *  This function does nothing but a safety check whether the polling
     88 *  was joined successfully.
     89 *
     90 * @param polling Polling data structure.
     91 */
     92void usb_polling_fini(usb_polling_t *polling)
     93{
     94        /* Nothing done at the moment. */
     95        assert(polling);
     96        assert(!polling->running);
     97}
    7298
    7399
    74100/** Polling fibril.
    75101 *
    76  * @param arg Pointer to polling_data_t.
     102 * @param arg Pointer to usb_polling_t.
    77103 * @return Always EOK.
    78104 */
     
    80106{
    81107        assert(arg);
    82         polling_data_t *data = arg;
    83         /* Helper to reduce typing. */
    84         const usb_device_auto_polling_t *params = &data->auto_polling;
    85 
    86         usb_pipe_t *pipe = &data->polling_mapping->pipe;
    87 
    88         if (params->debug > 0) {
     108        usb_polling_t *polling = arg;
     109
     110        fibril_mutex_lock(&polling->guard);
     111        polling->running = true;
     112        fibril_mutex_unlock(&polling->guard);
     113
     114        usb_pipe_t *pipe = &polling->ep_mapping->pipe;
     115
     116        if (polling->debug > 0) {
    89117                const usb_endpoint_mapping_t *mapping =
    90                     data->polling_mapping;
     118                    polling->ep_mapping;
    91119                usb_log_debug("Poll (%p): started polling of `%s' - " \
    92120                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    93                     data, usb_device_get_name(data->dev),
     121                    polling, usb_device_get_name(polling->device),
    94122                    (int) mapping->interface->interface_number,
    95123                    usb_str_class(mapping->interface->interface_class),
    96124                    (int) mapping->interface->interface_subclass,
    97125                    (int) mapping->interface->interface_protocol,
    98                     data->request_size, pipe->max_packet_size);
     126                    polling->request_size, pipe->desc.max_transfer_size);
    99127        }
    100128
    101129        size_t failed_attempts = 0;
    102         while (failed_attempts <= params->max_failures) {
     130        while (failed_attempts <= polling->max_failures) {
    103131                size_t actual_size;
    104                 const errno_t rc = usb_pipe_read(pipe, data->buffer,
    105                     data->request_size, &actual_size);
     132                const errno_t rc = usb_pipe_read(pipe, polling->buffer,
     133                    polling->request_size, &actual_size);
    106134
    107135                if (rc == EOK) {
    108                         if (params->debug > 1) {
     136                        if (polling->debug > 1) {
    109137                                usb_log_debug(
    110138                                    "Poll%p: received: '%s' (%zuB).\n",
    111                                     data,
    112                                     usb_debug_str_buffer(data->buffer,
     139                                    polling,
     140                                    usb_debug_str_buffer(polling->buffer,
    113141                                        actual_size, 16),
    114142                                    actual_size);
     
    117145                                usb_log_debug(
    118146                                    "Poll%p: polling failed: %s.\n",
    119                                     data, str_error(rc));
     147                                    polling, str_error(rc));
    120148                }
    121149
    122150                /* If the pipe stalled, we can try to reset the stall. */
    123                 if ((rc == ESTALL) && (params->auto_clear_halt)) {
     151                if (rc == ESTALL && polling->auto_clear_halt) {
    124152                        /*
    125153                         * We ignore error here as this is usually a futile
    126154                         * attempt anyway.
    127155                         */
    128                         usb_request_clear_endpoint_halt(
    129                             usb_device_get_default_pipe(data->dev),
    130                             pipe->endpoint_no);
     156                        usb_pipe_clear_halt(
     157                            usb_device_get_default_pipe(polling->device), pipe);
    131158                }
    132159
    133160                if (rc != EOK) {
    134161                        ++failed_attempts;
    135                         const bool cont = (params->on_error == NULL) ? true :
    136                             params->on_error(data->dev, rc, params->arg);
    137                         if (!cont) {
    138                                 failed_attempts = params->max_failures;
     162                        const bool carry_on = !polling->on_error ? true :
     163                            polling->on_error(polling->device, rc, polling->arg);
     164
     165                        if (!carry_on || polling->joining) {
     166                                /* This is user requested abort, erases failures. */
     167                                failed_attempts = 0;
     168                                break;
    139169                        }
    140170                        continue;
     
    142172
    143173                /* We have the data, execute the callback now. */
    144                 assert(params->on_data);
    145                 const bool carry_on = params->on_data(
    146                     data->dev, data->buffer, actual_size, params->arg);
     174                assert(polling->on_data);
     175                const bool carry_on = polling->on_data(polling->device,
     176                    polling->buffer, actual_size, polling->arg);
    147177
    148178                if (!carry_on) {
     
    156186
    157187                /* Take a rest before next request. */
    158                
     188
    159189                // FIXME TODO: This is broken, the time is in ms not us.
    160190                // but first we need to fix drivers to actually stop using this,
    161191                // since polling delay should be implemented in HC schedule
    162                 async_usleep(params->delay);
     192                async_usleep(polling->delay);
    163193        }
    164194
    165195        const bool failed = failed_attempts > 0;
    166196
    167         if (params->on_polling_end != NULL) {
    168                 params->on_polling_end(data->dev, failed, params->arg);
    169         }
    170 
    171         if (params->debug > 0) {
     197        if (polling->on_polling_end)
     198                polling->on_polling_end(polling->device, failed, polling->arg);
     199
     200        if (polling->debug > 0) {
    172201                if (failed) {
    173202                        usb_log_error("Polling of device `%s' terminated: "
    174203                            "recurring failures.\n",
    175                             usb_device_get_name(data->dev));
     204                            usb_device_get_name(polling->device));
    176205                } else {
    177206                        usb_log_debug("Polling of device `%s' terminated: "
    178207                            "driver request.\n",
    179                             usb_device_get_name(data->dev));
     208                            usb_device_get_name(polling->device));
    180209                }
    181210        }
    182211
    183         /* Free the allocated memory. */
    184         free(data->buffer);
    185         free(data);
    186 
     212        fibril_mutex_lock(&polling->guard);
     213        polling->running = false;
     214        fibril_mutex_unlock(&polling->guard);
     215
     216        /* Notify joiners, if any. */
     217        fibril_condvar_broadcast(&polling->cv);
    187218        return EOK;
    188219}
     
    198229 * first request would be executed prior to return from this function).
    199230 *
    200  * @param dev Device to be periodically polled.
    201  * @param epm Endpoint mapping to use.
    202  * @param polling Polling settings.
    203  * @param request_size How many bytes to ask for in each request.
    204  * @param arg Custom argument (passed as is to the callbacks).
     231 * @param polling Polling data structure.
    205232 * @return Error code.
    206233 * @retval EOK New fibril polling the device was already started.
    207234 */
    208 static errno_t usb_device_auto_polling_internal(usb_device_t *dev,
    209     usb_endpoint_mapping_t *epm, const usb_device_auto_polling_t *polling,
    210     size_t request_size)
    211 {
    212         if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     235errno_t usb_polling_start(usb_polling_t *polling)
     236{
     237        if (!polling || !polling->device || !polling->ep_mapping || !polling->on_data)
    213238                return EBADMEM;
    214         }
    215 
    216         if (request_size == 0)
     239
     240        if (!polling->request_size)
    217241                return EINVAL;
    218        
    219         if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) ||
    220             (epm->pipe.direction != USB_DIRECTION_IN))
     242
     243        if (!polling->ep_mapping || (polling->ep_mapping->pipe.desc.transfer_type != USB_TRANSFER_INTERRUPT)
     244            || (polling->ep_mapping->pipe.desc.direction != USB_DIRECTION_IN))
    221245                return EINVAL;
    222        
    223 
    224         polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    225         if (polling_data == NULL) {
     246
     247        /* Negative value means use descriptor provided value. */
     248        if (polling->delay < 0)
     249                polling->delay = polling->ep_mapping->descriptor->poll_interval;
     250
     251        polling->fibril = fibril_create(polling_fibril, polling);
     252        if (!polling->fibril)
    226253                return ENOMEM;
    227         }
    228 
    229         /* Fill-in the data. */
    230         polling_data->buffer = malloc(sizeof(request_size));
    231         if (polling_data->buffer == NULL) {
    232                 free(polling_data);
    233                 return ENOMEM;
    234         }
    235         polling_data->request_size = request_size;
    236         polling_data->dev = dev;
    237         polling_data->polling_mapping = epm;
    238 
    239         /* Copy provided settings. */
    240         polling_data->auto_polling = *polling;
    241 
    242         /* Negative value means use descriptor provided value. */
    243         if (polling->delay < 0) {
    244                 polling_data->auto_polling.delay =
    245                     epm->descriptor->poll_interval;
    246         }
    247 
    248         fid_t fibril = fibril_create(polling_fibril, polling_data);
    249         if (fibril == 0) {
    250                 free(polling_data->buffer);
    251                 free(polling_data);
    252                 return ENOMEM;
    253         }
    254         fibril_add_ready(fibril);
     254
     255        fibril_add_ready(polling->fibril);
    255256
    256257        /* Fibril launched. That fibril will free the allocated data. */
    257 
    258258        return EOK;
    259259}
    260 /** Start automatic device polling over interrupt in pipe.
    261  *
    262  * The polling settings is copied thus it is okay to destroy the structure
    263  * after this function returns.
    264  *
    265  * @warning There is no guarantee when the request to the device
    266  * will be sent for the first time (it is possible that this
    267  * first request would be executed prior to return from this function).
    268  *
    269  * @param dev Device to be periodically polled.
    270  * @param pipe_index Index of the endpoint pipe used for polling.
    271  * @param polling Polling settings.
    272  * @param req_size How many bytes to ask for in each request.
    273  * @param arg Custom argument (passed as is to the callbacks).
    274  * @return Error code.
    275  * @retval EOK New fibril polling the device was already started.
    276  */
    277 errno_t usb_device_auto_polling(usb_device_t *usb_dev, usb_endpoint_t ep,
    278     const usb_device_auto_polling_t *polling, size_t req_size)
    279 {
    280         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(usb_dev, ep);
    281         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    282 }
    283 
    284 /** Start automatic device polling over interrupt in pipe.
    285  *
    286  * @warning It is up to the callback to produce delays between individual
    287  * requests.
    288  *
    289  * @warning There is no guarantee when the request to the device
    290  * will be sent for the first time (it is possible that this
    291  * first request would be executed prior to return from this function).
    292  *
    293  * @param dev Device to be periodically polled.
    294  * @param ep Endpoint  used for polling.
    295  * @param callback Callback when data are available.
    296  * @param request_size How many bytes to ask for in each request.
    297  * @param delay NUmber of ms to wait between queries, -1 to use descriptor val.
    298  * @param terminated_callback Callback when polling is terminated.
    299  * @param arg Custom argument (passed as is to the callbacks).
    300  * @return Error code.
    301  * @retval EOK New fibril polling the device was already started.
    302  */
    303 errno_t usb_device_auto_poll(usb_device_t *dev, usb_endpoint_t ep,
    304     usb_polling_callback_t callback, size_t request_size, int delay,
    305     usb_polling_terminted_callback_t terminated_callback, void *arg)
    306 {
    307         const usb_device_auto_polling_t auto_polling = {
    308                 .debug = 1,
    309                 .auto_clear_halt = true,
    310                 .delay = delay,
    311                 .max_failures = MAX_FAILED_ATTEMPTS,
    312                 .on_data = callback,
    313                 .on_polling_end = terminated_callback,
    314                 .on_error = NULL,
    315                 .arg = arg,
    316         };
    317 
    318         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(dev, ep);
    319         return usb_device_auto_polling_internal(
    320             dev, epm, &auto_polling, request_size);
    321 }
    322 
    323 errno_t usb_device_auto_polling_desc(usb_device_t *usb_dev,
    324     const usb_endpoint_description_t *desc,
    325     const usb_device_auto_polling_t *polling, size_t req_size)
    326 {
    327         usb_endpoint_mapping_t *epm =
    328             usb_device_get_mapped_ep_desc(usb_dev, desc);
    329         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    330 }
    331 
    332 errno_t usb_device_auto_poll_desc(usb_device_t * usb_dev,
    333     const usb_endpoint_description_t *desc, usb_polling_callback_t callback,
    334     size_t req_size, int delay,
    335     usb_polling_terminted_callback_t terminated_callback, void *arg)
    336 {
    337         const usb_device_auto_polling_t auto_polling = {
    338                 .debug = 1,
    339                 .auto_clear_halt = true,
    340                 .delay = delay,
    341                 .max_failures = MAX_FAILED_ATTEMPTS,
    342                 .on_data = callback,
    343                 .on_polling_end = terminated_callback,
    344                 .on_error = NULL,
    345                 .arg = arg,
    346         };
    347 
    348         usb_endpoint_mapping_t *epm =
    349             usb_device_get_mapped_ep_desc(usb_dev, desc);
    350         return usb_device_auto_polling_internal(
    351             usb_dev, epm, &auto_polling, req_size);
     260
     261/** Close the polling pipe permanently and synchronously wait
     262 *  until the automatic polling fibril terminates.
     263 *
     264 *  It is safe to deallocate the polling data structure (and its
     265 *  data buffer) only after a successful call to this function.
     266 *
     267 *  @warning Call to this function will trigger execution of the
     268 *  on_error() callback with EINTR error code.
     269 *
     270 *  @parram polling Polling data structure.
     271 *  @return Error code.
     272 *  @retval EOK Polling fibril has been successfully terminated.
     273 */
     274errno_t usb_polling_join(usb_polling_t *polling)
     275{
     276        errno_t rc;
     277        if (!polling)
     278                return EBADMEM;
     279
     280        /* Check if the fibril already terminated. */
     281        if (!polling->running)
     282                return EOK;
     283
     284        /* Set the flag */
     285        polling->joining = true;
     286
     287        /* Unregister the pipe. */
     288        rc = usb_device_unmap_ep(polling->ep_mapping);
     289        if (rc != EOK && rc != ENOENT && rc != EHANGUP)
     290                return rc;
     291
     292        /* Wait for the fibril to terminate. */
     293        fibril_mutex_lock(&polling->guard);
     294        while (polling->running)
     295                fibril_condvar_wait(&polling->cv, &polling->guard);
     296        fibril_mutex_unlock(&polling->guard);
     297
     298        return EOK;
    352299}
    353300
  • uspace/lib/usbdev/src/dp.c

    rf5e5f73 rdf6ded8  
    6262        NESTING(CONFIGURATION, INTERFACE),
    6363        NESTING(INTERFACE, ENDPOINT),
     64        NESTING(ENDPOINT, SSPEED_EP_COMPANION),
    6465        NESTING(INTERFACE, HUB),
    6566        NESTING(INTERFACE, HID),
     
    126127 * @retval -1 Invalid input.
    127128 */
    128 static int get_descriptor_type(const usb_dp_parser_data_t *data, const uint8_t *start)
     129static int get_descriptor_type(const usb_dp_parser_data_t *data,
     130    const uint8_t *start)
    129131{
    130132        if (start == NULL) {
     
    257259        int parent_type = get_descriptor_type(data, parent);
    258260        int possible_sibling_type = get_descriptor_type(data, possible_sibling);
    259         if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) {
     261        if (is_nested_descriptor_type(parser,
     262                    possible_sibling_type, parent_type)) {
    260263                return possible_sibling;
    261264        } else {
  • uspace/lib/usbdev/src/driver.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2013 Jan Vesely
     4 * Copyright (c) 2018 Petr Manek
    45 * All rights reserved.
    56 *
     
    6263        errno_t rc = usb_device_create_ddf(gen_dev, driver->endpoints, &err_msg);
    6364        if (rc != EOK) {
    64                 usb_log_error("USB device `%s' init failed (%s): %s.\n",
     65                usb_log_error("USB device `%s' init failed (%s): %s.",
    6566                    ddf_dev_get_name(gen_dev), err_msg, str_error(rc));
    6667                return rc;
     
    8586        assert(driver);
    8687        assert(driver->ops);
    87         if (driver->ops->device_rem == NULL)
     88        if (driver->ops->device_remove == NULL)
    8889                return ENOTSUP;
     90
    8991        /* Just tell the driver to stop whatever it is doing */
    9092        usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
    91         const errno_t ret = driver->ops->device_rem(usb_dev);
     93        const errno_t ret = driver->ops->device_remove(usb_dev);
    9294        if (ret != EOK)
    9395                return ret;
     96
    9497        usb_device_destroy_ddf(gen_dev);
    9598        return EOK;
     
    117120}
    118121
     122/** Callback when the driver is asked to online a specific function.
     123 *
     124 * This callback is a wrapper for USB specific version of @c fun_online.
     125 *
     126 * @param gen_dev Device function structure as prepared by DDF.
     127 * @return Error code.
     128 */
     129static int generic_function_online(ddf_fun_t *fun)
     130{
     131        assert(driver);
     132        assert(driver->ops);
     133        if (driver->ops->function_online == NULL)
     134                return ENOTSUP;
     135        return driver->ops->function_online(fun);
     136}
     137
     138/** Callback when the driver is asked to offline a specific function.
     139 *
     140 * This callback is a wrapper for USB specific version of @c fun_offline.
     141 *
     142 * @param gen_dev Device function structure as prepared by DDF.
     143 * @return Error code.
     144 */
     145static int generic_function_offline(ddf_fun_t *fun)
     146{
     147        assert(driver);
     148        assert(driver->ops);
     149        if (driver->ops->function_offline == NULL)
     150                return ENOTSUP;
     151        return driver->ops->function_offline(fun);
     152}
     153
    119154static driver_ops_t generic_driver_ops = {
    120155        .dev_add = generic_device_add,
    121156        .dev_remove = generic_device_remove,
    122157        .dev_gone = generic_device_gone,
     158        .fun_online = generic_function_online,
     159        .fun_offline = generic_function_offline,
    123160};
    124161static driver_t generic_driver = {
  • uspace/lib/usbdev/src/pipes.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    45 * All rights reserved.
    56 *
     
    3637#include <usb/dev/request.h>
    3738#include <usb/usb.h>
    38 #include <usb_iface.h>
     39#include <usb/dma_buffer.h>
    3940
    4041#include <assert.h>
     42#include <bitops.h>
    4143#include <async.h>
     44#include <as.h>
    4245#include <errno.h>
    4346#include <mem.h>
     
    5154        assert(pipe != NULL);
    5255
    53         if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     56        if (!pipe->auto_reset_halt || (pipe->desc.endpoint_no != 0)) {
    5457                return;
    5558        }
     
    5760        /* Prevent infinite recursion. */
    5861        pipe->auto_reset_halt = false;
    59         usb_request_clear_endpoint_halt(pipe, 0);
     62        usb_pipe_clear_halt(pipe, pipe);
    6063        pipe->auto_reset_halt = true;
     64}
     65
     66/* Helper structure to avoid passing loads of arguments through */
     67typedef struct {
     68        usb_pipe_t *pipe;
     69        usb_direction_t dir;
     70        bool is_control;        // Only for checking purposes
     71
     72        usbhc_iface_transfer_request_t req;
     73
     74        size_t transferred_size;
     75} transfer_t;
     76
     77/**
     78 * Issue a transfer in a separate exchange.
     79 */
     80static errno_t transfer_common(transfer_t *t)
     81{
     82        if (!t->pipe)
     83                return EBADMEM;
     84
     85        /* Only control writes make sense without buffer */
     86        if ((t->dir != USB_DIRECTION_OUT || !t->is_control) && t->req.size == 0)
     87                return EINVAL;
     88
     89        /* Nonzero size requires buffer */
     90        if (!dma_buffer_is_set(&t->req.buffer) && t->req.size != 0)
     91                return EINVAL;
     92
     93        /* Check expected direction */
     94        if (t->pipe->desc.direction != USB_DIRECTION_BOTH &&
     95            t->pipe->desc.direction != t->dir)
     96                return EBADF;
     97
     98        /* Check expected transfer type */
     99        if ((t->pipe->desc.transfer_type == USB_TRANSFER_CONTROL) != t->is_control)
     100                return EBADF;
     101
     102        async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
     103        if (!exch)
     104                return ENOMEM;
     105
     106        t->req.dir = t->dir;
     107        t->req.endpoint = t->pipe->desc.endpoint_no;
     108
     109        const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
     110
     111        async_exchange_end(exch);
     112
     113        if (rc == ESTALL)
     114                clear_self_endpoint_halt(t->pipe);
     115
     116        return rc;
     117}
     118
     119/**
     120 * Setup the transfer request inside transfer according to dma buffer provided.
     121 *
     122 * TODO: The buffer could have been allocated as a more strict one. Currently,
     123 * we assume that the policy is just the requested one.
     124 */
     125static void setup_dma_buffer(transfer_t *t, void *base, void *ptr, size_t size)
     126{
     127        t->req.buffer.virt = base;
     128        t->req.buffer.policy = t->pipe->desc.transfer_buffer_policy;
     129        t->req.offset = ptr - base;
     130        t->req.size = size;
     131}
     132
     133/**
     134 * Compatibility wrapper for reads/writes without preallocated buffer.
     135 */
     136static errno_t transfer_wrap_dma(transfer_t *t, void *buf, size_t size)
     137{
     138        if (size == 0) {
     139                setup_dma_buffer(t, NULL, NULL, 0);
     140                return transfer_common(t);
     141        }
     142
     143        void *dma_buf = usb_pipe_alloc_buffer(t->pipe, size);
     144        setup_dma_buffer(t, dma_buf, dma_buf, size);
     145
     146        if (t->dir == USB_DIRECTION_OUT)
     147                memcpy(dma_buf, buf, size);
     148
     149        const errno_t err = transfer_common(t);
     150
     151        if (!err && t->dir == USB_DIRECTION_IN)
     152                memcpy(buf, dma_buf, t->transferred_size);
     153
     154        usb_pipe_free_buffer(t->pipe, dma_buf);
     155        return err;
     156}
     157
     158static errno_t prepare_control(transfer_t *t, const void *setup, size_t setup_size)
     159{
     160        if ((setup == NULL) || (setup_size != 8))
     161                return EINVAL;
     162       
     163        memcpy(&t->req.setup, setup, 8);
     164        return EOK;
    61165}
    62166
     
    70174 * @param[out] data_buffer Buffer for incoming data.
    71175 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    72  * @param[out] data_transfered_size Number of bytes that were actually
    73  *                                  transfered during the DATA stage.
     176 * @param[out] data_transferred_size Number of bytes that were actually
     177 *                                  transferred during the DATA stage.
    74178 * @return Error code.
    75179 */
    76180errno_t usb_pipe_control_read(usb_pipe_t *pipe,
    77181    const void *setup_buffer, size_t setup_buffer_size,
    78     void *buffer, size_t buffer_size, size_t *transfered_size)
    79 {
    80         assert(pipe);
    81 
    82         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    83                 return EINVAL;
    84         }
    85 
    86         if ((buffer == NULL) || (buffer_size == 0)) {
    87                 return EINVAL;
    88         }
    89 
    90         if ((pipe->direction != USB_DIRECTION_BOTH)
    91             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    92                 return EBADF;
    93         }
    94 
    95         uint64_t setup_packet;
    96         memcpy(&setup_packet, setup_buffer, 8);
    97 
    98         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    99         size_t act_size = 0;
    100         const errno_t rc = usb_read(exch, pipe->endpoint_no, setup_packet, buffer,
    101             buffer_size, &act_size);
    102         async_exchange_end(exch);
    103 
    104         if (rc == ESTALL) {
    105                 clear_self_endpoint_halt(pipe);
    106         }
    107 
    108         if (rc == EOK && transfered_size != NULL) {
    109                 *transfered_size = act_size;
    110         }
    111 
    112         return rc;
     182    void *buffer, size_t buffer_size, size_t *transferred_size)
     183{
     184        errno_t err;
     185        transfer_t transfer = {
     186                .pipe = pipe,
     187                .dir = USB_DIRECTION_IN,
     188                .is_control = true,
     189        };
     190
     191        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     192                return err;
     193
     194        if ((err = transfer_wrap_dma(&transfer, buffer, buffer_size)))
     195                return err;
     196
     197        if (transferred_size)
     198                *transferred_size = transfer.transferred_size;
     199
     200        return EOK;
    113201}
    114202
     
    129217{
    130218        assert(pipe);
    131 
    132         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    133                 return EINVAL;
    134         }
    135 
    136         if ((buffer == NULL) && (buffer_size > 0)) {
    137                 return EINVAL;
    138         }
    139 
    140         if ((buffer != NULL) && (buffer_size == 0)) {
    141                 return EINVAL;
    142         }
    143 
    144         if ((pipe->direction != USB_DIRECTION_BOTH)
    145             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    146                 return EBADF;
    147         }
    148 
    149         uint64_t setup_packet;
    150         memcpy(&setup_packet, setup_buffer, 8);
    151 
    152         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    153         const errno_t rc = usb_write(exch,
    154             pipe->endpoint_no, setup_packet, buffer, buffer_size);
    155         async_exchange_end(exch);
    156 
    157         if (rc == ESTALL) {
    158                 clear_self_endpoint_halt(pipe);
    159         }
    160 
    161         return rc;
     219        errno_t err;
     220        transfer_t transfer = {
     221                .pipe = pipe,
     222                .dir = USB_DIRECTION_OUT,
     223                .is_control = true,
     224        };
     225
     226        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     227                return err;
     228
     229        return transfer_wrap_dma(&transfer, (void *) buffer, buffer_size);
     230}
     231
     232/**
     233 * Allocate a buffer for data transmission, that satisfies the constraints
     234 * imposed by the host controller.
     235 *
     236 * @param[in] pipe Pipe for which the buffer is allocated
     237 * @param[in] size Size of the required buffer
     238 */
     239void *usb_pipe_alloc_buffer(usb_pipe_t *pipe, size_t size)
     240{
     241        dma_buffer_t buf;
     242        if (dma_buffer_alloc_policy(&buf, size, pipe->desc.transfer_buffer_policy))
     243                return NULL;
     244
     245        return buf.virt;
     246}
     247
     248void usb_pipe_free_buffer(usb_pipe_t *pipe, void *buffer)
     249{
     250        dma_buffer_t buf;
     251        buf.virt = buffer;
     252        dma_buffer_free(&buf);
    162253}
    163254
     
    167258 * @param[out] buffer Buffer where to store the data.
    168259 * @param[in] size Size of the buffer (in bytes).
    169  * @param[out] size_transfered Number of bytes that were actually transfered.
     260 * @param[out] size_transferred Number of bytes that were actually transferred.
    170261 * @return Error code.
    171262 */
    172263errno_t usb_pipe_read(usb_pipe_t *pipe,
    173     void *buffer, size_t size, size_t *size_transfered)
    174 {
    175         assert(pipe);
    176 
    177         if (buffer == NULL) {
    178                 return EINVAL;
    179         }
    180 
    181         if (size == 0) {
    182                 return EINVAL;
    183         }
    184 
    185         if (pipe->direction != USB_DIRECTION_IN) {
    186                 return EBADF;
    187         }
    188 
    189         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    190                 return EBADF;
    191         }
    192 
    193         /* Isochronous transfer are not supported (yet) */
    194         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    195             pipe->transfer_type != USB_TRANSFER_BULK)
    196             return ENOTSUP;
    197 
    198         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    199         size_t act_size = 0;
    200         const errno_t rc =
    201             usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size);
    202         async_exchange_end(exch);
    203 
    204         if (rc == EOK && size_transfered != NULL) {
    205                 *size_transfered = act_size;
    206         }
    207 
    208         return rc;
     264    void *buffer, size_t size, size_t *size_transferred)
     265{
     266        assert(pipe);
     267        errno_t err;
     268        transfer_t transfer = {
     269                .pipe = pipe,
     270                .dir = USB_DIRECTION_IN,
     271        };
     272
     273        if ((err = transfer_wrap_dma(&transfer, buffer, size)))
     274                return err;
     275
     276        if (size_transferred)
     277                *size_transferred = transfer.transferred_size;
     278
     279        return EOK;
    209280}
    210281
     
    219290{
    220291        assert(pipe);
    221 
    222         if (buffer == NULL || size == 0) {
    223                 return EINVAL;
    224         }
    225 
    226         if (pipe->direction != USB_DIRECTION_OUT) {
    227                 return EBADF;
    228         }
    229 
    230         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    231                 return EBADF;
    232         }
    233 
    234         /* Isochronous transfer are not supported (yet) */
    235         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    236             pipe->transfer_type != USB_TRANSFER_BULK)
    237             return ENOTSUP;
    238 
    239         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    240         const errno_t rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size);
    241         async_exchange_end(exch);
    242         return rc;
     292        transfer_t transfer = {
     293                .pipe = pipe,
     294                .dir = USB_DIRECTION_OUT,
     295        };
     296
     297        return transfer_wrap_dma(&transfer, (void *) buffer, size);
     298}
     299
     300/**
     301 * Request a read (in) transfer on an endpoint pipe, declaring that buffer
     302 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer.
     303 *
     304 * @param[in] pipe Pipe used for the transfer.
     305 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer.
     306 * @param[in] size Size of the buffer (in bytes).
     307 * @param[out] size_transferred Number of bytes that were actually transferred.
     308 * @return Error code.
     309 */
     310errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size,
     311    size_t *size_transferred)
     312{
     313        assert(pipe);
     314        errno_t err;
     315        transfer_t transfer = {
     316                .pipe = pipe,
     317                .dir = USB_DIRECTION_IN,
     318        };
     319
     320        setup_dma_buffer(&transfer, base, ptr, size);
     321
     322        if ((err = transfer_common(&transfer)))
     323                return err;
     324
     325        if (size_transferred)
     326                *size_transferred = transfer.transferred_size;
     327
     328        return EOK;
     329}
     330
     331/**
     332 * Request a write (out) transfer on an endpoint pipe, declaring that buffer
     333 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer.
     334 *
     335 * @param[in] pipe Pipe used for the transfer.
     336 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer.
     337 * @param[in] size Size of the buffer (in bytes).
     338 * @return Error code.
     339 */
     340errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size)
     341{
     342        assert(pipe);
     343        transfer_t transfer = {
     344                .pipe = pipe,
     345                .dir = USB_DIRECTION_OUT,
     346        };
     347
     348        setup_dma_buffer(&transfer, base, ptr, size);
     349
     350        return transfer_common(&transfer);
    243351}
    244352
     
    246354 *
    247355 * @param pipe Endpoint pipe to be initialized.
    248  * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
    249  * @param transfer_type Transfer type (e.g. interrupt or bulk).
    250  * @param max_packet_size Maximum packet size in bytes.
    251  * @param direction Endpoint direction (in/out).
    252  * @return Error code.
    253  */
    254 errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_endpoint_t endpoint_no,
    255     usb_transfer_type_t transfer_type, size_t max_packet_size,
    256     usb_direction_t direction, unsigned packets, usb_dev_session_t *bus_session)
    257 {
    258         assert(pipe);
    259 
    260         pipe->endpoint_no = endpoint_no;
    261         pipe->transfer_type = transfer_type;
    262         pipe->packets = packets;
    263         pipe->max_packet_size = max_packet_size;
    264         pipe->direction = direction;
     356 * @param bus_session Endpoint pipe to be initialized.
     357 * @return Error code.
     358 */
     359errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_dev_session_t *bus_session)
     360{
     361        assert(pipe);
     362
    265363        pipe->auto_reset_halt = false;
    266364        pipe->bus_session = bus_session;
     
    269367}
    270368
    271 /** Initialize USB endpoint pipe as the default zero control pipe.
     369static const usb_pipe_desc_t default_control_pipe = {
     370        .endpoint_no = 0,
     371        .transfer_type = USB_TRANSFER_CONTROL,
     372        .direction = USB_DIRECTION_BOTH,
     373        .max_transfer_size = CTRL_PIPE_MIN_PACKET_SIZE,
     374        .transfer_buffer_policy = DMA_POLICY_STRICT,
     375};
     376
     377/** Initialize USB default control pipe.
     378 *
     379 * This one is special because it must not be registered, it is registered
     380 * automatically.
    272381 *
    273382 * @param pipe Endpoint pipe to be initialized.
     383 * @param bus_session Endpoint pipe to be initialized.
    274384 * @return Error code.
    275385 */
     
    277387    usb_dev_session_t *bus_session)
    278388{
    279         assert(pipe);
    280 
    281         const errno_t rc = usb_pipe_initialize(pipe, 0, USB_TRANSFER_CONTROL,
    282             CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH, 1, bus_session);
    283 
     389        const errno_t ret = usb_pipe_initialize(pipe, bus_session);
     390        if (ret)
     391                return ret;
     392
     393        pipe->desc = default_control_pipe;
    284394        pipe->auto_reset_halt = true;
    285395
    286         return rc;
     396        return EOK;
    287397}
    288398
     
    290400 *
    291401 * @param pipe Pipe to be registered.
    292  * @param interval Polling interval.
    293  * @return Error code.
    294  */
    295 errno_t usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
     402 * @param ep_desc Matched endpoint descriptor
     403 * @param comp_desc Matched superspeed companion descriptro, if any
     404 * @return Error code.
     405 */
     406errno_t usb_pipe_register(usb_pipe_t *pipe,
     407    const usb_standard_endpoint_descriptor_t *ep_desc,
     408    const usb_superspeed_endpoint_companion_descriptor_t *comp_desc)
     409{
     410        assert(pipe);
     411        assert(pipe->bus_session);
     412        assert(ep_desc);
     413
     414        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
     415        if (!exch)
     416                return ENOMEM;
     417
     418        usb_endpoint_descriptors_t descriptors = { 0 };
     419
     420#define COPY(field) descriptors.endpoint.field = ep_desc->field
     421        COPY(endpoint_address);
     422        COPY(attributes);
     423        COPY(max_packet_size);
     424        COPY(poll_interval);
     425#undef COPY
     426
     427#define COPY(field) descriptors.companion.field = comp_desc->field
     428        if (comp_desc) {
     429                COPY(max_burst);
     430                COPY(attributes);
     431                COPY(bytes_per_interval);
     432        }
     433#undef COPY
     434
     435        const errno_t ret = usbhc_register_endpoint(exch,
     436            &pipe->desc, &descriptors);
     437        async_exchange_end(exch);
     438        return ret;
     439}
     440
     441/** Revert endpoint registration with the host controller.
     442 *
     443 * @param pipe Pipe to be unregistered.
     444 * @return Error code.
     445 */
     446errno_t usb_pipe_unregister(usb_pipe_t *pipe)
    296447{
    297448        assert(pipe);
     
    300451        if (!exch)
    301452                return ENOMEM;
    302         const errno_t ret = usb_register_endpoint(exch, pipe->endpoint_no,
    303             pipe->transfer_type, pipe->direction, pipe->max_packet_size,
    304             pipe->packets, interval);
     453
     454        const errno_t ret = usbhc_unregister_endpoint(exch, &pipe->desc);
     455
    305456        async_exchange_end(exch);
    306457        return ret;
    307458}
    308459
    309 /** Revert endpoint registration with the host controller.
    310  *
    311  * @param pipe Pipe to be unregistered.
    312  * @return Error code.
    313  */
    314 errno_t usb_pipe_unregister(usb_pipe_t *pipe)
    315 {
    316         assert(pipe);
    317         assert(pipe->bus_session);
    318         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    319         if (!exch)
    320                 return ENOMEM;
    321         const errno_t ret = usb_unregister_endpoint(exch, pipe->endpoint_no,
    322             pipe->direction);
    323         async_exchange_end(exch);
    324         return ret;
    325 }
    326 
    327460/**
    328461 * @}
  • uspace/lib/usbdev/src/pipesinit.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    34 * All rights reserved.
    45 *
     
    3839#include <usb/dev/request.h>
    3940#include <usb/usb.h>
     41#include <usb/debug.h>
    4042#include <usb/descriptor.h>
    4143
     
    5961        NESTING(INTERFACE, HID),
    6062        NESTING(HID, HID_REPORT),
     63        NESTING(ENDPOINT, SSPEED_EP_COMPANION),
    6164        LAST_NESTING
    6265};
     
    7073{
    7174        return descriptor[1] == USB_DESCTYPE_ENDPOINT;
     75}
     76
     77/** Tells whether given descriptor is of superspeed companion type.
     78 *
     79 * @param descriptor Descriptor in question.
     80 * @return Whether the given descriptor is superspeed companion descriptor.
     81 */
     82static inline bool is_superspeed_companion_descriptor(const uint8_t *descriptor)
     83{
     84        return descriptor[1] == USB_DESCTYPE_SSPEED_EP_COMPANION;
    7285}
    7386
     
    134147                if (interface_number_fits
    135148                    && interface_setting_fits
    136                     && endpoint_descriptions_fits) {
     149                    && endpoint_descriptions_fits
     150                    && !mapping->present) {
    137151                        return mapping;
    138152                }
     
    141155                mapping_count--;
    142156        }
     157
    143158        return NULL;
    144159}
     
    150165 * @param interface Interface descriptor under which belongs the @p endpoint.
    151166 * @param endpoint Endpoint descriptor.
     167 * @param companion Superspeed companion descriptor.
    152168 * @return Error code.
    153169 */
     
    156172    usb_standard_interface_descriptor_t *interface,
    157173    usb_standard_endpoint_descriptor_t *endpoint_desc,
     174    usb_superspeed_endpoint_companion_descriptor_t *companion_desc,
    158175    usb_dev_session_t *bus_session)
    159176{
     
    162179         * Get endpoint characteristics.
    163180         */
    164 
    165         /* Actual endpoint number is in bits 0..3 */
    166         const usb_endpoint_t ep_no = endpoint_desc->endpoint_address & 0x0F;
    167 
    168181        const usb_endpoint_description_t description = {
    169                 /* Endpoint direction is set by bit 7 */
    170                 .direction = (endpoint_desc->endpoint_address & 128)
    171                     ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
    172                 /* Transfer type is in bits 0..2 and
    173                  * the enum values corresponds 1:1 */
    174                 .transfer_type = endpoint_desc->attributes & 3,
     182                .transfer_type = USB_ED_GET_TRANSFER_TYPE(*endpoint_desc),
     183                .direction = USB_ED_GET_DIR(*endpoint_desc),
    175184
    176185                /* Get interface characteristics. */
     
    194203        }
    195204
    196         errno_t rc = usb_pipe_initialize(&ep_mapping->pipe,
    197             ep_no, description.transfer_type,
    198             ED_MPS_PACKET_SIZE_GET(
    199                 uint16_usb2host(endpoint_desc->max_packet_size)),
    200             description.direction,
    201             ED_MPS_TRANS_OPPORTUNITIES_GET(
    202                 uint16_usb2host(endpoint_desc->max_packet_size)), bus_session);
    203         if (rc != EOK) {
    204                 return rc;
    205         }
     205        errno_t err = usb_pipe_initialize(&ep_mapping->pipe, bus_session);
     206        if (err)
     207                return err;
    206208
    207209        ep_mapping->present = true;
    208210        ep_mapping->descriptor = endpoint_desc;
     211        ep_mapping->companion_descriptor = companion_desc;
    209212        ep_mapping->interface = interface;
    210213
     
    235238        do {
    236239                if (is_endpoint_descriptor(descriptor)) {
     240                        /* Check if companion descriptor is present too, it should immediatelly follow. */
     241                        const uint8_t *companion_desc = usb_dp_get_nested_descriptor(parser,
     242                                parser_data, descriptor);
     243                        if (companion_desc && !is_superspeed_companion_descriptor(companion_desc)) {
     244                                /* Not what we wanted, don't pass it further. */
     245                                companion_desc = NULL;
     246                        }
     247
    237248                        (void) process_endpoint(mapping, mapping_count,
    238249                            (usb_standard_interface_descriptor_t *)
     
    240251                            (usb_standard_endpoint_descriptor_t *)
    241252                                descriptor,
     253                            (usb_superspeed_endpoint_companion_descriptor_t *)
     254                                companion_desc,
    242255                            bus_session);
    243256                }
     
    288301        if (config_descriptor == NULL)
    289302                return EBADMEM;
    290        
     303
    291304        if (config_descriptor_size <
    292305            sizeof(usb_standard_configuration_descriptor_t)) {
     
    328341}
    329342
    330 /** Probe default control pipe for max packet size.
    331  *
    332  * The function tries to get the correct value of max packet size several
    333  * time before giving up.
    334  *
    335  * The session on the pipe shall not be started.
    336  *
    337  * @param pipe Default control pipe.
    338  * @return Error code.
    339  */
    340 errno_t usb_pipe_probe_default_control(usb_pipe_t *pipe)
    341 {
    342         assert(pipe);
    343         static_assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
    344 
    345         if ((pipe->direction != USB_DIRECTION_BOTH) ||
    346             (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
    347             (pipe->endpoint_no != 0)) {
    348                 return EINVAL;
    349         }
    350 
    351         uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    352         size_t transferred_size;
    353         errno_t rc;
    354         for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) {
    355                 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    356                     USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
    357                     0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
    358                     &transferred_size);
    359                 if (rc == EOK) {
    360                         if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
    361                                 rc = ELIMIT;
    362                                 continue;
    363                         }
    364                         break;
    365                 }
    366         }
    367         if (rc != EOK) {
    368                 return rc;
    369         }
    370 
    371         pipe->max_packet_size
    372             = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
    373 
    374         return EOK;
    375 }
    376 
    377343/**
    378344 * @}
  • uspace/lib/usbdev/src/request.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    118119 * @param data_size        Size of the @p data buffer
    119120 *                         (in native endianness).
    120  * @param actual_data_size Actual size of transfered data
     121 * @param actual_data_size Actual size of transferred data
    121122 *                         (in native endianness).
    122123 *
     
    183184
    184185        uint16_t status_usb_endianess;
    185         size_t data_transfered_size;
     186        size_t data_transferred_size;
    186187        errno_t rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD,
    187188            recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index),
    188             &status_usb_endianess, 2, &data_transfered_size);
    189         if (rc != EOK) {
    190                 return rc;
    191         }
    192         if (data_transfered_size != 2) {
     189            &status_usb_endianess, 2, &data_transferred_size);
     190        if (rc != EOK) {
     191                return rc;
     192        }
     193        if (data_transferred_size != 2) {
    193194                return ELIMIT;
    194195        }
     
    314315         */
    315316        uint8_t tmp_buffer;
    316         size_t bytes_transfered;
     317        size_t bytes_transferred;
    317318        rc = usb_request_get_descriptor(pipe, request_type, recipient,
    318319            descriptor_type, descriptor_index, language,
    319             &tmp_buffer, sizeof(tmp_buffer), &bytes_transfered);
    320         if (rc != EOK) {
    321                 return rc;
    322         }
    323         if (bytes_transfered != 1) {
     320            &tmp_buffer, sizeof(tmp_buffer), &bytes_transferred);
     321        if (rc != EOK) {
     322                return rc;
     323        }
     324        if (bytes_transferred != 1) {
    324325                return ELIMIT;
    325326        }
     
    340341        rc = usb_request_get_descriptor(pipe, request_type, recipient,
    341342            descriptor_type, descriptor_index, language,
    342             buffer, size, &bytes_transfered);
     343            buffer, size, &bytes_transferred);
    343344        if (rc != EOK) {
    344345                free(buffer);
    345346                return rc;
    346347        }
    347         if (bytes_transfered != size) {
     348        if (bytes_transferred != size) {
    348349                free(buffer);
    349350                return ELIMIT;
     
    824825 * @return Error code.
    825826 */
    826 errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
     827static errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
    827828{
    828829        return usb_request_clear_feature(pipe,
     
    843844                return EINVAL;
    844845        }
    845         return usb_request_clear_endpoint_halt(ctrl_pipe,
    846             target_pipe->endpoint_no);
     846
     847        uint16_t index = target_pipe->desc.endpoint_no;
     848        index |= (target_pipe->desc.direction == USB_DIRECTION_IN) << 7;
     849        return usb_request_clear_endpoint_halt(ctrl_pipe, index);
    847850}
    848851
     
    858861{
    859862        uint16_t status_tmp;
    860         uint16_t pipe_index = (uint16_t) pipe->endpoint_no;
     863        uint16_t pipe_index = (uint16_t) pipe->desc.endpoint_no;
    861864        errno_t rc = usb_request_get_status(ctrl_pipe,
    862865            USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index),
  • uspace/lib/usbhid/src/hiddescriptor.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Matej Klonfar
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    176177
    177178        if(report_item->usages_count > 0){
    178                 usages = malloc(sizeof(int32_t) * report_item->usages_count);
     179                usages = malloc(sizeof(uint32_t) * report_item->usages_count);
    179180                memcpy(usages, report_item->usages, sizeof(int32_t) *
    180181                                report_item->usages_count);
     
    247248                field->size = report_item->size;
    248249
    249                 if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
    250                         int offset = report_item->offset + report_item->size * i;
    251                         int field_offset = (offset/8)*8 + (offset/8 + 1) * 8 -
    252                                 offset - report_item->size;
    253                         if(field_offset < 0) {
    254                                 field->offset = 0;
    255                         }
    256                         else {
    257                                 field->offset = field_offset;
    258                         }
    259                 }
    260                 else {
    261                         field->offset = report_item->offset + (i * report_item->size);
    262                 }
    263 
     250                field->offset = report_item->offset + (i * report_item->size);
    264251
    265252                if(report->use_report_ids != 0) {
     
    896883{
    897884        if(list == NULL || list_empty(list)) {
    898             usb_log_debug("\tempty\n");
     885            usb_log_debug("\tempty");
    899886            return;
    900887        }
     
    902889        list_foreach(*list, ritems_link, usb_hid_report_field_t,
    903890            report_item) {
    904                 usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
    905                 usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
    906                 usb_log_debug("\t\tLOGMIN: %d\n",
     891                usb_log_debug("\t\tOFFSET: %u", report_item->offset);
     892                usb_log_debug("\t\tSIZE: %zu", report_item->size);
     893                usb_log_debug("\t\tLOGMIN: %d",
    907894                        report_item->logical_minimum);
    908                 usb_log_debug("\t\tLOGMAX: %d\n",
     895                usb_log_debug("\t\tLOGMAX: %d",
    909896                        report_item->logical_maximum);
    910                 usb_log_debug("\t\tPHYMIN: %d\n",
     897                usb_log_debug("\t\tPHYMIN: %d",
    911898                        report_item->physical_minimum);
    912                 usb_log_debug("\t\tPHYMAX: %d\n",
     899                usb_log_debug("\t\tPHYMAX: %d",
    913900                        report_item->physical_maximum);
    914                 usb_log_debug("\t\ttUSAGEMIN: %X\n",
     901                usb_log_debug("\t\ttUSAGEMIN: %X",
    915902                        report_item->usage_minimum);
    916                 usb_log_debug("\t\tUSAGEMAX: %X\n",
     903                usb_log_debug("\t\tUSAGEMAX: %X",
    917904                               report_item->usage_maximum);
    918                 usb_log_debug("\t\tUSAGES COUNT: %zu\n",
     905                usb_log_debug("\t\tUSAGES COUNT: %zu",
    919906                        report_item->usages_count);
    920907
    921                 usb_log_debug("\t\tVALUE: %X\n", report_item->value);
    922                 usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
    923                 usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
     908                usb_log_debug("\t\tVALUE: %X", report_item->value);
     909                usb_log_debug("\t\ttUSAGE: %X", report_item->usage);
     910                usb_log_debug("\t\tUSAGE PAGE: %X", report_item->usage_page);
    924911
    925912                usb_hid_print_usage_path(report_item->collection_path);
    926 
    927                 usb_log_debug("\n");
    928913        }
    929914}
     
    943928        list_foreach(report->reports, reports_link,
    944929            usb_hid_report_description_t, report_des) {
    945                 usb_log_debug("Report ID: %d\n", report_des->report_id);
    946                 usb_log_debug("\tType: %d\n", report_des->type);
    947                 usb_log_debug("\tLength: %zu\n", report_des->bit_length);
    948                 usb_log_debug("\tB Size: %zu\n",
     930                usb_log_debug("Report ID: %d", report_des->report_id);
     931                usb_log_debug("\tType: %d", report_des->type);
     932                usb_log_debug("\tLength: %zu", report_des->bit_length);
     933                usb_log_debug("\tB Size: %zu",
    949934                        usb_hid_report_byte_size(report,
    950935                                report_des->report_id,
    951936                                report_des->type));
    952                 usb_log_debug("\tItems: %zu\n", report_des->item_length);
     937                usb_log_debug("\tItems: %zu", report_des->item_length);
    953938
    954939                usb_hid_descriptor_print_list(&report_des->report_items);
  • uspace/lib/usbhid/src/hidparser.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Matej Klonfar
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4041#include <usb/debug.h>
    4142#include <assert.h>
     43#include <bitops.h>
     44#include <macros.h>
    4245
    4346
     
    4952int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
    5053
    51 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
    52         int32_t value);
     54uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
     55    int32_t value);
    5356
    5457
     
    7376 *
    7477 * @param parser Opaque report parser structure
    75  * @param report_id 
     78 * @param report_id
    7679 * @param type
    7780 * @return Number of items in specified report
    7881 */
    79 size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 
     82size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
    8083    usb_hid_report_type_t type)
    8184{
     
    97100 *
    98101 * @param parser Opaque report parser structure
    99  * @param report_id 
     102 * @param report_id
    100103 * @param type
    101104 * @return Number of items in specified report
    102105 */
    103 size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 
     106size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id,
    104107    usb_hid_report_type_t type)
    105108{
     
    114117                return 0;
    115118        } else {
    116                 return ((report_des->bit_length + 7) / 8) ;
     119                return ((report_des->bit_length + 7) / 8);
    117120        }
    118121}
     
    126129 * @param data Data for the report.
    127130 * @return Error code.
    128  */ 
    129 errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 
     131 */
     132errno_t usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
    130133    size_t size, uint8_t *report_id)
    131134{
    132135        usb_hid_report_description_t *report_des;
    133136        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    134        
     137
    135138        if (report == NULL) {
    136139                return EINVAL;
     
    143146        }
    144147
    145         report_des = usb_hid_report_find_description(report, *report_id, 
     148        report_des = usb_hid_report_find_description(report, *report_id,
    146149            type);
    147150
     
    155158
    156159                if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
    157                        
     160
    158161                        if (USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
    159162                                /* array */
    160                                 item->value = 
    161                                         usb_hid_translate_data(item, data);
    162                                
     163                                item->value =
     164                                    usb_hid_translate_data(item, data);
     165
    163166                                item->usage = USB_HID_EXTENDED_USAGE(
    164167                                    item->usages[item->value -
    165168                                    item->physical_minimum]);
    166169
    167                                 item->usage_page = 
     170                                item->usage_page =
    168171                                    USB_HID_EXTENDED_USAGE_PAGE(
    169172                                    item->usages[item->value -
     
    171174
    172175                                usb_hid_report_set_last_item(
    173                                     item->collection_path, 
    174                                     USB_HID_TAG_CLASS_GLOBAL, 
     176                                    item->collection_path,
     177                                    USB_HID_TAG_CLASS_GLOBAL,
    175178                                    item->usage_page);
    176179
    177180                                usb_hid_report_set_last_item(
    178                                     item->collection_path, 
     181                                    item->collection_path,
    179182                                    USB_HID_TAG_CLASS_LOCAL, item->usage);
    180183                        } else {
    181184                                /* variable item */
    182                                 item->value = usb_hid_translate_data(item, 
     185                                item->value = usb_hid_translate_data(item,
    183186                                    data);
    184187                        }
    185188                }
    186189        }
    187        
     190
    188191        return EOK;
    189192}
     
    199202int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    200203{
    201         int resolution;
    202         int offset;
    203         int part_size;
    204        
    205         int32_t value = 0;
    206         int32_t mask = 0;
    207         const uint8_t *foo = 0;
    208 
    209204        /* now only short tags are allowed */
    210205        if (item->size > 32) {
     
    214209        if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    215210                item->physical_minimum = item->logical_minimum;
    216                 item->physical_maximum = item->logical_maximum;                 
    217         }
    218        
    219 
     211                item->physical_maximum = item->logical_maximum;
     212        }
     213
     214        int resolution;
    220215        if (item->physical_maximum == item->physical_minimum) {
    221             resolution = 1;
    222         } else {
    223             resolution = (item->logical_maximum - item->logical_minimum) /
    224                 ((item->physical_maximum - item->physical_minimum) *
    225                 (usb_pow(10, (item->unit_exponent))));
    226         }
    227 
    228         offset = item->offset;
    229         // FIXME
    230         if ((size_t) (offset / 8) != (size_t) ((offset+item->size - 1) / 8)) {
    231                
    232                 part_size = 0;
    233 
    234                 size_t i = 0;
    235                 for (i = (size_t) (offset / 8);
    236                     i <= (size_t) (offset + item->size - 1) / 8; i++) {
    237                         if (i == (size_t) (offset / 8)) {
    238                                 /* the higher one */
    239                                 part_size = 8 - (offset % 8);
    240                                 foo = data + i;
    241                                 mask =  ((1 << (item->size - part_size)) - 1);
    242                                 value = (*foo & mask);
    243                         } else if (i == ((offset + item->size - 1) / 8)) {
    244                                 /* the lower one */
    245                                 foo = data + i;
    246                                 mask = ((1 << (item->size - part_size)) - 1) <<
    247                                     (8 - (item->size - part_size));
    248 
    249                                 value = (((*foo & mask) >> (8 -
    250                                     (item->size - part_size))) << part_size) +
    251                                     value;
    252                         } else {
    253                                 value = (*(data + 1) << (part_size + 8)) +
    254                                     value;
    255                                 part_size += 8;
    256                         }
    257                 }
    258         } else {               
    259                 foo = data + (offset / 8);
    260                 mask = ((1 << item->size) - 1) <<
    261                     (8 - ((offset % 8) + item->size));
    262                 value = (*foo & mask) >> (8 - ((offset % 8) + item->size));
     216                resolution = 1;
     217        } else {
     218                resolution = (item->logical_maximum - item->logical_minimum) /
     219                    ((item->physical_maximum - item->physical_minimum) *
     220                    (usb_pow(10, (item->unit_exponent))));
     221        }
     222
     223        int32_t value = 0;
     224
     225        /* First, skip all bytes we don't care */
     226        data += item->offset / 8;
     227
     228        int bits = item->size;
     229        int taken = 0;
     230
     231        /* Than we take the higher bits from the LSB */
     232        const unsigned bit_offset = item->offset % 8;
     233        const int lsb_bits = min(bits, 8);
     234
     235        value |= (*data >> bit_offset) & BIT_RRANGE(uint8_t, lsb_bits);
     236        bits -= lsb_bits;
     237        taken += lsb_bits;
     238        data++;
     239
     240        /* Then there may be bytes, which we take as a whole. */
     241        while (bits > 8) {
     242                value |= *data << taken;
     243                taken += 8;
     244                bits -= 8;
     245                data++;
     246        }
     247
     248        /* And, finally, lower bits from HSB. */
     249        if (bits > 0) {
     250                value |= (*data & BIT_RRANGE(uint8_t, bits)) << taken;
    263251        }
    264252
     
    267255        }
    268256
    269         return (int) (((value - item->logical_minimum) / resolution) + 
     257        return (int) (((value - item->logical_minimum) / resolution) +
    270258            item->physical_minimum);
    271259}
     
    274262/* OUTPUT API */
    275263
    276 /** 
     264/**
    277265 * Allocates output report buffer for output report
    278266 *
     
    282270 * @return Returns allocated output buffer for specified output
    283271 */
    284 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 
     272uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
    285273    uint8_t report_id)
    286274{
     
    334322 * @return Error code
    335323 */
    336 errno_t usb_hid_report_output_translate(usb_hid_report_t *report, 
     324errno_t usb_hid_report_output_translate(usb_hid_report_t *report,
    337325    uint8_t report_id, uint8_t *buffer, size_t size)
    338326{
     
    341329        int length;
    342330        int32_t tmp_value;
    343        
     331
    344332        if (report == NULL) {
    345333                return EINVAL;
     
    351339
    352340        usb_hid_report_description_t *report_des;
    353         report_des = usb_hid_report_find_description(report, report_id, 
     341        report_des = usb_hid_report_find_description(report, report_id,
    354342            USB_HID_REPORT_TYPE_OUTPUT);
    355        
     343
    356344        if (report_des == NULL) {
    357345                return EINVAL;
     
    360348        list_foreach(report_des->report_items, ritems_link,
    361349            usb_hid_report_field_t, report_item) {
    362                 value = usb_hid_translate_data_reverse(report_item, 
     350                value = usb_hid_translate_data_reverse(report_item,
    363351                    report_item->value);
    364352
    365353                offset = report_des->bit_length - report_item->offset - 1;
    366354                length = report_item->size;
    367                
    368                 usb_log_debug("\ttranslated value: %x\n", value);
     355
     356                usb_log_debug("\ttranslated value: %x", value);
    369357
    370358                if ((offset / 8) == ((offset + length - 1) / 8)) {
    371                         if (((size_t) (offset / 8) >= size) || 
     359                        if (((size_t) (offset / 8) >= size) ||
    372360                            ((size_t) (offset + length - 1) / 8) >= size) {
    373361                                break; // TODO ErrorCode
     
    376364                        value = value << shift;
    377365                        value = value & (((1 << length) - 1) << shift);
    378                        
     366
    379367                        uint8_t mask = 0;
    380368                        mask = 0xff - (((1 << length) - 1) << shift);
     
    388376                                if (i == (offset / 8)) {
    389377                                        tmp_value = value;
    390                                         tmp_value = tmp_value & 
     378                                        tmp_value = tmp_value &
    391379                                            ((1 << (8 - (offset % 8))) - 1);
    392380
    393381                                        tmp_value = tmp_value << (offset % 8);
    394                                        
     382
    395383                                        mask = ~(((1 << (8 - (offset % 8))) - 1)
    396384                                            << (offset % 8));
    397385
    398                                         buffer[i] = (buffer[i] & mask) | 
     386                                        buffer[i] = (buffer[i] & mask) |
    399387                                            tmp_value;
    400388                                } else if (i == ((offset + length - 1) / 8)) {
    401                                        
    402                                         value = value >> (length - 
     389
     390                                        value = value >> (length -
    403391                                            ((offset + length) % 8));
    404392
    405                                         value = value & ((1 << (length - 
     393                                        value = value & ((1 << (length -
    406394                                            ((offset + length) % 8))) - 1);
    407                                        
    408                                         mask = (1 << (length - 
     395
     396                                        mask = (1 << (length -
    409397                                            ((offset + length) % 8))) - 1;
    410398
     
    419407                report_item->value = 0;
    420408        }
    421        
     409
    422410        return EOK;
    423411}
     
    430418 * @return ranslated value
    431419 */
    432 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
     420uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
    433421    int value)
    434422{
     
    437425
    438426        if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
    439                 ret = item->logical_minimum;
     427                return item->logical_minimum;
    440428        }
    441429
    442430        if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    443431                item->physical_minimum = item->logical_minimum;
    444                 item->physical_maximum = item->logical_maximum;                 
    445         }
    446        
     432                item->physical_maximum = item->logical_maximum;
     433        }
     434
    447435        /* variable item */
    448436        if (item->physical_maximum == item->physical_minimum) {
    449             resolution = 1;
    450         } else {
    451             resolution = (item->logical_maximum - item->logical_minimum) /
    452                 ((item->physical_maximum - item->physical_minimum) *
    453                 (usb_pow(10, (item->unit_exponent))));
    454         }
    455 
    456         ret = ((value - item->physical_minimum) * resolution) + 
     437                resolution = 1;
     438        } else {
     439                resolution = (item->logical_maximum - item->logical_minimum) /
     440                    ((item->physical_maximum - item->physical_minimum) *
     441                    (usb_pow(10, (item->unit_exponent))));
     442        }
     443
     444        ret = ((value - item->physical_minimum) * resolution) +
    457445            item->logical_minimum;
    458446
    459447        usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), "
    460             "ret(%x)\n", value, resolution, item->physical_minimum, 
     448            "ret(%x)\n", value, resolution, item->physical_minimum,
    461449            item->logical_minimum, ret);
    462        
     450
    463451        if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) {
    464452                return USB_HID_INT32_TO_UINT32(ret, item->size);
     
    479467{
    480468        usb_hid_report_item_t *new_report_item;
    481        
     469
    482470        if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    483471                return NULL;
    484         }                                       
     472        }
    485473        memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
    486474        link_initialize(&(new_report_item->link));
     
    497485 * @param field Current field. If NULL is given, the first one in the report
    498486 * is returned. Otherwise the next one i nthe list is returned.
    499  * @param path Usage path specifying which fields wa are interested in. 
     487 * @param path Usage path specifying which fields wa are interested in.
    500488 * @param flags Flags defining mode of usage paths comparison
    501489 * @param type Type of report we search.
     
    503491 * @retval Pointer to the founded report structure when founded
    504492 */
    505 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 
    506     usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 
     493usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     494    usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
    507495    usb_hid_report_type_t type)
    508496{
    509         usb_hid_report_description_t *report_des = 
     497        usb_hid_report_description_t *report_des =
    510498            usb_hid_report_find_description(report, path->report_id, type);
    511499
    512500        link_t *field_it;
    513        
     501
    514502        if (report_des == NULL) {
    515503                return NULL;
     
    523511
    524512        while (field_it != &report_des->report_items.head) {
    525                 field = list_get_instance(field_it, usb_hid_report_field_t, 
     513                field = list_get_instance(field_it, usb_hid_report_field_t,
    526514                    ritems_link);
    527515
     
    565553        usb_hid_report_description_t *report_des;
    566554        link_t *report_it;
    567        
     555
    568556        if (report_id > 0) {
    569                 report_des = usb_hid_report_find_description(report, report_id, 
     557                report_des = usb_hid_report_find_description(report, report_id,
    570558                    type);
    571559                if (report_des == NULL) {
     
    573561                } else {
    574562                        report_it = report_des->reports_link.next;
    575                 }       
     563                }
    576564        } else {
    577565                report_it = report->reports.head.next;
     
    579567
    580568        while (report_it != &report->reports.head) {
    581                 report_des = list_get_instance(report_it, 
     569                report_des = list_get_instance(report_it,
    582570                    usb_hid_report_description_t, reports_link);
    583571
     
    606594                return;
    607595        }
    608        
     596
    609597        report_item->usages_count = 0;
    610598        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
    611        
     599
    612600        report_item->extended_usage_page = 0;
    613601        report_item->usage_minimum = 0;
  • uspace/lib/usbhid/src/hidpath.c

    rf5e5f73 rdf6ded8  
    7373 * @return Error code
    7474 */
    75 errno_t usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 
    76                                     int32_t usage_page, int32_t usage)
    77 {       
    78         usb_hid_report_usage_path_t *item
    79                 = malloc(sizeof(usb_hid_report_usage_path_t));
     75errno_t usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     76    int32_t usage_page, int32_t usage)
     77{
     78        usb_hid_report_usage_path_t *item =
     79            malloc(sizeof(usb_hid_report_usage_path_t));
    8080
    8181        if (item == NULL) {
     
    8787        item->usage_page = usage_page;
    8888        item->flags = 0;
    89        
     89
    9090        list_append (&item->rpath_items_link, &usage_path->items);
    9191        usage_path->depth++;
     
    9696/**
    9797 * Removes last item from the usage path structure
    98  * @param usage_path 
     98 * @param usage_path
    9999 * @return void
    100100 */
     
    103103        link_t *item_link;
    104104        usb_hid_report_usage_path_t *item;
    105        
    106         if(!list_empty(&usage_path->items)){
     105
     106        if (!list_empty(&usage_path->items)) {
    107107                item_link = list_last(&usage_path->items);
    108108                item = list_get_instance(item_link,
     
    124124{
    125125        usb_hid_report_usage_path_t *item;
    126        
    127         if(!list_empty(&usage_path->items)){
     126
     127        if (!list_empty(&usage_path->items)) {
    128128                item = list_get_instance(list_last(&usage_path->items),
    129                         usb_hid_report_usage_path_t, rpath_items_link);
     129                    usb_hid_report_usage_path_t, rpath_items_link);
    130130
    131131                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
     
    143143 * @return void
    144144 */
    145 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, 
    146                                   int32_t tag, int32_t data)
     145void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path,
     146    int32_t tag, int32_t data)
    147147{
    148148        usb_hid_report_usage_path_t *item;
    149        
    150         if(!list_empty(&usage_path->items)){
     149
     150        if (!list_empty(&usage_path->items)) {
    151151                item = list_get_instance(list_last(&usage_path->items),
    152152                     usb_hid_report_usage_path_t, rpath_items_link);
    153153
    154                 switch(tag) {
    155                         case USB_HID_TAG_CLASS_GLOBAL:
    156                                 item->usage_page = data;
    157                                 break;
    158                         case USB_HID_TAG_CLASS_LOCAL:
    159                                 item->usage = data;
    160                                 break;
    161                 }
    162         }
    163        
    164 }
    165 
    166 
    167 /**
    168  *
    169  *
    170  *
    171  *
    172  */
     154                switch (tag) {
     155                case USB_HID_TAG_CLASS_GLOBAL:
     156                        item->usage_page = data;
     157                        break;
     158                case USB_HID_TAG_CLASS_LOCAL:
     159                        item->usage = data;
     160                        break;
     161                }
     162        }
     163}
     164
    173165void usb_hid_print_usage_path(usb_hid_report_path_t *path)
    174166{
    175         usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
    176         usb_log_debug("\tLENGTH: %d\n", path->depth);
     167        usb_log_debug("USAGE_PATH FOR RId(%d):", path->report_id);
     168        usb_log_debug("\tLENGTH: %d", path->depth);
    177169
    178170        list_foreach(path->items, rpath_items_link,
    179171            usb_hid_report_usage_path_t, path_item) {
    180172
    181                 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
    182                 usb_log_debug("\tUSAGE: %X\n", path_item->usage);
    183                 usb_log_debug("\tFLAGS: %d\n", path_item->flags);
     173                usb_log_debug("\tUSAGE_PAGE: %X", path_item->usage_page);
     174                usb_log_debug("\tUSAGE: %X", path_item->usage);
     175                usb_log_debug("\tFLAGS: %d", path_item->flags);
    184176        }
    185177}
     
    199191        usb_hid_report_usage_path_t *report_item;
    200192        usb_hid_report_usage_path_t *path_item;
    201        
     193
    202194        link_t *report_link;
    203195        link_t *path_link;
    204        
     196
    205197        int only_page;
    206        
     198
    207199        if (report_path->report_id != path->report_id) {
    208200                if (path->report_id != 0) {
     
    210202                }
    211203        }
    212        
     204
    213205        // Empty path match all others
    214206        if (path->depth == 0) {
    215207                return 0;
    216208        }
    217        
     209
    218210        if ((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0) {
    219211                flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
    220212        }
    221        
     213
    222214        switch (flags) {
    223215        /* Path is somewhere in report_path */
     
    226218                        return 1;
    227219                }
    228                
     220
    229221                path_link = list_first(&path->items);
    230222                path_item = list_get_instance(path_link,
    231223                    usb_hid_report_usage_path_t, rpath_items_link);
    232                
     224
    233225                list_foreach(report_path->items, rpath_items_link,
    234226                    usb_hid_report_usage_path_t, report_item) {
    235227                        if (USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
    236228                            path_item->usage_page)) {
    237                                
     229
    238230                                if (only_page == 0) {
    239231                                        if (USB_HID_SAME_USAGE(report_item->usage,
     
    245237                        }
    246238                }
    247                
     239
    248240                return 1;
    249241                break;
    250        
     242
    251243        /* The paths must be identical */
    252244        case USB_HID_PATH_COMPARE_STRICT:
     
    255247                }
    256248                /* Fallthrough */
    257        
     249
    258250        /* Path is prefix of the report_path */
    259251        case USB_HID_PATH_COMPARE_BEGIN:
    260252                report_link = report_path->items.head.next;
    261253                path_link = path->items.head.next;
    262                
     254
    263255                while ((report_link != &report_path->items.head) &&
    264256                    (path_link != &path->items.head)) {
    265                        
     257
    266258                        report_item = list_get_instance(report_link,
    267259                            usb_hid_report_usage_path_t, rpath_items_link);
    268                        
     260
    269261                        path_item = list_get_instance(path_link,
    270262                            usb_hid_report_usage_path_t, rpath_items_link);
    271                        
     263
    272264                        if (!USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
    273265                            path_item->usage_page) || ((only_page == 0) &&
     
    280272                        }
    281273                }
    282                
     274
    283275                if ((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) &&
    284276                    (path_link == &path->items.head)) ||
     
    290282                }
    291283                break;
    292        
     284
    293285        /* Path is suffix of report_path */
    294286        case USB_HID_PATH_COMPARE_END:
    295287                report_link = report_path->items.head.prev;
    296288                path_link = path->items.head.prev;
    297                
     289
    298290                if (list_empty(&path->items)) {
    299291                        return 0;
    300292                }
    301                
     293
    302294                while ((report_link != &report_path->items.head) &&
    303295                      (path_link != &path->items.head)) {
    304296                        report_item = list_get_instance(report_link,
    305297                            usb_hid_report_usage_path_t, rpath_items_link);
    306                        
     298
    307299                        path_item = list_get_instance(path_link,
    308300                            usb_hid_report_usage_path_t, rpath_items_link);
    309                        
     301
    310302                        if (!USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
    311303                            path_item->usage_page) || ((only_page == 0) &&
     
    318310                        }
    319311                }
    320                
     312
    321313                if (path_link == &path->items.head) {
    322314                        return 0;
     
    325317                }
    326318                break;
    327        
     319
    328320        default:
    329321                return -1;
     
    340332        usb_hid_report_path_t *path;
    341333        path = malloc(sizeof(usb_hid_report_path_t));
    342         if(path == NULL){
     334        if (path == NULL) {
    343335                return NULL;
    344336        }
     
    363355        if (path == NULL)
    364356                return;
    365         while(!list_empty(&path->items)){
     357        while (!list_empty(&path->items)) {
    366358                usb_hid_report_remove_last_item(path);
    367359        }
     
    379371 */
    380372usb_hid_report_path_t *usb_hid_report_path_clone(
    381         usb_hid_report_path_t *usage_path)
     373    usb_hid_report_path_t *usage_path)
    382374{
    383375        usb_hid_report_usage_path_t *new_path_item;
    384376        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    385377
    386         if(new_usage_path == NULL){
     378        if (new_usage_path == NULL) {
    387379                return NULL;
    388380        }
    389381
    390382        new_usage_path->report_id = usage_path->report_id;
    391        
    392         if(list_empty(&usage_path->items)){
     383
     384        if (list_empty(&usage_path->items)) {
    393385                return new_usage_path;
    394386        }
     
    398390
    399391                new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
    400                 if(new_path_item == NULL) {
     392                if (new_path_item == NULL) {
    401393                        return NULL;
    402394                }
    403                
     395
    404396                link_initialize(&new_path_item->rpath_items_link);
    405397                new_path_item->usage_page = path_item->usage_page;
    406                 new_path_item->usage = path_item->usage;               
    407                 new_path_item->flags = path_item->flags;               
    408                
     398                new_path_item->usage = path_item->usage;
     399                new_path_item->flags = path_item->flags;
     400
    409401                list_append(&new_path_item->rpath_items_link,
    410402                    &new_usage_path->items);
     
    423415 * @return Error code
    424416 */
    425 errno_t usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, 
    426         uint8_t report_id)
    427 {
    428         if(path == NULL){
     417errno_t usb_hid_report_path_set_report_id(usb_hid_report_path_t *path,
     418    uint8_t report_id)
     419{
     420        if (path == NULL) {
    429421                return EINVAL;
    430422        }
  • uspace/lib/usbhid/src/hidreport.c

    rf5e5f73 rdf6ded8  
    7171        const uint8_t *d =
    7272            usb_dp_get_nested_descriptor(&parser, &parser_data,
    73                 usb_device_descriptors(dev)->full_config);
     73            usb_device_descriptors(dev)->full_config);
    7474       
    7575        /*
     
    8484       
    8585        if (d == NULL) {
    86                 usb_log_error("The %d. interface descriptor not found!\n",
     86                usb_log_error("The %d. interface descriptor not found!",
    8787                    usb_device_get_iface_number(dev));
    8888                return ENOENT;
     
    104104       
    105105        if (d == NULL) {
    106                 usb_log_fatal("No HID descriptor found!\n");
     106                usb_log_fatal("No HID descriptor found!");
    107107                return ENOENT;
    108108        }
     
    130130        }
    131131       
    132         usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
     132        usb_log_debug("Getting Report descriptor, expected size: %u", length);
    133133       
    134134        /*
     
    156156        *size = length;
    157157       
    158         usb_log_debug("Done.\n");
     158        usb_log_debug("Done.");
    159159       
    160160        return EOK;
     
    163163
    164164
    165 errno_t usb_hid_process_report_descriptor(usb_device_t *dev, 
     165errno_t usb_hid_process_report_descriptor(usb_device_t *dev,
    166166    usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size)
    167167{
     
    178178       
    179179        if (rc != EOK) {
    180                 usb_log_error("Problem with getting Report descriptor: %s.\n",
     180                usb_log_error("Problem with getting Report descriptor: %s.",
    181181                    str_error(rc));
    182182                if (*report_desc != NULL) {
     
    191191        rc = usb_hid_parse_report_descriptor(report, *report_desc, *report_size);
    192192        if (rc != EOK) {
    193                 usb_log_error("Problem parsing Report descriptor: %s.\n",
     193                usb_log_error("Problem parsing Report descriptor: %s.",
    194194                    str_error(rc));
    195195                free(*report_desc);
  • uspace/lib/usbhid/src/hidreq.c

    rf5e5f73 rdf6ded8  
    6262{
    6363        if (ctrl_pipe == NULL) {
    64                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    65                 return EINVAL;
    66         }
    67        
    68         if (iface_no < 0) {
    69                 usb_log_warning("usbhid_req_set_report(): no interface given."
    70                     "\n");
    71                 return EINVAL;
    72         }
    73        
    74         /*
    75          * No need for checking other parameters, as they are checked in
    76          * the called function (usb_control_request_set()).
    77          */
    78        
    79         errno_t rc;
    80        
     64                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     65                return EINVAL;
     66        }
     67
     68        if (iface_no < 0) {
     69                usb_log_warning("usbhid_req_set_report(): no interface given."
     70                    "\n");
     71                return EINVAL;
     72        }
     73
     74        /*
     75         * No need for checking other parameters, as they are checked in
     76         * the called function (usb_control_request_set()).
     77         */
     78
     79        errno_t rc;
     80
    8181        uint16_t value = 0;
    8282        value |= (type << 8);
    8383
    84         usb_log_debug("Sending Set Report request to the device.\n");
    85        
     84        usb_log_debug("Sending Set Report request to the device.");
     85
    8686        rc = usb_control_request_set(ctrl_pipe,
    8787            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     
    9393                return rc;
    9494        }
    95        
     95
    9696        return EOK;
    9797}
     
    112112{
    113113        if (ctrl_pipe == NULL) {
    114                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    115                 return EINVAL;
    116         }
    117        
    118         if (iface_no < 0) {
    119                 usb_log_warning("usbhid_req_set_report(): no interface given."
    120                     "\n");
    121                 return EINVAL;
    122         }
    123        
    124         /*
    125          * No need for checking other parameters, as they are checked in
    126          * the called function (usb_control_request_set()).
    127          */
    128        
     114                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     115                return EINVAL;
     116        }
     117
     118        if (iface_no < 0) {
     119                usb_log_warning("usbhid_req_set_report(): no interface given."
     120                    "\n");
     121                return EINVAL;
     122        }
     123
     124        /*
     125         * No need for checking other parameters, as they are checked in
     126         * the called function (usb_control_request_set()).
     127         */
     128
    129129        errno_t rc;
    130130
    131131        usb_log_debug("Sending Set Protocol request to the device ("
    132132            "protocol: %d, iface: %d).\n", protocol, iface_no);
    133        
    134         rc = usb_control_request_set(ctrl_pipe, 
    135             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
     133
     134        rc = usb_control_request_set(ctrl_pipe,
     135            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    136136            USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
    137137
     
    141141                return rc;
    142142        }
    143        
     143
    144144        return EOK;
    145145}
     
    160160{
    161161        if (ctrl_pipe == NULL) {
    162                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    163                 return EINVAL;
    164         }
    165        
    166         if (iface_no < 0) {
    167                 usb_log_warning("usbhid_req_set_report(): no interface given."
    168                     "\n");
    169                 return EINVAL;
    170         }
    171        
    172         /*
    173          * No need for checking other parameters, as they are checked in
    174          * the called function (usb_control_request_set()).
    175          */
    176        
     162                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     163                return EINVAL;
     164        }
     165
     166        if (iface_no < 0) {
     167                usb_log_warning("usbhid_req_set_report(): no interface given."
     168                    "\n");
     169                return EINVAL;
     170        }
     171
     172        /*
     173         * No need for checking other parameters, as they are checked in
     174         * the called function (usb_control_request_set()).
     175         */
     176
    177177        errno_t rc;
    178178
    179179        usb_log_debug("Sending Set Idle request to the device ("
    180180            "duration: %u, iface: %d).\n", duration, iface_no);
    181        
     181
    182182        uint16_t value = duration << 8;
    183        
     183
    184184        rc = usb_control_request_set(ctrl_pipe,
    185185            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     
    191191                return rc;
    192192        }
    193        
     193
    194194        return EOK;
    195195}
     
    203203 * @param[in][out] buffer Buffer for the report data.
    204204 * @param[in] buf_size Size of the buffer (in bytes).
    205  * @param[out] actual_size Actual size of report received from the device 
     205 * @param[out] actual_size Actual size of report received from the device
    206206 *                         (in bytes).
    207207 *
     
    210210 * @return Other value inherited from function usb_control_request_set().
    211211 */
    212 errno_t usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
    213     usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
     212errno_t usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no,
     213    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size,
    214214    size_t *actual_size)
    215215{
    216216        if (ctrl_pipe == NULL) {
    217                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    218                 return EINVAL;
    219         }
    220        
    221         if (iface_no < 0) {
    222                 usb_log_warning("usbhid_req_set_report(): no interface given."
    223                     "\n");
    224                 return EINVAL;
    225         }
    226        
    227         /*
    228          * No need for checking other parameters, as they are checked in
    229          * the called function (usb_control_request_set()).
    230          */
    231        
     217                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     218                return EINVAL;
     219        }
     220
     221        if (iface_no < 0) {
     222                usb_log_warning("usbhid_req_set_report(): no interface given."
     223                    "\n");
     224                return EINVAL;
     225        }
     226
     227        /*
     228         * No need for checking other parameters, as they are checked in
     229         * the called function (usb_control_request_set()).
     230         */
     231
    232232        errno_t rc;
    233233
    234234        uint16_t value = 0;
    235235        value |= (type << 8);
    236        
    237         usb_log_debug("Sending Get Report request to the device.\n");
    238        
    239         rc = usb_control_request_get(ctrl_pipe, 
    240             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
     236
     237        usb_log_debug("Sending Get Report request to the device.");
     238
     239        rc = usb_control_request_get(ctrl_pipe,
     240            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    241241            USB_HIDREQ_GET_REPORT, value, iface_no, buffer, buf_size,
    242242            actual_size);
     
    247247                return rc;
    248248        }
    249        
     249
    250250        return EOK;
    251251}
     
    262262 * @return Other value inherited from function usb_control_request_set().
    263263 */
    264 errno_t usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
     264errno_t usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
    265265    usb_hid_protocol_t *protocol)
    266266{
    267267        if (ctrl_pipe == NULL) {
    268                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    269                 return EINVAL;
    270         }
    271        
    272         if (iface_no < 0) {
    273                 usb_log_warning("usbhid_req_set_report(): no interface given."
    274                     "\n");
    275                 return EINVAL;
    276         }
    277        
    278         /*
    279          * No need for checking other parameters, as they are checked in
    280          * the called function (usb_control_request_set()).
    281          */
    282        
    283         errno_t rc;     
     268                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     269                return EINVAL;
     270        }
     271
     272        if (iface_no < 0) {
     273                usb_log_warning("usbhid_req_set_report(): no interface given."
     274                    "\n");
     275                return EINVAL;
     276        }
     277
     278        /*
     279         * No need for checking other parameters, as they are checked in
     280         * the called function (usb_control_request_set()).
     281         */
     282
     283        errno_t rc;
    284284
    285285        usb_log_debug("Sending Get Protocol request to the device ("
    286286            "iface: %d).\n", iface_no);
    287        
     287
    288288        uint8_t buffer[1];
    289289        size_t actual_size = 0;
    290        
    291         rc = usb_control_request_get(ctrl_pipe, 
    292             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
     290
     291        rc = usb_control_request_get(ctrl_pipe,
     292            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    293293            USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
    294294
     
    298298                return rc;
    299299        }
    300        
     300
    301301        if (actual_size != 1) {
    302                 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
    303                         actual_size);
     302                usb_log_warning("Wrong data size: %zu, expected: 1.",
     303                    actual_size);
    304304                return ELIMIT;
    305305        }
    306        
     306
    307307        *protocol = buffer[0];
    308        
     308
    309309        return EOK;
    310310}
     
    320320 * @retval EOK if successful.
    321321 * @retval EINVAL if no HID device is given.
    322  * @return Other value inherited from one of functions 
     322 * @return Other value inherited from one of functions
    323323 *         usb_pipe_start_session(), usb_pipe_end_session(),
    324324 *         usb_control_request_set().
    325325 */
    326 errno_t usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration)
    327 {
    328         if (ctrl_pipe == NULL) {
    329                 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
    330                 return EINVAL;
    331         }
    332        
    333         if (iface_no < 0) {
    334                 usb_log_warning("usbhid_req_set_report(): no interface given."
    335                     "\n");
    336                 return EINVAL;
    337         }
    338        
    339         /*
    340          * No need for checking other parameters, as they are checked in
    341          * the called function (usb_control_request_set()).
    342          */
    343        
     326errno_t usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no,
     327    uint8_t *duration)
     328{
     329        if (ctrl_pipe == NULL) {
     330                usb_log_warning("usbhid_req_set_report(): no pipe given.");
     331                return EINVAL;
     332        }
     333
     334        if (iface_no < 0) {
     335                usb_log_warning("usbhid_req_set_report(): no interface given."
     336                    "\n");
     337                return EINVAL;
     338        }
     339
     340        /*
     341         * No need for checking other parameters, as they are checked in
     342         * the called function (usb_control_request_set()).
     343         */
     344
    344345        errno_t rc;
    345346
    346347        usb_log_debug("Sending Get Idle request to the device ("
    347348            "iface: %d).\n", iface_no);
    348        
     349
    349350        uint16_t value = 0;
    350351        uint8_t buffer[1];
    351352        size_t actual_size = 0;
    352        
    353         rc = usb_control_request_get(ctrl_pipe, 
    354             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
    355             USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1, 
     353
     354        rc = usb_control_request_get(ctrl_pipe,
     355            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     356            USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1,
    356357            &actual_size);
    357358
     
    361362                return rc;
    362363        }
    363        
     364
    364365        if (actual_size != 1) {
    365                 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
    366                         actual_size);
     366                usb_log_warning("Wrong data size: %zu, expected: 1.",
     367                    actual_size);
    367368                return ELIMIT;
    368369        }
    369        
     370
    370371        *duration = buffer[0];
    371        
     372
    372373        return EOK;
    373374}
  • uspace/lib/usbhost/Makefile

    rf5e5f73 rdf6ded8  
    3737        src/endpoint.c \
    3838        src/hcd.c \
    39         src/usb_bus.c \
     39        src/bus.c \
     40        src/usb2_bus.c \
     41        src/bandwidth.c \
     42        src/utility.c \
    4043        src/usb_transfer_batch.c
    4144
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2012 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_DDF_HELPERS_H
    3839
    39 #include <usb/host/hcd.h>
    40 #include <usb/host/usb_bus.h>
     40#include <ddf/driver.h>
     41#include <ddf/interrupt.h>
    4142#include <usb/usb.h>
    4243
    43 #include <ddf/driver.h>
    44 #include <ddf/interrupt.h>
    45 #include <device/hw_res_parsed.h>
     44#include <usb/host/hcd.h>
     45#include <usb/descriptor.h>
    4646
    47 typedef errno_t (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool);
    48 typedef void (*driver_fini_t)(hcd_t *);
    49 typedef errno_t (*claim_t)(ddf_dev_t *);
    50 typedef errno_t (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *, int *);
    5147
    52 typedef struct {
    53         hcd_ops_t ops;
    54         claim_t claim;
    55         usb_speed_t hc_speed;
    56         driver_init_t init;
    57         driver_fini_t fini;
    58         interrupt_handler_t *irq_handler;
    59         irq_code_gen_t irq_code_gen;
    60         const char *name;
    61 } ddf_hc_driver_t;
     48errno_t hcd_ddf_setup_hc(ddf_dev_t *, size_t);
     49void hcd_ddf_clean_hc(hc_device_t *);
    6250
    63 errno_t hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver);
    6451
    65 errno_t hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    66     size_t bw, bw_count_func_t bw_count);
    67 void hcd_ddf_clean_hc(ddf_dev_t *device);
    68 errno_t hcd_ddf_setup_root_hub(ddf_dev_t *device);
     52device_t *hcd_ddf_fun_create(hc_device_t *, usb_speed_t);
     53void hcd_ddf_fun_destroy(device_t *);
    6954
    70 hcd_t *dev_to_hcd(ddf_dev_t *dev);
     55errno_t hcd_ddf_setup_match_ids(device_t *, usb_standard_device_descriptor_t *);
    7156
    72 errno_t hcd_ddf_enable_interrupt(ddf_dev_t *device, int);
    73 errno_t hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res);
    74 errno_t hcd_ddf_setup_interrupts(ddf_dev_t *device,
    75     const hw_res_list_parsed_t *hw_res,
    76     interrupt_handler_t handler,
    77     errno_t (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
    78     cap_handle_t *handle);
    79 void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev);
     57errno_t hcd_ddf_enable_interrupt(hc_device_t *hcd, int);
     58errno_t hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res);
     59
     60void hcd_ddf_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    8061
    8162#endif
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3233/** @file
    3334 *
     35 * Endpoint structure is tightly coupled to the bus. The bus controls the
     36 * life-cycle of endpoint. In order to keep endpoints lightweight, operations
     37 * on endpoints are part of the bus structure.
     38 *
    3439 */
    3540#ifndef LIBUSBHOST_HOST_ENDPOINT_H
    3641#define LIBUSBHOST_HOST_ENDPOINT_H
    3742
     43#include <adt/list.h>
     44#include <atomic.h>
     45#include <fibril_synch.h>
    3846#include <stdbool.h>
    39 #include <adt/list.h>
    40 #include <fibril_synch.h>
     47#include <sys/time.h>
    4148#include <usb/usb.h>
    42 #include <atomic.h>
     49#include <usb/host/bus.h>
     50#include <usbhc_iface.h>
    4351
    44 /** Host controller side endpoint structure. */
     52typedef struct bus bus_t;
     53typedef struct device device_t;
     54typedef struct transfer_request transfer_request_t;
     55typedef struct usb_transfer_batch usb_transfer_batch_t;
     56
     57/**
     58 * Host controller side endpoint structure.
     59 *
     60 * This structure, though reference-counted, is very fragile. It is responsible
     61 * for synchronizing transfer batch scheduling and completion.
     62 *
     63 * To avoid situations, in which two locks must be obtained to schedule/finish
     64 * a transfer, the endpoint inherits a lock from the outside. Because the
     65 * concrete instance of mutex can be unknown at the time of initialization,
     66 * the HC shall pass the right lock at the time of onlining the endpoint.
     67 *
     68 * The fields used for scheduling (online, active_batch) are to be used only
     69 * under that guard and by functions designed for this purpose. The driver can
     70 * also completely avoid using this mechanism, in which case it is on its own in
     71 * question of transfer aborting.
     72 *
     73 * Relevant information can be found in the documentation of HelenOS xHCI
     74 * project.
     75 */
    4576typedef struct endpoint {
     77        /** USB device */
     78        device_t *device;
    4679        /** Reference count. */
    47         atomic_t refcnt;       
    48         /** Part of linked list. */
    49         link_t link;
    50         /** USB address. */
    51         usb_address_t address;
    52         /** USB endpoint number. */
     80        atomic_t refcnt;
     81
     82        /** An inherited guard */
     83        fibril_mutex_t *guard;
     84        /** Whether it's allowed to schedule on this endpoint */
     85        bool online;
     86        /** The currently active transfer batch. */
     87        usb_transfer_batch_t *active_batch;
     88        /** Signals change of active status. */
     89        fibril_condvar_t avail;
     90
     91        /** Endpoint number */
    5392        usb_endpoint_t endpoint;
    5493        /** Communication direction. */
     
    5695        /** USB transfer type. */
    5796        usb_transfer_type_t transfer_type;
    58         /** Communication speed. */
    59         usb_speed_t speed;
    60         /** Maximum size of data packets. */
     97        /** Maximum size of one packet */
    6198        size_t max_packet_size;
    62         /** Additional opportunities per uframe */
    63         unsigned packets;
    64         /** Necessary bandwidth. */
    65         size_t bandwidth;
    66         /** Value of the toggle bit. */
    67         unsigned toggle:1;
    68         /** True if there is a batch using this scheduled for this endpoint. */
    69         volatile bool active;
    70         /** Protects resources and active status changes. */
    71         fibril_mutex_t guard;
    72         /** Signals change of active status. */
    73         fibril_condvar_t avail;
    74         /** High speed TT data */
    75         struct {
    76                 usb_address_t address;
    77                 unsigned port;
    78         } tt;
    79         /** Optional device specific data. */
    80         struct {
    81                 /** Device specific data. */
    82                 void *data;
    83                 /** Callback to get the value of toggle bit. */
    84                 int (*toggle_get)(void *);
    85                 /** Callback to set the value of toggle bit. */
    86                 void (*toggle_set)(void *, int);
    87         } hc_data;
     99
     100        /** Maximum size of one transfer */
     101        size_t max_transfer_size;
     102
     103        /* Policies for transfer buffers */
     104        /** A hint for optimal performance. */
     105        dma_policy_t transfer_buffer_policy;
     106        /** Enforced by the library. */
     107        dma_policy_t required_transfer_buffer_policy;
     108
     109        /**
     110         * Number of packets that can be sent in one service interval
     111         * (not necessarily uframe, despite its name)
     112         */
     113        unsigned packets_per_uframe;
     114
     115        /* This structure is meant to be extended by overriding. */
    88116} endpoint_t;
    89117
    90 extern endpoint_t *endpoint_create(usb_address_t, usb_endpoint_t,
    91     usb_direction_t, usb_transfer_type_t, usb_speed_t, size_t, unsigned int,
    92     size_t, usb_address_t, unsigned int);
    93 extern void endpoint_destroy(endpoint_t *);
     118extern void endpoint_init(endpoint_t *, device_t *,
     119    const usb_endpoint_descriptors_t *);
    94120
    95121extern void endpoint_add_ref(endpoint_t *);
    96122extern void endpoint_del_ref(endpoint_t *);
    97123
    98 extern void endpoint_set_hc_data(endpoint_t *, void *, int (*)(void *),
    99     void (*)(void *, int));
    100 extern void endpoint_clear_hc_data(endpoint_t *);
     124extern void endpoint_set_online(endpoint_t *, fibril_mutex_t *);
     125extern void endpoint_set_offline_locked(endpoint_t *);
    101126
    102 extern void endpoint_use(endpoint_t *);
    103 extern void endpoint_release(endpoint_t *);
     127extern void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t);
     128extern int endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *);
     129extern void endpoint_deactivate_locked(endpoint_t *);
    104130
    105 extern int endpoint_toggle_get(endpoint_t *);
    106 extern void endpoint_toggle_set(endpoint_t *, int);
     131int endpoint_send_batch(endpoint_t *, const transfer_request_t *);
    107132
    108 /** list_get_instance wrapper.
    109  *
    110  * @param item Pointer to link member.
    111  *
    112  * @return Pointer to endpoint_t structure.
    113  *
    114  */
    115 static inline endpoint_t * endpoint_get_instance(link_t *item)
     133static inline bus_t *endpoint_get_bus(endpoint_t *ep)
    116134{
    117         return item ? list_get_instance(item, endpoint_t, link) : NULL;
     135        device_t * const device = ep->device;
     136        return device ? device->bus : NULL;
    118137}
     138
    119139#endif
    120140
  • uspace/lib/usbhost/include/usb/host/hcd.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_HCD_H
    3839
    39 #include <usb/host/endpoint.h>
    40 #include <usb/host/usb_bus.h>
    41 #include <usb/host/usb_transfer_batch.h>
    42 #include <usb/usb.h>
     40#include <ddf/driver.h>
     41#include <usb/request.h>
    4342
    44 #include <assert.h>
    45 #include <usbhc_iface.h>
    46 #include <stddef.h>
    47 #include <stdint.h>
     43typedef struct hw_resource_list_parsed hw_res_list_parsed_t;
     44typedef struct bus bus_t;
     45typedef struct device device_t;
    4846
    49 typedef struct hcd hcd_t;
     47/* Treat this header as read-only in driver code.
     48 * It could be opaque, but why to complicate matters.
     49 */
     50typedef struct hc_device {
     51        /* Bus instance */
     52        bus_t *bus;
    5053
    51 typedef errno_t (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *);
    52 typedef errno_t (*ep_add_hook_t)(hcd_t *, endpoint_t *);
    53 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *);
    54 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
    55 typedef errno_t (*status_hook_t)(hcd_t *, uint32_t *);
     54        /* Managed DDF device */
     55        ddf_dev_t *ddf_dev;
    5656
    57 typedef struct {
    58         /** Transfer scheduling, implement in device driver. */
    59         schedule_hook_t schedule;
    60         /** Hook called upon registering new endpoint. */
    61         ep_add_hook_t ep_add_hook;
    62         /** Hook called upon removing of an endpoint. */
    63         ep_remove_hook_t ep_remove_hook;
    64         /** Hook to be called on device interrupt, passes ARG1 */
    65         interrupt_hook_t irq_hook;
    66         /** Periodic polling hook */
    67         status_hook_t status_hook;
    68 } hcd_ops_t;
     57        /* Control function */
     58        ddf_fun_t *ctl_fun;
    6959
    70 /** Generic host controller driver structure. */
    71 struct hcd {
    72         /** Endpoint manager. */
    73         usb_bus_t bus;
     60        /* Result of enabling HW IRQs */
     61        int irq_cap;
    7462
    7563        /** Interrupt replacement fibril */
    7664        fid_t polling_fibril;
    7765
    78         /** Driver implementation */
    79         hcd_ops_t ops;
    80         /** Device specific driver data. */
    81         void * driver_data;
    82 };
     66        /* This structure is meant to be extended by driver code. */
     67} hc_device_t;
    8368
    84 extern void hcd_init(hcd_t *, usb_speed_t, size_t, bw_count_func_t);
     69typedef struct hc_driver {
     70        const char *name;
    8571
    86 static inline void hcd_set_implementation(hcd_t *hcd, void *data,
    87     const hcd_ops_t *ops)
     72        /** Size of the device data to be allocated, and passed as the
     73         * hc_device_t. */
     74        size_t hc_device_size;
     75
     76        /** Initialize device structures. */
     77        int (*hc_add)(hc_device_t *, const hw_res_list_parsed_t *);
     78
     79        /** Generate IRQ code to handle interrupts. */
     80        int (*irq_code_gen)(irq_code_t *, hc_device_t *,
     81            const hw_res_list_parsed_t *, int *);
     82
     83        /** Claim device from BIOS. */
     84        int (*claim)(hc_device_t *);
     85
     86        /** Start the host controller. */
     87        int (*start)(hc_device_t *);
     88
     89        /** Setup the virtual roothub. */
     90        int (*setup_root_hub)(hc_device_t *);
     91
     92        /** Stop the host controller (after start has been called) */
     93        int (*stop)(hc_device_t *);
     94
     95        /** HC was asked to be removed (after hc_add has been called) */
     96        int (*hc_remove)(hc_device_t *);
     97
     98        /** HC is gone. */
     99        int (*hc_gone)(hc_device_t *);
     100} hc_driver_t;
     101
     102/* Drivers should call this before leaving hc_add */
     103static inline void hc_device_setup(hc_device_t *hcd, bus_t *bus)
    88104{
    89         assert(hcd);
    90         if (ops) {
    91                 hcd->driver_data = data;
    92                 hcd->ops = *ops;
    93         } else {
    94                 memset(&hcd->ops, 0, sizeof(hcd->ops));
    95         }
     105        hcd->bus = bus;
    96106}
    97107
    98 static inline void * hcd_get_driver_data(hcd_t *hcd)
     108static inline hc_device_t *dev_to_hcd(ddf_dev_t *dev)
    99109{
    100         assert(hcd);
    101         return hcd->driver_data;
     110        return ddf_dev_data_get(dev);
    102111}
    103112
    104 extern errno_t hcd_request_address(hcd_t *, usb_speed_t, usb_address_t *);
    105 
    106 extern errno_t hcd_release_address(hcd_t *, usb_address_t);
    107 
    108 extern errno_t hcd_reserve_default_address(hcd_t *, usb_speed_t);
    109 
    110 static inline errno_t hcd_release_default_address(hcd_t *hcd)
    111 {
    112         return hcd_release_address(hcd, USB_ADDRESS_DEFAULT);
    113 }
    114 
    115 extern errno_t hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t,
    116     usb_transfer_type_t, size_t, unsigned int, size_t, usb_address_t,
    117     unsigned int);
    118 
    119 extern errno_t hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t);
    120 
    121 extern errno_t hcd_send_batch(hcd_t *, usb_target_t, usb_direction_t, void *,
    122     size_t, uint64_t, usbhc_iface_transfer_in_callback_t,
    123     usbhc_iface_transfer_out_callback_t, void *, const char *);
    124 
    125 extern errno_t hcd_send_batch_sync(hcd_t *, usb_target_t, usb_direction_t,
    126     void *, size_t, uint64_t, const char *, size_t *);
     113extern errno_t hc_driver_main(const hc_driver_t *);
    127114
    128115#endif
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H
    3839
    39 #include <usb/host/endpoint.h>
    40 #include <usb/usb.h>
    41 
    42 #include <assert.h>
     40#include <atomic.h>
     41#include <errno.h>
    4342#include <stddef.h>
    4443#include <stdint.h>
     44#include <usb/dma_buffer.h>
     45#include <usb/request.h>
     46#include <usb/usb.h>
    4547#include <usbhc_iface.h>
    4648
    47 #define USB_SETUP_PACKET_SIZE 8
     49#include <usb/host/hcd.h>
     50#include <usb/host/endpoint.h>
     51#include <usb/host/bus.h>
     52
     53typedef struct endpoint endpoint_t;
     54typedef struct bus bus_t;
    4855
    4956/** Structure stores additional data needed for communication with EP */
    5057typedef struct usb_transfer_batch {
     58        /** Target for communication */
     59        usb_target_t target;
     60        /** Direction of the transfer */
     61        usb_direction_t dir;
     62
    5163        /** Endpoint used for communication */
    5264        endpoint_t *ep;
    53         /** Function called on completion (IN version) */
    54         usbhc_iface_transfer_in_callback_t callback_in;
    55         /** Function called on completion (OUT version) */
    56         usbhc_iface_transfer_out_callback_t callback_out;
    57         /** Argument to pass to the completion function */
    58         void *arg;
    59         /** Place for data to send/receive */
    60         char *buffer;
    61         /** Size of memory pointed to by buffer member */
    62         size_t buffer_size;
     65
    6366        /** Place to store SETUP data needed by control transfers */
    64         char setup_buffer[USB_SETUP_PACKET_SIZE];
    65         /** Used portion of setup_buffer member
    66          *
    67          * SETUP buffer must be 8 bytes for control transfers and is left
    68          * unused for all other transfers. Thus, this field is either 0 or 8.
     67        union {
     68                char buffer [USB_SETUP_PACKET_SIZE];
     69                usb_device_request_setup_packet_t packet;
     70                uint64_t packed;
     71        } setup;
     72
     73        /** DMA buffer with enforced policy */
     74        dma_buffer_t dma_buffer;
     75        /** Size of memory buffer */
     76        size_t offset, size;
     77
     78        /**
     79         * In case a bounce buffer is allocated, the original buffer must to be
     80         * stored to be filled after the IN transaction is finished.
    6981         */
    70         size_t setup_size;
     82        char *original_buffer;
     83        bool is_bounced;
    7184
    72         /** Actually used portion of the buffer
    73          * This member is never accessed by functions provided in this header,
    74          * with the exception of usb_transfer_batch_finish. For external use.
    75          */
    76         size_t transfered_size;
    77         /** Indicates success/failure of the communication
    78          * This member is never accessed by functions provided in this header,
    79          * with the exception of usb_transfer_batch_finish. For external use.
    80          */
     85        /** Indicates success/failure of the communication */
    8186        errno_t error;
     87        /** Actually used portion of the buffer */
     88        size_t transferred_size;
     89
     90        /** Function called on completion */
     91        usbhc_iface_transfer_callback_t on_complete;
     92        /** Arbitrary data for the handler */
     93        void *on_complete_data;
    8294} usb_transfer_batch_t;
    8395
    84 /** Printf formatting string for dumping usb_transfer_batch_t. */
     96/**
     97 * Printf formatting string for dumping usb_transfer_batch_t.
     98 *  [address:endpoint speed transfer_type-direction buffer_sizeB/max_packet_size]
     99 * */
    85100#define USB_TRANSFER_BATCH_FMT "[%d:%d %s %s-%s %zuB/%zu]"
    86101
     
    89104 */
    90105#define USB_TRANSFER_BATCH_ARGS(batch) \
    91         (batch).ep->address, (batch).ep->endpoint, \
    92         usb_str_speed((batch).ep->speed), \
     106        ((batch).ep->device->address), ((batch).ep->endpoint), \
     107        usb_str_speed((batch).ep->device->speed), \
    93108        usb_str_transfer_type_short((batch).ep->transfer_type), \
    94         usb_str_direction((batch).ep->direction), \
    95         (batch).buffer_size, (batch).ep->max_packet_size
     109        usb_str_direction((batch).dir), \
     110        (batch).size, (batch).ep->max_packet_size
    96111
     112/** Wrapper for bus operation. */
     113usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *);
    97114
    98 usb_transfer_batch_t * usb_transfer_batch_create(
    99     endpoint_t *ep,
    100     char *buffer,
    101     size_t buffer_size,
    102     uint64_t setup_buffer,
    103     usbhc_iface_transfer_in_callback_t func_in,
    104     usbhc_iface_transfer_out_callback_t func_out,
    105     void *arg
    106 );
    107 void usb_transfer_batch_destroy(usb_transfer_batch_t *instance);
     115/** Batch initializer. */
     116void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
    108117
    109 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    110     const void* data, size_t size, errno_t error);
     118/** Buffer handling */
     119bool usb_transfer_batch_bounce_required(usb_transfer_batch_t *);
     120errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *);
    111121
    112 /** Finish batch using stored error value and transferred size.
    113  *
    114  * @param[in] instance Batch structure to use.
    115  * @param[in] data Data to copy to the output buffer.
     122/** Batch finalization. */
     123void usb_transfer_batch_finish(usb_transfer_batch_t *);
     124
     125/** To be called from outside only when the transfer is not going to be finished
     126 * (i.o.w. until successfuly scheduling)
    116127 */
    117 static inline void usb_transfer_batch_finish(
    118     const usb_transfer_batch_t *instance, const void* data)
    119 {
    120         assert(instance);
    121         usb_transfer_batch_finish_error(
    122             instance, data, instance->transfered_size, instance->error);
    123 }
    124 
    125 /** Determine batch direction based on the callbacks present
    126  * @param[in] instance Batch structure to use, non-null.
    127  * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT.
    128  */
    129 static inline usb_direction_t usb_transfer_batch_direction(
    130     const usb_transfer_batch_t *instance)
    131 {
    132         assert(instance);
    133         if (instance->callback_in) {
    134                 assert(instance->callback_out == NULL);
    135                 assert(instance->ep == NULL
    136                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    137                     || instance->ep->direction == USB_DIRECTION_IN);
    138                 return USB_DIRECTION_IN;
    139         }
    140         if (instance->callback_out) {
    141                 assert(instance->callback_in == NULL);
    142                 assert(instance->ep == NULL
    143                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    144                     || instance->ep->direction == USB_DIRECTION_OUT);
    145                 return USB_DIRECTION_OUT;
    146         }
    147         assert(false);
    148 }
     128void usb_transfer_batch_destroy(usb_transfer_batch_t *);
    149129
    150130#endif
  • uspace/lib/usbhost/src/ddf_helpers.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2013 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch, Petr Manek
    34 * All rights reserved.
    45 *
     
    3132 */
    3233/** @file
    33  *
    34  */
    35 
    36 #include <usb/classes/classes.h>
    37 #include <usb/debug.h>
    38 #include <usb/descriptor.h>
    39 #include <usb/request.h>
    40 #include <usb/usb.h>
     34 * Helpers to work with the DDF interface.
     35 */
    4136
    4237#include <adt/list.h>
     
    4742#include <device/hw_res_parsed.h>
    4843#include <errno.h>
    49 #include <fibril_synch.h>
    50 #include <macros.h>
    51 #include <stdio.h>
    52 #include <stdlib.h>
    5344#include <str_error.h>
     45#include <usb/classes/classes.h>
     46#include <usb/debug.h>
     47#include <usb/descriptor.h>
     48#include <usb/usb.h>
     49#include <usb/dma_buffer.h>
    5450#include <usb_iface.h>
     51#include <usbhc_iface.h>
     52
     53#include "bus.h"
     54#include "endpoint.h"
    5555
    5656#include "ddf_helpers.h"
    5757
    58 #define CTRL_PIPE_MIN_PACKET_SIZE 8
    59 
    60 typedef struct usb_dev {
    61         link_t link;
    62         list_t devices;
    63         fibril_mutex_t guard;
    64         ddf_fun_t *fun;
    65         usb_address_t address;
    66         usb_speed_t speed;
    67         usb_address_t tt_address;
    68         unsigned port;
    69 } usb_dev_t;
    70 
    71 typedef struct hc_dev {
    72         ddf_fun_t *ctl_fun;
    73         hcd_t hcd;
    74         usb_dev_t *root_hub;
    75 } hc_dev_t;
    76 
    77 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev)
    78 {
    79         return ddf_dev_data_get(dev);
    80 }
    81 
    82 hcd_t *dev_to_hcd(ddf_dev_t *dev)
    83 {
    84         hc_dev_t *hc_dev = dev_to_hc_dev(dev);
    85         if (!hc_dev) {
    86                 usb_log_error("Invalid HCD device.\n");
    87                 return NULL;
    88         }
    89         return &hc_dev->hcd;
    90 }
    91 
    92 
    93 static errno_t hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
    94 static errno_t hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port);
    95 
    96 
    97 /* DDF INTERFACE */
    98 
    99 /** Register endpoint interface function.
    100  * @param fun DDF function.
    101  * @param address USB address of the device.
    102  * @param endpoint USB endpoint number to be registered.
    103  * @param transfer_type Endpoint's transfer type.
    104  * @param direction USB communication direction the endpoint is capable of.
    105  * @param max_packet_size Maximu size of packets the endpoint accepts.
    106  * @param interval Preferred timeout between communication.
     58/**
     59 * DDF usbhc_iface callback. Passes the endpoint descriptors, fills the pipe
     60 * descriptor according to the contents of the endpoint.
     61 *
     62 * @param[in] fun DDF function of the device in question.
     63 * @param[out] pipe_desc The pipe descriptor to be filled.
     64 * @param[in] endpoint_desc Endpoint descriptors from the device.
    10765 * @return Error code.
    10866 */
    109 static errno_t register_endpoint(
    110     ddf_fun_t *fun, usb_endpoint_t endpoint,
    111     usb_transfer_type_t transfer_type, usb_direction_t direction,
    112     size_t max_packet_size, unsigned packets, unsigned interval)
    113 {
    114         assert(fun);
    115         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    116         usb_dev_t *dev = ddf_fun_data_get(fun);
     67static errno_t register_endpoint(ddf_fun_t *fun, usb_pipe_desc_t *pipe_desc,
     68     const usb_endpoint_descriptors_t *ep_desc)
     69{
     70        assert(fun);
     71        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     72        device_t *dev = ddf_fun_data_get(fun);
    11773        assert(hcd);
     74        assert(hcd->bus);
    11875        assert(dev);
    119         const size_t size = max_packet_size;
    120         const usb_target_t target =
    121             {{.address = dev->address, .endpoint = endpoint}};
    122 
    123         usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
    124             dev->address, endpoint, usb_str_transfer_type(transfer_type),
    125             usb_str_direction(direction), max_packet_size, interval);
    126 
    127         return hcd_add_ep(hcd, target, direction, transfer_type,
    128             max_packet_size, packets, size, dev->tt_address, dev->port);
    129 }
    130 
    131 /** Unregister endpoint interface function.
    132  * @param fun DDF function.
    133  * @param address USB address of the endpoint.
    134  * @param endpoint USB endpoint number.
    135  * @param direction Communication direction of the enpdoint to unregister.
     76
     77        endpoint_t *ep;
     78        const int err = bus_endpoint_add(dev, ep_desc, &ep);
     79        if (err)
     80                return err;
     81
     82        if (pipe_desc) {
     83                pipe_desc->endpoint_no = ep->endpoint;
     84                pipe_desc->direction = ep->direction;
     85                pipe_desc->transfer_type = ep->transfer_type;
     86                pipe_desc->max_transfer_size = ep->max_transfer_size;
     87                pipe_desc->transfer_buffer_policy = ep->transfer_buffer_policy;
     88        }
     89        endpoint_del_ref(ep);
     90
     91        return EOK;
     92}
     93
     94 /**
     95  * DDF usbhc_iface callback. Unregister endpoint that makes the other end of
     96  * the pipe described.
     97  *
     98  * @param fun DDF function of the device in question.
     99  * @param pipe_desc Pipe description.
     100  * @return Error code.
     101  */
     102static errno_t unregister_endpoint(ddf_fun_t *fun, const usb_pipe_desc_t *pipe_desc)
     103{
     104        assert(fun);
     105        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     106        device_t *dev = ddf_fun_data_get(fun);
     107        assert(hcd);
     108        assert(hcd->bus);
     109        assert(dev);
     110
     111        endpoint_t *ep = bus_find_endpoint(dev, pipe_desc->endpoint_no, pipe_desc->direction);
     112        if (!ep)
     113                return ENOENT;
     114
     115        const errno_t err = bus_endpoint_remove(ep);
     116
     117        endpoint_del_ref(ep);
     118        return err;
     119}
     120
     121/**
     122 * DDF usbhc_iface callback. Calls the respective bus operation directly.
     123 *
     124 * @param fun DDF function of the device (hub) requesting the address.
     125 */
     126static errno_t default_address_reservation(ddf_fun_t *fun, bool reserve)
     127{
     128        assert(fun);
     129        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     130        device_t *dev = ddf_fun_data_get(fun);
     131        assert(hcd);
     132        assert(hcd->bus);
     133        assert(dev);
     134
     135        usb_log_debug("Device %d %s default address", dev->address, reserve ? "requested" : "releasing");
     136        if (reserve) {
     137                return bus_reserve_default_address(hcd->bus, dev);
     138        } else {
     139                bus_release_default_address(hcd->bus, dev);
     140                return EOK;
     141        }
     142}
     143
     144/**
     145 * DDF usbhc_iface callback. Calls the bus operation directly.
     146 *
     147 * @param fun DDF function of the device (hub) requesting the address.
     148 * @param speed USB speed of the new device
     149 */
     150static errno_t device_enumerate(ddf_fun_t *fun, unsigned port, usb_speed_t speed)
     151{
     152        assert(fun);
     153        ddf_dev_t *hc = ddf_fun_get_dev(fun);
     154        assert(hc);
     155        hc_device_t *hcd = dev_to_hcd(hc);
     156        assert(hcd);
     157        device_t *hub = ddf_fun_data_get(fun);
     158        assert(hub);
     159
     160        errno_t err;
     161
     162        if (!usb_speed_is_valid(speed))
     163                return EINVAL;
     164
     165        usb_log_debug("Hub %d reported a new %s speed device on port: %u",
     166            hub->address, usb_str_speed(speed), port);
     167
     168        device_t *dev = hcd_ddf_fun_create(hcd, speed);
     169        if (!dev) {
     170                usb_log_error("Failed to create USB device function.");
     171                return ENOMEM;
     172        }
     173
     174        dev->hub = hub;
     175        dev->tier = hub->tier + 1;
     176        dev->port = port;
     177        dev->speed = speed;
     178
     179        if ((err = bus_device_enumerate(dev))) {
     180                usb_log_error("Failed to initialize USB dev memory structures.");
     181                goto err_usb_dev;
     182        }
     183
     184        /* If the driver didn't name the dev when enumerating,
     185         * do it in some generic way.
     186         */
     187        if (!ddf_fun_get_name(dev->fun)) {
     188                bus_device_set_default_name(dev);
     189        }
     190
     191        if ((err = ddf_fun_bind(dev->fun))) {
     192                usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err));
     193                goto err_usb_dev;
     194        }
     195
     196        return EOK;
     197
     198err_usb_dev:
     199        hcd_ddf_fun_destroy(dev);
     200        return err;
     201}
     202
     203static errno_t device_remove(ddf_fun_t *fun, unsigned port)
     204{
     205        assert(fun);
     206        device_t *hub = ddf_fun_data_get(fun);
     207        assert(hub);
     208        usb_log_debug("Hub `%s' reported removal of device on port %u",
     209            ddf_fun_get_name(fun), port);
     210
     211        device_t *victim = NULL;
     212
     213        fibril_mutex_lock(&hub->guard);
     214        list_foreach(hub->devices, link, device_t, it) {
     215                if (it->port == port) {
     216                        victim = it;
     217                        break;
     218                }
     219        }
     220        fibril_mutex_unlock(&hub->guard);
     221
     222        if (!victim) {
     223                usb_log_warning("Hub '%s' tried to remove non-existent"
     224                    " device.", ddf_fun_get_name(fun));
     225                return ENOENT;
     226        }
     227
     228        assert(victim->fun);
     229        assert(victim->port == port);
     230        assert(victim->hub == hub);
     231
     232        bus_device_gone(victim);
     233        return EOK;
     234}
     235
     236/**
     237 * Gets description of the device that is calling.
     238 *
     239 * @param[in] fun Device function.
     240 * @param[out] desc Device descriptor to be filled.
    136241 * @return Error code.
    137242 */
    138 static errno_t unregister_endpoint(
    139     ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction)
    140 {
    141         assert(fun);
    142         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    143         usb_dev_t *dev = ddf_fun_data_get(fun);
    144         assert(hcd);
     243static errno_t get_device_description(ddf_fun_t *fun, usb_device_desc_t *desc)
     244{
     245        assert(fun);
     246        device_t *dev = ddf_fun_data_get(fun);
    145247        assert(dev);
    146         const usb_target_t target =
    147             {{.address = dev->address, .endpoint = endpoint}};
    148         usb_log_debug("Unregister endpoint %d:%d %s.\n",
    149             dev->address, endpoint, usb_str_direction(direction));
    150         return hcd_remove_ep(hcd, target, direction);
    151 }
    152 
    153 static errno_t reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    154 {
    155         assert(fun);
    156         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    157         usb_dev_t *dev = ddf_fun_data_get(fun);
    158         assert(hcd);
    159         assert(dev);
    160 
    161         usb_log_debug("Device %d requested default address at %s speed\n",
    162             dev->address, usb_str_speed(speed));
    163         return hcd_reserve_default_address(hcd, speed);
    164 }
    165 
    166 static errno_t release_default_address(ddf_fun_t *fun)
    167 {
    168         assert(fun);
    169         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    170         usb_dev_t *dev = ddf_fun_data_get(fun);
    171         assert(hcd);
    172         assert(dev);
    173 
    174         usb_log_debug("Device %d released default address\n", dev->address);
    175         return hcd_release_default_address(hcd);
    176 }
    177 
    178 static errno_t device_enumerate(ddf_fun_t *fun, unsigned port)
    179 {
    180         assert(fun);
    181         ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    182         usb_dev_t *dev = ddf_fun_data_get(fun);
    183         assert(ddf_dev);
    184         assert(dev);
    185         usb_log_debug("Hub %d reported a new USB device on port: %u\n",
    186             dev->address, port);
    187         return hcd_ddf_new_device(ddf_dev, dev, port);
    188 }
    189 
    190 static errno_t device_remove(ddf_fun_t *fun, unsigned port)
    191 {
    192         assert(fun);
    193         ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun);
    194         usb_dev_t *dev = ddf_fun_data_get(fun);
    195         assert(ddf_dev);
    196         assert(dev);
    197         usb_log_debug("Hub `%s' reported removal of device on port %u\n",
    198             ddf_fun_get_name(fun), port);
    199         return hcd_ddf_remove_device(ddf_dev, dev, port);
    200 }
    201 
    202 /** Gets handle of the respective device.
    203  *
    204  * @param[in] fun Device function.
    205  * @param[out] handle Place to write the handle.
    206  * @return Error code.
    207  */
    208 static errno_t get_my_device_handle(ddf_fun_t *fun, devman_handle_t *handle)
    209 {
    210         assert(fun);
    211         if (handle)
    212                 *handle = ddf_fun_get_handle(fun);
    213         return EOK;
    214 }
    215 
    216 /** Inbound communication interface function.
     248
     249        if (!desc)
     250                return EOK;
     251
     252        *desc = (usb_device_desc_t) {
     253                .address = dev->address,
     254                .depth = dev->tier,
     255                .speed = dev->speed,
     256                .handle = ddf_fun_get_handle(fun),
     257                .iface = -1,
     258        };
     259        return EOK;
     260}
     261
     262/**
     263 * Transfer issuing interface function.
     264 *
    217265 * @param fun DDF function.
    218266 * @param target Communication target.
     267 * @param dir Communication direction.
    219268 * @param setup_data Data to use in setup stage (control transfers).
    220269 * @param data Pointer to data buffer.
     
    224273 * @return Error code.
    225274 */
    226 static errno_t dev_read(ddf_fun_t *fun, usb_endpoint_t endpoint,
    227     uint64_t setup_data, uint8_t *data, size_t size,
    228     usbhc_iface_transfer_in_callback_t callback, void *arg)
    229 {
    230         assert(fun);
    231         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    232         assert(usb_dev);
     275static errno_t transfer(ddf_fun_t *fun,
     276    const usbhc_iface_transfer_request_t *ifreq,
     277    usbhc_iface_transfer_callback_t callback, void *arg)
     278{
     279        assert(fun);
     280        device_t *dev = ddf_fun_data_get(fun);
     281        assert(dev);
     282
    233283        const usb_target_t target = {{
    234             .address =  usb_dev->address,
    235             .endpoint = endpoint,
     284                .address = dev->address,
     285                .endpoint = ifreq->endpoint,
     286                .stream = ifreq->stream,
    236287        }};
    237         return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)), target,
    238             USB_DIRECTION_IN, data, size, setup_data, callback, NULL, arg,
    239             "READ");
    240 }
    241 
    242 /** Outbound communication interface function.
    243  * @param fun DDF function.
    244  * @param target Communication target.
    245  * @param setup_data Data to use in setup stage (control transfers).
    246  * @param data Pointer to data buffer.
    247  * @param size Size of the data buffer.
    248  * @param callback Function to call on communication end.
    249  * @param arg Argument passed to the callback function.
    250  * @return Error code.
    251  */
    252 static errno_t dev_write(ddf_fun_t *fun, usb_endpoint_t endpoint,
    253     uint64_t setup_data, const uint8_t *data, size_t size,
    254     usbhc_iface_transfer_out_callback_t callback, void *arg)
    255 {
    256         assert(fun);
    257         usb_dev_t *usb_dev = ddf_fun_data_get(fun);
    258         assert(usb_dev);
    259         const usb_target_t target = {{
    260             .address =  usb_dev->address,
    261             .endpoint = endpoint,
    262         }};
    263         return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)),
    264             target, USB_DIRECTION_OUT, (uint8_t*)data, size, setup_data, NULL,
    265             callback, arg, "WRITE");
     288
     289        if (!usb_target_is_valid(&target))
     290                return EINVAL;
     291
     292        if (ifreq->offset > 0 && ifreq->size == 0)
     293                return EINVAL;
     294
     295        if (ifreq->size > 0 && !dma_buffer_is_set(&ifreq->buffer))
     296                return EBADMEM;
     297
     298        if (!callback && arg)
     299                return EBADMEM;
     300
     301        const transfer_request_t request = {
     302                .target = target,
     303                .dir = ifreq->dir,
     304                .buffer = ifreq->buffer,
     305                .offset = ifreq->offset,
     306                .size = ifreq->size,
     307                .setup = ifreq->setup,
     308                .on_complete = callback,
     309                .arg = arg,
     310                .name = (ifreq->dir == USB_DIRECTION_IN) ? "READ" : "WRITE",
     311        };
     312
     313        return bus_issue_transfer(dev, &request);
    266314}
    267315
    268316/** USB device interface */
    269317static usb_iface_t usb_iface = {
    270         .get_my_device_handle = get_my_device_handle,
    271 
    272         .reserve_default_address = reserve_default_address,
    273         .release_default_address = release_default_address,
     318        .get_my_description = get_device_description,
     319};
     320
     321/** USB host controller interface */
     322static usbhc_iface_t usbhc_iface = {
     323        .default_address_reservation = default_address_reservation,
    274324
    275325        .device_enumerate = device_enumerate,
     
    279329        .unregister_endpoint = unregister_endpoint,
    280330
    281         .read = dev_read,
    282         .write = dev_write,
     331        .transfer = transfer,
    283332};
    284333
     
    286335static ddf_dev_ops_t usb_ops = {
    287336        .interfaces[USB_DEV_IFACE] = &usb_iface,
     337        .interfaces[USBHC_DEV_IFACE] = &usbhc_iface,
    288338};
    289339
    290340
    291341/* DDF HELPERS */
    292 
    293 #define GET_DEVICE_DESC(size) \
    294 { \
    295         .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \
    296             | (USB_REQUEST_TYPE_STANDARD << 5) \
    297             | USB_REQUEST_RECIPIENT_DEVICE, \
    298         .request = USB_DEVREQ_GET_DESCRIPTOR, \
    299         .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \
    300         .index = uint16_host2usb(0), \
    301         .length = uint16_host2usb(size), \
    302 };
    303 
    304 #define SET_ADDRESS(address) \
    305 { \
    306         .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \
    307             | (USB_REQUEST_TYPE_STANDARD << 5) \
    308             | USB_REQUEST_RECIPIENT_DEVICE, \
    309         .request = USB_DEVREQ_SET_ADDRESS, \
    310         .value = uint16_host2usb(address), \
    311         .index = uint16_host2usb(0), \
    312         .length = uint16_host2usb(0), \
    313 };
    314 
    315 static errno_t hcd_ddf_add_device(ddf_dev_t *parent, usb_dev_t *hub_dev,
    316     unsigned port, usb_address_t address, usb_speed_t speed, const char *name,
    317     const match_id_list_t *mids)
    318 {
    319         assert(parent);
    320 
    321         char default_name[10] = { 0 }; /* usbxyz-ss */
    322         if (!name) {
    323                 snprintf(default_name, sizeof(default_name) - 1,
    324                     "usb%u-%cs", address, usb_str_speed(speed)[0]);
    325                 name = default_name;
    326         }
    327 
    328         ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name);
    329         if (!fun)
    330                 return ENOMEM;
    331         usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t));
    332         if (!info) {
    333                 ddf_fun_destroy(fun);
    334                 return ENOMEM;
    335         }
    336         info->address = address;
    337         info->speed = speed;
    338         info->fun = fun;
    339         info->port = port;
    340         info->tt_address = hub_dev ? hub_dev->tt_address : -1;
    341         link_initialize(&info->link);
    342         list_initialize(&info->devices);
    343         fibril_mutex_initialize(&info->guard);
    344 
    345         if (hub_dev && hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed))
    346                 info->tt_address = hub_dev->address;
    347 
    348         ddf_fun_set_ops(fun, &usb_ops);
    349         list_foreach(mids->ids, link, const match_id_t, mid) {
    350                 ddf_fun_add_match_id(fun, mid->id, mid->score);
    351         }
    352 
    353         errno_t ret = ddf_fun_bind(fun);
    354         if (ret != EOK) {
    355                 ddf_fun_destroy(fun);
    356                 return ret;
    357         }
    358 
    359         if (hub_dev) {
    360                 fibril_mutex_lock(&hub_dev->guard);
    361                 list_append(&info->link, &hub_dev->devices);
    362                 fibril_mutex_unlock(&hub_dev->guard);
    363         } else {
    364                 hc_dev_t *hc_dev = dev_to_hc_dev(parent);
    365                 assert(hc_dev->root_hub == NULL);
    366                 hc_dev->root_hub = info;
    367         }
    368         return EOK;
    369 }
    370342
    371343#define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \
     
    394366        assert(l);
    395367        assert(d);
    396        
     368
    397369        if (d->vendor_id != 0) {
    398370                /* First, with release number. */
     
    401373                    d->vendor_id, d->product_id, (d->device_version >> 8),
    402374                    (d->device_version & 0xff));
    403        
     375
    404376                /* Next, without release number. */
    405377                ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x",
     
    415387
    416388        return EOK;
    417 
    418 }
    419 
    420 static errno_t hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub,
    421     unsigned port)
    422 {
    423         assert(device);
    424 
    425         hcd_t *hcd = dev_to_hcd(device);
    426         assert(hcd);
    427 
    428         hc_dev_t *hc_dev = dev_to_hc_dev(device);
    429         assert(hc_dev);
    430 
    431         fibril_mutex_lock(&hub->guard);
    432 
    433         usb_dev_t *victim = NULL;
    434 
    435         list_foreach(hub->devices, link, usb_dev_t, it) {
    436                 if (it->port == port) {
    437                         victim = it;
    438                         break;
    439                 }
    440         }
    441         if (victim) {
    442                 assert(victim->port == port);
    443                 list_remove(&victim->link);
    444                 fibril_mutex_unlock(&hub->guard);
    445                 const errno_t ret = ddf_fun_unbind(victim->fun);
    446                 if (ret == EOK) {
    447                         usb_address_t address = victim->address;
    448                         ddf_fun_destroy(victim->fun);
    449                         hcd_release_address(hcd, address);
    450                 } else {
    451                         usb_log_warning("Failed to unbind device `%s': %s\n",
    452                             ddf_fun_get_name(victim->fun), str_error(ret));
    453                 }
    454                 return EOK;
    455         }
    456         fibril_mutex_unlock(&hub->guard);
    457         return ENOENT;
    458 }
    459 
    460 static errno_t hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port)
    461 {
    462         assert(device);
    463 
    464         hcd_t *hcd = dev_to_hcd(device);
    465         assert(hcd);
    466 
    467         usb_speed_t speed = USB_SPEED_MAX;
    468 
    469         /* This checks whether the default address is reserved and gets speed */
    470         errno_t ret = usb_bus_get_speed(&hcd->bus, USB_ADDRESS_DEFAULT, &speed);
    471         if (ret != EOK) {
    472                 usb_log_error("Failed to verify speed: %s.", str_error(ret));
    473                 return ret;
    474         }
    475 
    476         usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed));
    477 
    478         static const usb_target_t default_target = {{
    479                 .address = USB_ADDRESS_DEFAULT,
    480                 .endpoint = 0,
    481         }};
    482 
    483         usb_address_t address;
    484         ret = hcd_request_address(hcd, speed, &address);
    485         if (ret != EOK) {
    486                 usb_log_error("Failed to reserve new address: %s.",
    487                     str_error(ret));
    488                 return ret;
    489         }
    490 
    491         usb_log_debug("Reserved new address: %d\n", address);
    492 
    493         const usb_target_t target = {{
    494                 .address = address,
    495                 .endpoint = 0,
    496         }};
    497 
    498         const usb_address_t tt_address = hub ? hub->tt_address : -1;
    499 
    500         /* Add default pipe on default address */
    501         usb_log_debug("Device(%d): Adding default target(0:0)\n", address);
    502         ret = hcd_add_ep(hcd,
    503             default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    504             CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1,
    505             tt_address, port);
    506         if (ret != EOK) {
    507                 usb_log_error("Device(%d): Failed to add default target: %s.",
    508                     address, str_error(ret));
    509                 hcd_release_address(hcd, address);
    510                 return ret;
    511         }
    512 
    513         /* Get max packet size for default pipe */
    514         usb_standard_device_descriptor_t desc = { 0 };
    515         const usb_device_request_setup_packet_t get_device_desc_8 =
    516             GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
    517 
    518         // TODO CALLBACKS
    519         usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
    520             address);
    521         size_t got;
    522         ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
    523             &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
    524             "read first 8 bytes of dev descriptor", &got);
    525 
    526         if (ret == EOK && got != CTRL_PIPE_MIN_PACKET_SIZE) {
    527                 ret = EOVERFLOW;
    528         }
    529 
    530         if (ret != EOK) {
    531                 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
    532                     address, str_error(ret));
    533                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    534                 hcd_release_address(hcd, address);
    535                 return ret;
    536         }
    537 
    538         /* Register EP on the new address */
    539         usb_log_debug("Device(%d): Registering control EP.", address);
    540         ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    541             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    542             ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
    543             ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
    544             tt_address, port);
    545         if (ret != EOK) {
    546                 usb_log_error("Device(%d): Failed to register EP0: %s",
    547                     address, str_error(ret));
    548                 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    549                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    550                 hcd_release_address(hcd, address);
    551                 return ret;
    552         }
    553 
    554         /* Set new address */
    555         const usb_device_request_setup_packet_t set_address =
    556             SET_ADDRESS(target.address);
    557 
    558         usb_log_debug("Device(%d): Setting USB address.", address);
    559         ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
    560             NULL, 0, *(uint64_t *)&set_address, "set address", &got);
    561 
    562         usb_log_debug("Device(%d): Removing default (0:0) EP.", address);
    563         hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH);
    564 
    565         if (ret != EOK) {
    566                 usb_log_error("Device(%d): Failed to set new address: %s.",
    567                     address, str_error(ret));
    568                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    569                 hcd_release_address(hcd, address);
    570                 return ret;
    571         }
    572 
    573         /* Get std device descriptor */
    574         const usb_device_request_setup_packet_t get_device_desc =
    575             GET_DEVICE_DESC(sizeof(desc));
    576 
    577         usb_log_debug("Device(%d): Requesting full device descriptor.",
    578             address);
    579         ret = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN,
    580             &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    581             "read device descriptor", &got);
    582         if (ret != EOK) {
    583                 usb_log_error("Device(%d): Failed to set get dev descriptor: %s",
    584                     address, str_error(ret));
    585                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    586                 hcd_release_address(hcd, target.address);
    587                 return ret;
    588         }
     389}
     390
     391device_t *hcd_ddf_fun_create(hc_device_t *hc, usb_speed_t speed)
     392{
     393        /* Create DDF function for the new device */
     394        ddf_fun_t *fun = ddf_fun_create(hc->ddf_dev, fun_inner, NULL);
     395        if (!fun)
     396                return NULL;
     397
     398        ddf_fun_set_ops(fun, &usb_ops);
     399
     400        /* Create USB device node for the new device */
     401        device_t *dev = ddf_fun_data_alloc(fun, hc->bus->device_size);
     402        if (!dev) {
     403                ddf_fun_destroy(fun);
     404                return NULL;
     405        }
     406
     407        bus_device_init(dev, hc->bus);
     408        dev->fun = fun;
     409        dev->speed = speed;
     410        return dev;
     411}
     412
     413void hcd_ddf_fun_destroy(device_t *dev)
     414{
     415        assert(dev);
     416        assert(dev->fun);
     417        ddf_fun_destroy(dev->fun);
     418}
     419
     420errno_t hcd_ddf_setup_match_ids(device_t *device, usb_standard_device_descriptor_t *desc)
     421{
     422        errno_t err;
     423        match_id_list_t mids;
     424
     425        init_match_ids(&mids);
    589426
    590427        /* Create match ids from the device descriptor */
    591         match_id_list_t mids;
    592         init_match_ids(&mids);
    593 
    594         usb_log_debug("Device(%d): Creating match IDs.", address);
    595         ret = create_match_ids(&mids, &desc);
    596         if (ret != EOK) {
    597                 usb_log_error("Device(%d): Failed to create match ids: %s",
    598                     address, str_error(ret));
    599                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    600                 hcd_release_address(hcd, target.address);
    601                 return ret;
    602         }
    603 
    604         /* Register device */
    605         usb_log_debug("Device(%d): Registering DDF device.", address);
    606         ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids);
    607         clean_match_ids(&mids);
    608         if (ret != EOK) {
    609                 usb_log_error("Device(%d): Failed to register: %s.",
    610                     address, str_error(ret));
    611                 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH);
    612                 hcd_release_address(hcd, target.address);
    613         }
    614 
    615         return ret;
    616 }
    617 
    618 /** Announce root hub to the DDF
    619  *
    620  * @param[in] device Host controller ddf device
    621  * @return Error code
    622  */
    623 errno_t hcd_ddf_setup_root_hub(ddf_dev_t *device)
    624 {
    625         assert(device);
    626         hcd_t *hcd = dev_to_hcd(device);
    627         assert(hcd);
    628 
    629         hcd_reserve_default_address(hcd, hcd->bus.max_speed);
    630         const errno_t ret = hcd_ddf_new_device(device, NULL, 0);
    631         hcd_release_default_address(hcd);
    632         return ret;
     428        usb_log_debug("Device(%d): Creating match IDs.", device->address);
     429        if ((err = create_match_ids(&mids, desc))) {
     430                return err;
     431        }
     432
     433        list_foreach(mids.ids, link, const match_id_t, mid) {
     434                ddf_fun_add_match_id(device->fun, mid->id, mid->score);
     435        }
     436
     437        return EOK;
    633438}
    634439
     
    643448 * This function does all the ddf work for hc driver.
    644449 */
    645 errno_t hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    646     size_t bw, bw_count_func_t bw_count)
     450errno_t hcd_ddf_setup_hc(ddf_dev_t *device, size_t size)
    647451{
    648452        assert(device);
    649453
    650         hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t));
     454        hc_device_t *instance = ddf_dev_data_alloc(device, size);
    651455        if (instance == NULL) {
    652                 usb_log_error("Failed to allocate HCD ddf structure.\n");
     456                usb_log_error("Failed to allocate HCD ddf structure.");
    653457                return ENOMEM;
    654458        }
    655         instance->root_hub = NULL;
    656         hcd_init(&instance->hcd, max_speed, bw, bw_count);
     459        instance->ddf_dev = device;
    657460
    658461        errno_t ret = ENOMEM;
    659462        instance->ctl_fun = ddf_fun_create(device, fun_exposed, "ctl");
    660463        if (!instance->ctl_fun) {
    661                 usb_log_error("Failed to create HCD ddf fun.\n");
     464                usb_log_error("Failed to create HCD ddf fun.");
    662465                goto err_destroy_fun;
    663466        }
     
    665468        ret = ddf_fun_bind(instance->ctl_fun);
    666469        if (ret != EOK) {
    667                 usb_log_error("Failed to bind ctl_fun: %s.\n", str_error(ret));
     470                usb_log_error("Failed to bind ctl_fun: %s.", str_error(ret));
    668471                goto err_destroy_fun;
    669472        }
     
    671474        ret = ddf_fun_add_to_category(instance->ctl_fun, USB_HC_CATEGORY);
    672475        if (ret != EOK) {
    673                 usb_log_error("Failed to add fun to category: %s.\n",
     476                usb_log_error("Failed to add fun to category: %s.",
    674477                    str_error(ret));
    675478                ddf_fun_unbind(instance->ctl_fun);
     
    686489}
    687490
    688 void hcd_ddf_clean_hc(ddf_dev_t *device)
    689 {
    690         assert(device);
    691         hc_dev_t *hc = dev_to_hc_dev(device);
    692         assert(hc);
    693         const errno_t ret = ddf_fun_unbind(hc->ctl_fun);
    694         if (ret == EOK)
    695                 ddf_fun_destroy(hc->ctl_fun);
    696 }
    697 
    698 //TODO: Cache parent session in HCD
     491void hcd_ddf_clean_hc(hc_device_t *hcd)
     492{
     493        if (ddf_fun_unbind(hcd->ctl_fun) == EOK)
     494                ddf_fun_destroy(hcd->ctl_fun);
     495}
     496
    699497/** Call the parent driver with a request to enable interrupt
    700498 *
     
    703501 * @return Error code.
    704502 */
    705 errno_t hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum)
    706 {
    707         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     503errno_t hcd_ddf_enable_interrupt(hc_device_t *hcd, int inum)
     504{
     505        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    708506        if (parent_sess == NULL)
    709507                return EIO;
     
    712510}
    713511
    714 //TODO: Cache parent session in HCD
    715 errno_t hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res)
    716 {
    717         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     512errno_t hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res)
     513{
     514        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    718515        if (parent_sess == NULL)
    719516                return EIO;
     
    726523}
    727524
    728 // TODO: move this someplace else
    729 static inline void irq_code_clean(irq_code_t *code)
    730 {
    731         if (code) {
    732                 free(code->ranges);
    733                 free(code->cmds);
    734                 code->ranges = NULL;
    735                 code->cmds = NULL;
    736                 code->rangecount = 0;
    737                 code->cmdcount = 0;
    738         }
    739 }
    740 
    741 /** Register interrupt handler
    742  *
    743  * @param[in] device Host controller DDF device
    744  * @param[in] regs Register range
    745  * @param[in] irq Interrupt number
    746  * @paran[in] handler Interrupt handler
    747  * @param[in] gen_irq_code IRQ code generator.
    748  *
    749  * @param[out] handle  IRQ capability handle on success.
    750  *
    751  * @return Error code.
    752  */
    753 errno_t hcd_ddf_setup_interrupts(ddf_dev_t *device,
    754     const hw_res_list_parsed_t *hw_res,
    755     interrupt_handler_t handler,
    756     errno_t (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
    757     cap_handle_t *handle)
    758 {
    759 
    760         assert(device);
    761         if (!handler || !gen_irq_code)
    762                 return ENOTSUP;
    763 
    764         irq_code_t irq_code = {0};
    765 
    766         int irq;
    767         errno_t ret = gen_irq_code(&irq_code, hw_res, &irq);
    768         if (ret != EOK) {
    769                 usb_log_error("Failed to generate IRQ code: %s.\n",
    770                     str_error(ret));
    771                 return ret;
    772         }
    773 
    774         /* Register handler to avoid interrupt lockup */
    775         ret = register_interrupt_handler(device, irq, handler,
    776             &irq_code, handle);
    777         irq_code_clean(&irq_code);
    778         if (ret != EOK) {
    779                 usb_log_error("Failed to register interrupt handler: %s.\n",
    780                     str_error(ret));
    781                 return ret;
    782         }
    783 
    784         /* Enable interrupts */
    785         ret = hcd_ddf_enable_interrupt(device, irq);
    786         if (ret != EOK) {
    787                 usb_log_error("Failed to register interrupt handler: %s.\n",
    788                     str_error(ret));
    789                 unregister_interrupt_handler(device, *handle);
    790         }
    791         return ret;
    792 }
    793 
    794 /** IRQ handling callback, forward status from call to diver structure.
    795  *
    796  * @param[in] dev DDF instance of the device to use.
    797  * @param[in] call Pointer to the call from kernel.
    798  */
    799 void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
    800 {
    801         assert(dev);
    802         hcd_t *hcd = dev_to_hcd(dev);
    803         if (!hcd || !hcd->ops.irq_hook) {
    804                 usb_log_error("Interrupt on not yet initialized device.\n");
    805                 return;
    806         }
    807         const uint32_t status = IPC_GET_ARG1(*call);
    808         hcd->ops.irq_hook(hcd, status);
    809 }
    810 
    811 static errno_t interrupt_polling(void *arg)
    812 {
    813         hcd_t *hcd = arg;
    814         assert(hcd);
    815         if (!hcd->ops.status_hook || !hcd->ops.irq_hook)
    816                 return ENOTSUP;
    817         uint32_t status = 0;
    818         while (hcd->ops.status_hook(hcd, &status) == EOK) {
    819                 hcd->ops.irq_hook(hcd, status);
    820                 status = 0;
    821                 /* We should wait 1 frame - 1ms here, but this polling is a
    822                  * lame crutch anyway so don't hog the system. 10ms is still
    823                  * good enough for emergency mode */
    824                 async_usleep(10000);
    825         }
    826         return EOK;
    827 }
    828 
    829 /** Initialize hc and rh DDF structures and their respective drivers.
    830  *
    831  * @param device DDF instance of the device to use
    832  * @param speed Maximum supported speed
    833  * @param bw Available bandwidth (arbitrary units)
    834  * @param bw_count Bandwidth computing function
    835  * @param irq_handler IRQ handling function
    836  * @param gen_irq_code Function to generate IRQ pseudocode
    837  *                     (it needs to return used irq number)
    838  * @param driver_init Function to initialize HC driver
    839  * @param driver_fini Function to cleanup HC driver
    840  * @return Error code
    841  *
    842  * This function does all the preparatory work for hc and rh drivers:
    843  *  - gets device's hw resources
    844  *  - attempts to enable interrupts
    845  *  - registers interrupt handler
    846  *  - calls driver specific initialization
    847  *  - registers root hub
    848  */
    849 errno_t hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver)
    850 {
    851         assert(driver);
    852         static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = {
    853             [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    854                                  .bw_count = bandwidth_count_usb11 },
    855             [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11,
    856                                  .bw_count = bandwidth_count_usb11 },
    857         };
    858 
    859         errno_t ret = EOK;
    860         const usb_speed_t speed = driver->hc_speed;
    861         if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) {
    862                 usb_log_error("Driver `%s' reported unsupported speed: %s",
    863                     driver->name, usb_str_speed(speed));
    864                 return ENOTSUP;
    865         }
    866 
    867         hw_res_list_parsed_t hw_res;
    868         ret = hcd_ddf_get_registers(device, &hw_res);
    869         if (ret != EOK) {
    870                 usb_log_error("Failed to get register memory addresses "
    871                     "for `%s': %s.\n", ddf_dev_get_name(device),
    872                     str_error(ret));
    873                 return ret;
    874         }
    875 
    876         ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count);
    877         if (ret != EOK) {
    878                 usb_log_error("Failed to setup generic HCD.\n");
    879                 hw_res_list_parsed_clean(&hw_res);
    880                 return ret;
    881         }
    882 
    883         interrupt_handler_t *irq_handler =
    884             driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    885         int irq_cap;
    886         errno_t irq_ret = hcd_ddf_setup_interrupts(device, &hw_res,
    887             irq_handler, driver->irq_code_gen, &irq_cap);
    888         bool irqs_enabled = (irq_ret == EOK);
    889         if (irqs_enabled) {
    890                 usb_log_debug("Hw interrupts enabled.\n");
    891         }
    892 
    893         if (driver->claim) {
    894                 ret = driver->claim(device);
    895                 if (ret != EOK) {
    896                         usb_log_error("Failed to claim `%s' for driver `%s'",
    897                             ddf_dev_get_name(device), driver->name);
    898                         return ret;
    899                 }
    900         }
    901 
    902 
    903         /* Init hw driver */
    904         hcd_t *hcd = dev_to_hcd(device);
    905         ret = driver->init(hcd, &hw_res, irqs_enabled);
    906         hw_res_list_parsed_clean(&hw_res);
    907         if (ret != EOK) {
    908                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    909                 goto irq_unregister;
    910         }
    911 
    912         /* Need working irq replacement to setup root hub */
    913         if (!irqs_enabled && hcd->ops.status_hook) {
    914                 hcd->polling_fibril = fibril_create(interrupt_polling, hcd);
    915                 if (hcd->polling_fibril == 0) {
    916                         usb_log_error("Failed to create polling fibril\n");
    917                         ret = ENOMEM;
    918                         goto irq_unregister;
    919                 }
    920                 fibril_add_ready(hcd->polling_fibril);
    921                 usb_log_warning("Failed to enable interrupts: %s."
    922                     " Falling back to polling.\n", str_error(irq_ret));
    923         }
    924 
    925         /*
    926          * Creating root hub registers a new USB device so HC
    927          * needs to be ready at this time.
    928          */
    929         ret = hcd_ddf_setup_root_hub(device);
    930         if (ret != EOK) {
    931                 usb_log_error("Failed to setup HC root hub: %s.\n",
    932                     str_error(ret));
    933                 driver->fini(dev_to_hcd(device));
    934 irq_unregister:
    935                 /* Unregistering non-existent should be ok */
    936                 unregister_interrupt_handler(device, irq_cap);
    937                 hcd_ddf_clean_hc(device);
    938                 return ret;
    939         }
    940 
    941         usb_log_info("Controlling new `%s' device `%s'.\n",
    942             driver->name, ddf_dev_get_name(device));
    943         return EOK;
    944 }
    945525/**
    946526 * @}
  • uspace/lib/usbhost/src/endpoint.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3435 */
    3536
    36 #include <usb/host/endpoint.h>
    37 
    3837#include <assert.h>
     38#include <atomic.h>
     39#include <mem.h>
    3940#include <stdlib.h>
    40 #include <atomic.h>
    41 
    42 /** Allocate ad initialize endpoint_t structure.
    43  * @param address USB address.
    44  * @param endpoint USB endpoint number.
    45  * @param direction Communication direction.
    46  * @param type USB transfer type.
    47  * @param speed Communication speed.
    48  * @param max_packet_size Maximum size of data packets.
    49  * @param bw Required bandwidth.
    50  * @return Pointer to initialized endpoint_t structure, NULL on failure.
    51  */
    52 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
    53     usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    54     size_t max_packet_size, unsigned packets, size_t bw,
    55     usb_address_t tt_address, unsigned tt_p)
    56 {
    57         endpoint_t *instance = malloc(sizeof(endpoint_t));
    58         if (instance) {
    59                 atomic_set(&instance->refcnt, 0);
    60                 instance->address = address;
    61                 instance->endpoint = endpoint;
    62                 instance->direction = direction;
    63                 instance->transfer_type = type;
    64                 instance->speed = speed;
    65                 instance->max_packet_size = max_packet_size;
    66                 instance->packets = packets;
    67                 instance->bandwidth = bw;
    68                 instance->toggle = 0;
    69                 instance->active = false;
    70                 instance->tt.address = tt_address;
    71                 instance->tt.port = tt_p;
    72                 instance->hc_data.data = NULL;
    73                 instance->hc_data.toggle_get = NULL;
    74                 instance->hc_data.toggle_set = NULL;
    75                 link_initialize(&instance->link);
    76                 fibril_mutex_initialize(&instance->guard);
    77                 fibril_condvar_initialize(&instance->avail);
    78         }
    79         return instance;
    80 }
    81 
    82 /** Properly dispose of endpoint_t structure.
    83  * @param instance endpoint_t structure.
    84  */
    85 void endpoint_destroy(endpoint_t *instance)
    86 {
    87         assert(instance);
    88         assert(!instance->active);
    89         assert(instance->hc_data.data == NULL);
    90         free(instance);
    91 }
    92 
    93 void endpoint_add_ref(endpoint_t *instance)
    94 {
    95         atomic_inc(&instance->refcnt);
    96 }
    97 
    98 void endpoint_del_ref(endpoint_t *instance)
    99 {
    100         if (atomic_predec(&instance->refcnt) == 0)
    101                 endpoint_destroy(instance);
    102 }
    103 
    104 /** Set device specific data and hooks.
    105  * @param instance endpoint_t structure.
    106  * @param data device specific data.
    107  * @param toggle_get Hook to call when retrieving value of toggle bit.
    108  * @param toggle_set Hook to call when setting the value of toggle bit.
    109  */
    110 void endpoint_set_hc_data(endpoint_t *instance,
    111     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    112 {
    113         assert(instance);
    114         fibril_mutex_lock(&instance->guard);
    115         instance->hc_data.data = data;
    116         instance->hc_data.toggle_get = toggle_get;
    117         instance->hc_data.toggle_set = toggle_set;
    118         fibril_mutex_unlock(&instance->guard);
    119 }
    120 
    121 /** Clear device specific data and hooks.
    122  * @param instance endpoint_t structure.
    123  * @note This function does not free memory pointed to by data pointer.
    124  */
    125 void endpoint_clear_hc_data(endpoint_t *instance)
    126 {
    127         assert(instance);
    128         endpoint_set_hc_data(instance, NULL, NULL, NULL);
    129 }
    130 
    131 /** Mark the endpoint as active and block access for further fibrils.
    132  * @param instance endpoint_t structure.
    133  */
    134 void endpoint_use(endpoint_t *instance)
    135 {
    136         assert(instance);
    137         /* Add reference for active endpoint. */
    138         endpoint_add_ref(instance);
    139         fibril_mutex_lock(&instance->guard);
    140         while (instance->active)
    141                 fibril_condvar_wait(&instance->avail, &instance->guard);
    142         instance->active = true;
    143         fibril_mutex_unlock(&instance->guard);
    144 }
    145 
    146 /** Mark the endpoint as inactive and allow access for further fibrils.
    147  * @param instance endpoint_t structure.
    148  */
    149 void endpoint_release(endpoint_t *instance)
    150 {
    151         assert(instance);
    152         fibril_mutex_lock(&instance->guard);
    153         instance->active = false;
    154         fibril_mutex_unlock(&instance->guard);
    155         fibril_condvar_signal(&instance->avail);
    156         /* Drop reference for active endpoint. */
    157         endpoint_del_ref(instance);
    158 }
    159 
    160 /** Get the value of toggle bit.
    161  * @param instance endpoint_t structure.
    162  * @note Will use provided hook.
    163  */
    164 int endpoint_toggle_get(endpoint_t *instance)
    165 {
    166         assert(instance);
    167         fibril_mutex_lock(&instance->guard);
    168         if (instance->hc_data.toggle_get)
    169                 instance->toggle =
    170                     instance->hc_data.toggle_get(instance->hc_data.data);
    171         const int ret = instance->toggle;
    172         fibril_mutex_unlock(&instance->guard);
     41#include <str_error.h>
     42#include <usb/debug.h>
     43#include <usb/descriptor.h>
     44#include <usb/host/hcd.h>
     45#include <usb/host/utility.h>
     46
     47#include "usb_transfer_batch.h"
     48#include "bus.h"
     49
     50#include "endpoint.h"
     51
     52/**
     53 * Initialize provided endpoint structure.
     54 */
     55void endpoint_init(endpoint_t *ep, device_t *dev, const usb_endpoint_descriptors_t *desc)
     56{
     57        memset(ep, 0, sizeof(endpoint_t));
     58
     59        assert(dev);
     60        ep->device = dev;
     61
     62        atomic_set(&ep->refcnt, 0);
     63        fibril_condvar_initialize(&ep->avail);
     64
     65        ep->endpoint = USB_ED_GET_EP(desc->endpoint);
     66        ep->direction = USB_ED_GET_DIR(desc->endpoint);
     67        ep->transfer_type = USB_ED_GET_TRANSFER_TYPE(desc->endpoint);
     68        ep->max_packet_size = USB_ED_GET_MPS(desc->endpoint);
     69        ep->packets_per_uframe = USB_ED_GET_ADD_OPPS(desc->endpoint) + 1;
     70
     71        /** Direction both is our construct never present in descriptors */
     72        if (ep->transfer_type == USB_TRANSFER_CONTROL)
     73                ep->direction = USB_DIRECTION_BOTH;
     74
     75        ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     76        ep->transfer_buffer_policy = DMA_POLICY_STRICT;
     77        ep->required_transfer_buffer_policy = DMA_POLICY_STRICT;
     78}
     79
     80/**
     81 * Get the bus endpoint belongs to.
     82 */
     83static inline const bus_ops_t *get_bus_ops(endpoint_t *ep)
     84{
     85        return ep->device->bus->ops;
     86}
     87
     88/**
     89 * Increase the reference count on endpoint.
     90 */
     91void endpoint_add_ref(endpoint_t *ep)
     92{
     93        atomic_inc(&ep->refcnt);
     94}
     95
     96/**
     97 * Call the desctruction callback. Default behavior is to free the memory directly.
     98 */
     99static inline void endpoint_destroy(endpoint_t *ep)
     100{
     101        const bus_ops_t *ops = get_bus_ops(ep);
     102        if (ops->endpoint_destroy) {
     103                ops->endpoint_destroy(ep);
     104        } else {
     105                assert(ep->active_batch == NULL);
     106
     107                /* Assume mostly the eps will be allocated by malloc. */
     108                free(ep);
     109        }
     110}
     111
     112/**
     113 * Decrease the reference count.
     114 */
     115void endpoint_del_ref(endpoint_t *ep)
     116{
     117        if (atomic_predec(&ep->refcnt) == 0) {
     118                endpoint_destroy(ep);
     119        }
     120}
     121
     122/**
     123 * Mark the endpoint as online. Supply a guard to be used for this endpoint
     124 * synchronization.
     125 */
     126void endpoint_set_online(endpoint_t *ep, fibril_mutex_t *guard)
     127{
     128        ep->guard = guard;
     129        ep->online = true;
     130}
     131
     132/**
     133 * Mark the endpoint as offline. All other fibrils waiting to activate this
     134 * endpoint will be interrupted.
     135 */
     136void endpoint_set_offline_locked(endpoint_t *ep)
     137{
     138        assert(ep);
     139        assert(fibril_mutex_is_locked(ep->guard));
     140
     141        ep->online = false;
     142        fibril_condvar_broadcast(&ep->avail);
     143}
     144
     145/**
     146 * Wait until a transfer finishes. Can be used even when the endpoint is
     147 * offline (and is interrupted by the endpoint going offline).
     148 */
     149void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t timeout)
     150{
     151        assert(ep);
     152        assert(fibril_mutex_is_locked(ep->guard));
     153
     154        if (ep->active_batch == NULL)
     155                return;
     156
     157        fibril_condvar_wait_timeout(&ep->avail, ep->guard, timeout);
     158}
     159
     160/**
     161 * Mark the endpoint as active and block access for further fibrils. If the
     162 * endpoint is already active, it will block on ep->avail condvar.
     163 *
     164 * Call only under endpoint guard. After you activate the endpoint and release
     165 * the guard, you must assume that particular transfer is already
     166 * finished/aborted.
     167 *
     168 * Activation and deactivation is not done by the library to maximize
     169 * performance. The HC might want to prepare some memory buffers prior to
     170 * interfering with other world.
     171 *
     172 * @param batch Transfer batch this endpoint is blocked by.
     173 */
     174int endpoint_activate_locked(endpoint_t *ep, usb_transfer_batch_t *batch)
     175{
     176        assert(ep);
     177        assert(batch);
     178        assert(batch->ep == ep);
     179        assert(ep->guard);
     180        assert(fibril_mutex_is_locked(ep->guard));
     181
     182        while (ep->online && ep->active_batch != NULL)
     183                fibril_condvar_wait(&ep->avail, ep->guard);
     184
     185        if (!ep->online)
     186                return EINTR;
     187
     188        assert(ep->active_batch == NULL);
     189        ep->active_batch = batch;
     190        return EOK;
     191}
     192
     193/**
     194 * Mark the endpoint as inactive and allow access for further fibrils.
     195 */
     196void endpoint_deactivate_locked(endpoint_t *ep)
     197{
     198        assert(ep);
     199        assert(fibril_mutex_is_locked(ep->guard));
     200
     201        ep->active_batch = NULL;
     202        fibril_condvar_signal(&ep->avail);
     203}
     204
     205/**
     206 * Initiate a transfer on an endpoint. Creates a transfer batch, checks the
     207 * bandwidth requirements and schedules the batch.
     208 *
     209 * @param endpoint Endpoint for which to send the batch
     210 */
     211errno_t endpoint_send_batch(endpoint_t *ep, const transfer_request_t *req)
     212{
     213        assert(ep);
     214        assert(req);
     215
     216        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     217                usb_log_debug("%s %d:%d %zu/%zuB, setup %#016" PRIx64, req->name,
     218                    req->target.address, req->target.endpoint,
     219                    req->size, ep->max_packet_size,
     220                    req->setup);
     221        } else {
     222                usb_log_debug("%s %d:%d %zu/%zuB", req->name,
     223                    req->target.address, req->target.endpoint,
     224                    req->size, ep->max_packet_size);
     225        }
     226
     227        device_t * const device = ep->device;
     228        if (!device) {
     229                usb_log_warning("Endpoint detached");
     230                return EAGAIN;
     231        }
     232
     233        const bus_ops_t *ops = device->bus->ops;
     234        if (!ops->batch_schedule) {
     235                usb_log_error("HCD does not implement scheduler.");
     236                return ENOTSUP;
     237        }
     238
     239        size_t size = req->size;
     240        /*
     241         * Limit transfers with reserved bandwidth to the amount reserved.
     242         * OUT transfers are rejected, IN can be just trimmed in advance.
     243         */
     244        if (size > ep->max_transfer_size &&
     245            (ep->transfer_type == USB_TRANSFER_INTERRUPT
     246             || ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)) {
     247                if (req->dir == USB_DIRECTION_OUT)
     248                        return ENOSPC;
     249                else
     250                        size = ep->max_transfer_size;
     251        }
     252
     253        /* Offline devices don't schedule transfers other than on EP0. */
     254        if (!device->online && ep->endpoint > 0)
     255                return EAGAIN;
     256
     257        usb_transfer_batch_t *batch = usb_transfer_batch_create(ep);
     258        if (!batch) {
     259                usb_log_error("Failed to create transfer batch.");
     260                return ENOMEM;
     261        }
     262
     263        batch->target = req->target;
     264        batch->setup.packed = req->setup;
     265        batch->dir = req->dir;
     266        batch->size = size;
     267        batch->offset = req->offset;
     268        batch->dma_buffer = req->buffer;
     269
     270        dma_buffer_acquire(&batch->dma_buffer);
     271
     272        if (batch->offset != 0) {
     273                usb_log_debug("A transfer with nonzero offset requested.");
     274                usb_transfer_batch_bounce(batch);
     275        }
     276
     277        if (usb_transfer_batch_bounce_required(batch))
     278                usb_transfer_batch_bounce(batch);
     279
     280        batch->on_complete = req->on_complete;
     281        batch->on_complete_data = req->arg;
     282
     283        const int ret = ops->batch_schedule(batch);
     284        if (ret != EOK) {
     285                usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));
     286                usb_transfer_batch_destroy(batch);
     287        }
     288
    173289        return ret;
    174290}
    175291
    176 /** Set the value of toggle bit.
    177  * @param instance endpoint_t structure.
    178  * @note Will use provided hook.
    179  */
    180 void endpoint_toggle_set(endpoint_t *instance, int toggle)
    181 {
    182         assert(instance);
    183         assert(toggle == 0 || toggle == 1);
    184         fibril_mutex_lock(&instance->guard);
    185         instance->toggle = toggle;
    186         if (instance->hc_data.toggle_set)
    187                 instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    188         fibril_mutex_unlock(&instance->guard);
    189 }
    190 
    191292/**
    192293 * @}
  • uspace/lib/usbhost/src/hcd.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3233/** @file
    3334 *
    34  */
    35 
    36 #include <usb/debug.h>
    37 #include <usb/request.h>
     35 * Host controller driver framework. Encapsulates DDF device of HC to an
     36 * hc_device_t, which is passed to driver implementing hc_driver_t.
     37 */
    3838
    3939#include <assert.h>
    4040#include <async.h>
     41#include <ddf/interrupt.h>
    4142#include <errno.h>
     43#include <macros.h>
     44#include <str_error.h>
     45#include <usb/debug.h>
     46#include <usb/descriptor.h>
     47#include <usb/request.h>
    4248#include <usb_iface.h>
    4349
     50#include "bus.h"
     51#include "ddf_helpers.h"
     52#include "endpoint.h"
     53#include "usb_transfer_batch.h"
     54
    4455#include "hcd.h"
    4556
    46 /** Calls ep_add_hook upon endpoint registration.
    47  * @param ep Endpoint to be registered.
    48  * @param arg hcd_t in disguise.
    49  * @return Error code.
    50  */
    51 static errno_t register_helper(endpoint_t *ep, void *arg)
    52 {
    53         hcd_t *hcd = arg;
    54         assert(ep);
     57int hc_dev_add(ddf_dev_t *);
     58int hc_dev_remove(ddf_dev_t *);
     59int hc_dev_gone(ddf_dev_t *);
     60int hc_fun_online(ddf_fun_t *);
     61int hc_fun_offline(ddf_fun_t *);
     62
     63static driver_ops_t hc_driver_ops = {
     64        .dev_add = hc_dev_add,
     65        .dev_remove = hc_dev_remove,
     66        .dev_gone = hc_dev_gone,
     67        .fun_online = hc_fun_online,
     68        .fun_offline = hc_fun_offline,
     69};
     70
     71static const hc_driver_t *hc_driver;
     72
     73/**
     74 * The main HC driver routine.
     75 */
     76int hc_driver_main(const hc_driver_t *driver)
     77{
     78        driver_t ddf_driver = {
     79                .name = driver->name,
     80                .driver_ops = &hc_driver_ops,
     81        };
     82
     83        /* Remember ops to call. */
     84        hc_driver = driver;
     85
     86        return ddf_driver_main(&ddf_driver);
     87}
     88
     89/**
     90 * IRQ handling callback. Call the bus operation.
     91 *
     92 * Currently, there is a bus ops lookup to find the interrupt handler. So far,
     93 * the mechanism is too flexible, as it allows different instances of HC to
     94 * have different IRQ handlers, disallowing us to optimize the lookup here.
     95 * TODO: Make the bus mechanism less flexible in irq handling and remove the
     96 * lookup.
     97 */
     98static void irq_handler(ipc_call_t *call, ddf_dev_t *dev)
     99{
     100        assert(dev);
     101        hc_device_t *hcd = dev_to_hcd(dev);
     102
     103        const uint32_t status = IPC_GET_ARG1(*call);
     104        hcd->bus->ops->interrupt(hcd->bus, status);
     105}
     106
     107/**
     108 * Worker for the HW interrupt replacement fibril.
     109 */
     110static errno_t interrupt_polling(void *arg)
     111{
     112        bus_t *bus = arg;
     113        assert(bus);
     114
     115        if (!bus->ops->interrupt || !bus->ops->status)
     116                return ENOTSUP;
     117
     118        uint32_t status = 0;
     119        while (bus->ops->status(bus, &status) == EOK) {
     120                bus->ops->interrupt(bus, status);
     121                status = 0;
     122                /* We should wait 1 frame - 1ms here, but this polling is a
     123                 * lame crutch anyway so don't hog the system. 10ms is still
     124                 * good enough for emergency mode */
     125                async_usleep(10000);
     126        }
     127        return EOK;
     128}
     129
     130/**
     131 * Clean the IRQ code bottom-half.
     132 */
     133static inline void irq_code_clean(irq_code_t *code)
     134{
     135        if (code) {
     136                free(code->ranges);
     137                free(code->cmds);
     138                code->ranges = NULL;
     139                code->cmds = NULL;
     140                code->rangecount = 0;
     141                code->cmdcount = 0;
     142        }
     143}
     144
     145/**
     146 * Register an interrupt handler. If there is a callback to setup the bottom half,
     147 * invoke it and register it. Register for notifications.
     148 *
     149 * If this method fails, a polling fibril is started instead.
     150 *
     151 * @param[in] hcd Host controller device.
     152 * @param[in] hw_res Resources to be used.
     153 *
     154 * @return IRQ capability handle on success.
     155 * @return Negative error code.
     156 */
     157static errno_t hcd_ddf_setup_interrupts(hc_device_t *hcd,
     158    const hw_res_list_parsed_t *hw_res)
     159{
    55160        assert(hcd);
    56         if (hcd->ops.ep_add_hook)
    57                 return hcd->ops.ep_add_hook(hcd, ep);
     161        irq_code_t irq_code = { 0 };
     162
     163        if (!hc_driver->irq_code_gen)
     164                return ENOTSUP;
     165
     166        int irq;
     167        errno_t ret;
     168        ret = hc_driver->irq_code_gen(&irq_code, hcd, hw_res, &irq);
     169        if (ret != EOK) {
     170                usb_log_error("Failed to generate IRQ code: %s.",
     171                    str_error(irq));
     172                return irq;
     173        }
     174
     175        /* Register handler to avoid interrupt lockup */
     176        int irq_cap;
     177        ret = register_interrupt_handler(hcd->ddf_dev, irq, irq_handler,
     178            &irq_code, &irq_cap);
     179        irq_code_clean(&irq_code);
     180        if (ret != EOK) {
     181                usb_log_error("Failed to register interrupt handler: %s.",
     182                    str_error(irq_cap));
     183                return irq_cap;
     184        }
     185
     186        /* Enable interrupts */
     187        ret = hcd_ddf_enable_interrupt(hcd, irq);
     188        if (ret != EOK) {
     189                usb_log_error("Failed to enable interrupts: %s.",
     190                    str_error(ret));
     191                unregister_interrupt_handler(hcd->ddf_dev, irq_cap);
     192                return ret;
     193        }
     194        return irq_cap;
     195}
     196
     197/**
     198 * Initialize HC in memory of the driver.
     199 *
     200 * This function does all the preparatory work for hc and rh drivers:
     201 *  - gets device's hw resources
     202 *  - attempts to enable interrupts
     203 *  - registers interrupt handler
     204 *  - calls driver specific initialization
     205 *  - registers root hub
     206 *
     207 * @param device DDF instance of the device to use
     208 * @return Error code
     209 */
     210errno_t hc_dev_add(ddf_dev_t *device)
     211{
     212        errno_t ret = EOK;
     213        assert(device);
     214
     215        if (!hc_driver->hc_add) {
     216                usb_log_error("Driver '%s' does not support adding devices.",
     217                    hc_driver->name);
     218                return ENOTSUP;
     219        }
     220
     221        ret = hcd_ddf_setup_hc(device, hc_driver->hc_device_size);
     222        if (ret != EOK) {
     223                usb_log_error("Failed to setup HC device.");
     224                return ret;
     225        }
     226
     227        hc_device_t *hcd = dev_to_hcd(device);
     228
     229        hw_res_list_parsed_t hw_res;
     230        ret = hcd_ddf_get_registers(hcd, &hw_res);
     231        if (ret != EOK) {
     232                usb_log_error("Failed to get register memory addresses "
     233                    "for `%s': %s.", ddf_dev_get_name(device),
     234                    str_error(ret));
     235                goto err_hcd;
     236        }
     237
     238        ret = hc_driver->hc_add(hcd, &hw_res);
     239        if (ret != EOK) {
     240                usb_log_error("Failed to init HCD.");
     241                goto err_hw_res;
     242        }
     243
     244        assert(hcd->bus);
     245
     246        /* Setup interrupts  */
     247        hcd->irq_cap = hcd_ddf_setup_interrupts(hcd, &hw_res);
     248        if (hcd->irq_cap >= 0) {
     249                usb_log_debug("Hw interrupts enabled.");
     250        }
     251
     252        /* Claim the device from BIOS */
     253        if (hc_driver->claim)
     254                ret = hc_driver->claim(hcd);
     255        if (ret != EOK) {
     256                usb_log_error("Failed to claim `%s' for `%s': %s",
     257                    ddf_dev_get_name(device), hc_driver->name, str_error(ret));
     258                goto err_irq;
     259        }
     260
     261        /* Start hw */
     262        if (hc_driver->start)
     263                ret = hc_driver->start(hcd);
     264        if (ret != EOK) {
     265                usb_log_error("Failed to start HCD: %s.", str_error(ret));
     266                goto err_irq;
     267        }
     268
     269        const bus_ops_t *ops = hcd->bus->ops;
     270
     271        /* Need working irq replacement to setup root hub */
     272        if (hcd->irq_cap < 0 && ops->status) {
     273                hcd->polling_fibril = fibril_create(interrupt_polling, hcd->bus);
     274                if (!hcd->polling_fibril) {
     275                        usb_log_error("Failed to create polling fibril");
     276                        ret = ENOMEM;
     277                        goto err_started;
     278                }
     279                fibril_add_ready(hcd->polling_fibril);
     280                usb_log_warning("Failed to enable interrupts: %s."
     281                    " Falling back to polling.", str_error(hcd->irq_cap));
     282        }
     283
     284        /*
     285         * Creating root hub registers a new USB device so HC
     286         * needs to be ready at this time.
     287         */
     288        if (hc_driver->setup_root_hub)
     289                ret = hc_driver->setup_root_hub(hcd);
     290        if (ret != EOK) {
     291                usb_log_error("Failed to setup HC root hub: %s.",
     292                    str_error(ret));
     293                goto err_polling;
     294        }
     295
     296        usb_log_info("Controlling new `%s' device `%s'.",
     297            hc_driver->name, ddf_dev_get_name(device));
    58298        return EOK;
    59 }
    60 
    61 /** Calls ep_remove_hook upon endpoint removal.
    62  * @param ep Endpoint to be unregistered.
    63  * @param arg hcd_t in disguise.
    64  */
    65 static void unregister_helper(endpoint_t *ep, void *arg)
    66 {
    67         hcd_t *hcd = arg;
    68         assert(ep);
    69         assert(hcd);
    70         if (hcd->ops.ep_remove_hook)
    71                 hcd->ops.ep_remove_hook(hcd, ep);
    72 }
    73 
    74 /** Calls ep_remove_hook upon endpoint removal. Prints warning.
    75  *  * @param ep Endpoint to be unregistered.
    76  *   * @param arg hcd_t in disguise.
    77  *    */
    78 static void unregister_helper_warn(endpoint_t *ep, void *arg)
    79 {
    80         assert(ep);
    81         usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
    82             ep->address, ep->endpoint, usb_str_direction(ep->direction));
    83         unregister_helper(ep, arg);
    84 }
    85 
    86 
    87 /** Initialize hcd_t structure.
    88  * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
    89  *
    90  * @param hcd hcd_t structure to initialize, non-null.
    91  * @param max_speed Maximum supported USB speed (full, high).
    92  * @param bandwidth Available bandwidth, passed to endpoint manager.
    93  * @param bw_count Bandwidth compute function, passed to endpoint manager.
    94  */
    95 void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
    96     bw_count_func_t bw_count)
    97 {
    98         assert(hcd);
    99         usb_bus_init(&hcd->bus, bandwidth, bw_count, max_speed);
    100 
    101         hcd_set_implementation(hcd, NULL, NULL);
    102 }
    103 
    104 errno_t hcd_request_address(hcd_t *hcd, usb_speed_t speed, usb_address_t *address)
    105 {
    106         assert(hcd);
    107         return usb_bus_request_address(&hcd->bus, address, false, speed);
    108 }
    109 
    110 errno_t hcd_release_address(hcd_t *hcd, usb_address_t address)
    111 {
    112         assert(hcd);
    113         return usb_bus_remove_address(&hcd->bus, address,
    114             unregister_helper_warn, hcd);
    115 }
    116 
    117 errno_t hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed)
    118 {
    119         assert(hcd);
    120         usb_address_t address = 0;
    121         return usb_bus_request_address(&hcd->bus, &address, true, speed);
    122 }
    123 
    124 errno_t hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir,
    125     usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
    126     size_t size, usb_address_t tt_address, unsigned tt_port)
    127 {
    128         assert(hcd);
    129         return usb_bus_add_ep(&hcd->bus, target.address,
    130             target.endpoint, dir, type, max_packet_size, packets, size,
    131             register_helper, hcd, tt_address, tt_port);
    132 }
    133 
    134 errno_t hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir)
    135 {
    136         assert(hcd);
    137         return usb_bus_remove_ep(&hcd->bus, target.address,
    138             target.endpoint, dir, unregister_helper, hcd);
    139 }
    140 
    141 
    142 typedef struct {
    143         void *original_data;
    144         usbhc_iface_transfer_out_callback_t original_callback;
    145         usb_target_t target;
    146         hcd_t *hcd;
    147 } toggle_t;
    148 
    149 static void toggle_reset_callback(errno_t retval, void *arg)
    150 {
    151         assert(arg);
    152         toggle_t *toggle = arg;
    153         if (retval == EOK) {
    154                 usb_log_debug2("Reseting toggle on %d:%d.\n",
    155                     toggle->target.address, toggle->target.endpoint);
    156                 usb_bus_reset_toggle(&toggle->hcd->bus,
    157                     toggle->target, toggle->target.endpoint == 0);
    158         }
    159 
    160         toggle->original_callback(retval, toggle->original_data);
    161 }
    162 
    163 /** Prepare generic usb_transfer_batch and schedule it.
    164  * @param hcd Host controller driver.
    165  * @param fun DDF fun
    166  * @param target address and endpoint number.
    167  * @param setup_data Data to use in setup stage (Control communication type)
    168  * @param in Callback for device to host communication.
    169  * @param out Callback for host to device communication.
    170  * @param arg Callback parameter.
    171  * @param name Communication identifier (for nicer output).
    172  * @return Error code.
    173  */
    174 errno_t hcd_send_batch(
    175     hcd_t *hcd, usb_target_t target, usb_direction_t direction,
    176     void *data, size_t size, uint64_t setup_data,
    177     usbhc_iface_transfer_in_callback_t in,
    178     usbhc_iface_transfer_out_callback_t out, void *arg, const char* name)
    179 {
    180         assert(hcd);
    181 
    182         endpoint_t *ep = usb_bus_find_ep(&hcd->bus,
    183             target.address, target.endpoint, direction);
    184         if (ep == NULL) {
    185                 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
    186                     target.address, target.endpoint, name);
    187                 return ENOENT;
    188         }
    189 
    190         usb_log_debug2("%s %d:%d %zu(%zu).\n",
    191             name, target.address, target.endpoint, size, ep->max_packet_size);
    192 
    193         const size_t bw = bandwidth_count_usb11(
    194             ep->speed, ep->transfer_type, size, ep->max_packet_size);
    195         /* Check if we have enough bandwidth reserved */
    196         if (ep->bandwidth < bw) {
    197                 usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    198                     "but only %zu is reserved.\n",
    199                     ep->address, ep->endpoint, name, bw, ep->bandwidth);
    200                 return ENOSPC;
    201         }
    202         if (!hcd->ops.schedule) {
    203                 usb_log_error("HCD does not implement scheduler.\n");
    204                 return ENOTSUP;
    205         }
    206 
    207         /* Check for commands that reset toggle bit */
    208         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    209                 const int reset_toggle = usb_request_needs_toggle_reset(
    210                     (usb_device_request_setup_packet_t *) &setup_data);
    211                 if (reset_toggle >= 0) {
    212                         assert(out);
    213                         toggle_t *toggle = malloc(sizeof(toggle_t));
    214                         if (!toggle)
    215                                 return ENOMEM;
    216                         toggle->target.address = target.address;
    217                         toggle->target.endpoint = reset_toggle;
    218                         toggle->original_callback = out;
    219                         toggle->original_data = arg;
    220                         toggle->hcd = hcd;
    221 
    222                         arg = toggle;
    223                         out = toggle_reset_callback;
    224                 }
    225         }
    226 
    227         usb_transfer_batch_t *batch = usb_transfer_batch_create(
    228             ep, data, size, setup_data, in, out, arg);
    229         if (!batch) {
    230                 usb_log_error("Failed to create transfer batch.\n");
    231                 return ENOMEM;
    232         }
    233 
    234         const errno_t ret = hcd->ops.schedule(hcd, batch);
    235         if (ret != EOK)
    236                 usb_transfer_batch_destroy(batch);
    237 
    238         /* Drop our own reference to ep. */
    239         endpoint_del_ref(ep);
    240 
     299
     300err_polling:
     301        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     302        //
     303err_started:
     304        if (hc_driver->stop)
     305                hc_driver->stop(hcd);
     306err_irq:
     307        unregister_interrupt_handler(device, hcd->irq_cap);
     308        if (hc_driver->hc_remove)
     309                hc_driver->hc_remove(hcd);
     310err_hw_res:
     311        hw_res_list_parsed_clean(&hw_res);
     312err_hcd:
     313        hcd_ddf_clean_hc(hcd);
    241314        return ret;
    242315}
    243316
    244 typedef struct {
    245         volatile unsigned done;
    246         errno_t ret;
    247         size_t size;
    248 } sync_data_t;
    249 
    250 static void transfer_in_cb(errno_t ret, size_t size, void* data)
    251 {
    252         sync_data_t *d = data;
    253         assert(d);
    254         d->ret = ret;
    255         d->done = 1;
    256         d->size = size;
    257 }
    258 
    259 static void transfer_out_cb(errno_t ret, void* data)
    260 {
    261         sync_data_t *d = data;
    262         assert(data);
    263         d->ret = ret;
    264         d->done = 1;
    265 }
    266 
    267 /** this is really ugly version of sync usb communication */
    268 errno_t hcd_send_batch_sync(
    269     hcd_t *hcd, usb_target_t target, usb_direction_t dir,
    270     void *data, size_t size, uint64_t setup_data, const char* name, size_t *out_size)
    271 {
    272         assert(hcd);
    273         sync_data_t sd = { .done = 0, .ret = EBUSY, .size = size };
    274 
    275         const errno_t ret = hcd_send_batch(hcd, target, dir, data, size, setup_data,
    276             dir == USB_DIRECTION_IN ? transfer_in_cb : NULL,
    277             dir == USB_DIRECTION_OUT ? transfer_out_cb : NULL, &sd, name);
    278         if (ret != EOK)
    279                 return ret;
    280 
    281         while (!sd.done) {
    282                 async_usleep(1000);
    283         }
    284 
    285         if (sd.ret == EOK)
    286                 *out_size = sd.size;
    287         return sd.ret;
     317errno_t hc_dev_remove(ddf_dev_t *dev)
     318{
     319        errno_t err;
     320        hc_device_t *hcd = dev_to_hcd(dev);
     321
     322        if (hc_driver->stop)
     323                if ((err = hc_driver->stop(hcd)))
     324                        return err;
     325
     326        unregister_interrupt_handler(dev, hcd->irq_cap);
     327
     328        if (hc_driver->hc_remove)
     329                if ((err = hc_driver->hc_remove(hcd)))
     330                        return err;
     331
     332        hcd_ddf_clean_hc(hcd);
     333
     334        // TODO probably not complete
     335
     336        return EOK;
     337}
     338
     339errno_t hc_dev_gone(ddf_dev_t *dev)
     340{
     341        errno_t err = ENOTSUP;
     342        hc_device_t *hcd = dev_to_hcd(dev);
     343
     344        if (hc_driver->hc_gone)
     345                err = hc_driver->hc_gone(hcd);
     346
     347        hcd_ddf_clean_hc(hcd);
     348
     349        return err;
     350}
     351
     352errno_t hc_fun_online(ddf_fun_t *fun)
     353{
     354        assert(fun);
     355
     356        device_t *dev = ddf_fun_data_get(fun);
     357        assert(dev);
     358
     359        usb_log_info("Device(%d): Requested to be brought online.", dev->address);
     360        return bus_device_online(dev);
     361}
     362
     363int hc_fun_offline(ddf_fun_t *fun)
     364{
     365        assert(fun);
     366
     367        device_t *dev = ddf_fun_data_get(fun);
     368        assert(dev);
     369
     370        usb_log_info("Device(%d): Requested to be taken offline.", dev->address);
     371        return bus_device_offline(dev);
    288372}
    289373
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3334 */
    3435
    35 #include <usb/host/usb_transfer_batch.h>
    36 #include <usb/debug.h>
    37 
    3836#include <assert.h>
    3937#include <errno.h>
    40 #include <macros.h>
    41 #include <mem.h>
    4238#include <stdlib.h>
    43 #include <usbhc_iface.h>
    44 
    45 /** Allocate and initialize usb_transfer_batch structure.
    46  * @param ep endpoint used by the transfer batch.
    47  * @param buffer data to send/recieve.
    48  * @param buffer_size Size of data buffer.
    49  * @param setup_buffer Data to send in SETUP stage of control transfer.
    50  * @param func_in callback on IN transfer completion.
    51  * @param func_out callback on OUT transfer completion.
    52  * @param fun DDF function (passed to callback function).
    53  * @param arg Argument to pass to the callback function.
    54  * @param private_data driver specific per batch data.
    55  * @param private_data_dtor Function to properly destroy private_data.
    56  * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure.
    57  */
    58 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep, char *buffer,
    59     size_t buffer_size,
    60     uint64_t setup_buffer,
    61     usbhc_iface_transfer_in_callback_t func_in,
    62     usbhc_iface_transfer_out_callback_t func_out,
    63     void *arg)
    64 {
    65         if (func_in == NULL && func_out == NULL)
    66                 return NULL;
    67         if (func_in != NULL && func_out != NULL)
    68                 return NULL;
    69 
    70         usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    71         if (instance) {
    72                 instance->ep = ep;
    73                 instance->callback_in = func_in;
    74                 instance->callback_out = func_out;
    75                 instance->arg = arg;
    76                 instance->buffer = buffer;
    77                 instance->buffer_size = buffer_size;
    78                 instance->setup_size = 0;
    79                 instance->transfered_size = 0;
    80                 instance->error = EOK;
    81                 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) {
    82                         memcpy(instance->setup_buffer, &setup_buffer,
    83                             USB_SETUP_PACKET_SIZE);
    84                         instance->setup_size = USB_SETUP_PACKET_SIZE;
     39#include <str_error.h>
     40#include <usb/debug.h>
     41
     42#include "endpoint.h"
     43#include "bus.h"
     44
     45#include "usb_transfer_batch.h"
     46
     47/**
     48 * Create a batch on a given endpoint.
     49 *
     50 * If the bus callback is not defined, it just creates a default batch.
     51 */
     52usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep)
     53{
     54        assert(ep);
     55
     56        bus_t *bus = endpoint_get_bus(ep);
     57
     58        if (!bus->ops->batch_create) {
     59                usb_transfer_batch_t *batch = calloc(1, sizeof(usb_transfer_batch_t));
     60                if (!batch)
     61                        return NULL;
     62                usb_transfer_batch_init(batch, ep);
     63                return batch;
     64        }
     65
     66        return bus->ops->batch_create(ep);
     67}
     68
     69/**
     70 * Initialize given batch structure.
     71 */
     72void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep)
     73{
     74        assert(ep);
     75        /* Batch reference */
     76        endpoint_add_ref(ep);
     77        batch->ep = ep;
     78}
     79
     80/**
     81 * Destroy the batch. If there's no bus callback, just free it.
     82 */
     83void usb_transfer_batch_destroy(usb_transfer_batch_t *batch)
     84{
     85        assert(batch);
     86        assert(batch->ep);
     87
     88        bus_t *bus = endpoint_get_bus(batch->ep);
     89        endpoint_t *ep = batch->ep;
     90
     91        if (bus->ops) {
     92                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.",
     93                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
     94                bus->ops->batch_destroy(batch);
     95        }
     96        else {
     97                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.",
     98                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
     99                free(batch);
     100        }
     101
     102        /* Batch reference */
     103        endpoint_del_ref(ep);
     104}
     105
     106bool usb_transfer_batch_bounce_required(usb_transfer_batch_t *batch)
     107{
     108        if (!batch->size)
     109                return false;
     110
     111        unsigned flags = batch->dma_buffer.policy & DMA_POLICY_FLAGS_MASK;
     112        unsigned required_flags =
     113            batch->ep->required_transfer_buffer_policy & DMA_POLICY_FLAGS_MASK;
     114
     115        if (required_flags & ~flags)
     116                return true;
     117
     118        size_t chunk_mask = dma_policy_chunk_mask(batch->dma_buffer.policy);
     119        size_t required_chunk_mask =
     120             dma_policy_chunk_mask(batch->ep->required_transfer_buffer_policy);
     121
     122        /* If the chunks are at least as large as required, we're good */
     123        if ((required_chunk_mask & ~chunk_mask) == 0)
     124                return false;
     125
     126        size_t start_chunk = batch->offset & ~chunk_mask;
     127        size_t end_chunk = (batch->offset + batch->size - 1) & ~chunk_mask;
     128
     129        /* The requested area crosses a chunk boundary */
     130        if (start_chunk != end_chunk)
     131                return true;
     132
     133        return false;
     134}
     135
     136errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *batch)
     137{
     138        assert(batch);
     139        assert(!batch->is_bounced);
     140
     141        dma_buffer_release(&batch->dma_buffer);
     142
     143        batch->original_buffer = batch->dma_buffer.virt + batch->offset;
     144
     145        usb_log_debug("Batch(%p): Buffer cannot be used directly, "
     146            "falling back to bounce buffer!", batch);
     147
     148        const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
     149            batch->size, batch->ep->transfer_buffer_policy);
     150        if (err)
     151                return err;
     152
     153        /* Copy the data out */
     154        if (batch->dir == USB_DIRECTION_OUT)
     155                memcpy(batch->dma_buffer.virt,
     156                    batch->original_buffer,
     157                    batch->size);
     158
     159        batch->is_bounced = true;
     160        batch->offset = 0;
     161
     162        return err;
     163}
     164
     165/**
     166 * Finish a transfer batch: call handler, destroy batch, release endpoint.
     167 *
     168 * Call only after the batch have been scheduled && completed!
     169 */
     170void usb_transfer_batch_finish(usb_transfer_batch_t *batch)
     171{
     172        assert(batch);
     173        assert(batch->ep);
     174
     175        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.",
     176            batch, USB_TRANSFER_BATCH_ARGS(*batch));
     177
     178        if (batch->error == EOK && batch->size > 0) {
     179                if (batch->is_bounced) {
     180                        /* We we're forced to use bounce buffer, copy it back */
     181                        if (batch->dir == USB_DIRECTION_IN)
     182                        memcpy(batch->original_buffer,
     183                            batch->dma_buffer.virt,
     184                            batch->transferred_size);
     185
     186                        dma_buffer_free(&batch->dma_buffer);
    85187                }
    86                 if (instance->ep)
    87                         endpoint_use(instance->ep);
    88         }
    89         return instance;
    90 }
    91 
    92 /** Correctly dispose all used data structures.
    93  *
    94  * @param[in] instance Batch structure to use.
    95  */
    96 void usb_transfer_batch_destroy(usb_transfer_batch_t *instance)
    97 {
    98         if (!instance)
    99                 return;
    100         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    101             instance, USB_TRANSFER_BATCH_ARGS(*instance));
    102         if (instance->ep) {
    103                 endpoint_release(instance->ep);
    104         }
    105         free(instance);
    106 }
    107 
    108 /** Prepare data and call the right callback.
    109  *
    110  * @param[in] instance Batch structure to use.
    111  * @param[in] data Data to copy to the output buffer.
    112  * @param[in] size Size of @p data.
    113  * @param[in] error Error value to use.
    114  */
    115 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    116     const void *data, size_t size, errno_t error)
    117 {
    118         assert(instance);
    119         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n",
    120             instance, USB_TRANSFER_BATCH_ARGS(*instance));
    121 
    122         /* NOTE: Only one of these pointers should be set. */
    123         if (instance->callback_out) {
    124                 instance->callback_out(error, instance->arg);
    125         }
    126 
    127         if (instance->callback_in) {
    128                 /* We care about the data and there are some to copy */
    129                 const size_t safe_size = min(size, instance->buffer_size);
    130                 if (data) {
    131                         memcpy(instance->buffer, data, safe_size);
     188                else {
     189                        dma_buffer_release(&batch->dma_buffer);
    132190                }
    133                 instance->callback_in(error, safe_size, instance->arg);
    134         }
    135 }
     191        }
     192
     193        if (batch->on_complete) {
     194                const int err = batch->on_complete(batch->on_complete_data, batch->error, batch->transferred_size);
     195                if (err)
     196                        usb_log_warning("Batch %p failed to complete: %s",
     197                            batch, str_error(err));
     198        }
     199
     200        usb_transfer_batch_destroy(batch);
     201}
     202
    136203/**
    137204 * @}
  • uspace/lib/usbvirt/src/ctrltransfer.c

    rf5e5f73 rdf6ded8  
    6868                }
    6969
    70                 usb_log_debug("Control transfer: %s(%s)\n", handler->name,
     70                usb_log_debug("Control transfer: %s(%s)", handler->name,
    7171                    usb_debug_str_buffer((uint8_t*) setup, sizeof(*setup), 0));
    7272                errno_t rc = handler->callback(dev, setup, data, data_sent_size);
  • uspace/lib/usbvirt/src/ipc_hc.c

    rf5e5f73 rdf6ded8  
    5050 * @param data_buffer Data buffer (DATA stage of control transfer).
    5151 * @param data_buffer_size Size of data buffer in bytes.
    52  * @param data_transfered_size Number of actually transferred bytes.
     52 * @param data_transferred_size Number of actually transferred bytes.
    5353 *
    5454 * @return Error code.
     
    5757errno_t usbvirt_ipc_send_control_read(async_sess_t *sess, void *setup_buffer,
    5858    size_t setup_buffer_size, void *data_buffer, size_t data_buffer_size,
    59     size_t *data_transfered_size)
     59    size_t *data_transferred_size)
    6060{
    6161        if (!sess)
     
    7777        }
    7878       
    79         errno_t rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     79        errno_t rc = async_data_write_start(exch, setup_buffer,
     80            setup_buffer_size);
    8081        if (rc != EOK) {
    8182                async_exchange_end(exch);
     
    8586       
    8687        ipc_call_t data_request_call;
    87         aid_t data_request = async_data_read(exch, data_buffer, data_buffer_size,
    88             &data_request_call);
     88        aid_t data_request = async_data_read(exch, data_buffer,
     89            data_buffer_size, &data_request_call);
    8990       
    9091        async_exchange_end(exch);
     
    111112                return (errno_t) opening_request_rc;
    112113       
    113         if (data_transfered_size != NULL)
    114                 *data_transfered_size = IPC_GET_ARG2(data_request_call);
     114        if (data_transferred_size != NULL)
     115                *data_transferred_size = IPC_GET_ARG2(data_request_call);
    115116       
    116117        return EOK;
     
    150151        }
    151152       
    152         errno_t rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
     153        errno_t rc = async_data_write_start(exch, setup_buffer,
     154            setup_buffer_size);
    153155        if (rc != EOK) {
    154156                async_exchange_end(exch);
     
    158160       
    159161        if (data_buffer_size > 0) {
    160                 rc = async_data_write_start(exch, data_buffer, data_buffer_size);
     162                rc = async_data_write_start(exch, data_buffer,
     163                    data_buffer_size);
    161164                if (rc != EOK) {
    162165                        async_exchange_end(exch);
  • uspace/lib/usbvirt/src/transfer.c

    rf5e5f73 rdf6ded8  
    7979
    8080        if (rc == EFORWARD) {
    81                 usb_log_warning("Control transfer {%s (%s)} not handled.\n",
     81                usb_log_warning("Control transfer {%s (%s)} not handled.",
    8282                    usb_debug_str_buffer(setup, setup_size, 10),
    8383                    setup_packet->request_type & 0x80
     
    119119 * @return Error code.
    120120 */
    121 errno_t usbvirt_control_read(usbvirt_device_t *dev, const void *setup, size_t setup_size,
     121errno_t usbvirt_control_read(usbvirt_device_t *dev,
     122    const void *setup, size_t setup_size,
    122123    void *data, size_t data_size, size_t *data_size_sent)
    123124{
Note: See TracChangeset for help on using the changeset viewer.