Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fd07e526 in mainline


Ignore:
Timestamp:
2011-09-16T14:50:20Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
432a269, d1e18573
Parents:
47fecbb (diff), 82a31261 (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.
Message:

Merge USB changes from bzr://krabicka.net/orome/helenos/usb/

  • Move common HC code from uhci/ohci drivers to libusbhost
  • Rewrite USB HC interface to have common read/write functions for all transfer types.
  • Restructure hc drivers to avoid some hooks and void* casts
  • Cleanup the code and remove unnecessary mallocs.
Location:
uspace
Files:
6 added
8 deleted
42 edited
6 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/hc_iface.c

    r47fecbb rfd07e526  
    145145}
    146146
    147 /** Schedule interrupt out transfer.
    148  *
    149  * The callback is supposed to be called once the transfer (on the wire) is
    150  * complete regardless of the outcome.
    151  * However, the callback could be called only when this function returns
    152  * with success status (i.e. returns EOK).
    153  *
    154  * @param[in] fun Device function the action was invoked on.
    155  * @param[in] target Target pipe (address and endpoint number) specification.
    156  * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    157  *      by the caller).
    158  * @param[in] size Size of the @p data buffer in bytes.
    159  * @param[in] callback Callback to be issued once the transfer is complete.
    160  * @param[in] arg Pass-through argument to the callback.
    161  * @return Error code.
    162  */
    163 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    164     void *data, size_t size,
    165     usbhc_iface_transfer_out_callback_t callback, void *arg)
    166 {
    167         UNSUPPORTED("interrupt_out");
    168 
    169         return ENOTSUP;
    170 }
    171 
    172 /** Schedule interrupt in transfer.
    173  *
    174  * The callback is supposed to be called once the transfer (on the wire) is
    175  * complete regardless of the outcome.
    176  * However, the callback could be called only when this function returns
    177  * with success status (i.e. returns EOK).
    178  *
    179  * @param[in] fun Device function the action was invoked on.
    180  * @param[in] target Target pipe (address and endpoint number) specification.
    181  * @param[in] data Buffer where to store the data (in USB endianess,
    182  *      allocated and deallocated by the caller).
    183  * @param[in] size Size of the @p data buffer in bytes.
    184  * @param[in] callback Callback to be issued once the transfer is complete.
    185  * @param[in] arg Pass-through argument to the callback.
    186  * @return Error code.
    187  */
    188 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    189     void *data, size_t size,
    190     usbhc_iface_transfer_in_callback_t callback, void *arg)
    191 {
    192         UNSUPPORTED("interrupt_in");
    193 
    194         return ENOTSUP;
    195 }
    196 
    197 /** Schedule bulk out transfer.
    198  *
    199  * The callback is supposed to be called once the transfer (on the wire) is
    200  * complete regardless of the outcome.
    201  * However, the callback could be called only when this function returns
    202  * with success status (i.e. returns EOK).
    203  *
    204  * @param[in] fun Device function the action was invoked on.
    205  * @param[in] target Target pipe (address and endpoint number) specification.
    206  * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    207  *      by the caller).
    208  * @param[in] size Size of the @p data buffer in bytes.
    209  * @param[in] callback Callback to be issued once the transfer is complete.
    210  * @param[in] arg Pass-through argument to the callback.
    211  * @return Error code.
    212  */
    213 static int bulk_out(ddf_fun_t *fun, usb_target_t target,
    214     void *data, size_t size,
    215     usbhc_iface_transfer_out_callback_t callback, void *arg)
    216 {
    217         UNSUPPORTED("bulk_out");
    218 
    219         return ENOTSUP;
    220 }
    221 
    222 /** Schedule bulk in transfer.
    223  *
    224  * The callback is supposed to be called once the transfer (on the wire) is
    225  * complete regardless of the outcome.
    226  * However, the callback could be called only when this function returns
    227  * with success status (i.e. returns EOK).
    228  *
    229  * @param[in] fun Device function the action was invoked on.
    230  * @param[in] target Target pipe (address and endpoint number) specification.
    231  * @param[in] data Buffer where to store the data (in USB endianess,
    232  *      allocated and deallocated by the caller).
    233  * @param[in] size Size of the @p data buffer in bytes.
    234  * @param[in] callback Callback to be issued once the transfer is complete.
    235  * @param[in] arg Pass-through argument to the callback.
    236  * @return Error code.
    237  */
    238 static int bulk_in(ddf_fun_t *fun, usb_target_t target,
    239     void *data, size_t size,
    240     usbhc_iface_transfer_in_callback_t callback, void *arg)
    241 {
    242         UNSUPPORTED("bulk_in");
    243 
    244         return ENOTSUP;
    245 }
    246 
    247 /** Schedule control write transfer.
    248  *
    249  * The callback is supposed to be called once the transfer (on the wire) is
    250  * complete regardless of the outcome.
    251  * However, the callback could be called only when this function returns
    252  * with success status (i.e. returns EOK).
    253  *
    254  * @param[in] fun Device function the action was invoked on.
    255  * @param[in] target Target pipe (address and endpoint number) specification.
    256  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    257  *      and deallocated by the caller).
    258  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
    259  * @param[in] data_buffer Data buffer (in USB endianess, allocated and
    260  *      deallocated by the caller).
    261  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
    262  * @param[in] callback Callback to be issued once the transfer is complete.
    263  * @param[in] arg Pass-through argument to the callback.
    264  * @return Error code.
    265  */
    266 static int control_write(ddf_fun_t *fun, usb_target_t target,
    267     void *setup_packet, size_t setup_packet_size,
    268     void *data_buffer, size_t data_buffer_size,
    269     usbhc_iface_transfer_out_callback_t callback, void *arg)
    270 {
    271         UNSUPPORTED("control_write");
    272 
    273         return ENOTSUP;
    274 }
    275 
    276 /** Schedule control read transfer.
    277  *
    278  * The callback is supposed to be called once the transfer (on the wire) is
    279  * complete regardless of the outcome.
    280  * However, the callback could be called only when this function returns
    281  * with success status (i.e. returns EOK).
    282  *
    283  * @param[in] fun Device function the action was invoked on.
    284  * @param[in] target Target pipe (address and endpoint number) specification.
    285  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    286  *      and deallocated by the caller).
    287  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
    288  * @param[in] data_buffer Buffer where to store the data (in USB endianess,
    289  *      allocated and deallocated by the caller).
    290  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
    291  * @param[in] callback Callback to be issued once the transfer is complete.
    292  * @param[in] arg Pass-through argument to the callback.
    293  * @return Error code.
    294  */
    295 static int control_read(ddf_fun_t *fun, usb_target_t target,
    296     void *setup_packet, size_t setup_packet_size,
    297     void *data_buffer, size_t data_buffer_size,
    298     usbhc_iface_transfer_in_callback_t callback, void *arg)
    299 {
    300         UNSUPPORTED("control_read");
    301 
    302         return ENOTSUP;
    303 }
    304 
    305147/** Host controller interface implementation for EHCI. */
    306148usbhc_iface_t ehci_hc_iface = {
     
    312154        .register_endpoint = register_endpoint,
    313155        .unregister_endpoint = unregister_endpoint,
    314 
    315         .interrupt_out = interrupt_out,
    316         .interrupt_in = interrupt_in,
    317 
    318         .bulk_out = bulk_out,
    319         .bulk_in = bulk_in,
    320 
    321         .control_write = control_write,
    322         .control_read = control_read
    323156};
    324157
  • uspace/drv/bus/usb/ohci/Makefile

    r47fecbb rfd07e526  
    4444
    4545SOURCES = \
    46         batch.c \
    4746        endpoint_list.c \
    4847        hc.c \
    49         hcd_endpoint.c \
    50         iface.c \
    5148        main.c \
    5249        ohci.c \
     50        ohci_batch.c \
     51        ohci_endpoint.c \
    5352        pci.c \
    5453        root_hub.c \
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    r47fecbb rfd07e526  
    8787 * The endpoint is added to the end of the list and queue.
    8888 */
    89 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     89void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep)
    9090{
    9191        assert(instance);
    92         assert(hcd_ep);
    93         usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
    94             instance->name, hcd_ep);
     92        assert(ep);
     93        usb_log_debug2("Queue %s: Adding endpoint(%p).\n", instance->name, ep);
    9594
    9695        fibril_mutex_lock(&instance->guard);
     
    103102        } else {
    104103                /* There are active EDs, get the last one */
    105                 hcd_endpoint_t *last = list_get_instance(
    106                     list_last(&instance->endpoint_list), hcd_endpoint_t, link);
     104                ohci_endpoint_t *last = list_get_instance(
     105                    list_last(&instance->endpoint_list), ohci_endpoint_t, link);
    107106                last_ed = last->ed;
    108107        }
    109108        /* Keep link */
    110         hcd_ep->ed->next = last_ed->next;
     109        ep->ed->next = last_ed->next;
    111110        /* Make sure ED is written to the memory */
    112111        write_barrier();
    113112
    114113        /* Add ed to the hw queue */
    115         ed_append_ed(last_ed, hcd_ep->ed);
     114        ed_append_ed(last_ed, ep->ed);
    116115        /* Make sure ED is updated */
    117116        write_barrier();
    118117
    119118        /* Add to the sw list */
    120         list_append(&hcd_ep->link, &instance->endpoint_list);
     119        list_append(&ep->link, &instance->endpoint_list);
    121120
    122         hcd_endpoint_t *first = list_get_instance(
    123             list_first(&instance->endpoint_list), hcd_endpoint_t, link);
     121        ohci_endpoint_t *first = list_get_instance(
     122            list_first(&instance->endpoint_list), ohci_endpoint_t, link);
    124123        usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
    125                 hcd_ep, instance->name, first, first->ed);
     124                ep, instance->name, first, first->ed);
    126125        if (last_ed == instance->list_head) {
    127126                usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
     
    138137 * @param[in] endpoint Endpoint to remove.
    139138 */
    140 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     139void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep)
    141140{
    142141        assert(instance);
    143142        assert(instance->list_head);
    144         assert(hcd_ep);
    145         assert(hcd_ep->ed);
     143        assert(ep);
     144        assert(ep->ed);
    146145
    147146        fibril_mutex_lock(&instance->guard);
    148147
    149         usb_log_debug2(
    150             "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
     148        usb_log_debug2("Queue %s: removing endpoint(%p).\n", instance->name, ep);
    151149
    152150        const char *qpos = NULL;
    153151        ed_t *prev_ed;
    154152        /* Remove from the hardware queue */
    155         if (list_first(&instance->endpoint_list) == &hcd_ep->link) {
     153        if (list_first(&instance->endpoint_list) == &ep->link) {
    156154                /* I'm the first one here */
    157155                prev_ed = instance->list_head;
    158156                qpos = "FIRST";
    159157        } else {
    160                 hcd_endpoint_t *prev =
    161                     list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
     158                ohci_endpoint_t *prev =
     159                    list_get_instance(ep->link.prev, ohci_endpoint_t, link);
    162160                prev_ed = prev->ed;
    163161                qpos = "NOT FIRST";
    164162        }
    165         assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
    166         prev_ed->next = hcd_ep->ed->next;
     163        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(ep->ed));
     164        prev_ed->next = ep->ed->next;
    167165        /* Make sure ED is updated */
    168166        write_barrier();
    169167
    170168        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
    171             hcd_ep, qpos, instance->name, hcd_ep->ed->next);
     169            ep, qpos, instance->name, ep->ed->next);
    172170
    173171        /* Remove from the endpoint list */
    174         list_remove(&hcd_ep->link);
     172        list_remove(&ep->link);
    175173        fibril_mutex_unlock(&instance->guard);
    176174}
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r47fecbb rfd07e526  
    3737#include <fibril_synch.h>
    3838
    39 #include "hcd_endpoint.h"
     39#include "ohci_endpoint.h"
    4040#include "hw_struct/endpoint_descriptor.h"
    4141#include "utils/malloc32.h"
     
    6969int endpoint_list_init(endpoint_list_t *instance, const char *name);
    7070void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
    71 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    72 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
     71void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
     72void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
    7373#endif
    7474/**
  • uspace/drv/bus/usb/ohci/hc.c

    r47fecbb rfd07e526  
    4242
    4343#include "hc.h"
    44 #include "hcd_endpoint.h"
     44#include "ohci_endpoint.h"
    4545
    4646#define OHCI_USED_INTERRUPTS \
     
    6161static int hc_init_memory(hc_t *instance);
    6262static int interrupt_emulator(hc_t *instance);
    63 
     63static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    6464/*----------------------------------------------------------------------------*/
    6565/** Get number of commands used in IRQ code.
     
    128128
    129129        const usb_address_t hub_address =
    130             device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
     130            usb_device_manager_get_free_address(
     131                &instance->generic.dev_manager, USB_SPEED_FULL);
    131132        if (hub_address <= 0) {
    132133                usb_log_error("Failed to get OHCI root hub address: %s\n",
     
    135136        }
    136137        instance->rh.address = hub_address;
    137         usb_device_keeper_bind(
    138             &instance->manager, hub_address, hub_fun->handle);
    139 
    140 #define CHECK_RET_RELEASE(ret, message...) \
     138        usb_device_manager_bind(
     139            &instance->generic.dev_manager, hub_address, hub_fun->handle);
     140
     141#define CHECK_RET_UNREG_RETURN(ret, message...) \
    141142if (ret != EOK) { \
    142143        usb_log_error(message); \
    143         hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
    144         usb_device_keeper_release(&instance->manager, hub_address); \
     144        usb_endpoint_manager_unregister_ep( \
     145            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\
     146        usb_device_manager_release( \
     147            &instance->generic.dev_manager, hub_address); \
    145148        return ret; \
    146149} else (void)0
    147 
    148         int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
    149             USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    150         CHECK_RET_RELEASE(ret,
    151             "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret));
     150        int ret = usb_endpoint_manager_add_ep(
     151            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
     152            USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0);
     153        CHECK_RET_UNREG_RETURN(ret,
     154            "Failed to register root hub control endpoint: %s.\n",
     155            str_error(ret));
    152156
    153157        ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
    154         CHECK_RET_RELEASE(ret,
     158        CHECK_RET_UNREG_RETURN(ret,
    155159            "Failed to add root hub match-id: %s.\n", str_error(ret));
    156160
    157161        ret = ddf_fun_bind(hub_fun);
    158         CHECK_RET_RELEASE(ret,
     162        CHECK_RET_UNREG_RETURN(ret,
    159163            "Failed to bind root hub function: %s.\n", str_error(ret));
    160164
     
    187191
    188192        list_initialize(&instance->pending_batches);
    189         usb_device_keeper_init(&instance->manager);
    190 
    191         ret = usb_endpoint_manager_init(&instance->ep_manager,
    192             BANDWIDTH_AVAILABLE_USB11);
    193         CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
     193
     194        ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     195            bandwidth_count_usb11);
     196        CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",
    194197            str_error(ret));
     198        instance->generic.private_data = instance;
     199        instance->generic.schedule = hc_schedule;
     200        instance->generic.ep_add_hook = ohci_endpoint_init;
    195201
    196202        ret = hc_init_memory(instance);
     
    215221}
    216222/*----------------------------------------------------------------------------*/
    217 /** Create and register endpoint structures.
    218  *
    219  * @param[in] instance OHCI driver structure.
    220  * @param[in] address USB address of the device.
    221  * @param[in] endpoint USB endpoint number.
    222  * @param[in] speed Communication speeed of the device.
    223  * @param[in] type Endpoint's transfer type.
    224  * @param[in] direction Endpoint's direction.
    225  * @param[in] mps Maximum packet size the endpoint accepts.
    226  * @param[in] size Maximum allowed buffer size.
    227  * @param[in] interval Time between transfers(interrupt transfers only).
    228  * @return Error code
    229  */
    230 int hc_add_endpoint(
    231     hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
    232     usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
    233     size_t mps, size_t size, unsigned interval)
    234 {
    235         endpoint_t *ep =
    236             endpoint_get(address, endpoint, direction, type, speed, mps);
    237         if (ep == NULL)
    238                 return ENOMEM;
    239 
    240         hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
    241         if (hcd_ep == NULL) {
    242                 endpoint_destroy(ep);
    243                 return ENOMEM;
    244         }
    245 
    246         int ret =
    247             usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
    248         if (ret != EOK) {
    249                 hcd_endpoint_clear(ep);
    250                 endpoint_destroy(ep);
    251                 return ret;
    252         }
    253 
    254         /* Enqueue hcd_ep */
     223void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep)
     224{
     225        endpoint_list_t *list = &instance->lists[ep->transfer_type];
     226        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     227        /* Enqueue ep */
    255228        switch (ep->transfer_type) {
    256229        case USB_TRANSFER_CONTROL:
    257230                instance->registers->control &= ~C_CLE;
    258                 endpoint_list_add_ep(
    259                     &instance->lists[ep->transfer_type], hcd_ep);
     231                endpoint_list_add_ep(list, ohci_ep);
    260232                instance->registers->control_current = 0;
    261233                instance->registers->control |= C_CLE;
     
    263235        case USB_TRANSFER_BULK:
    264236                instance->registers->control &= ~C_BLE;
    265                 endpoint_list_add_ep(
    266                     &instance->lists[ep->transfer_type], hcd_ep);
     237                endpoint_list_add_ep(list, ohci_ep);
    267238                instance->registers->control |= C_BLE;
    268239                break;
     
    270241        case USB_TRANSFER_INTERRUPT:
    271242                instance->registers->control &= (~C_PLE & ~C_IE);
    272                 endpoint_list_add_ep(
    273                     &instance->lists[ep->transfer_type], hcd_ep);
     243                endpoint_list_add_ep(list, ohci_ep);
    274244                instance->registers->control |= C_PLE | C_IE;
    275245                break;
    276246        }
    277 
    278         return EOK;
    279 }
    280 /*----------------------------------------------------------------------------*/
    281 /** Dequeue and delete endpoint structures
    282  *
    283  * @param[in] instance OHCI hc driver structure.
    284  * @param[in] address USB address of the device.
    285  * @param[in] endpoint USB endpoint number.
    286  * @param[in] direction Direction of the endpoint.
    287  * @return Error code
    288  */
    289 int hc_remove_endpoint(hc_t *instance, usb_address_t address,
    290     usb_endpoint_t endpoint, usb_direction_t direction)
    291 {
    292         assert(instance);
    293         fibril_mutex_lock(&instance->guard);
    294         endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
    295             address, endpoint, direction, NULL);
    296         if (ep == NULL) {
    297                 usb_log_error("Endpoint unregister failed: No such EP.\n");
    298                 fibril_mutex_unlock(&instance->guard);
    299                 return ENOENT;
    300         }
    301 
    302         hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
    303         if (hcd_ep) {
    304                 /* Dequeue hcd_ep */
    305                 switch (ep->transfer_type) {
    306                 case USB_TRANSFER_CONTROL:
    307                         instance->registers->control &= ~C_CLE;
    308                         endpoint_list_remove_ep(
    309                             &instance->lists[ep->transfer_type], hcd_ep);
    310                         instance->registers->control_current = 0;
    311                         instance->registers->control |= C_CLE;
    312                         break;
    313                 case USB_TRANSFER_BULK:
    314                         instance->registers->control &= ~C_BLE;
    315                         endpoint_list_remove_ep(
    316                             &instance->lists[ep->transfer_type], hcd_ep);
    317                         instance->registers->control |= C_BLE;
    318                         break;
    319                 case USB_TRANSFER_ISOCHRONOUS:
    320                 case USB_TRANSFER_INTERRUPT:
    321                         instance->registers->control &= (~C_PLE & ~C_IE);
    322                         endpoint_list_remove_ep(
    323                             &instance->lists[ep->transfer_type], hcd_ep);
    324                         instance->registers->control |= C_PLE | C_IE;
    325                         break;
    326                 default:
    327                         break;
    328                 }
    329                 hcd_endpoint_clear(ep);
    330         } else {
    331                 usb_log_warning("Endpoint without hcd equivalent structure.\n");
    332         }
    333         int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
    334             address, endpoint, direction);
    335         fibril_mutex_unlock(&instance->guard);
    336         return ret;
    337 }
    338 /*----------------------------------------------------------------------------*/
    339 /** Get access to endpoint structures
    340  *
    341  * @param[in] instance OHCI hc driver structure.
    342  * @param[in] address USB address of the device.
    343  * @param[in] endpoint USB endpoint number.
    344  * @param[in] direction Direction of the endpoint.
    345  * @param[out] bw Reserved bandwidth.
    346  * @return Error code
    347  */
    348 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
    349     usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
    350 {
    351         assert(instance);
    352         fibril_mutex_lock(&instance->guard);
    353         endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
    354             address, endpoint, direction, bw);
    355         fibril_mutex_unlock(&instance->guard);
    356         return ep;
     247}
     248/*----------------------------------------------------------------------------*/
     249void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep)
     250{
     251        /* Dequeue ep */
     252        endpoint_list_t *list = &instance->lists[ep->transfer_type];
     253        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     254        switch (ep->transfer_type) {
     255        case USB_TRANSFER_CONTROL:
     256                instance->registers->control &= ~C_CLE;
     257                endpoint_list_remove_ep(list, ohci_ep);
     258                instance->registers->control_current = 0;
     259                instance->registers->control |= C_CLE;
     260                break;
     261        case USB_TRANSFER_BULK:
     262                instance->registers->control &= ~C_BLE;
     263                endpoint_list_remove_ep(list, ohci_ep);
     264                instance->registers->control |= C_BLE;
     265                break;
     266        case USB_TRANSFER_ISOCHRONOUS:
     267        case USB_TRANSFER_INTERRUPT:
     268                instance->registers->control &= (~C_PLE & ~C_IE);
     269                endpoint_list_remove_ep(list, ohci_ep);
     270                instance->registers->control |= C_PLE | C_IE;
     271                break;
     272        default:
     273                break;
     274        }
    357275}
    358276/*----------------------------------------------------------------------------*/
     
    363281 * @return Error code.
    364282 */
    365 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    366 {
    367         assert(instance);
    368         assert(batch);
    369         assert(batch->ep);
     283int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     284{
     285        assert(hcd);
     286        hc_t *instance = hcd->private_data;
     287        assert(instance);
    370288
    371289        /* Check for root hub communication */
     
    374292                return EOK;
    375293        }
     294        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     295        if (!ohci_batch)
     296                return ENOMEM;
    376297
    377298        fibril_mutex_lock(&instance->guard);
    378         list_append(&batch->link, &instance->pending_batches);
    379         batch_commit(batch);
     299        list_append(&ohci_batch->link, &instance->pending_batches);
     300        ohci_transfer_batch_commit(ohci_batch);
    380301
    381302        /* Control and bulk schedules need a kick to start working */
     
    417338                    instance->registers->periodic_current);
    418339
    419                 link_t *current = instance->pending_batches.head.next;
    420                 while (current != &instance->pending_batches.head) {
     340                link_t *current = list_first(&instance->pending_batches);
     341                while (current && current != &instance->pending_batches.head) {
    421342                        link_t *next = current->next;
    422                         usb_transfer_batch_t *batch =
    423                             usb_transfer_batch_from_link(current);
    424 
    425                         if (batch_is_complete(batch)) {
     343                        ohci_transfer_batch_t *batch =
     344                            ohci_transfer_batch_from_link(current);
     345
     346                        if (ohci_transfer_batch_is_complete(batch)) {
    426347                                list_remove(current);
    427                                 usb_transfer_batch_finish(batch);
     348                                ohci_transfer_batch_finish_dispose(batch);
    428349                        }
    429350
     
    434355
    435356        if (status & I_UE) {
     357                usb_log_fatal("Error like no other!\n");
    436358                hc_start(instance);
    437359        }
  • uspace/drv/bus/usb/ohci/hc.h

    r47fecbb rfd07e526  
    4141
    4242#include <usb/usb.h>
    43 #include <usb/host/device_keeper.h>
    44 #include <usb/host/usb_endpoint_manager.h>
    45 #include <usbhc_iface.h>
     43#include <usb/host/hcd.h>
    4644
    47 #include "batch.h"
     45#include "ohci_batch.h"
    4846#include "ohci_regs.h"
    4947#include "root_hub.h"
     
    5351/** Main OHCI driver structure */
    5452typedef struct hc {
    55         /** USB bus driver, devices and addresses */
    56         usb_device_keeper_t manager;
    57         /** USB bus driver, endpoints */
    58         usb_endpoint_manager_t ep_manager;
     53        /** Generic USB hc driver */
     54        hcd_t generic;
    5955
    6056        /** Memory mapped I/O registers area */
     
    8177int hc_get_irq_commands(
    8278    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     79int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    8380int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    84 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    8581
    8682/** Safely dispose host controller internal structures
     
    8884 * @param[in] instance Host controller structure to use.
    8985 */
    90 static inline void hc_fini(hc_t *instance)
    91         { /* TODO: implement*/ };
     86static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
    9287
    93 int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
    94     usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
    95     size_t max_packet_size, size_t size, unsigned interval);
    96 int hc_remove_endpoint(hc_t *instance, usb_address_t address,
    97     usb_endpoint_t endpoint, usb_direction_t direction);
    98 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
    99     usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
     88void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);
     89void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);
    10090
    101 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    10291void hc_interrupt(hc_t *instance, uint32_t status);
    103 
    104 /** Get and cast pointer to the driver data
    105  *
    106  * @param[in] fun DDF function pointer
    107  * @return cast pointer to driver_data
    108  */
    109 static inline hc_t * fun_to_hc(ddf_fun_t *fun)
    110         { return fun->driver_data; }
    11192#endif
    11293/**
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c

    r47fecbb rfd07e526  
    3939static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
    4040
    41 void td_init(
    42     td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle)
     41void td_init(td_t *instance,
     42    usb_direction_t dir, const void *buffer, size_t size, int toggle)
    4343{
    4444        assert(instance);
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h

    r47fecbb rfd07e526  
    7575} __attribute__((packed)) td_t;
    7676
    77 void td_init(
    78     td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
     77void td_init(td_t *instance,
     78    usb_direction_t dir, const void *buffer, size_t size, int toggle);
    7979
    8080inline static void td_set_next(td_t *instance, td_t *next)
  • uspace/drv/bus/usb/ohci/ohci.c

    r47fecbb rfd07e526  
    4242
    4343#include "ohci.h"
    44 #include "iface.h"
    4544#include "pci.h"
    4645#include "hc.h"
    47 #include "root_hub.h"
    4846
    4947typedef struct ohci {
     
    5250
    5351        hc_t hc;
    54         rh_t rh;
    5552} ohci_t;
    5653
     
    8986{
    9087        assert(fun);
    91         usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
    92 
    93         usb_address_t addr = usb_device_keeper_find(manager, handle);
     88        usb_device_manager_t *manager =
     89            &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
     90
     91        const usb_address_t addr = usb_device_manager_find(manager, handle);
    9492        if (addr < 0) {
    9593                return addr;
     
    129127/** Standard USB HC options (HC interface) */
    130128static ddf_dev_ops_t hc_ops = {
    131         .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
     129        .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    132130};
    133131/*----------------------------------------------------------------------------*/
     
    150148int device_setup_ohci(ddf_dev_t *device)
    151149{
     150        assert(device);
     151
    152152        ohci_t *instance = malloc(sizeof(ohci_t));
    153153        if (instance == NULL) {
     
    155155                return ENOMEM;
    156156        }
     157        instance->rh_fun = NULL;
     158        instance->hc_fun = NULL;
    157159
    158160#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
    159161if (ret != EOK) { \
    160162        if (instance->hc_fun) { \
    161                 instance->hc_fun->ops = NULL; \
    162                 instance->hc_fun->driver_data = NULL; \
    163163                ddf_fun_destroy(instance->hc_fun); \
    164164        } \
    165165        if (instance->rh_fun) { \
    166                 instance->rh_fun->ops = NULL; \
    167                 instance->rh_fun->driver_data = NULL; \
    168166                ddf_fun_destroy(instance->rh_fun); \
    169167        } \
    170168        free(instance); \
    171         device->driver_data = NULL; \
    172169        usb_log_error(message); \
    173170        return ret; \
    174171} else (void)0
    175172
    176         instance->rh_fun = NULL;
    177173        instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
    178174        int ret = instance->hc_fun ? EOK : ENOMEM;
     
    194190        ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
    195191        CHECK_RET_DEST_FREE_RETURN(ret,
    196             "Failed to get memory addresses for %" PRIun ": %s.\n",
     192            "Failed to get register memory addresses for %" PRIun ": %s.\n",
    197193            device->handle, str_error(ret));
    198194        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     
    201197        const size_t cmd_count = hc_irq_cmd_count();
    202198        irq_cmd_t irq_cmds[cmd_count];
     199        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     200
    203201        ret =
    204202            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     
    206204            "Failed to generate IRQ commands: %s.\n", str_error(ret));
    207205
    208         irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
    209206
    210207        /* Register handler to avoid interrupt lockup */
     
    234231#define CHECK_RET_FINI_RETURN(ret, message...) \
    235232if (ret != EOK) { \
     233        hc_fini(&instance->hc); \
    236234        unregister_interrupt_handler(device, irq); \
    237         hc_fini(&instance->hc); \
    238235        CHECK_RET_DEST_FREE_RETURN(ret, message); \
    239236} else (void)0
     
    248245            "Failed to add OHCI to HC class: %s.\n", str_error(ret));
    249246
    250         hc_register_hub(&instance->hc, instance->rh_fun);
    251         return EOK;
    252 
    253 #undef CHECK_RET_DEST_FUN_RETURN
     247        ret = hc_register_hub(&instance->hc, instance->rh_fun);
     248        CHECK_RET_FINI_RETURN(ret,
     249            "Failed to register OHCI root hub: %s.\n", str_error(ret));
     250        return ret;
     251
    254252#undef CHECK_RET_FINI_RETURN
    255253}
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    r47fecbb rfd07e526  
    3535#define DRV_OHCI_BATCH_H
    3636
     37#include <adt/list.h>
    3738#include <usbhc_iface.h>
    3839#include <usb/usb.h>
    39 #include <usb/host/device_keeper.h>
    40 #include <usb/host/endpoint.h>
    41 #include <usb/host/batch.h>
     40#include <usb/host/usb_transfer_batch.h>
    4241
    43 usb_transfer_batch_t * batch_get(
    44     ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
    45     const char *setup_buffer, size_t setup_size,
    46     usbhc_iface_transfer_in_callback_t func_in,
    47     usbhc_iface_transfer_out_callback_t func_out,
    48     void *arg);
     42#include "hw_struct/transfer_descriptor.h"
     43#include "hw_struct/endpoint_descriptor.h"
    4944
    50 bool batch_is_complete(usb_transfer_batch_t *instance);
     45/** OHCI specific data required for USB transfer */
     46typedef struct ohci_transfer_batch {
     47        /** Link */
     48        link_t link;
     49        /** Endpoint descriptor of the target endpoint. */
     50        ed_t *ed;
     51        /** List of TDs needed for the transfer */
     52        td_t **tds;
     53        /** Number of TDs used by the transfer */
     54        size_t td_count;
     55        /** Dummy TD to be left at the ED and used by the next transfer */
     56        size_t leave_td;
     57        /** Data buffer, must be accessible by the OHCI hw. */
     58        char *device_buffer;
     59        /** Generic USB transfer structure */
     60        usb_transfer_batch_t *usb_batch;
     61} ohci_transfer_batch_t;
    5162
    52 void batch_commit(usb_transfer_batch_t *instance);
    53 
    54 void batch_control_write(usb_transfer_batch_t *instance);
    55 
    56 void batch_control_read(usb_transfer_batch_t *instance);
    57 
    58 void batch_interrupt_in(usb_transfer_batch_t *instance);
    59 
    60 void batch_interrupt_out(usb_transfer_batch_t *instance);
    61 
    62 void batch_bulk_in(usb_transfer_batch_t *instance);
    63 
    64 void batch_bulk_out(usb_transfer_batch_t *instance);
     63ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch);
     64bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *batch);
     65void ohci_transfer_batch_commit(ohci_transfer_batch_t *batch);
     66void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
     67/*----------------------------------------------------------------------------*/
     68static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l)
     69{
     70        assert(l);
     71        return list_get_instance(l, ohci_transfer_batch_t, link);
     72}
    6573#endif
    6674/**
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    r47fecbb rfd07e526  
    3333 */
    3434#include "utils/malloc32.h"
    35 #include "hcd_endpoint.h"
     35#include "ohci_endpoint.h"
     36#include "hc.h"
    3637
    3738/** Callback to set toggle on ED.
     
    4041 * @param[in] toggle new value of toggle bit
    4142 */
    42 static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
     43static void ohci_ep_toggle_set(void *ohci_ep, int toggle)
    4344{
    44         hcd_endpoint_t *instance = hcd_ep;
     45        ohci_endpoint_t *instance = ohci_ep;
    4546        assert(instance);
    4647        assert(instance->ed);
     
    5354 * @return Current value of toggle bit.
    5455 */
    55 static int hcd_ep_toggle_get(void *hcd_ep)
     56static int ohci_ep_toggle_get(void *ohci_ep)
    5657{
    57         hcd_endpoint_t *instance = hcd_ep;
     58        ohci_endpoint_t *instance = ohci_ep;
    5859        assert(instance);
    5960        assert(instance->ed);
    6061        return ed_toggle_get(instance->ed);
     62}
     63/*----------------------------------------------------------------------------*/
     64/** Disposes hcd endpoint structure
     65 *
     66 * @param[in] hcd_ep endpoint structure
     67 */
     68static void ohci_endpoint_fini(endpoint_t *ep)
     69{
     70        ohci_endpoint_t *instance = ep->hc_data.data;
     71        hc_dequeue_endpoint(instance->hcd->private_data, ep);
     72        if (instance) {
     73                free32(instance->ed);
     74                free32(instance->td);
     75                free(instance);
     76        }
    6177}
    6278/*----------------------------------------------------------------------------*/
     
    6682 * @return pointer to a new hcd endpoint structure, NULL on failure.
    6783 */
    68 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
     84int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep)
    6985{
    7086        assert(ep);
    71         hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
    72         if (hcd_ep == NULL)
    73                 return NULL;
     87        ohci_endpoint_t *ohci_ep = malloc(sizeof(ohci_endpoint_t));
     88        if (ohci_ep == NULL)
     89                return ENOMEM;
    7490
    75         hcd_ep->ed = malloc32(sizeof(ed_t));
    76         if (hcd_ep->ed == NULL) {
    77                 free(hcd_ep);
    78                 return NULL;
     91        ohci_ep->ed = malloc32(sizeof(ed_t));
     92        if (ohci_ep->ed == NULL) {
     93                free(ohci_ep);
     94                return ENOMEM;
    7995        }
    8096
    81         hcd_ep->td = malloc32(sizeof(td_t));
    82         if (hcd_ep->td == NULL) {
    83                 free32(hcd_ep->ed);
    84                 free(hcd_ep);
    85                 return NULL;
     97        ohci_ep->td = malloc32(sizeof(td_t));
     98        if (ohci_ep->td == NULL) {
     99                free32(ohci_ep->ed);
     100                free(ohci_ep);
     101                return ENOMEM;
    86102        }
    87103
    88         ed_init(hcd_ep->ed, ep);
    89         ed_set_td(hcd_ep->ed, hcd_ep->td);
    90         endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set);
    91 
    92         return hcd_ep;
    93 }
    94 /*----------------------------------------------------------------------------*/
    95 /** Disposes assigned hcd endpoint structure
    96  *
    97  * @param[in] ep USBD endpoint structure
    98  */
    99 void hcd_endpoint_clear(endpoint_t *ep)
    100 {
    101         assert(ep);
    102         hcd_endpoint_t *hcd_ep = ep->hc_data.data;
    103         assert(hcd_ep);
    104         free32(hcd_ep->ed);
    105         free32(hcd_ep->td);
    106         free(hcd_ep);
     104        ed_init(ohci_ep->ed, ep);
     105        ed_set_td(ohci_ep->ed, ohci_ep->td);
     106        endpoint_set_hc_data(
     107            ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set);
     108        ohci_ep->hcd = hcd;
     109        hc_enqueue_endpoint(hcd->private_data, ep);
     110        return EOK;
    107111}
    108112/**
  • uspace/drv/bus/usb/ohci/ohci_endpoint.h

    r47fecbb rfd07e526  
    3838#include <adt/list.h>
    3939#include <usb/host/endpoint.h>
     40#include <usb/host/hcd.h>
    4041
    4142#include "hw_struct/endpoint_descriptor.h"
     
    4344
    4445/** Connector structure linking ED to to prepared TD. */
    45 typedef struct hcd_endpoint {
     46typedef struct ohci_endpoint {
    4647        /** OHCI endpoint descriptor */
    4748        ed_t *ed;
     
    5051        /** Linked list used by driver software */
    5152        link_t link;
    52 } hcd_endpoint_t;
     53        /** Device using this ep */
     54        hcd_t *hcd;
     55} ohci_endpoint_t;
    5356
    54 hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
    55 void hcd_endpoint_clear(endpoint_t *ep);
     57int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
    5658
    57 /** Get and convert assigned hcd_endpoint_t structure
     59/** Get and convert assigned ohci_endpoint_t structure
    5860 * @param[in] ep USBD endpoint structure.
    5961 * @return Pointer to assigned hcd endpoint structure
    6062 */
    61 static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
     63static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep)
    6264{
    6365        assert(ep);
  • uspace/drv/bus/usb/ohci/root_hub.c

    r47fecbb rfd07e526  
    121121        assert(request);
    122122
    123         memcpy(request->data_buffer, &mask, size);
    124123        request->transfered_size = size;
    125         usb_transfer_batch_finish_error(request, EOK);
     124        usb_transfer_batch_finish_error(request, &mask, size, EOK);
    126125}
    127126
     
    206205                usb_log_debug("Root hub got CONTROL packet\n");
    207206                const int ret = control_request(instance, request);
    208                 usb_transfer_batch_finish_error(request, ret);
     207                usb_transfer_batch_finish_error(request, NULL, 0, ret);
    209208                break;
    210209        case USB_TRANSFER_INTERRUPT:
     
    215214                        assert(instance->unfinished_interrupt_transfer == NULL);
    216215                        instance->unfinished_interrupt_transfer = request;
    217                         break;
     216                        return;
    218217                }
    219218                usb_log_debug("Processing changes...\n");
     
    223222        default:
    224223                usb_log_error("Root hub got unsupported request.\n");
    225                 usb_transfer_batch_finish_error(request, EINVAL);
    226         }
     224                usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
     225        }
     226        usb_transfer_batch_dispose(request);
    227227}
    228228/*----------------------------------------------------------------------------*/
     
    244244        interrupt_request(instance->unfinished_interrupt_transfer,
    245245            mask, instance->interrupt_mask_size);
     246        usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer);
    246247
    247248        instance->unfinished_interrupt_transfer = NULL;
     
    389390                const uint32_t data = instance->registers->rh_status &
    390391                    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
    391                 memcpy(request->data_buffer, &data, 4);
    392                 TRANSFER_OK(4);
     392                memcpy(request->buffer, &data, sizeof(data));
     393                TRANSFER_OK(sizeof(data));
    393394        }
    394395
     
    402403                const uint32_t data =
    403404                    instance->registers->rh_port_status[port - 1];
    404                 memcpy(request->data_buffer, &data, 4);
    405                 TRANSFER_OK(4);
     405                memcpy(request->buffer, &data, sizeof(data));
     406                TRANSFER_OK(sizeof(data));
    406407        }
    407408
     
    483484        }
    484485
    485         memcpy(request->data_buffer, descriptor, size);
     486        memcpy(request->buffer, descriptor, size);
    486487        TRANSFER_OK(size);
    487488}
     
    713714                if (request->buffer_size != 1)
    714715                        return EINVAL;
    715                 request->data_buffer[0] = 1;
     716                request->buffer[0] = 1;
    716717                TRANSFER_OK(1);
    717718
  • uspace/drv/bus/usb/ohci/root_hub.h

    r47fecbb rfd07e526  
    3737#include <usb/usb.h>
    3838#include <usb/dev/driver.h>
     39#include <usb/host/usb_transfer_batch.h>
    3940
    4041#include "ohci_regs.h"
    41 #include "batch.h"
    4242
    4343#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
     
    6666        /** size of hub descriptor */
    6767        size_t hub_descriptor_size;
    68 
    6968} rh_t;
    7069
  • uspace/drv/bus/usb/ohci/utils/malloc32.h

    r47fecbb rfd07e526  
    4646 * @return Physical address if exists, NULL otherwise.
    4747 */
    48 static inline uintptr_t addr_to_phys(void *addr)
     48static inline uintptr_t addr_to_phys(const void *addr)
    4949{
    5050        uintptr_t result;
  • uspace/drv/bus/usb/uhci/Makefile

    r47fecbb rfd07e526  
    4242
    4343SOURCES = \
    44         iface.c \
     44        hc.c \
    4545        main.c \
     46        pci.c \
     47        root_hub.c \
    4648        transfer_list.c \
    4749        uhci.c \
    48         hc.c \
    49         root_hub.c \
    50         hw_struct/transfer_descriptor.c \
    51         pci.c \
    52         batch.c
     50        uhci_batch.c \
     51        hw_struct/transfer_descriptor.c
    5352
    5453include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/bus/usb/uhci/hc.c

    r47fecbb rfd07e526  
    4141
    4242#include "hc.h"
     43#include "uhci_batch.h"
    4344
    4445#define UHCI_INTR_ALLOW_INTERRUPTS \
     
    4647#define UHCI_STATUS_USED_INTERRUPTS \
    4748    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
     49
    4850
    4951static const irq_cmd_t uhci_irq_commands[] =
     
    5759};
    5860
     61static void hc_init_hw(const hc_t *instance);
     62static int hc_init_mem_structures(hc_t *instance);
    5963static int hc_init_transfer_lists(hc_t *instance);
    60 static int hc_init_mem_structures(hc_t *instance);
    61 static void hc_init_hw(hc_t *instance);
     64static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    6265
    6366static int hc_interrupt_emulator(void *arg);
     
    9598        cmds[3].addr = (void*)&registers->usbsts;
    9699        return EOK;
     100}
     101/*----------------------------------------------------------------------------*/
     102/** Take action based on the interrupt cause.
     103 *
     104 * @param[in] instance UHCI structure to use.
     105 * @param[in] status Value of the status register at the time of interrupt.
     106 *
     107 * Interrupt might indicate:
     108 * - transaction completed, either by triggering IOC, SPD, or an error
     109 * - some kind of device error
     110 * - resume from suspend state (not implemented)
     111 */
     112void hc_interrupt(hc_t *instance, uint16_t status)
     113{
     114        assert(instance);
     115        /* Lower 2 bits are transaction error and transaction complete */
     116        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     117                LIST_INITIALIZE(done);
     118                transfer_list_remove_finished(
     119                    &instance->transfers_interrupt, &done);
     120                transfer_list_remove_finished(
     121                    &instance->transfers_control_slow, &done);
     122                transfer_list_remove_finished(
     123                    &instance->transfers_control_full, &done);
     124                transfer_list_remove_finished(
     125                    &instance->transfers_bulk_full, &done);
     126
     127                while (!list_empty(&done)) {
     128                        link_t *item = list_first(&done);
     129                        list_remove(item);
     130                        uhci_transfer_batch_t *batch =
     131                            uhci_transfer_batch_from_link(item);
     132                        uhci_transfer_batch_call_dispose(batch);
     133                }
     134        }
     135        /* Resume interrupts are not supported */
     136        if (status & UHCI_STATUS_RESUME) {
     137                usb_log_error("Resume interrupt!\n");
     138        }
     139
     140        /* Bits 4 and 5 indicate hc error */
     141        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
     142                usb_log_error("UHCI hardware failure!.\n");
     143                ++instance->hw_failures;
     144                transfer_list_abort_all(&instance->transfers_interrupt);
     145                transfer_list_abort_all(&instance->transfers_control_slow);
     146                transfer_list_abort_all(&instance->transfers_control_full);
     147                transfer_list_abort_all(&instance->transfers_bulk_full);
     148
     149                if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
     150                        /* reinitialize hw, this triggers virtual disconnect*/
     151                        hc_init_hw(instance);
     152                } else {
     153                        usb_log_fatal("Too many UHCI hardware failures!.\n");
     154                        hc_fini(instance);
     155                }
     156        }
    97157}
    98158/*----------------------------------------------------------------------------*/
     
    132192            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    133193
     194        ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     195            bandwidth_count_usb11);
     196        CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
     197            str_error(ret));
     198
     199        instance->generic.private_data = instance;
     200        instance->generic.schedule = hc_schedule;
     201        instance->generic.ep_add_hook = NULL;
     202
     203#undef CHECK_RET_DEST_FUN_RETURN
     204
    134205        ret = hc_init_mem_structures(instance);
    135         CHECK_RET_RETURN(ret,
    136             "Failed to initialize UHCI memory structures: %s.\n",
    137             str_error(ret));
     206        if (ret != EOK) {
     207                usb_log_error(
     208                    "Failed to initialize UHCI memory structures: %s.\n",
     209                    str_error(ret));
     210                hcd_destroy(&instance->generic);
     211                return ret;
     212        }
    138213
    139214        hc_init_hw(instance);
     
    146221
    147222        return EOK;
    148 #undef CHECK_RET_DEST_FUN_RETURN
    149223}
    150224/*----------------------------------------------------------------------------*/
     
    154228 * For magic values see UHCI Design Guide
    155229 */
    156 void hc_init_hw(hc_t *instance)
     230void hc_init_hw(const hc_t *instance)
    157231{
    158232        assert(instance);
     
    198272 *
    199273 * Structures:
    200  *  - interrupt code (I/O addressses are customized per instance)
    201274 *  - transfer lists (queue heads need to be accessible by the hw)
    202275 *  - frame list page (needs to be one UHCI hw accessible 4K page)
     
    205278{
    206279        assert(instance);
    207 #define CHECK_RET_RETURN(ret, message...) \
    208         if (ret != EOK) { \
    209                 usb_log_error(message); \
    210                 return ret; \
    211         } else (void) 0
     280
     281        /* Init USB frame list page */
     282        instance->frame_list = get_page();
     283        if (!instance->frame_list) {
     284                return ENOMEM;
     285        }
     286        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    212287
    213288        /* Init transfer lists */
    214289        int ret = hc_init_transfer_lists(instance);
    215         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     290        if (ret != EOK) {
     291                usb_log_error("Failed to initialize transfer lists.\n");
     292                return_page(instance->frame_list);
     293                return ENOMEM;
     294        }
    216295        usb_log_debug("Initialized transfer lists.\n");
    217296
    218         /* Init device keeper */
    219         usb_device_keeper_init(&instance->manager);
    220         usb_log_debug("Initialized device keeper.\n");
    221 
    222         ret = usb_endpoint_manager_init(&instance->ep_manager,
    223             BANDWIDTH_AVAILABLE_USB11);
    224         CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    225             str_error(ret));
    226 
    227         /* Init USB frame list page*/
    228         instance->frame_list = get_page();
    229         if (!instance->frame_list) {
    230                 usb_log_error("Failed to get frame list page.\n");
    231                 usb_endpoint_manager_destroy(&instance->ep_manager);
    232                 return ENOMEM;
    233         }
    234         usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    235297
    236298        /* Set all frames to point to the first queue head */
     
    243305
    244306        return EOK;
    245 #undef CHECK_RET_RETURN
    246307}
    247308/*----------------------------------------------------------------------------*/
     
    316377 * Checks for bandwidth availability and appends the batch to the proper queue.
    317378 */
    318 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    319 {
     379int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     380{
     381        assert(hcd);
     382        hc_t *instance = hcd->private_data;
    320383        assert(instance);
    321384        assert(batch);
     385        uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
     386        if (!uhci_batch) {
     387                usb_log_error("Failed to create UHCI transfer structures.\n");
     388                return ENOMEM;
     389        }
    322390
    323391        transfer_list_t *list =
    324392            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    325393        assert(list);
    326         transfer_list_add_batch(list, batch);
    327 
    328         return EOK;
    329 }
    330 /*----------------------------------------------------------------------------*/
    331 /** Take action based on the interrupt cause.
    332  *
    333  * @param[in] instance UHCI structure to use.
    334  * @param[in] status Value of the status register at the time of interrupt.
    335  *
    336  * Interrupt might indicate:
    337  * - transaction completed, either by triggering IOC, SPD, or an error
    338  * - some kind of device error
    339  * - resume from suspend state (not implemented)
    340  */
    341 void hc_interrupt(hc_t *instance, uint16_t status)
    342 {
    343         assert(instance);
    344         /* Lower 2 bits are transaction error and transaction complete */
    345         if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    346                 LIST_INITIALIZE(done);
    347                 transfer_list_remove_finished(
    348                     &instance->transfers_interrupt, &done);
    349                 transfer_list_remove_finished(
    350                     &instance->transfers_control_slow, &done);
    351                 transfer_list_remove_finished(
    352                     &instance->transfers_control_full, &done);
    353                 transfer_list_remove_finished(
    354                     &instance->transfers_bulk_full, &done);
    355 
    356                 while (!list_empty(&done)) {
    357                         link_t *item = list_first(&done);
    358                         list_remove(item);
    359                         usb_transfer_batch_t *batch =
    360                             list_get_instance(item, usb_transfer_batch_t, link);
    361                         usb_transfer_batch_finish(batch);
    362                 }
    363         }
    364         /* Resume interrupts are not supported */
    365         if (status & UHCI_STATUS_RESUME) {
    366                 usb_log_error("Resume interrupt!\n");
    367         }
    368 
    369         /* Bits 4 and 5 indicate hc error */
    370         if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    371                 usb_log_error("UHCI hardware failure!.\n");
    372                 ++instance->hw_failures;
    373                 transfer_list_abort_all(&instance->transfers_interrupt);
    374                 transfer_list_abort_all(&instance->transfers_control_slow);
    375                 transfer_list_abort_all(&instance->transfers_control_full);
    376                 transfer_list_abort_all(&instance->transfers_bulk_full);
    377 
    378                 if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
    379                         /* reinitialize hw, this triggers virtual disconnect*/
    380                         hc_init_hw(instance);
    381                 } else {
    382                         usb_log_fatal("Too many UHCI hardware failures!.\n");
    383                         hc_fini(instance);
    384                 }
    385         }
     394        transfer_list_add_batch(list, uhci_batch);
     395
     396        return EOK;
    386397}
    387398/*----------------------------------------------------------------------------*/
     
    403414                if (status != 0)
    404415                        usb_log_debug2("UHCI status: %x.\n", status);
    405 // Qemu fails to report stalled communication
    406 // see https://bugs.launchpad.net/qemu/+bug/757654
    407 // This is a simple workaround to force queue processing every time
    408         //      status |= 1;
    409416                hc_interrupt(instance, status);
    410417                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    412419        return EOK;
    413420}
    414 /*---------------------------------------------------------------------------*/
     421/*----------------------------------------------------------------------------*/
    415422/** Debug function, checks consistency of memory structures.
    416423 *
  • uspace/drv/bus/usb/uhci/hc.h

    r47fecbb rfd07e526  
    3939#include <ddi.h>
    4040
    41 #include <usb/host/device_keeper.h>
    42 #include <usb/host/usb_endpoint_manager.h>
    43 #include <usb/host/batch.h>
     41#include <usb/host/hcd.h>
    4442
    4543#include "transfer_list.h"
     
    9492/** Main UHCI driver structure */
    9593typedef struct hc {
    96         /** USB bus driver, devices and addresses */
    97         usb_device_keeper_t manager;
    98         /** USB bus driver, endpoints */
    99         usb_endpoint_manager_t ep_manager;
     94        /** Generic HCD driver structure */
     95        hcd_t generic;
    10096
    10197        /** Addresses of I/O registers */
     
    124120        unsigned hw_failures;
    125121} hc_t;
     122
    126123size_t hc_irq_cmd_count(void);
    127124int hc_get_irq_commands(
    128125    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     126void hc_interrupt(hc_t *instance, uint16_t status);
    129127int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
    130 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    131 void hc_interrupt(hc_t *instance, uint16_t status);
    132128
    133129/** Safely dispose host controller internal structures
     
    135131 * @param[in] instance Host controller structure to use.
    136132 */
    137 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
    138 
    139 /** Get and cast pointer to the driver data
    140  *
    141  * @param[in] fun DDF function pointer
    142  * @return cast pointer to driver_data
    143  */
    144 static inline hc_t * fun_to_hc(ddf_fun_t *fun)
    145 {
    146         assert(fun);
    147         return fun->driver_data;
    148 }
     133static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/
    149134#endif
    150135/**
  • uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h

    r47fecbb rfd07e526  
    3535#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
    3636
    37 /* UHCI link pointer, used by many data structures */
     37/** UHCI link pointer, used by many data structures */
    3838typedef uint32_t link_pointer_t;
    3939
  • uspace/drv/bus/usb/uhci/hw_struct/queue_head.h

    r47fecbb rfd07e526  
    5858        assert(instance);
    5959
    60         instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    61         instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
     60        instance->element = LINK_POINTER_TERM;
     61        instance->next = LINK_POINTER_TERM;
    6262}
    6363/*----------------------------------------------------------------------------*/
     
    7171static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
    7272{
    73         uint32_t pa = addr_to_phys(next);
     73        /* Physical address has to be below 4GB,
     74         * it is an UHCI limitation and malloc32
     75         * should guarantee this */
     76        const uint32_t pa = addr_to_phys(next);
    7477        if (pa) {
    7578                instance->next = LINK_POINTER_QH(pa);
     
    8891static inline void qh_set_element_td(qh_t *instance, td_t *td)
    8992{
    90         uint32_t pa = addr_to_phys(td);
     93        /* Physical address has to be below 4GB,
     94         * it is an UHCI limitation and malloc32
     95         * should guarantee this */
     96        const uint32_t pa = addr_to_phys(td);
    9197        if (pa) {
    9298                instance->element = LINK_POINTER_TD(pa);
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c

    r47fecbb rfd07e526  
    6161 */
    6262void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
    63     bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
    64     td_t *next)
     63    bool low_speed, usb_target_t target, usb_packet_id pid, const void *buffer,
     64    const td_t *next)
    6565{
    6666        assert(instance);
     
    113113 * @return Error code.
    114114 */
    115 int td_status(td_t *instance)
     115int td_status(const td_t *instance)
    116116{
    117117        assert(instance);
     
    119119        /* This is hc internal error it should never be reported. */
    120120        if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
    121                 return EAGAIN;
     121                return EIO;
    122122
    123123        /* CRC or timeout error, like device not present or bad data,
     
    150150 * @param[in] instance TD structure to use.
    151151 */
    152 void td_print_status(td_t *instance)
     152void td_print_status(const td_t *instance)
    153153{
    154154        assert(instance);
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h

    r47fecbb rfd07e526  
    6969#define TD_STATUS_ACTLEN_MASK 0x7ff
    7070
    71         /* double word with USB device specific info */
     71        /** Double word with USB device specific info */
    7272        volatile uint32_t device;
    7373#define TD_DEVICE_MAXLEN_POS 21
     
    8787        /* According to UHCI design guide, there is 16 bytes of
    8888         * data available here.
    89          * According to linux kernel the hardware does not care,
    90          * it just needs to be aligned. We don't use it anyway.
     89         * According to Linux kernel the hardware does not care,
     90         * memory just needs to be aligned. We don't use it anyway.
    9191         */
    9292} __attribute__((packed)) td_t;
     
    9595void td_init(td_t *instance, int error_count, size_t size, bool toggle,
    9696    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
    97     void *buffer, td_t *next);
     97    const void *buffer, const td_t *next);
    9898
    99 int td_status(td_t *instance);
     99int td_status(const td_t *instance);
    100100
    101 void td_print_status(td_t *instance);
     101void td_print_status(const td_t *instance);
    102102/*----------------------------------------------------------------------------*/
    103103/** Helper function for parsing actual size out of TD.
     
    106106 * @return Parsed actual size.
    107107 */
    108 static inline size_t td_act_size(td_t *instance)
     108static inline size_t td_act_size(const td_t *instance)
    109109{
    110110        assert(instance);
    111111        const uint32_t s = instance->status;
     112        /* Actual size is encoded as n-1 (UHCI design guide p. 23) */
    112113        return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
    113114}
     
    119120 * false otherwise.
    120121 */
    121 static inline bool td_is_short(td_t *instance)
     122static inline bool td_is_short(const td_t *instance)
    122123{
    123124        const size_t act_size = td_act_size(instance);
     
    134135 * @return Toggle bit value.
    135136 */
    136 static inline int td_toggle(td_t *instance)
     137static inline int td_toggle(const td_t *instance)
    137138{
    138139        assert(instance);
     
    145146 * @return Active bit value.
    146147 */
    147 static inline bool td_is_active(td_t *instance)
     148static inline bool td_is_active(const td_t *instance)
    148149{
    149150        assert(instance);
  • uspace/drv/bus/usb/uhci/main.c

    r47fecbb rfd07e526  
    6464        assert(device);
    6565
    66         int ret = device_setup_uhci(device);
     66        const int ret = device_setup_uhci(device);
    6767        if (ret != EOK) {
    6868                usb_log_error("Failed to initialize UHCI driver: %s.\n",
    6969                    str_error(ret));
    70                 return ret;
     70        } else {
     71                usb_log_info("Controlling new UHCI device '%s'.\n",
     72                    device->name);
    7173        }
    72         usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
    7374
    74         return EOK;
     75        return ret;
    7576}
    7677/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/uhci/pci.c

    r47fecbb rfd07e526  
    6161        assert(io_reg_size);
    6262        assert(irq_no);
    63        
     63
    6464        async_sess_t *parent_sess =
    6565            devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
     
    6767        if (!parent_sess)
    6868                return ENOMEM;
    69        
     69
    7070        hw_resource_list_t hw_resources;
    7171        int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
     
    7474                return rc;
    7575        }
    76        
     76
    7777        uintptr_t io_address = 0;
    7878        size_t io_size = 0;
     
    102102                }
    103103        }
    104        
     104
    105105        async_hangup(parent_sess);
    106        
     106
    107107        if (!io_found || !irq_found)
    108108                return ENOENT;
    109        
     109
    110110        *io_reg_address = io_address;
    111111        *io_reg_size = io_size;
    112112        *irq_no = irq;
    113        
     113
    114114        return EOK;
    115115}
    116 
     116/*----------------------------------------------------------------------------*/
    117117/** Call the PCI driver with a request to enable interrupts
    118118 *
     
    127127        if (!parent_sess)
    128128                return ENOMEM;
    129        
     129
    130130        const bool enabled = hw_res_enable_interrupt(parent_sess);
    131131        async_hangup(parent_sess);
    132        
     132
    133133        return enabled ? EOK : EIO;
    134134}
    135 
     135/*----------------------------------------------------------------------------*/
    136136/** Call the PCI driver with a request to clear legacy support register
    137137 *
     
    142142{
    143143        assert(device);
    144        
     144
    145145        async_sess_t *parent_sess =
    146146            devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
     
    148148        if (!parent_sess)
    149149                return ENOMEM;
    150        
     150
    151151        /* See UHCI design guide for these values p.45,
    152152         * write all WC bits in USB legacy register */
    153153        const sysarg_t address = 0xc0;
    154154        const sysarg_t value = 0xaf00;
    155        
     155
    156156        async_exch_t *exch = async_exchange_begin(parent_sess);
    157        
     157
    158158        const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
    159159            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
    160        
     160
    161161        async_exchange_end(exch);
    162162        async_hangup(parent_sess);
    163        
     163
    164164        return rc;
    165165}
  • uspace/drv/bus/usb/uhci/root_hub.c

    r47fecbb rfd07e526  
    5050int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
    5151{
    52         int ret;
    53 
     52        assert(instance);
    5453        assert(fun);
    55 
    56         ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    57         if (ret != EOK) {
    58                 usb_log_error("Failed to add root hub match id: %s\n",
    59                     str_error(ret));
    60                 return ret;
    61         }
    6254
    6355        /* Initialize resource structure */
     
    7062        instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
    7163
    72         return EOK;
     64        const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
     65        if (ret != EOK) {
     66                usb_log_error("Failed to add root hub match id: %s\n",
     67                    str_error(ret));
     68        }
     69        return ret;
    7370}
    7471/**
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r47fecbb rfd07e526  
    3737#include <usb/debug.h>
    3838#include <libarch/barrier.h>
     39
    3940#include "transfer_list.h"
    40 #include "batch.h"
    4141
    4242static void transfer_list_remove_batch(
    43     transfer_list_t *instance, usb_transfer_batch_t *batch);
     43    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch);
    4444/*----------------------------------------------------------------------------*/
    4545/** Initialize transfer list structures.
     
    106106 */
    107107void transfer_list_add_batch(
    108     transfer_list_t *instance, usb_transfer_batch_t *batch)
    109 {
    110         assert(instance);
    111         assert(batch);
    112         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     108    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
     109{
     110        assert(instance);
     111        assert(uhci_batch);
     112        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name,
     113            uhci_batch->usb_batch);
    113114
    114115        fibril_mutex_lock(&instance->guard);
    115116
    116         qh_t *last_qh = NULL;
     117        /* Assume there is nothing scheduled */
     118        qh_t *last_qh = instance->queue_head;
     119        /* There is something scheduled */
     120        if (!list_empty(&instance->batch_list)) {
     121                last_qh = uhci_transfer_batch_from_link(
     122                    list_last(&instance->batch_list))->qh;
     123        }
    117124        /* Add to the hardware queue. */
    118         if (list_empty(&instance->batch_list)) {
    119                 /* There is nothing scheduled */
    120                 last_qh = instance->queue_head;
    121         } else {
    122                 /* There is something scheduled */
    123                 usb_transfer_batch_t *last = usb_transfer_batch_from_link(
    124                     list_last(&instance->batch_list));
    125                 last_qh = batch_qh(last);
    126         }
    127         const uint32_t pa = addr_to_phys(batch_qh(batch));
     125        const uint32_t pa = addr_to_phys(uhci_batch->qh);
    128126        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    129127
     
    132130
    133131        /* keep link */
    134         batch_qh(batch)->next = last_qh->next;
    135         qh_set_next_qh(last_qh, batch_qh(batch));
     132        uhci_batch->qh->next = last_qh->next;
     133        qh_set_next_qh(last_qh, uhci_batch->qh);
    136134
    137135        /* Make sure the pointer is updated */
     
    139137
    140138        /* Add to the driver's list */
    141         list_append(&batch->link, &instance->batch_list);
     139        list_append(&uhci_batch->link, &instance->batch_list);
    142140
    143141        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
    144             batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
     142            uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     143            instance->name);
    145144        fibril_mutex_unlock(&instance->guard);
    146145}
     
    157156
    158157        fibril_mutex_lock(&instance->guard);
    159         link_t *current = instance->batch_list.head.next;
    160         while (current != &instance->batch_list.head) {
     158        link_t *current = list_first(&instance->batch_list);
     159        while (current && current != &instance->batch_list.head) {
    161160                link_t * const next = current->next;
    162                 usb_transfer_batch_t *batch =
    163                     usb_transfer_batch_from_link(current);
    164 
    165                 if (batch_is_complete(batch)) {
     161                uhci_transfer_batch_t *batch =
     162                    uhci_transfer_batch_from_link(current);
     163
     164                if (uhci_transfer_batch_is_complete(batch)) {
    166165                        /* Save for processing */
    167166                        transfer_list_remove_batch(instance, batch);
     
    182181        while (!list_empty(&instance->batch_list)) {
    183182                link_t * const current = list_first(&instance->batch_list);
    184                 usb_transfer_batch_t *batch =
    185                     usb_transfer_batch_from_link(current);
     183                uhci_transfer_batch_t *batch =
     184                    uhci_transfer_batch_from_link(current);
    186185                transfer_list_remove_batch(instance, batch);
    187                 usb_transfer_batch_finish_error(batch, EINTR);
     186                batch->usb_batch->error = EINTR;
     187                uhci_transfer_batch_call_dispose(batch);
    188188        }
    189189        fibril_mutex_unlock(&instance->guard);
     
    198198 */
    199199void transfer_list_remove_batch(
    200     transfer_list_t *instance, usb_transfer_batch_t *batch)
     200    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
    201201{
    202202        assert(instance);
    203203        assert(instance->queue_head);
    204         assert(batch);
    205         assert(batch_qh(batch));
     204        assert(uhci_batch);
     205        assert(uhci_batch->qh);
    206206        assert(fibril_mutex_is_locked(&instance->guard));
    207207
    208         usb_log_debug2(
    209             "Queue %s: removing batch(%p).\n", instance->name, batch);
    210 
    211         const char *qpos = NULL;
    212         qh_t *prev_qh = NULL;
     208        usb_log_debug2("Queue %s: removing batch(%p).\n",
     209            instance->name, uhci_batch->usb_batch);
     210
     211        /* Assume I'm the first */
     212        const char *qpos = "FIRST";
     213        qh_t *prev_qh = instance->queue_head;
    213214        /* Remove from the hardware queue */
    214         if (list_first(&instance->batch_list) == &batch->link) {
    215                 /* I'm the first one here */
    216                 prev_qh = instance->queue_head;
    217                 qpos = "FIRST";
    218         } else {
    219                 /* The thing before me is a batch too */
    220                 usb_transfer_batch_t *prev =
    221                     usb_transfer_batch_from_link(batch->link.prev);
    222                 prev_qh = batch_qh(prev);
     215        if (list_first(&instance->batch_list) != &uhci_batch->link) {
     216                /* There is a batch in front of me */
     217                prev_qh =
     218                    uhci_transfer_batch_from_link(uhci_batch->link.prev)->qh;
    223219                qpos = "NOT FIRST";
    224220        }
    225221        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
    226             == addr_to_phys(batch_qh(batch)));
    227         prev_qh->next = batch_qh(batch)->next;
     222            == addr_to_phys(uhci_batch->qh));
     223        prev_qh->next = uhci_batch->qh->next;
    228224
    229225        /* Make sure the pointer is updated */
     
    231227
    232228        /* Remove from the batch list */
    233         list_remove(&batch->link);
     229        list_remove(&uhci_batch->link);
    234230        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
    235231            "from %s, next: %x.\n",
    236             batch, USB_TRANSFER_BATCH_ARGS(*batch),
    237             qpos, instance->name, batch_qh(batch)->next);
     232            uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     233            qpos, instance->name, uhci_batch->qh->next);
    238234}
    239235/**
  • uspace/drv/bus/usb/uhci/transfer_list.h

    r47fecbb rfd07e526  
    3636
    3737#include <fibril_synch.h>
    38 #include <usb/host/batch.h>
    3938
    4039#include "hw_struct/queue_head.h"
    41 
     40#include "uhci_batch.h"
    4241/** Structure maintaining both hw queue and software list
    4342 * of currently executed transfers
     
    4645        /** Guard against multiple add/remove races */
    4746        fibril_mutex_t guard;
    48         /** UHCI hw structure represeting this queue */
     47        /** UHCI hw structure representing this queue */
    4948        qh_t *queue_head;
    5049        /** Assigned name, for nicer debug output */
     
    5857void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    5958void transfer_list_add_batch(
    60     transfer_list_t *instance, usb_transfer_batch_t *batch);
     59    transfer_list_t *instance, uhci_transfer_batch_t *batch);
    6160void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
    6261void transfer_list_abort_all(transfer_list_t *instance);
  • uspace/drv/bus/usb/uhci/uhci.c

    r47fecbb rfd07e526  
    4141
    4242#include "uhci.h"
    43 #include "iface.h"
    4443#include "pci.h"
    4544
     
    8786/** Operations supported by the HC driver */
    8887static ddf_dev_ops_t hc_ops = {
    89         .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
     88        .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
    9089};
    9190/*----------------------------------------------------------------------------*/
     
    10099{
    101100        assert(fun);
    102         usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
    103         usb_address_t addr = usb_device_keeper_find(manager, handle);
     101        usb_device_manager_t *manager =
     102            &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
     103        const usb_address_t addr = usb_device_manager_find(manager, handle);
    104104
    105105        if (addr < 0) {
     
    202202        CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
    203203        instance->hc_fun->ops = &hc_ops;
    204         instance->hc_fun->driver_data = &instance->hc;
     204        instance->hc_fun->driver_data = &instance->hc.generic;
    205205
    206206        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
  • uspace/drv/bus/usb/uhci/utils/malloc32.h

    r47fecbb rfd07e526  
    5050 * @return Physical address if exists, NULL otherwise.
    5151 */
    52 static inline uintptr_t addr_to_phys(void *addr)
     52static inline uintptr_t addr_to_phys(const void *addr)
    5353{
    5454        if (addr == NULL)
     
    102102        if (free_address == 0)
    103103                return NULL;
    104         void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
     104        void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    105105                  AS_AREA_READ | AS_AREA_WRITE);
    106         if (ret != free_address)
     106        if (address != free_address)
    107107                return NULL;
    108         return ret;
     108        return address;
     109}
     110/*----------------------------------------------------------------------------*/
     111static inline void return_page(void *page)
     112{
     113        if (page)
     114                as_area_destroy(page);
    109115}
    110116
  • uspace/drv/bus/usb/vhc/connhost.c

    r47fecbb rfd07e526  
    6262        VHC_DATA(vhc, fun);
    6363
    64         usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
    65             USB_SPEED_HIGH);
     64        usb_address_t addr = usb_device_manager_get_free_address(
     65            &vhc->dev_manager, USB_SPEED_HIGH);
    6666        if (addr < 0) {
    6767                return addr;
     
    8888        usb_log_debug("Binding handle %" PRIun " to address %d.\n",
    8989            handle, address);
    90         usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
     90        usb_device_manager_bind(&vhc->dev_manager, address, handle);
    9191
    9292        return EOK;
     
    105105        VHC_DATA(vhc, fun);
    106106        bool found =
    107             usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
     107            usb_device_manager_find_by_address(&vhc->dev_manager, address, handle);
    108108        return found ? EOK : ENOENT;
    109109}
     
    119119        VHC_DATA(vhc, fun);
    120120        usb_log_debug("Releasing address %d...\n", address);
    121         usb_device_keeper_release(&vhc->dev_keeper, address);
     121        usb_device_manager_release(&vhc->dev_manager, address);
    122122
    123123        return ENOTSUP;
     
    172172        VHC_DATA(vhc, fun);
    173173
    174         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    175             address, endpoint, direction, NULL);
    176         if (ep == NULL) {
    177                 return ENOENT;
    178         }
    179 
    180174        int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
    181175            address, endpoint, direction);
     
    183177        return rc;
    184178}
    185 
     179#if 0
    186180/** Schedule interrupt out transfer.
    187181 *
     
    413407        return EOK;
    414408}
     409#endif
     410static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer,
     411    uint8_t *data_buffer, size_t data_buffer_size,
     412    usbhc_iface_transfer_in_callback_t callback, void *arg)
     413{
     414        VHC_DATA(vhc, fun);
     415
     416        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     417            target.address, target.endpoint, USB_DIRECTION_IN, NULL);
     418        if (ep == NULL) {
     419                return ENOENT;
     420        }
     421        const usb_transfer_type_t transfer_type = ep->transfer_type;
     422
     423
     424        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     425            target.endpoint, USB_DIRECTION_IN, transfer_type,
     426            fun, arg);
     427        if (transfer == NULL) {
     428                return ENOMEM;
     429        }
     430        if (transfer_type == USB_TRANSFER_CONTROL) {
     431                transfer->setup_buffer = malloc(sizeof(uint64_t));
     432                assert(transfer->setup_buffer);
     433                memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t));
     434                transfer->setup_buffer_size = sizeof(uint64_t);
     435        }
     436        transfer->data_buffer = data_buffer;
     437        transfer->data_buffer_size = data_buffer_size;
     438        transfer->callback_in = callback;
     439
     440        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     441        if (rc != EOK) {
     442                free(transfer->setup_buffer);
     443                free(transfer);
     444                return rc;
     445        }
     446
     447        return EOK;
     448}
     449
     450static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_buffer,
     451    const uint8_t *data_buffer, size_t data_buffer_size,
     452    usbhc_iface_transfer_out_callback_t callback, void *arg)
     453{
     454        VHC_DATA(vhc, fun);
     455
     456        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     457            target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
     458        if (ep == NULL) {
     459                return ENOENT;
     460        }
     461        const usb_transfer_type_t transfer_type = ep->transfer_type;
     462
     463
     464        vhc_transfer_t *transfer = vhc_transfer_create(target.address,
     465            target.endpoint, USB_DIRECTION_OUT, transfer_type,
     466            fun, arg);
     467        if (transfer == NULL) {
     468                return ENOMEM;
     469        }
     470        if (transfer_type == USB_TRANSFER_CONTROL) {
     471                transfer->setup_buffer = malloc(sizeof(uint64_t));
     472                assert(transfer->setup_buffer);
     473                memcpy(transfer->setup_buffer, &setup_buffer, sizeof(uint64_t));
     474                transfer->setup_buffer_size = sizeof(uint64_t);
     475        }
     476        transfer->data_buffer = (void*)data_buffer;
     477        transfer->data_buffer_size = data_buffer_size;
     478        transfer->callback_out = callback;
     479
     480        int rc = vhc_virtdev_add_transfer(vhc, transfer);
     481        if (rc != EOK) {
     482                free(transfer->setup_buffer);
     483                free(transfer);
     484                return rc;
     485        }
     486
     487        return EOK;
     488}
    415489
    416490static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
     
    442516
    443517        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
    444         usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
     518        usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle);
    445519        if (addr < 0) {
    446520                return addr;
     
    460534        .unregister_endpoint = unregister_endpoint,
    461535
    462         .interrupt_out = interrupt_out,
    463         .interrupt_in = interrupt_in,
    464 
    465         .bulk_in = bulk_in,
    466         .bulk_out = bulk_out,
    467 
    468         .control_write = control_write,
    469         .control_read = control_read
     536        .write = usb_write,
     537        .read = usb_read,
    470538};
    471539
  • uspace/drv/bus/usb/vhc/main.c

    r47fecbb rfd07e526  
    7373        }
    7474        data->magic = 0xDEADBEEF;
    75         rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
     75        rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1,
     76            bandwidth_count_usb11);
    7677        if (rc != EOK) {
    7778                usb_log_fatal("Failed to initialize endpoint manager.\n");
     
    7980                return rc;
    8081        }
    81         usb_device_keeper_init(&data->dev_keeper);
     82        usb_device_manager_init(&data->dev_manager);
    8283
    8384        ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
  • uspace/drv/bus/usb/vhc/vhcd.h

    r47fecbb rfd07e526  
    3939#include <usbvirt/device.h>
    4040#include <usb/host/usb_endpoint_manager.h>
    41 #include <usb/host/device_keeper.h>
     41#include <usb/host/usb_device_manager.h>
    4242#include <usbhc_iface.h>
    4343#include <async.h>
     
    6060        fibril_mutex_t guard;
    6161        usb_endpoint_manager_t ep_manager;
    62         usb_device_keeper_t dev_keeper;
     62        usb_device_manager_t dev_manager;
    6363        usbvirt_device_t *hub;
    6464        ddf_fun_t *hc_fun;
  • uspace/lib/c/generic/as.c

    r47fecbb rfd07e526  
    123123 * @retval ENOENT Mapping not found.
    124124 */
    125 int as_get_physical_mapping(void *address, uintptr_t *frame)
     125int as_get_physical_mapping(const void *address, uintptr_t *frame)
    126126{
    127127        uintptr_t tmp_frame;
  • uspace/lib/c/include/as.h

    r47fecbb rfd07e526  
    6060extern void *set_maxheapsize(size_t);
    6161extern void *as_get_mappable_page(size_t);
    62 extern int as_get_physical_mapping(void *, uintptr_t *);
     62extern int as_get_physical_mapping(const void *, uintptr_t *);
    6363
    6464#endif
  • uspace/lib/drv/generic/remote_usbhc.c

    r47fecbb rfd07e526  
    4141
    4242#define USB_MAX_PAYLOAD_SIZE 1020
    43 #define HACK_MAX_PACKET_SIZE 8
    44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
    45 
    46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     43
    5244static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5345static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    5648static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5749static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     50static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     51static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5852//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5953
    6054/** Remote USB host controller interface operations. */
    61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    62         remote_usbhc_request_address,
    63         remote_usbhc_bind_address,
    64         remote_usbhc_find_by_address,
    65         remote_usbhc_release_address,
    66 
    67         remote_usbhc_interrupt_out,
    68         remote_usbhc_interrupt_in,
    69 
    70         remote_usbhc_bulk_out,
    71         remote_usbhc_bulk_in,
    72 
    73         remote_usbhc_control_write,
    74         remote_usbhc_control_read,
    75 
    76         remote_usbhc_register_endpoint,
    77         remote_usbhc_unregister_endpoint
     55static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
     56        [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
     57        [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
     58        [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
     59        [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
     60
     61        [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     62        [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
     63
     64        [IPC_M_USBHC_READ] = remote_usbhc_read,
     65        [IPC_M_USBHC_WRITE] = remote_usbhc_write,
    7866};
    7967
     
    9078        ipc_callid_t data_caller;
    9179        void *buffer;
    92         void *setup_packet;
    9380        size_t size;
    9481} async_transaction_t;
     
    9885        if (trans == NULL) {
    9986                return;
    100         }
    101 
    102         if (trans->setup_packet != NULL) {
    103                 free(trans->setup_packet);
    10487        }
    10588        if (trans->buffer != NULL) {
     
    120103        trans->data_caller = 0;
    121104        trans->buffer = NULL;
    122         trans->setup_packet = NULL;
    123105        trans->size = 0;
    124106
     
    135117                return;
    136118        }
    137        
     119
    138120        usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    139121
     
    239221        async_transaction_destroy(trans);
    240222}
    241 
    242 /** Process an outgoing transfer (both OUT and SETUP).
    243  *
    244  * @param device Target device.
    245  * @param callid Initiating caller.
    246  * @param call Initiating call.
    247  * @param transfer_func Transfer function (might be NULL).
    248  */
    249 static void remote_usbhc_out_transfer(ddf_fun_t *fun,
    250     ipc_callid_t callid, ipc_call_t *call,
    251     usbhc_iface_transfer_out_t transfer_func)
    252 {
    253         if (!transfer_func) {
    254                 async_answer_0(callid, ENOTSUP);
    255                 return;
    256         }
    257 
    258         usb_target_t target = {
    259                 .address = DEV_IPC_GET_ARG1(*call),
    260                 .endpoint = DEV_IPC_GET_ARG2(*call)
    261         };
    262 
    263         size_t len = 0;
    264         void *buffer = NULL;
    265 
    266         int rc = async_data_write_accept(&buffer, false,
    267             1, USB_MAX_PAYLOAD_SIZE,
    268             0, &len);
    269 
    270         if (rc != EOK) {
    271                 async_answer_0(callid, rc);
    272                 return;
    273         }
    274 
    275         async_transaction_t *trans = async_transaction_create(callid);
    276         if (trans == NULL) {
    277                 if (buffer != NULL) {
    278                         free(buffer);
    279                 }
    280                 async_answer_0(callid, ENOMEM);
    281                 return;
    282         }
    283 
    284         trans->buffer = buffer;
    285         trans->size = len;
    286 
    287         rc = transfer_func(fun, target,
    288             buffer, len,
    289             callback_out, trans);
    290 
    291         if (rc != EOK) {
    292                 async_answer_0(callid, rc);
    293                 async_transaction_destroy(trans);
    294         }
    295 }
    296 
    297 /** Process an incoming transfer.
    298  *
    299  * @param device Target device.
    300  * @param callid Initiating caller.
    301  * @param call Initiating call.
    302  * @param transfer_func Transfer function (might be NULL).
    303  */
    304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,
    305     ipc_callid_t callid, ipc_call_t *call,
    306     usbhc_iface_transfer_in_t transfer_func)
    307 {
    308         if (!transfer_func) {
    309                 async_answer_0(callid, ENOTSUP);
    310                 return;
    311         }
    312 
    313         usb_target_t target = {
    314                 .address = DEV_IPC_GET_ARG1(*call),
    315                 .endpoint = DEV_IPC_GET_ARG2(*call)
    316         };
    317 
    318         size_t len;
    319         ipc_callid_t data_callid;
    320         if (!async_data_read_receive(&data_callid, &len)) {
    321                 async_answer_0(callid, EPARTY);
    322                 return;
    323         }
    324 
    325         async_transaction_t *trans = async_transaction_create(callid);
    326         if (trans == NULL) {
    327                 async_answer_0(data_callid, ENOMEM);
    328                 async_answer_0(callid, ENOMEM);
    329                 return;
    330         }
    331         trans->data_caller = data_callid;
    332         trans->buffer = malloc(len);
    333         trans->size = len;
    334 
    335         int rc = transfer_func(fun, target,
    336             trans->buffer, len,
    337             callback_in, trans);
    338 
    339         if (rc != EOK) {
    340                 async_answer_0(data_callid, rc);
    341                 async_answer_0(callid, rc);
    342                 async_transaction_destroy(trans);
    343         }
    344 }
    345 
    346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,
    347     ipc_callid_t callid, ipc_call_t *call)
    348 {
    349         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    350         assert(usb_iface != NULL);
    351 
    352         return remote_usbhc_out_transfer(fun, callid, call,
    353             usb_iface->interrupt_out);
    354 }
    355 
    356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,
    357     ipc_callid_t callid, ipc_call_t *call)
    358 {
    359         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    360         assert(usb_iface != NULL);
    361 
    362         return remote_usbhc_in_transfer(fun, callid, call,
    363             usb_iface->interrupt_in);
    364 }
    365 
    366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,
    367     ipc_callid_t callid, ipc_call_t *call)
    368 {
    369         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    370         assert(usb_iface != NULL);
    371 
    372         return remote_usbhc_out_transfer(fun, callid, call,
    373             usb_iface->bulk_out);
    374 }
    375 
    376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,
    377     ipc_callid_t callid, ipc_call_t *call)
    378 {
    379         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    380         assert(usb_iface != NULL);
    381 
    382         return remote_usbhc_in_transfer(fun, callid, call,
    383             usb_iface->bulk_in);
    384 }
    385 
    386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
    387 ipc_callid_t callid, ipc_call_t *call)
    388 {
    389         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    390         assert(usb_iface != NULL);
    391 
    392         if (!usb_iface->control_write) {
    393                 async_answer_0(callid, ENOTSUP);
    394                 return;
    395         }
    396 
    397         usb_target_t target = {
    398                 .address = DEV_IPC_GET_ARG1(*call),
    399                 .endpoint = DEV_IPC_GET_ARG2(*call)
    400         };
    401         size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
    402 
    403         int rc;
    404 
    405         void *setup_packet = NULL;
    406         void *data_buffer = NULL;
    407         size_t setup_packet_len = 0;
    408 
    409         rc = async_data_write_accept(&setup_packet, false,
    410             1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
    411         if (rc != EOK) {
    412                 async_answer_0(callid, rc);
    413                 return;
    414         }
    415 
    416         if (data_buffer_len > 0) {
    417                 rc = async_data_write_accept(&data_buffer, false,
    418                     1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
    419                 if (rc != EOK) {
    420                         async_answer_0(callid, rc);
    421                         free(setup_packet);
    422                         return;
    423                 }
    424         }
    425 
    426         async_transaction_t *trans = async_transaction_create(callid);
    427         if (trans == NULL) {
    428                 async_answer_0(callid, ENOMEM);
    429                 free(setup_packet);
    430                 free(data_buffer);
    431                 return;
    432         }
    433         trans->setup_packet = setup_packet;
    434         trans->buffer = data_buffer;
    435         trans->size = data_buffer_len;
    436 
    437         rc = usb_iface->control_write(fun, target,
    438             setup_packet, setup_packet_len,
    439             data_buffer, data_buffer_len,
    440             callback_out, trans);
    441 
    442         if (rc != EOK) {
    443                 async_answer_0(callid, rc);
    444                 async_transaction_destroy(trans);
    445         }
    446 }
    447 
    448 
    449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
    450 ipc_callid_t callid, ipc_call_t *call)
    451 {
    452         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    453         assert(usb_iface != NULL);
    454 
    455         if (!usb_iface->control_read) {
    456                 async_answer_0(callid, ENOTSUP);
    457                 return;
    458         }
    459 
    460         usb_target_t target = {
    461                 .address = DEV_IPC_GET_ARG1(*call),
    462                 .endpoint = DEV_IPC_GET_ARG2(*call)
    463         };
    464 
    465         int rc;
    466 
    467         void *setup_packet = NULL;
    468         size_t setup_packet_len = 0;
    469         size_t data_len = 0;
    470 
    471         rc = async_data_write_accept(&setup_packet, false,
    472             1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
    473         if (rc != EOK) {
    474                 async_answer_0(callid, rc);
    475                 return;
    476         }
    477 
    478         ipc_callid_t data_callid;
    479         if (!async_data_read_receive(&data_callid, &data_len)) {
    480                 async_answer_0(callid, EPARTY);
    481                 free(setup_packet);
    482                 return;
    483         }
    484 
    485         async_transaction_t *trans = async_transaction_create(callid);
    486         if (trans == NULL) {
    487                 async_answer_0(data_callid, ENOMEM);
    488                 async_answer_0(callid, ENOMEM);
    489                 free(setup_packet);
    490                 return;
    491         }
    492         trans->data_caller = data_callid;
    493         trans->setup_packet = setup_packet;
    494         trans->size = data_len;
    495         trans->buffer = malloc(data_len);
    496         if (trans->buffer == NULL) {
    497                 async_answer_0(data_callid, ENOMEM);
    498                 async_answer_0(callid, ENOMEM);
    499                 async_transaction_destroy(trans);
    500                 return;
    501         }
    502 
    503         rc = usb_iface->control_read(fun, target,
    504             setup_packet, setup_packet_len,
    505             trans->buffer, trans->size,
    506             callback_in, trans);
    507 
    508         if (rc != EOK) {
    509                 async_answer_0(data_callid, rc);
    510                 async_answer_0(callid, rc);
    511                 async_transaction_destroy(trans);
    512         }
    513 }
    514 
    515223
    516224void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     
    535243        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
    536244
    537         _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
    538         _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
     245        const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    539246
    540247        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     
    551258#undef _INIT_FROM_LOW_DATA3
    552259
    553         int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
    554             transfer_type, direction, max_packet_size, interval);
     260        int rc = usb_iface->register_endpoint(fun, target.address, speed,
     261            target.endpoint, transfer_type, direction, max_packet_size, interval);
    555262
    556263        async_answer_0(callid, rc);
    557264}
    558 
    559265
    560266void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     
    578284}
    579285
     286void remote_usbhc_read(
     287    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     288{
     289        assert(fun);
     290        assert(iface);
     291        assert(call);
     292
     293        const usbhc_iface_t *hc_iface = iface;
     294
     295        if (!hc_iface->read) {
     296                async_answer_0(callid, ENOTSUP);
     297                return;
     298        }
     299
     300        const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     301        const uint64_t setup =
     302            ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
     303            (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
     304
     305        async_transaction_t *trans = async_transaction_create(callid);
     306        if (trans == NULL) {
     307                async_answer_0(callid, ENOMEM);
     308                return;
     309        }
     310
     311        if (!async_data_read_receive(&trans->data_caller, &trans->size)) {
     312                async_answer_0(callid, EPARTY);
     313                return;
     314        }
     315
     316        trans->buffer = malloc(trans->size);
     317        if (trans->buffer == NULL) {
     318                async_answer_0(trans->data_caller, ENOMEM);
     319                async_answer_0(callid, ENOMEM);
     320                async_transaction_destroy(trans);
     321        }
     322
     323        const int rc = hc_iface->read(
     324            fun, target, setup, trans->buffer, trans->size, callback_in, trans);
     325
     326        if (rc != EOK) {
     327                async_answer_0(trans->data_caller, rc);
     328                async_answer_0(callid, rc);
     329                async_transaction_destroy(trans);
     330        }
     331}
     332
     333void remote_usbhc_write(
     334    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     335{
     336        assert(fun);
     337        assert(iface);
     338        assert(call);
     339
     340        const usbhc_iface_t *hc_iface = iface;
     341
     342        if (!hc_iface->write) {
     343                async_answer_0(callid, ENOTSUP);
     344                return;
     345        }
     346
     347        const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
     348        const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
     349        const uint64_t setup =
     350            ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
     351            (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
     352
     353        async_transaction_t *trans = async_transaction_create(callid);
     354        if (trans == NULL) {
     355                async_answer_0(callid, ENOMEM);
     356                return;
     357        }
     358
     359        if (data_buffer_len > 0) {
     360                int rc = async_data_write_accept(&trans->buffer, false,
     361                    1, USB_MAX_PAYLOAD_SIZE,
     362                    0, &trans->size);
     363
     364                if (rc != EOK) {
     365                        async_answer_0(callid, rc);
     366                        async_transaction_destroy(trans);
     367                        return;
     368                }
     369        }
     370
     371        int rc = hc_iface->write(
     372            fun, target, setup, trans->buffer, trans->size, callback_out, trans);
     373
     374        if (rc != EOK) {
     375                async_answer_0(callid, rc);
     376                async_transaction_destroy(trans);
     377        }
     378}
     379
    580380
    581381/**
  • uspace/lib/drv/include/usbhc_iface.h

    r47fecbb rfd07e526  
    123123        IPC_M_USBHC_RELEASE_ADDRESS,
    124124
    125 
    126         /** Send interrupt data to device.
    127          * See explanation at usb_iface_funcs_t (OUT transaction).
    128          */
    129         IPC_M_USBHC_INTERRUPT_OUT,
    130 
    131         /** Get interrupt data from device.
    132          * See explanation at usb_iface_funcs_t (IN transaction).
    133          */
    134         IPC_M_USBHC_INTERRUPT_IN,
    135 
    136         /** Send bulk data to device.
    137          * See explanation at usb_iface_funcs_t (OUT transaction).
    138          */
    139         IPC_M_USBHC_BULK_OUT,
    140 
    141         /** Get bulk data from device.
    142          * See explanation at usb_iface_funcs_t (IN transaction).
    143          */
    144         IPC_M_USBHC_BULK_IN,
    145 
    146         /** Issue control WRITE transfer.
    147          * See explanation at usb_iface_funcs_t (OUT transaction) for
    148          * call parameters.
    149          * This call is immediately followed by two IPC data writes
    150          * from the caller (setup packet and actual data).
    151          */
    152         IPC_M_USBHC_CONTROL_WRITE,
    153 
    154         /** Issue control READ transfer.
    155          * See explanation at usb_iface_funcs_t (IN transaction) for
    156          * call parameters.
    157          * This call is immediately followed by IPC data write from the caller
    158          * (setup packet) and IPC data read (buffer that was read).
    159          */
    160         IPC_M_USBHC_CONTROL_READ,
    161 
    162125        /** Register endpoint attributes at host controller.
    163126         * This is used to reserve portion of USB bandwidth.
     
    185148         * - ENOENT - unknown endpoint
    186149         */
    187         IPC_M_USBHC_UNREGISTER_ENDPOINT
     150        IPC_M_USBHC_UNREGISTER_ENDPOINT,
     151
     152        /** Get data from device.
     153         * See explanation at usb_iface_funcs_t (IN transaction).
     154         */
     155        IPC_M_USBHC_READ,
     156
     157        /** Send data to device.
     158         * See explanation at usb_iface_funcs_t (OUT transaction).
     159         */
     160        IPC_M_USBHC_WRITE,
    188161} usbhc_iface_funcs_t;
    189162
    190163/** Callback for outgoing transfer. */
    191 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *,
    192     int, void *);
     164typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *);
    193165
    194166/** Callback for incoming transfer. */
    195167typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
    196168    int, size_t, void *);
    197 
    198 
    199 /** Out transfer processing function prototype. */
    200 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
    201     void *, size_t,
    202     usbhc_iface_transfer_out_callback_t, void *);
    203 
    204 /** Setup transfer processing function prototype. @deprecated */
    205 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
    206 
    207 /** In transfer processing function prototype. */
    208 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
    209     void *, size_t,
    210     usbhc_iface_transfer_in_callback_t, void *);
    211169
    212170/** USB host controller communication interface. */
     
    223181            usb_direction_t);
    224182
    225         usbhc_iface_transfer_out_t interrupt_out;
    226         usbhc_iface_transfer_in_t interrupt_in;
     183        int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t,
     184            usbhc_iface_transfer_in_callback_t, void *);
    227185
    228         usbhc_iface_transfer_out_t bulk_out;
    229         usbhc_iface_transfer_in_t bulk_in;
    230 
    231         int (*control_write)(ddf_fun_t *, usb_target_t,
    232             void *, size_t, void *, size_t,
    233             usbhc_iface_transfer_out_callback_t, void *);
    234 
    235         int (*control_read)(ddf_fun_t *, usb_target_t,
    236             void *, size_t, void *, size_t,
    237             usbhc_iface_transfer_in_callback_t, void *);
     186        int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *,
     187            size_t, usbhc_iface_transfer_out_callback_t, void *);
    238188} usbhc_iface_t;
    239189
  • uspace/lib/usb/include/usb/hc.h

    r47fecbb rfd07e526  
    6262    devman_handle_t *);
    6363
    64 int usb_hc_get_address_by_handle(devman_handle_t);
     64usb_address_t usb_hc_get_address_by_handle(devman_handle_t);
    6565
    6666int usb_hc_find(devman_handle_t, devman_handle_t *);
  • uspace/lib/usb/include/usb/usb.h

    r47fecbb rfd07e526  
    3636#define LIBUSB_USB_H_
    3737
     38#include <bool.h>
    3839#include <sys/types.h>
    3940#include <byteorder.h>
     
    105106 * Negative values could be used to indicate error.
    106107 */
    107 typedef int usb_address_t;
     108typedef int16_t usb_address_t;
    108109
    109110/** Default USB address. */
     
    115116 * Negative values could be used to indicate error.
    116117 */
    117 typedef int usb_endpoint_t;
     118typedef int16_t usb_endpoint_t;
    118119
    119120/** Maximum endpoint number in USB 1.1.
     
    125126 * Pair address + endpoint is identification of transaction recipient.
    126127 */
    127 typedef struct {
    128         usb_address_t address;
    129         usb_endpoint_t endpoint;
     128typedef union {
     129        struct {
     130                usb_address_t address;
     131                usb_endpoint_t endpoint;
     132        } __attribute__((packed));
     133        uint32_t packed;
    130134} usb_target_t;
     135
     136/** Check USB target for allowed values (address and endpoint).
     137 *
     138 * @param target.
     139 * @return True, if values are wihtin limits, false otherwise.
     140 */
     141static inline bool usb_target_is_valid(usb_target_t target)
     142{
     143        return !(target.endpoint > 15 || target.endpoint < 0
     144            || target.address >= USB11_ADDRESS_MAX || target.address < 0);
     145}
    131146
    132147/** Compare USB targets (addresses and endpoints).
  • uspace/lib/usbdev/src/pipesinit.c

    r47fecbb rfd07e526  
    486486                return EBADF;
    487487       
     488        const usb_target_t target =
     489            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    488490#define _PACK2(high, low) (((high) << 16) + (low))
    489491#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     
    491493        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    492494        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    493             IPC_M_USBHC_REGISTER_ENDPOINT,
    494             _PACK2(pipe->wire->address, pipe->endpoint_no),
     495            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    495496            _PACK3(speed, pipe->transfer_type, pipe->direction),
    496497            _PACK2(pipe->max_packet_size, interval));
  • uspace/lib/usbdev/src/pipesio.c

    r47fecbb rfd07e526  
    6565    void *buffer, size_t size, size_t *size_transfered)
    6666{
    67         /*
    68          * Get corresponding IPC method.
    69          * In future, replace with static array of mappings
    70          * transfer type -> method.
    71          */
    72         usbhc_iface_funcs_t ipc_method;
    73         switch (pipe->transfer_type) {
    74                 case USB_TRANSFER_INTERRUPT:
    75                         ipc_method = IPC_M_USBHC_INTERRUPT_IN;
    76                         break;
    77                 case USB_TRANSFER_BULK:
    78                         ipc_method = IPC_M_USBHC_BULK_IN;
    79                         break;
    80                 default:
    81                         return ENOTSUP;
    82         }
     67        /* Only interrupt and bulk transfers are supported */
     68        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
     69            pipe->transfer_type != USB_TRANSFER_BULK)
     70            return ENOTSUP;
     71
     72        const usb_target_t target =
     73            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    8374       
    8475        /* Ensure serialization over the phone. */
     
    8980         * Make call identifying target USB device and type of transfer.
    9081         */
    91         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    92             ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     82        aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USBHC_READ, target.packed, NULL);
    9384       
    9485        if (opening_request == 0) {
     
    213204    void *buffer, size_t size)
    214205{
    215         /*
    216          * Get corresponding IPC method.
    217          * In future, replace with static array of mappings
    218          * transfer type -> method.
    219          */
    220         usbhc_iface_funcs_t ipc_method;
    221         switch (pipe->transfer_type) {
    222                 case USB_TRANSFER_INTERRUPT:
    223                         ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
    224                         break;
    225                 case USB_TRANSFER_BULK:
    226                         ipc_method = IPC_M_USBHC_BULK_OUT;
    227                         break;
    228                 default:
    229                         return ENOTSUP;
    230         }
     206        /* Only interrupt and bulk transfers are supported */
     207        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
     208            pipe->transfer_type != USB_TRANSFER_BULK)
     209            return ENOTSUP;
     210
     211        const usb_target_t target =
     212            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    231213
    232214        /* Ensure serialization over the phone. */
     
    238220         */
    239221        aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    240             ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
     222            IPC_M_USBHC_WRITE, target.packed, size, NULL);
    241223       
    242224        if (opening_request == 0) {
     
    352334        pipe_start_transaction(pipe);
    353335
     336        const usb_target_t target =
     337            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     338
     339        assert(setup_buffer_size == 8);
     340        uint64_t setup_packet;
     341        memcpy(&setup_packet, setup_buffer, 8);
    354342        /*
    355343         * Make call identifying target USB device and control transfer type.
    356344         */
    357345        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    358         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    359             IPC_M_USBHC_CONTROL_READ, pipe->wire->address, pipe->endpoint_no,
    360             NULL);
    361        
     346        aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     347            IPC_M_USBHC_READ, target.packed,
     348            (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
     349
    362350        if (opening_request == 0) {
    363351                async_exchange_end(exch);
    364352                return ENOMEM;
    365353        }
    366        
    367         /*
    368          * Send the setup packet.
    369          */
    370         int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
    371         if (rc != EOK) {
    372                 async_exchange_end(exch);
    373                 pipe_end_transaction(pipe);
    374                 async_wait_for(opening_request, NULL);
    375                 return rc;
    376         }
    377        
     354
    378355        /*
    379356         * Retrieve the data.
     
    498475        pipe_start_transaction(pipe);
    499476
     477        const usb_target_t target =
     478            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     479        assert(setup_buffer_size == 8);
     480        uint64_t setup_packet;
     481        memcpy(&setup_packet, setup_buffer, 8);
     482
    500483        /*
    501484         * Make call identifying target USB device and control transfer type.
    502485         */
    503486        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    504         aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    505             IPC_M_USBHC_CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,
    506             data_buffer_size, NULL);
     487        aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     488            IPC_M_USBHC_WRITE, target.packed, data_buffer_size,
     489            (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    507490       
    508491        if (opening_request == 0) {
     
    511494                return ENOMEM;
    512495        }
    513        
    514         /*
    515          * Send the setup packet.
    516          */
    517         int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
    518         if (rc != EOK) {
    519                 async_exchange_end(exch);
    520                 pipe_end_transaction(pipe);
    521                 async_wait_for(opening_request, NULL);
    522                 return rc;
    523         }
    524        
     496
    525497        /*
    526498         * Send the data (if any).
    527499         */
    528500        if (data_buffer_size > 0) {
    529                 rc = async_data_write_start(exch, data_buffer, data_buffer_size);
     501                int rc = async_data_write_start(exch, data_buffer, data_buffer_size);
    530502               
    531503                /* All data sent, pipe can be released. */
  • uspace/lib/usbhost/Makefile

    r47fecbb rfd07e526  
    3232        -I$(LIBUSB_PREFIX)/include \
    3333        -I$(LIBDRV_PREFIX)/include \
    34         -Iinclude
     34        -Iinclude 
    3535
    3636SOURCES = \
    37         src/batch.c \
    38         src/device_keeper.c \
    3937        src/endpoint.c \
    40         src/usb_endpoint_manager.c
     38        src/iface.c \
     39        src/usb_device_manager.c \
     40        src/usb_endpoint_manager.c \
     41        src/usb_transfer_batch.c
    4142
    4243include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r47fecbb rfd07e526  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
     56        void (*destroy_hook)(struct endpoint *);
    5657        struct {
    5758                void *data;
     
    6869
    6970void endpoint_set_hc_data(endpoint_t *instance,
    70     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71    void *data, void (*destroy_hook)(endpoint_t *),
     72    int (*toggle_get)(void *), void (*toggle_set)(void *, int));
    7173
    7274void endpoint_clear_hc_data(endpoint_t *instance);
  • uspace/lib/usbhost/include/usb/host/usb_device_manager.h

    r47fecbb rfd07e526  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/** @addtogroup libusbhost
    3029 * @{
    3130 */
    3231/** @file
    33  * Device keeper structure and functions.
     32 * Device manager structure and functions.
    3433 *
    3534 * Typical USB host controller needs to keep track of various settings for
     
    3837 * This structure shall simplify the management.
    3938 */
    40 #ifndef LIBUSBHOST_HOST_DEVICE_KEEPER_H
    41 #define LIBUSBHOST_HOST_DEVICE_KEEPER_H
     39#ifndef LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H
     40#define LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H
    4241
    4342#include <adt/list.h>
     
    5756};
    5857
    59 /** Host controller device keeper.
     58/** Host controller device manager.
    6059 * You shall not access members directly but only using functions below.
    6160 */
     
    6463        fibril_mutex_t guard;
    6564        usb_address_t last_address;
    66 } usb_device_keeper_t;
     65} usb_device_manager_t;
    6766
    68 void usb_device_keeper_init(usb_device_keeper_t *instance);
     67void usb_device_manager_init(usb_device_manager_t *instance);
    6968
    70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
    71     usb_speed_t speed);
     69usb_address_t usb_device_manager_get_free_address(
     70    usb_device_manager_t *instance, usb_speed_t speed);
    7271
    73 void usb_device_keeper_bind(usb_device_keeper_t *instance,
     72void usb_device_manager_bind(usb_device_manager_t *instance,
    7473    usb_address_t address, devman_handle_t handle);
    7574
    76 void usb_device_keeper_release(usb_device_keeper_t *instance,
     75void usb_device_manager_release(usb_device_manager_t *instance,
    7776    usb_address_t address);
    7877
    79 usb_address_t usb_device_keeper_find(usb_device_keeper_t *instance,
     78usb_address_t usb_device_manager_find(usb_device_manager_t *instance,
    8079    devman_handle_t handle);
    8180
    82 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
     81bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
    8382    usb_address_t address, devman_handle_t *handle);
    8483
    85 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
     84usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance,
    8685    usb_address_t address);
    8786#endif
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r47fecbb rfd07e526  
    3838 */
    3939#ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    40 #define LIBUSBHOST_HOST_YSB_ENDPOINT_MANAGER_H
     40#define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    4141
    4242#include <stdlib.h>
     
    5252        hash_table_t ep_table;
    5353        fibril_mutex_t guard;
    54         fibril_condvar_t change;
    5554        size_t free_bw;
     55        size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
    5656} usb_endpoint_manager_t;
    5757
     
    6060
    6161int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    62     size_t available_bandwidth);
     62    size_t available_bandwidth,
     63    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
    6364
    6465void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
     
    7778    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    7879
     80/** Wrapper combining allocation and insertion */
    7981static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
    8082    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
  • uspace/lib/usbhost/src/endpoint.c

    r47fecbb rfd07e526  
    5353                instance->toggle = 0;
    5454                instance->active = false;
     55                instance->destroy_hook = NULL;
     56                instance->hc_data.data = NULL;
     57                instance->hc_data.toggle_get = NULL;
     58                instance->hc_data.toggle_set = NULL;
    5559                fibril_mutex_initialize(&instance->guard);
    5660                fibril_condvar_initialize(&instance->avail);
     
    6468        assert(instance);
    6569        assert(!instance->active);
     70        if (instance->hc_data.data) {
     71                assert(instance->destroy_hook);
     72                instance->destroy_hook(instance);
     73        }
    6674        free(instance);
    6775}
    6876/*----------------------------------------------------------------------------*/
    6977void endpoint_set_hc_data(endpoint_t *instance,
    70     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     78    void *data, void (*destroy_hook)(endpoint_t *),
     79    int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    7180{
    7281        assert(instance);
     82        instance->destroy_hook = destroy_hook;
    7383        instance->hc_data.data = data;
    7484        instance->hc_data.toggle_get = toggle_get;
     
    7989{
    8090        assert(instance);
     91        instance->destroy_hook = NULL;
    8192        instance->hc_data.data = NULL;
    8293        instance->hc_data.toggle_get = NULL;
  • uspace/lib/usbhost/src/usb_device_manager.c

    r47fecbb rfd07e526  
    3131 */
    3232/** @file
    33  * Device keeper structure and functions (implementation).
     33 * Device manager structure and functions (implementation).
    3434 */
    3535#include <assert.h>
    3636#include <errno.h>
    3737#include <usb/debug.h>
    38 #include <usb/host/device_keeper.h>
    39 
    40 /*----------------------------------------------------------------------------*/
    41 /** Initialize device keeper structure.
     38#include <usb/host/usb_device_manager.h>
     39
     40/*----------------------------------------------------------------------------*/
     41/** Initialize device manager structure.
    4242 *
    4343 * @param[in] instance Memory place to initialize.
     
    4545 * Set all values to false/0.
    4646 */
    47 void usb_device_keeper_init(usb_device_keeper_t *instance)
     47void usb_device_manager_init(usb_device_manager_t *instance)
    4848{
    4949        assert(instance);
     
    6363/** Get a free USB address
    6464 *
    65  * @param[in] instance Device keeper structure to use.
     65 * @param[in] instance Device manager structure to use.
    6666 * @param[in] speed Speed of the device requiring address.
    6767 * @return Free address, or error code.
    6868 */
    69 usb_address_t device_keeper_get_free_address(
    70     usb_device_keeper_t *instance, usb_speed_t speed)
     69usb_address_t usb_device_manager_get_free_address(
     70    usb_device_manager_t *instance, usb_speed_t speed)
    7171{
    7272        assert(instance);
     
    9797/** Bind USB address to devman handle.
    9898 *
    99  * @param[in] instance Device keeper structure to use.
     99 * @param[in] instance Device manager structure to use.
    100100 * @param[in] address Device address
    101101 * @param[in] handle Devman handle of the device.
    102102 */
    103 void usb_device_keeper_bind(usb_device_keeper_t *instance,
     103void usb_device_manager_bind(usb_device_manager_t *instance,
    104104    usb_address_t address, devman_handle_t handle)
    105105{
     
    117117/** Release used USB address.
    118118 *
    119  * @param[in] instance Device keeper structure to use.
     119 * @param[in] instance Device manager structure to use.
    120120 * @param[in] address Device address
    121121 */
    122 void usb_device_keeper_release(
    123     usb_device_keeper_t *instance, usb_address_t address)
     122void usb_device_manager_release(
     123    usb_device_manager_t *instance, usb_address_t address)
    124124{
    125125        assert(instance);
     
    136136/** Find USB address associated with the device
    137137 *
    138  * @param[in] instance Device keeper structure to use.
     138 * @param[in] instance Device manager structure to use.
    139139 * @param[in] handle Devman handle of the device seeking its address.
    140140 * @return USB Address, or error code.
    141141 */
    142 usb_address_t usb_device_keeper_find(
    143     usb_device_keeper_t *instance, devman_handle_t handle)
     142usb_address_t usb_device_manager_find(
     143    usb_device_manager_t *instance, devman_handle_t handle)
    144144{
    145145        assert(instance);
     
    161161 * Intentionally refuse to find handle of default address.
    162162 *
    163  * @param[in] instance Device keeper structure to use.
     163 * @param[in] instance Device manager structure to use.
    164164 * @param[in] address Address the caller wants to find.
    165165 * @param[out] handle Where to store found handle.
    166166 * @return Whether such address is currently occupied.
    167167 */
    168 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
     168bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
    169169    usb_address_t address, devman_handle_t *handle)
    170170{
     
    191191/** Get speed associated with the address
    192192 *
    193  * @param[in] instance Device keeper structure to use.
     193 * @param[in] instance Device manager structure to use.
    194194 * @param[in] address Address of the device.
    195195 * @return USB speed.
    196196 */
    197 usb_speed_t usb_device_keeper_get_speed(
    198     usb_device_keeper_t *instance, usb_address_t address)
     197usb_speed_t usb_device_manager_get_speed(
     198    usb_device_manager_t *instance, usb_address_t address)
    199199{
    200200        assert(instance);
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r47fecbb rfd07e526  
    4545static hash_index_t node_hash(unsigned long key[])
    4646{
    47         hash_index_t hash = 0;
    48         unsigned i = 0;
    49         for (;i < MAX_KEYS; ++i) {
    50                 hash ^= key[i];
    51         }
    52         hash %= BUCKET_COUNT;
    53         return hash;
     47        /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1])
     48         * produces unique value for every address.endpoint pair */
     49        return ((key[0] << 4) | key[1]) % BUCKET_COUNT;
    5450}
    5551/*----------------------------------------------------------------------------*/
     
    6359        switch (keys) {
    6460        case 3:
    65                 match = match && (key[2] == node->ep->direction);
     61                match = match &&
     62                    ((key[2] == node->ep->direction)
     63                    || (node->ep->direction == USB_DIRECTION_BOTH));
    6664        case 2:
    6765                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     
    140138/*----------------------------------------------------------------------------*/
    141139int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    142     size_t available_bandwidth)
     140    size_t available_bandwidth,
     141    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
    143142{
    144143        assert(instance);
    145144        fibril_mutex_initialize(&instance->guard);
    146         fibril_condvar_initialize(&instance->change);
    147145        instance->free_bw = available_bandwidth;
    148         bool ht =
     146        instance->bw_count = bw_count;
     147        const bool ht =
    149148            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
    150149        return ht ? EOK : ENOMEM;
     
    159158    endpoint_t *ep, size_t data_size)
    160159{
     160        assert(instance);
     161        assert(instance->bw_count);
    161162        assert(ep);
    162         size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
     163        const size_t bw = instance->bw_count(ep->speed, ep->transfer_type,
    163164            data_size, ep->max_packet_size);
    164         assert(instance);
     165
     166        fibril_mutex_lock(&instance->guard);
     167
     168        if (bw > instance->free_bw) {
     169                fibril_mutex_unlock(&instance->guard);
     170                return ENOSPC;
     171        }
    165172
    166173        unsigned long key[MAX_KEYS] =
    167174            {ep->address, ep->endpoint, ep->direction};
    168         fibril_mutex_lock(&instance->guard);
    169 
    170         link_t *item =
     175
     176        const link_t *item =
    171177            hash_table_find(&instance->ep_table, key);
    172178        if (item != NULL) {
    173179                fibril_mutex_unlock(&instance->guard);
    174180                return EEXISTS;
    175         }
    176 
    177         if (bw > instance->free_bw) {
    178                 fibril_mutex_unlock(&instance->guard);
    179                 return ENOSPC;
    180181        }
    181182
     
    193194        instance->free_bw -= bw;
    194195        fibril_mutex_unlock(&instance->guard);
    195         fibril_condvar_broadcast(&instance->change);
    196196        return EOK;
    197197}
     
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
    213         if (node->ep->active)
     213        if (node->ep->active) {
     214                fibril_mutex_unlock(&instance->guard);
    214215                return EBUSY;
     216        }
    215217
    216218        instance->free_bw += node->bw;
     
    218220
    219221        fibril_mutex_unlock(&instance->guard);
    220         fibril_condvar_broadcast(&instance->change);
    221222        return EOK;
    222223}
     
    230231
    231232        fibril_mutex_lock(&instance->guard);
    232         link_t *item = hash_table_find(&instance->ep_table, key);
     233        const link_t *item = hash_table_find(&instance->ep_table, key);
    233234        if (item == NULL) {
    234235                fibril_mutex_unlock(&instance->guard);
    235236                return NULL;
    236237        }
    237         node_t *node = hash_table_get_instance(item, node_t, link);
     238        const node_t *node = hash_table_get_instance(item, node_t, link);
    238239        if (bw)
    239240                *bw = node->bw;
     
    255256{
    256257        assert(instance);
    257         if (target.endpoint > 15 || target.endpoint < 0
    258             || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     258        if (!usb_target_is_valid(target)) {
    259259                usb_log_error("Invalid data when checking for toggle reset.\n");
    260260                return;
    261261        }
    262262
     263        assert(data);
    263264        switch (data[1])
    264265        {
    265         case 0x01: /*clear feature*/
    266                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     266        case 0x01: /* Clear Feature -- resets only cleared ep */
     267                /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    267268                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    268269                        /* endpoint number is < 16, thus first byte is enough */
     
    276277        break;
    277278
    278         case 0x9: /* set configuration */
    279         case 0x11: /* set interface */
    280                 /* target must be device */
     279        case 0x9: /* Set Configuration */
     280        case 0x11: /* Set Interface */
     281                /* Recipient must be device */
    281282                if ((data[0] & 0xf) == 0) {
    282283                        usb_target_t reset_target =
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r47fecbb rfd07e526  
    3737#include <usb/usb.h>
    3838#include <usb/debug.h>
    39 #include <usb/host/batch.h>
     39#include <usb/host/usb_transfer_batch.h>
     40#include <usb/host/hcd.h>
    4041
    41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    43 
    44 void usb_transfer_batch_init(
    45     usb_transfer_batch_t *instance,
     42usb_transfer_batch_t * usb_transfer_batch_get(
    4643    endpoint_t *ep,
    4744    char *buffer,
    48     char *data_buffer,
    4945    size_t buffer_size,
    50     char *setup_buffer,
    51     size_t setup_size,
     46    uint64_t setup_buffer,
    5247    usbhc_iface_transfer_in_callback_t func_in,
    5348    usbhc_iface_transfer_out_callback_t func_out,
     
    5550    ddf_fun_t *fun,
    5651    void *private_data,
    57     void (*private_data_dtor)(void *p_data)
     52    void (*private_data_dtor)(void *)
    5853    )
    5954{
    60         assert(instance);
    61         link_initialize(&instance->link);
    62         instance->ep = ep;
    63         instance->callback_in = func_in;
    64         instance->callback_out = func_out;
    65         instance->arg = arg;
    66         instance->buffer = buffer;
    67         instance->data_buffer = data_buffer;
    68         instance->buffer_size = buffer_size;
    69         instance->setup_buffer = setup_buffer;
    70         instance->setup_size = setup_size;
    71         instance->fun = fun;
    72         instance->private_data = private_data;
    73         instance->private_data_dtor = private_data_dtor;
    74         instance->transfered_size = 0;
    75         instance->next_step = NULL;
    76         instance->error = EOK;
    77         endpoint_use(instance->ep);
     55        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
     56        if (instance) {
     57                instance->ep = ep;
     58                instance->callback_in = func_in;
     59                instance->callback_out = func_out;
     60                instance->arg = arg;
     61                instance->buffer = buffer;
     62                instance->buffer_size = buffer_size;
     63                instance->setup_size = 0;
     64                instance->fun = fun;
     65                instance->private_data = private_data;
     66                instance->private_data_dtor = private_data_dtor;
     67                instance->transfered_size = 0;
     68                instance->error = EOK;
     69                if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) {
     70                        memcpy(instance->setup_buffer, &setup_buffer,
     71                            USB_SETUP_PACKET_SIZE);
     72                        instance->setup_size = USB_SETUP_PACKET_SIZE;
     73                }
     74                if (instance->ep)
     75                        endpoint_use(instance->ep);
     76        }
     77        return instance;
    7878}
    7979/*----------------------------------------------------------------------------*/
    80 /** Helper function, calls callback and correctly destroys batch structure.
     80/** Mark batch as finished and run callback.
    8181 *
    8282 * @param[in] instance Batch structure to use.
     83 * @param[in] data Data to copy to the output buffer.
     84 * @param[in] size Size of @p data.
    8385 */
    84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    85 {
    86         assert(instance);
    87         usb_transfer_batch_call_in(instance);
    88         usb_transfer_batch_dispose(instance);
    89 }
    90 /*----------------------------------------------------------------------------*/
    91 /** Helper function calls callback and correctly destroys batch structure.
    92  *
    93  * @param[in] instance Batch structure to use.
    94  */
    95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    96 {
    97         assert(instance);
    98         usb_transfer_batch_call_out(instance);
    99         usb_transfer_batch_dispose(instance);
    100 }
    101 /*----------------------------------------------------------------------------*/
    102 /** Mark batch as finished and continue with next step.
    103  *
    104  * @param[in] instance Batch structure to use.
    105  *
    106  */
    107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
     86void usb_transfer_batch_finish(
     87    usb_transfer_batch_t *instance, const void *data, size_t size)
    10888{
    10989        assert(instance);
    11090        assert(instance->ep);
    111         assert(instance->next_step);
    112         endpoint_release(instance->ep);
    113         instance->next_step(instance);
     91        /* we care about the data and there are some to copy */
     92        if (instance->ep->direction != USB_DIRECTION_OUT
     93            && data) {
     94                const size_t min_size =
     95                    size < instance->buffer_size ? size : instance->buffer_size;
     96                memcpy(instance->buffer, data, min_size);
     97        }
     98        if (instance->callback_out)
     99                usb_transfer_batch_call_out(instance);
     100        if (instance->callback_in)
     101                usb_transfer_batch_call_in(instance);
     102
    114103}
    115104/*----------------------------------------------------------------------------*/
     
    124113        assert(instance);
    125114        assert(instance->callback_in);
    126         assert(instance->ep);
    127 
    128         /* We are data in, we need data */
    129         memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    130115
    131116        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
     
    150135            str_error(instance->error));
    151136
     137        if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
     138            && instance->error == EOK) {
     139                const usb_target_t target =
     140                    {{ instance->ep->address, instance->ep->endpoint }};
     141                reset_ep_if_need(
     142                    fun_to_hcd(instance->fun), target, instance->setup_buffer);
     143        }
     144
    152145        instance->callback_out(instance->fun,
    153146            instance->error, instance->arg);
     
    160153void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
    161154{
    162         assert(instance);
     155        if (!instance)
     156                return;
    163157        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    164158            instance, USB_TRANSFER_BATCH_ARGS(*instance));
     159        if (instance->ep) {
     160                endpoint_release(instance->ep);
     161        }
    165162        if (instance->private_data) {
    166163                assert(instance->private_data_dtor);
Note: See TracChangeset for help on using the changeset viewer.