Changes in / [153cc76a:2f0dd2a] in mainline


Ignore:
Location:
uspace
Files:
4 added
3 deleted
52 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/mkbd/main.c

    r153cc76a r2f0dd2a  
    4848#include <usb/dev/pipes.h>
    4949#include <async.h>
    50 #include <usb/dev.h>
    5150#include <usb/hid/usages/core.h>
    5251#include <usb/hid/hidparser.h>
  • uspace/app/usbinfo/dev.c

    r153cc76a r2f0dd2a  
    3434 * Representation of queried device.
    3535 */
    36 #include <usb/dev.h>
    37 #include <usb/hc.h>
     36#include <usb/dev/pipes.h>
    3837#include <errno.h>
    3938#include <str_error.h>
     
    5352        bool transfer_started = false;
    5453
    55         usb_hc_connection_initialize(&dev->hc_conn, hc_handle);
    56 
    57         rc = usb_device_connection_initialize(
    58             &dev->wire, &dev->hc_conn, dev_addr);
     54        rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
    5955        if (rc != EOK) {
    6056                fprintf(stderr,
  • uspace/app/usbinfo/info.c

    r153cc76a r2f0dd2a  
    287287void dump_strings(usbinfo_device_t *dev)
    288288{
    289         /* Find used indexes. Devices with more than 64 strings are very rare.*/
    290         uint64_t str_mask = 0;
    291         find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
    292             &str_mask);
    293         usb_dp_walk_simple(dev->full_configuration_descriptor,
    294             dev->full_configuration_descriptor_size,
    295             usb_dp_standard_descriptor_nesting,
    296             find_string_indexes_callback,
    297             &str_mask);
    298 
    299         if (str_mask == 0) {
    300                 printf("Device does not support string descriptors.\n");
    301                 return;
    302         }
    303 
    304289        /* Get supported languages. */
    305290        l18_win_locales_t *langs;
     
    320305        }
    321306        printf(".\n");
     307
     308        /* Find used indexes. Device with more than 64 strings are very rare.
     309         */
     310        uint64_t str_mask = 0;
     311        find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
     312            &str_mask);
     313        usb_dp_walk_simple(dev->full_configuration_descriptor,
     314            dev->full_configuration_descriptor_size,
     315            usb_dp_standard_descriptor_nesting,
     316            find_string_indexes_callback,
     317            &str_mask);
    322318
    323319        /* Get all strings and dump them. */
  • uspace/app/usbinfo/main.c

    r153cc76a r2f0dd2a  
    4444#include <loc.h>
    4545#include <usb/hc.h>
    46 #include <usb/dev.h>
    4746#include <usb/dev/pipes.h>
    4847#include "usbinfo.h"
  • uspace/app/usbinfo/usbinfo.h

    r153cc76a r2f0dd2a  
    4444
    4545typedef struct {
    46         usb_hc_connection_t hc_conn;
     46        usb_pipe_t ctrl_pipe;
    4747        usb_device_connection_t wire;
    48         usb_pipe_t ctrl_pipe;
    4948        usb_standard_device_descriptor_t device_descriptor;
    5049        uint8_t *full_configuration_descriptor;
  • uspace/drv/bus/usb/ohci/hc.c

    r153cc76a r2f0dd2a  
    137137                return ret;
    138138        }
     139        usb_device_manager_bind_address(&instance->generic.dev_manager,
     140            instance->rh.address, hub_fun->handle);
    139141
    140142#define CHECK_RET_UNREG_RETURN(ret, message...) \
     
    148150        return ret; \
    149151} else (void)0
    150 
    151152        ret = usb_endpoint_manager_add_ep(
    152153            &instance->generic.ep_manager, instance->rh.address, 0,
     
    164165        CHECK_RET_UNREG_RETURN(ret,
    165166            "Failed to bind root hub function: %s.\n", str_error(ret));
    166 
    167         ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
    168             instance->rh.address, hub_fun->handle);
    169         if (ret != EOK)
    170                 usb_log_warning("Failed to bind root hub address: %s.\n",
    171                     str_error(ret));
    172167
    173168        return EOK;
  • uspace/drv/bus/usb/ohci/ohci.c

    r153cc76a r2f0dd2a  
    140140int device_setup_ohci(ddf_dev_t *device)
    141141{
    142         if (device == NULL)
    143                 return EBADMEM;
    144 
    145         ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t));
     142        assert(device);
     143
     144        ohci_t *instance = malloc(sizeof(ohci_t));
    146145        if (instance == NULL) {
    147146                usb_log_error("Failed to allocate OHCI driver.\n");
    148147                return ENOMEM;
    149148        }
     149        instance->rh_fun = NULL;
     150        instance->hc_fun = NULL;
    150151
    151152#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
    152153if (ret != EOK) { \
    153154        if (instance->hc_fun) { \
    154                 instance->hc_fun->driver_data = NULL; \
    155155                ddf_fun_destroy(instance->hc_fun); \
    156156        } \
    157157        if (instance->rh_fun) { \
    158                 instance->rh_fun->driver_data = NULL; \
    159158                ddf_fun_destroy(instance->rh_fun); \
    160159        } \
     160        free(instance); \
    161161        usb_log_error(message); \
    162162        return ret; \
     
    219219            "Failed to init ohci_hcd: %s.\n", str_error(ret));
    220220
     221        device->driver_data = instance;
     222
    221223#define CHECK_RET_FINI_RETURN(ret, message...) \
    222224if (ret != EOK) { \
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r153cc76a r2f0dd2a  
    3434#include <errno.h>
    3535#include <str_error.h>
    36 #include <macros.h>
    3736
    3837#include <usb/usb.h>
     
    5453                return;
    5554        if (ohci_batch->tds) {
    56                 const ohci_endpoint_t *ohci_ep =
    57                     ohci_endpoint_get(ohci_batch->usb_batch->ep);
    58                 assert(ohci_ep);
    5955                for (unsigned i = 0; i < ohci_batch->td_count; ++i) {
    60                         if (ohci_batch->tds[i] != ohci_ep->td)
     56                        if (i != ohci_batch->leave_td)
    6157                                free32(ohci_batch->tds[i]);
    6258                }
     
    6864}
    6965/*----------------------------------------------------------------------------*/
    70 /** Finishes usb_transfer_batch and destroys the structure.
    71  *
    72  * @param[in] uhci_batch Instance to finish and destroy.
    73  */
    7466void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch)
    7567{
     
    7769        assert(ohci_batch->usb_batch);
    7870        usb_transfer_batch_finish(ohci_batch->usb_batch,
    79             ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size);
     71            ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size,
     72            ohci_batch->usb_batch->buffer_size);
    8073        ohci_transfer_batch_dispose(ohci_batch);
    8174}
    8275/*----------------------------------------------------------------------------*/
    83 /** Allocate memory and initialize internal data structure.
    84  *
    85  * @param[in] usb_batch Pointer to generic USB batch structure.
    86  * @return Valid pointer if all structures were successfully created,
    87  * NULL otherwise.
    88  *
    89  * Determines the number of needed transfer descriptors (TDs).
    90  * Prepares a transport buffer (that is accessible by the hardware).
    91  * Initializes parameters needed for the transfer and callback.
    92  */
    9376ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
    9477{
     
    122105        ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed;
    123106        ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td;
     107        ohci_batch->leave_td = 0;
    124108
    125109        for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
     
    168152 * completes with the last TD.
    169153 */
    170 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch)
     154bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *ohci_batch)
    171155{
    172156        assert(ohci_batch);
     
    190174
    191175        /* Assume we will leave the last(unused) TD behind */
    192         unsigned leave_td = ohci_batch->td_count;
     176        ohci_batch->leave_td = ohci_batch->td_count;
    193177
    194178        /* Check all TDs */
     
    228212                         * It will be the one TD we leave behind.
    229213                         */
    230                         leave_td = i + 1;
     214                        ohci_batch->leave_td = i + 1;
    231215
    232216                        /* Check TD assumption */
    233                         const uint32_t pa =
    234                             addr_to_phys(ohci_batch->tds[leave_td]);
    235                         assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)
     217                        const uint32_t pa = addr_to_phys(
     218                            ohci_batch->tds[ohci_batch->leave_td]);
     219                        assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
    236220                            == pa);
    237221
    238222                        ed_set_tail_td(ohci_batch->ed,
    239                             ohci_batch->tds[leave_td]);
     223                            ohci_batch->tds[ohci_batch->leave_td]);
    240224
    241225                        /* Clear possible ED HALT */
     
    250234        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
    251235        assert(ohci_ep);
    252         ohci_ep->td = ohci_batch->tds[leave_td];
     236        ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
    253237
    254238        /* Make sure that we are leaving the right TD behind */
     
    264248 * @param[in] ohci_batch Batch structure to use
    265249 */
    266 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch)
     250void ohci_transfer_batch_commit(ohci_transfer_batch_t *ohci_batch)
    267251{
    268252        assert(ohci_batch);
     
    311295        while (remain_size > 0) {
    312296                const size_t transfer_size =
    313                     min(remain_size, OHCI_TD_MAX_TRANSFER);
     297                    remain_size > OHCI_TD_MAX_TRANSFER ?
     298                    OHCI_TD_MAX_TRANSFER : remain_size;
    314299                toggle = 1 - toggle;
    315300
     
    393378}
    394379/*----------------------------------------------------------------------------*/
    395 /** Transfer setup table. */
    396380static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) =
    397381{
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    r153cc76a r2f0dd2a  
    5353        /** Number of TDs used by the transfer */
    5454        size_t td_count;
     55        /** Dummy TD to be left at the ED and used by the next transfer */
     56        size_t leave_td;
    5557        /** Data buffer, must be accessible by the OHCI hw. */
    5658        char *device_buffer;
     
    6062
    6163ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch);
    62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch);
    63 void ohci_transfer_batch_commit(const ohci_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);
    6466void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
    6567/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/ohci/pci.c

    r153cc76a r2f0dd2a  
    4242#include <ddi.h>
    4343#include <libarch/ddi.h>
    44 #include <device/hw_res_parsed.h>
     44#include <device/hw_res.h>
    4545
    4646#include <usb/debug.h>
     
    6161{
    6262        assert(dev);
     63        assert(mem_reg_address);
     64        assert(mem_reg_size);
     65        assert(irq_no);
    6366
    6467        async_sess_t *parent_sess =
     
    6871                return ENOMEM;
    6972
    70         hw_res_list_parsed_t hw_res;
    71         hw_res_list_parsed_init(&hw_res);
    72         const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
     73        hw_resource_list_t hw_resources;
     74        int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
    7375        async_hangup(parent_sess);
    74         if (ret != EOK) {
    75                 return ret;
     76        if (rc != EOK) {
     77                return rc;
    7678        }
    7779
    78         /* We want one irq and one mem range. */
    79         if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
    80                 hw_res_list_parsed_clean(&hw_res);
    81                 return EINVAL;
     80        uintptr_t mem_address = 0;
     81        size_t mem_size = 0;
     82        bool mem_found = false;
     83
     84        int irq = 0;
     85        bool irq_found = false;
     86
     87        for (size_t i = 0; i < hw_resources.count; i++) {
     88                hw_resource_t *res = &hw_resources.resources[i];
     89                switch (res->type) {
     90                case INTERRUPT:
     91                        irq = res->res.interrupt.irq;
     92                        irq_found = true;
     93                        usb_log_debug2("Found interrupt: %d.\n", irq);
     94                        break;
     95                case MEM_RANGE:
     96                        if (res->res.mem_range.address != 0
     97                            && res->res.mem_range.size != 0 ) {
     98                                mem_address = res->res.mem_range.address;
     99                                mem_size = res->res.mem_range.size;
     100                                usb_log_debug2("Found mem: %p %zu.\n",
     101                                    (void *) mem_address, mem_size);
     102                                mem_found = true;
     103                        }
     104                default:
     105                        break;
     106                }
    82107        }
     108        free(hw_resources.resources);
    83109
    84         if (mem_reg_address)
    85                 *mem_reg_address = hw_res.mem_ranges.ranges[0].address;
    86         if (mem_reg_size)
    87                 *mem_reg_size = hw_res.mem_ranges.ranges[0].size;
    88         if (irq_no)
    89                 *irq_no = hw_res.irqs.irqs[0];
    90 
    91         hw_res_list_parsed_clean(&hw_res);
    92         return EOK;
     110        if (mem_found && irq_found) {
     111                *mem_reg_address = mem_address;
     112                *mem_reg_size = mem_size;
     113                *irq_no = irq;
     114                return EOK;
     115        }
     116        return ENOENT;
    93117}
    94118
  • uspace/drv/bus/usb/ohci/root_hub.c

    r153cc76a r2f0dd2a  
    100100        .attributes = USB_TRANSFER_INTERRUPT,
    101101        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    102         .endpoint_address = 1 | (1 << 7),
     102        .endpoint_address = 1 + (1 << 7),
    103103        .length = sizeof(usb_standard_endpoint_descriptor_t),
    104104        .max_packet_size = 2,
     
    109109static void rh_init_descriptors(rh_t *instance);
    110110static uint16_t create_interrupt_mask(const rh_t *instance);
    111 static void get_status(const rh_t *instance, usb_transfer_batch_t *request);
    112 static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
    113 static void set_feature(const rh_t *instance, usb_transfer_batch_t *request);
    114 static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
     111static int get_status(const rh_t *instance, usb_transfer_batch_t *request);
     112static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
     113static int set_feature(const rh_t *instance, usb_transfer_batch_t *request);
     114static int clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
    115115static int set_feature_port(
    116116    const rh_t *instance, uint16_t feature, uint16_t port);
    117117static int clear_feature_port(
    118118    const rh_t *instance, uint16_t feature, uint16_t port);
    119 static void control_request(rh_t *instance, usb_transfer_batch_t *request);
     119static int control_request(rh_t *instance, usb_transfer_batch_t *request);
    120120static inline void interrupt_request(
    121121    usb_transfer_batch_t *request, uint16_t mask, size_t size)
    122122{
    123123        assert(request);
     124
     125        request->transfered_size = size;
    124126        usb_transfer_batch_finish_error(request, &mask, size, EOK);
    125         usb_transfer_batch_destroy(request);
    126 }
    127 
    128 #define TRANSFER_END_DATA(request, data, bytes) \
     127}
     128
     129#define TRANSFER_OK(bytes) \
    129130do { \
    130         usb_transfer_batch_finish_error(request, data, bytes, EOK); \
    131         usb_transfer_batch_destroy(request); \
    132         return; \
    133 } while (0)
    134 
    135 #define TRANSFER_END(request, error) \
    136 do { \
    137         usb_transfer_batch_finish_error(request, NULL, 0, error); \
    138         usb_transfer_batch_destroy(request); \
    139         return; \
     131        request->transfered_size = bytes; \
     132        return EOK; \
    140133} while (0)
    141134
     
    219212        case USB_TRANSFER_CONTROL:
    220213                usb_log_debug("Root hub got CONTROL packet\n");
    221                 control_request(instance, request);
     214                const int ret = control_request(instance, request);
     215                usb_transfer_batch_finish_error(request, NULL, 0, ret);
    222216                break;
    223 
    224217        case USB_TRANSFER_INTERRUPT:
    225218                usb_log_debug("Root hub got INTERRUPT packet\n");
     
    228221                const uint16_t mask = create_interrupt_mask(instance);
    229222                if (mask == 0) {
    230                         usb_log_debug("No changes...\n");
     223                        usb_log_debug("No changes..\n");
    231224                        instance->unfinished_interrupt_transfer = request;
    232                 } else {
    233                         usb_log_debug("Processing changes...\n");
    234                         interrupt_request(
    235                             request, mask, instance->interrupt_mask_size);
     225                        fibril_mutex_unlock(&instance->guard);
     226                        return;
    236227                }
     228                usb_log_debug("Processing changes...\n");
     229                interrupt_request(request, mask, instance->interrupt_mask_size);
    237230                fibril_mutex_unlock(&instance->guard);
    238231                break;
     
    240233        default:
    241234                usb_log_error("Root hub got unsupported request.\n");
    242                 TRANSFER_END(request, ENOTSUP);
    243         }
     235                usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
     236        }
     237        usb_transfer_batch_destroy(request);
    244238}
    245239/*----------------------------------------------------------------------------*/
     
    260254                interrupt_request(instance->unfinished_interrupt_transfer,
    261255                    mask, instance->interrupt_mask_size);
     256                usb_transfer_batch_destroy(
     257                    instance->unfinished_interrupt_transfer);
    262258                instance->unfinished_interrupt_transfer = NULL;
    263259        }
     
    388384 * @return error code
    389385 */
    390 void get_status(const rh_t *instance, usb_transfer_batch_t *request)
     386int get_status(const rh_t *instance, usb_transfer_batch_t *request)
    391387{
    392388        assert(instance);
    393389        assert(request);
    394 
    395390
    396391        const usb_device_request_setup_packet_t *request_packet =
    397392            (usb_device_request_setup_packet_t*)request->setup_buffer;
    398393
    399         switch (request_packet->request_type)
    400         {
    401         case USB_HUB_REQ_TYPE_GET_HUB_STATUS:
     394        if (request->buffer_size < 4) {
     395                usb_log_error("Buffer too small for get status request.\n");
     396                return EOVERFLOW;
     397        }
     398
    402399        /* Hub status: just filter relevant info from rh_status reg */
    403                 if (request->buffer_size < 4) {
    404                         usb_log_error("Buffer(%zu) too small for hub get "
    405                             "status request.\n", request->buffer_size);
    406                         TRANSFER_END(request, EOVERFLOW);
    407                 } else {
    408                         const uint32_t data = instance->registers->rh_status &
    409                             (RHS_LPS_FLAG | RHS_LPSC_FLAG
    410                                 | RHS_OCI_FLAG | RHS_OCIC_FLAG);
    411                         TRANSFER_END_DATA(request, &data, sizeof(data));
    412                 }
     400        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
     401                const uint32_t data = instance->registers->rh_status &
     402                    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     403                memcpy(request->buffer, &data, sizeof(data));
     404                TRANSFER_OK(sizeof(data));
     405        }
    413406
    414407        /* Copy appropriate rh_port_status register, OHCI designers were
    415408         * kind enough to make those bit values match USB specification */
    416         case USB_HUB_REQ_TYPE_GET_PORT_STATUS:
    417                 if (request->buffer_size < 4) {
    418                         usb_log_error("Buffer(%zu) too small for hub get "
    419                             "status request.\n", request->buffer_size);
    420                         TRANSFER_END(request, EOVERFLOW);
    421                 } else {
    422                         const unsigned port = request_packet->index;
    423                         if (port < 1 || port > instance->port_count)
    424                                 TRANSFER_END(request, EINVAL);
    425 
    426                         const uint32_t data =
    427                             instance->registers->rh_port_status[port - 1];
    428                         TRANSFER_END_DATA(request, &data, sizeof(data));
    429                 }
    430         case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE):
    431                 if (request->buffer_size < 2) {
    432                         usb_log_error("Buffer(%zu) too small for hub generic "
    433                             "get status request.\n", request->buffer_size);
    434                         TRANSFER_END(request, EOVERFLOW);
    435                 } else {
    436                         static const uint16_t data =
    437                             uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
    438                         TRANSFER_END_DATA(request, &data, sizeof(data));
    439                 }
    440 
    441         case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
    442                 /* Hubs are allowed to have only one interface */
    443                 if (request_packet->index != 0)
    444                         TRANSFER_END(request, EINVAL);
    445                 /* Fall through, as the answer will be the same: 0x0000 */
    446         case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
    447                 /* Endpoint 0 (default control) and 1 (interrupt) */
    448                 if (request_packet->index >= 2)
    449                         TRANSFER_END(request, EINVAL);
    450 
    451                 if (request->buffer_size < 2) {
    452                         usb_log_error("Buffer(%zu) too small for hub generic "
    453                             "get status request.\n", request->buffer_size);
    454                         TRANSFER_END(request, EOVERFLOW);
    455                 } else {
    456                         /* Endpoints are OK. (We don't halt) */
    457                         static const uint16_t data = 0;
    458                         TRANSFER_END_DATA(request, &data, sizeof(data));
    459                 }
    460 
    461         default:
    462                 usb_log_error("Unsupported GET_STATUS request.\n");
    463                 TRANSFER_END(request, ENOTSUP);
    464         }
    465 
     409        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
     410                const unsigned port = request_packet->index;
     411                if (port < 1 || port > instance->port_count)
     412                        return EINVAL;
     413
     414                const uint32_t data =
     415                    instance->registers->rh_port_status[port - 1];
     416                memcpy(request->buffer, &data, sizeof(data));
     417                TRANSFER_OK(sizeof(data));
     418        }
     419
     420        return ENOTSUP;
    466421}
    467422/*----------------------------------------------------------------------------*/
     
    475430 * @return Error code
    476431 */
    477 void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
     432int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
    478433{
    479434        assert(instance);
     
    482437        const usb_device_request_setup_packet_t *setup_request =
    483438            (usb_device_request_setup_packet_t *) request->setup_buffer;
     439        size_t size;
     440        const void *descriptor = NULL;
    484441        const uint16_t setup_request_value = setup_request->value_high;
     442        //(setup_request->value_low << 8);
    485443        switch (setup_request_value)
    486444        {
    487445        case USB_DESCTYPE_HUB:
    488446                usb_log_debug2("USB_DESCTYPE_HUB\n");
    489                 /* Hub descriptor was generated locally.
    490                  * Class specific request. */
    491                 TRANSFER_END_DATA(request, instance->descriptors.hub,
    492                     instance->hub_descriptor_size);
     447                /* Hub descriptor was generated locally */
     448                descriptor = instance->descriptors.hub;
     449                size = instance->hub_descriptor_size;
     450                break;
    493451
    494452        case USB_DESCTYPE_DEVICE:
    495453                usb_log_debug2("USB_DESCTYPE_DEVICE\n");
    496                 /* Device descriptor is shared
    497                  * (No one should ask for it, as the device is already setup)
    498                  * Standard USB device request. */
    499                 TRANSFER_END_DATA(request, &ohci_rh_device_descriptor,
    500                     sizeof(ohci_rh_device_descriptor));
     454                /* Device descriptor is shared (No one should ask for it)*/
     455                descriptor = &ohci_rh_device_descriptor;
     456                size = sizeof(ohci_rh_device_descriptor);
     457                break;
    501458
    502459        case USB_DESCTYPE_CONFIGURATION:
    503460                usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
    504461                /* Start with configuration and add others depending on
    505                  * request size. Standard USB request. */
    506                 TRANSFER_END_DATA(request, &instance->descriptors,
    507                     instance->descriptors.configuration.total_length);
     462                 * request size */
     463                descriptor = &instance->descriptors;
     464                size = instance->descriptors.configuration.total_length;
     465                break;
    508466
    509467        case USB_DESCTYPE_INTERFACE:
    510468                usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
    511469                /* Use local interface descriptor. There is one and it
    512                  * might be modified. Hub driver should not ask or this
    513                  * descriptor as it is not part of standard requests set. */
    514                 TRANSFER_END_DATA(request, &instance->descriptors.interface,
    515                     sizeof(instance->descriptors.interface));
     470                 * might be modified */
     471                descriptor = &instance->descriptors.interface;
     472                size = sizeof(instance->descriptors.interface);
     473                break;
    516474
    517475        case USB_DESCTYPE_ENDPOINT:
    518476                /* Use local endpoint descriptor. There is one
    519                  * it might have max_packet_size field modified. Hub driver
    520                  * should not ask for this descriptor as it is not part
    521                  * of standard requests set. */
     477                 * it might have max_packet_size field modified*/
    522478                usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
    523                 TRANSFER_END_DATA(request, &instance->descriptors.endpoint,
    524                     sizeof(instance->descriptors.endpoint));
     479                descriptor = &instance->descriptors.endpoint;
     480                size = sizeof(instance->descriptors.endpoint);
     481                break;
    525482
    526483        default:
     
    532489                    setup_request_value, setup_request->index,
    533490                    setup_request->length);
    534                 TRANSFER_END(request, EINVAL);
    535         }
    536 
    537         TRANSFER_END(request, ENOTSUP);
     491                return EINVAL;
     492        }
     493        if (request->buffer_size < size) {
     494                size = request->buffer_size;
     495        }
     496
     497        memcpy(request->buffer, descriptor, size);
     498        TRANSFER_OK(size);
    538499}
    539500/*----------------------------------------------------------------------------*/
     
    643604 * @return error code
    644605 */
    645 void set_feature(const rh_t *instance, usb_transfer_batch_t *request)
     606int set_feature(const rh_t *instance, usb_transfer_batch_t *request)
    646607{
    647608        assert(instance);
     
    654615        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
    655616                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    656                 const int ret = set_feature_port(instance,
     617                return set_feature_port(instance,
    657618                    setup_request->value, setup_request->index);
    658                 TRANSFER_END(request, ret);
    659619
    660620        case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
     
    663623                 * features. It makes no sense to SET either. */
    664624                usb_log_error("Invalid HUB set feature request.\n");
    665                 TRANSFER_END(request, ENOTSUP);
    666         //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
     625                return ENOTSUP;
    667626        default:
    668627                usb_log_error("Invalid set feature request type: %d\n",
    669628                    setup_request->request_type);
    670                 TRANSFER_END(request, ENOTSUP);
     629                return EINVAL;
    671630        }
    672631}
     
    681640 * @return error code
    682641 */
    683 void clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
     642int clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
    684643{
    685644        assert(instance);
     
    688647        const usb_device_request_setup_packet_t *setup_request =
    689648            (usb_device_request_setup_packet_t *) request->setup_buffer;
     649
     650        request->transfered_size = 0;
    690651
    691652        switch (setup_request->request_type)
     
    693654        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
    694655                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
    695                 const int ret = clear_feature_port(instance,
     656                return clear_feature_port(instance,
    696657                    setup_request->value, setup_request->index);
    697                 TRANSFER_END(request, ret);
    698658
    699659        case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
     
    708668                if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
    709669                        instance->registers->rh_status = RHS_OCIC_FLAG;
    710                         TRANSFER_END(request, EOK);
     670                        TRANSFER_OK(0);
    711671                }
    712         //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
    713672        default:
    714673                usb_log_error("Invalid clear feature request type: %d\n",
    715674                    setup_request->request_type);
    716                 TRANSFER_END(request, ENOTSUP);
     675                return EINVAL;
    717676        }
    718677}
     
    736695 * @return error code
    737696 */
    738 void control_request(rh_t *instance, usb_transfer_batch_t *request)
     697int control_request(rh_t *instance, usb_transfer_batch_t *request)
    739698{
    740699        assert(instance);
     
    743702        if (!request->setup_buffer) {
    744703                usb_log_error("Root hub received empty transaction!");
    745                 TRANSFER_END(request, EBADMEM);
     704                return EINVAL;
    746705        }
    747706
    748707        if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
    749708                usb_log_error("Setup packet too small\n");
    750                 TRANSFER_END(request, EOVERFLOW);
     709                return EOVERFLOW;
    751710        }
    752711
     
    759718        case USB_DEVREQ_GET_STATUS:
    760719                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    761                 get_status(instance, request);
    762                 break;
     720                return get_status(instance, request);
    763721
    764722        case USB_DEVREQ_GET_DESCRIPTOR:
    765723                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    766                 get_descriptor(instance, request);
    767                 break;
     724                return get_descriptor(instance, request);
    768725
    769726        case USB_DEVREQ_GET_CONFIGURATION:
    770727                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    771                 if (request->buffer_size == 0)
    772                         TRANSFER_END(request, EOVERFLOW);
    773                 static const uint8_t config = 1;
    774                 TRANSFER_END_DATA(request, &config, sizeof(config));
     728                if (request->buffer_size != 1)
     729                        return EINVAL;
     730                request->buffer[0] = 1;
     731                TRANSFER_OK(1);
    775732
    776733        case USB_DEVREQ_CLEAR_FEATURE:
    777                 usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n");
    778                 clear_feature(instance, request);
    779                 break;
     734                usb_log_debug2("Processing request without "
     735                    "additional data\n");
     736                return clear_feature(instance, request);
    780737
    781738        case USB_DEVREQ_SET_FEATURE:
    782                 usb_log_debug2("USB_DEVREQ_SET_FEATURE\n");
    783                 set_feature(instance, request);
    784                 break;
     739                usb_log_debug2("Processing request without "
     740                    "additional data\n");
     741                return set_feature(instance, request);
    785742
    786743        case USB_DEVREQ_SET_ADDRESS:
    787                 usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n",
    788                     setup_request->value);
    789                 if (uint16_usb2host(setup_request->value) > 127)
    790                         TRANSFER_END(request, EINVAL);
    791 
     744                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    792745                instance->address = setup_request->value;
    793                 TRANSFER_END(request, EOK);
     746                TRANSFER_OK(0);
    794747
    795748        case USB_DEVREQ_SET_CONFIGURATION:
    796                 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
    797                     setup_request->value);
    798                 /* We have only one configuration, it's number is 1 */
    799                 if (uint16_usb2host(setup_request->value) != 1)
    800                         TRANSFER_END(request, EINVAL);
    801                 TRANSFER_END(request, EOK);
    802 
    803         /* Both class specific and std is optional for hubs */
    804         case USB_DEVREQ_SET_DESCRIPTOR:
    805         /* Hubs have only one interface GET/SET is not supported */
    806         case USB_DEVREQ_GET_INTERFACE:
    807         case USB_DEVREQ_SET_INTERFACE:
     749                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
     750                /* We don't need to do anything */
     751                TRANSFER_OK(0);
     752
     753        case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
    808754        default:
    809                 /* Hub class GET_STATE(2) falls in here too. */
    810755                usb_log_error("Received unsupported request: %d.\n",
    811756                    setup_request->request);
    812                 TRANSFER_END(request, ENOTSUP);
    813         }
    814 }
     757                return ENOTSUP;
     758        }
     759}
     760
    815761/**
    816762 * @}
  • uspace/drv/bus/usb/uhci/hc.c

    r153cc76a r2f0dd2a  
    130130                        uhci_transfer_batch_t *batch =
    131131                            uhci_transfer_batch_from_link(item);
    132                         uhci_transfer_batch_finish_dispose(batch);
     132                        uhci_transfer_batch_call_dispose(batch);
    133133                }
    134134        }
  • uspace/drv/bus/usb/uhci/pci.c

    r153cc76a r2f0dd2a  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/**
    2930 * @addtogroup drvusbuhcihc
     
    3839#include <assert.h>
    3940#include <devman.h>
    40 #include <device/hw_res_parsed.h>
     41#include <device/hw_res.h>
    4142
    4243#include <usb/debug.h>
     
    6768                return ENOMEM;
    6869
    69         hw_res_list_parsed_t hw_res;
    70         hw_res_list_parsed_init(&hw_res);
    71         const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
     70        hw_resource_list_t hw_resources;
     71        const int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
    7272        async_hangup(parent_sess);
    73         if (ret != EOK) {
    74                 return ret;
     73        if (rc != EOK) {
     74                return rc;
    7575        }
    7676
    77         /* We want one irq and one io range. */
    78         if (hw_res.irqs.count != 1 || hw_res.io_ranges.count != 1) {
    79                 hw_res_list_parsed_clean(&hw_res);
    80                 return EINVAL;
     77        uintptr_t io_address = 0;
     78        size_t io_size = 0;
     79        bool io_found = false;
     80
     81        int irq = 0;
     82        bool irq_found = false;
     83
     84        for (size_t i = 0; i < hw_resources.count; i++) {
     85                const hw_resource_t *res = &hw_resources.resources[i];
     86                switch (res->type) {
     87                case INTERRUPT:
     88                        irq = res->res.interrupt.irq;
     89                        irq_found = true;
     90                        usb_log_debug2("Found interrupt: %d.\n", irq);
     91                        break;
     92                case IO_RANGE:
     93                        io_address = res->res.io_range.address;
     94                        io_size = res->res.io_range.size;
     95                        usb_log_debug2("Found io: %" PRIx64" %zu.\n",
     96                            res->res.io_range.address, res->res.io_range.size);
     97                        io_found = true;
     98                        break;
     99                default:
     100                        break;
     101                }
    81102        }
     103        free(hw_resources.resources);
    82104
    83         if (io_reg_address)
    84                 *io_reg_address = hw_res.io_ranges.ranges[0].address;
    85         if (io_reg_size)
    86                 *io_reg_size = hw_res.io_ranges.ranges[0].size;
    87         if (irq_no)
    88                 *irq_no = hw_res.irqs.irqs[0];
     105        if (!io_found || !irq_found)
     106                return ENOENT;
    89107
    90         hw_res_list_parsed_clean(&hw_res);
     108        *io_reg_address = io_address;
     109        *io_reg_size = io_size;
     110        *irq_no = irq;
     111
    91112        return EOK;
    92113}
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r153cc76a r2f0dd2a  
    184184                    uhci_transfer_batch_from_link(current);
    185185                transfer_list_remove_batch(instance, batch);
    186                 uhci_transfer_batch_abort(batch);
     186                batch->usb_batch->error = EINTR;
     187                uhci_transfer_batch_call_dispose(batch);
    187188        }
    188189        fibril_mutex_unlock(&instance->guard);
  • uspace/drv/bus/usb/uhci/uhci.c

    r153cc76a r2f0dd2a  
    148148int device_setup_uhci(ddf_dev_t *device)
    149149{
    150         if (!device)
    151                 return EBADMEM;
    152 
    153         uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t));
     150        assert(device);
     151        uhci_t *instance = malloc(sizeof(uhci_t));
    154152        if (instance == NULL) {
    155153                usb_log_error("Failed to allocate OHCI driver.\n");
     
    160158if (ret != EOK) { \
    161159        if (instance->hc_fun) \
     160                instance->hc_fun->ops = NULL; \
    162161                instance->hc_fun->driver_data = NULL; \
    163162                ddf_fun_destroy(instance->hc_fun); \
    164163        if (instance->rh_fun) {\
     164                instance->rh_fun->ops = NULL; \
    165165                instance->rh_fun->driver_data = NULL; \
    166166                ddf_fun_destroy(instance->rh_fun); \
    167167        } \
     168        device->driver_data = NULL; \
    168169        usb_log_error(message); \
    169170        return ret; \
     
    226227            "Failed to init uhci_hcd: %s.\n", str_error(ret));
    227228
     229        device->driver_data = instance;
     230
    228231#define CHECK_RET_FINI_RETURN(ret, message...) \
    229232if (ret != EOK) { \
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r153cc76a r2f0dd2a  
    3434#include <errno.h>
    3535#include <str_error.h>
    36 #include <macros.h>
    3736
    3837#include <usb/usb.h>
     
    4645#define DEFAULT_ERROR_COUNT 3
    4746
    48 /** Safely destructs uhci_transfer_batch_t structure.
    49  *
    50  * @param[in] uhci_batch Instance to destroy.
    51  */
    5247static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
    5348{
     
    5954}
    6055/*----------------------------------------------------------------------------*/
    61 /** Finishes usb_transfer_batch and destroys the structure.
    62  *
    63  * @param[in] uhci_batch Instance to finish and destroy.
    64  */
    65 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch)
     56/** Safely destructs uhci_transfer_batch_t structure
     57 *
     58 * @param[in] uhci_batch Instance to destroy.
     59 */
     60void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch)
    6661{
    6762        assert(uhci_batch);
    6863        assert(uhci_batch->usb_batch);
    6964        usb_transfer_batch_finish(uhci_batch->usb_batch,
    70             uhci_transfer_batch_data_buffer(uhci_batch));
     65            uhci_transfer_batch_data_buffer(uhci_batch),
     66            uhci_batch->usb_batch->buffer_size);
    7167        uhci_transfer_batch_dispose(uhci_batch);
    7268}
    7369/*----------------------------------------------------------------------------*/
    74 /** Transfer batch setup table. */
    7570static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
    7671/*----------------------------------------------------------------------------*/
    7772/** Allocate memory and initialize internal data structure.
    7873 *
    79  * @param[in] usb_batch Pointer to generic USB batch structure.
     74 * @param[in] fun DDF function to pass to callback.
     75 * @param[in] ep Communication target
     76 * @param[in] buffer Data source/destination.
     77 * @param[in] buffer_size Size of the buffer.
     78 * @param[in] setup_buffer Setup data source (if not NULL)
     79 * @param[in] setup_size Size of setup_buffer (should be always 8)
     80 * @param[in] func_in function to call on inbound transfer completion
     81 * @param[in] func_out function to call on outbound transfer completion
     82 * @param[in] arg additional parameter to func_in or func_out
    8083 * @return Valid pointer if all structures were successfully created,
    8184 * NULL otherwise.
     
    153156 * is reached.
    154157 */
    155 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch)
     158bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch)
    156159{
    157160        assert(uhci_batch);
     
    197200}
    198201/*----------------------------------------------------------------------------*/
    199 /** Direction to pid conversion table */
    200202static const usb_packet_id direction_pids[] = {
    201203        [USB_DIRECTION_IN] = USB_PID_IN,
     
    235237
    236238        while (remain_size > 0) {
    237                 const size_t packet_size = min(remain_size, mps);
     239                const size_t packet_size =
     240                    (remain_size < mps) ? remain_size : mps;
    238241
    239242                const td_t *next_td = (td + 1 < uhci_batch->td_count)
     
    306309
    307310        while (remain_size > 0) {
    308                 const size_t packet_size = min(remain_size, mps);
     311                const size_t packet_size =
     312                    (remain_size < mps) ? remain_size : mps;
    309313
    310314                td_init(
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    r153cc76a r2f0dd2a  
    6161
    6262uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch);
    63 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch);
    64 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch);
     63void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch);
     64bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch);
    6565
    66 /** Get offset to setup buffer accessible to the HC hw.
    67  * @param uhci_batch UHCI batch structure.
    68  * @return Pointer to the setup buffer.
    69  */
    7066static inline void * uhci_transfer_batch_setup_buffer(
    7167    const uhci_transfer_batch_t *uhci_batch)
     
    7773}
    7874/*----------------------------------------------------------------------------*/
    79 /** Get offset to data buffer accessible to the HC hw.
    80  * @param uhci_batch UHCI batch structure.
    81  * @return Pointer to the data buffer.
    82  */
    8375static inline void * uhci_transfer_batch_data_buffer(
    8476    const uhci_transfer_batch_t *uhci_batch)
     
    9082}
    9183/*----------------------------------------------------------------------------*/
    92 /** Aborts the batch.
    93  * Sets error to EINTR and size off transferd data to 0, before finishing the
    94  * batch.
    95  * @param uhci_batch Batch to abort.
    96  */
    97 static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch)
    98 {
    99         assert(uhci_batch);
    100         assert(uhci_batch->usb_batch);
    101         uhci_batch->usb_batch->error = EINTR;
    102         uhci_batch->usb_batch->transfered_size = 0;
    103         uhci_transfer_batch_finish_dispose(uhci_batch);
    104 }
    105 /*----------------------------------------------------------------------------*/
    106 /** Linked list conversion wrapper.
    107  * @param l Linked list link.
    108  * @return Pointer to the uhci batch structure.
    109  */
    11084static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l)
    11185{
  • uspace/drv/bus/usb/uhcirh/main.c

    r153cc76a r2f0dd2a  
    3636#include <ddf/driver.h>
    3737#include <devman.h>
    38 #include <device/hw_res_parsed.h>
     38#include <device/hw_res.h>
    3939#include <errno.h>
    4040#include <str_error.h>
     
    136136{
    137137        assert(dev);
    138 
     138       
    139139        async_sess_t *parent_sess =
    140140            devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
     
    142142        if (!parent_sess)
    143143                return ENOMEM;
    144 
    145         hw_res_list_parsed_t hw_res;
    146         hw_res_list_parsed_init(&hw_res);
    147         const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
    148         async_hangup(parent_sess);
     144       
     145        hw_resource_list_t hw_resources;
     146        const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
    149147        if (ret != EOK) {
     148                async_hangup(parent_sess);
    150149                return ret;
    151150        }
    152 
    153         if (hw_res.io_ranges.count != 1) {
    154                 hw_res_list_parsed_clean(&hw_res);
    155                 return EINVAL;
     151       
     152        uintptr_t io_address = 0;
     153        size_t io_size = 0;
     154        bool io_found = false;
     155       
     156        size_t i = 0;
     157        for (; i < hw_resources.count; i++) {
     158                hw_resource_t *res = &hw_resources.resources[i];
     159                if (res->type == IO_RANGE) {
     160                        io_address = res->res.io_range.address;
     161                        io_size = res->res.io_range.size;
     162                        io_found = true;
     163                }
     164       
    156165        }
    157 
     166        async_hangup(parent_sess);
     167       
     168        if (!io_found)
     169                return ENOENT;
     170       
    158171        if (io_reg_address != NULL)
    159                 *io_reg_address = hw_res.io_ranges.ranges[0].address;
    160 
     172                *io_reg_address = io_address;
     173       
    161174        if (io_reg_size != NULL)
    162                 *io_reg_size = hw_res.io_ranges.ranges[0].size;
    163 
    164         hw_res_list_parsed_clean(&hw_res);
     175                *io_reg_size = io_size;
     176       
    165177        return EOK;
    166178}
  • uspace/drv/bus/usb/uhcirh/port.c

    r153cc76a r2f0dd2a  
    260260{
    261261        assert(port);
     262        assert(usb_hc_connection_is_opened(&port->hc_connection));
    262263
    263264        usb_log_debug("%s: Detected new device.\n", port->id_string);
     
    313314
    314315        /* Driver stopped, free used address */
    315         ret = usb_hub_unregister_device(&port->hc_connection,
    316             &port->attached_device);
     316        ret = usb_hc_unregister_device(&port->hc_connection,
     317            port->attached_device.address);
    317318        if (ret != EOK) {
    318319                usb_log_error("%s: Failed to unregister address of removed "
  • uspace/drv/bus/usb/usbhub/port.c

    r153cc76a r2f0dd2a  
    288288        port->attached_device.fun = NULL;
    289289
    290         ret = usb_hub_unregister_device(&hub->usb_device->hc_conn,
    291             &port->attached_device);
    292         if (ret != EOK) {
    293                 usb_log_warning("Failed to unregister address of the "
    294                     "removed device: %s.\n", str_error(ret));
     290        ret = usb_hc_connection_open(&hub->connection);
     291        if (ret == EOK) {
     292                ret = usb_hc_unregister_device(&hub->connection,
     293                    port->attached_device.address);
     294                if (ret != EOK) {
     295                        usb_log_warning("Failed to unregister address of the "
     296                            "removed device: %s.\n", str_error(ret));
     297                }
     298                ret = usb_hc_connection_close(&hub->connection);
     299                if (ret != EOK) {
     300                        usb_log_warning("Failed to close hc connection %s.\n",
     301                            str_error(ret));
     302                }
     303
     304        } else {
     305                usb_log_warning("Failed to open hc connection %s.\n",
     306                    str_error(ret));
    295307        }
    296308
     
    426438
    427439        const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    428             &data->hub->usb_device->hc_conn, data->speed, enable_port_callback,
     440            &data->hub->connection, data->speed, enable_port_callback,
    429441            data->port, &new_address, NULL, NULL, &child_fun);
    430442
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r153cc76a r2f0dd2a  
    9999        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
    100100
    101 
    102         int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe);
    103         if (opResult != EOK) {
    104                 usb_log_error("Failed to start long ctrl pipe transfer: %s\n",
     101        /* Create hc connection */
     102        usb_log_debug("Initializing USB wire abstraction.\n");
     103        int opResult = usb_hc_connection_initialize_from_device(
     104            &hub_dev->connection, hub_dev->usb_device->ddf_dev);
     105        if (opResult != EOK) {
     106                usb_log_error("Could not initialize connection to device: %s\n",
    105107                    str_error(opResult));
    106108                return opResult;
     
    110112        opResult = usb_set_first_configuration(usb_dev);
    111113        if (opResult != EOK) {
    112                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    113114                usb_log_error("Could not set hub configuration: %s\n",
    114115                    str_error(opResult));
     
    119120        opResult = usb_hub_process_hub_specific_info(hub_dev);
    120121        if (opResult != EOK) {
    121                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    122122                usb_log_error("Could process hub specific info, %s\n",
    123123                    str_error(opResult));
     
    130130            fun_exposed, HUB_FNC_NAME);
    131131        if (hub_dev->hub_fun == NULL) {
    132                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    133132                usb_log_error("Failed to create hub function.\n");
    134133                return ENOMEM;
     
    138137        opResult = ddf_fun_bind(hub_dev->hub_fun);
    139138        if (opResult != EOK) {
    140                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    141139                usb_log_error("Failed to bind hub function: %s.\n",
    142140                   str_error(opResult));
     
    150148            usb_hub_polling_terminated_callback, hub_dev);
    151149        if (opResult != EOK) {
    152                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    153150                /* Function is already bound */
    154151                ddf_fun_unbind(hub_dev->hub_fun);
     
    162159            hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
    163160
    164         usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    165161        return EOK;
    166162}
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r153cc76a r2f0dd2a  
    5757        /** Port structures, one for each port */
    5858        usb_hub_port_t *ports;
     59        /** Connection to hcd */
     60        usb_hc_connection_t connection;
    5961        /** Generic usb device data*/
    6062        usb_device_t *usb_device;
  • uspace/drv/bus/usb/usbmid/main.c

    r153cc76a r2f0dd2a  
    5353        usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
    5454
    55         const bool accept = usbmid_explore_device(dev);
     55        usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     56
     57        bool accept = usbmid_explore_device(dev);
     58
     59        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    5660
    5761        if (!accept) {
  • uspace/drv/bus/usb/vhc/hub.c

    r153cc76a r2f0dd2a  
    107107
    108108        usb_hc_connection_t hc_conn;
    109         usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
     109        rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
     110        assert(rc == EOK);
    110111
    111112        rc = usb_hc_connection_open(&hc_conn);
  • uspace/lib/drv/include/usbhc_iface.h

    r153cc76a r2f0dd2a  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libdrv
    3030 * @addtogroup usb
     
    4646int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *);
    4747int usbhc_release_address(async_exch_t *, usb_address_t);
    48 int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
     48int usbhc_register_endpoint(async_exch_t *, usb_address_t,  usb_endpoint_t,
    4949    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    5050int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
  • uspace/lib/usb/Makefile

    r153cc76a r2f0dd2a  
    3737        src/class.c \
    3838        src/ddfiface.c \
    39         src/dev.c \
    4039        src/debug.c \
    4140        src/dump.c \
    4241        src/hc.c \
     42        src/resolve.c \
    4343        src/usb.c
    4444
  • uspace/lib/usb/include/usb/classes/hub.h

    r153cc76a r2f0dd2a  
    8484
    8585/**
    86  * @brief usb hub descriptor
    87  *
    88  * For more information see Universal Serial Bus Specification Revision 1.1
    89  * chapter 11.16.2
     86 *      @brief usb hub descriptor
     87 *
     88 *      For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
    9089 */
    9190typedef struct usb_hub_descriptor_type {
  • uspace/lib/usb/include/usb/hc.h

    r153cc76a r2f0dd2a  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libusb
    3030 * @{
    3131 */
    3232/** @file
    33  * General communication with host controller.
     33 * General communication with host controller driver.
    3434 */
    3535#ifndef LIBUSB_HC_H_
    3636#define LIBUSB_HC_H_
    3737
    38 #include <async.h>
    39 #include <devman.h>
     38#include <sys/types.h>
     39#include <ipc/devman.h>
     40#include <ipc/loc.h>
    4041#include <ddf/driver.h>
    4142#include <bool.h>
    42 #include <fibril_synch.h>
     43#include <async.h>
    4344#include <usb/usb.h>
    4445
    45 /** Connection to the host controller driver.
    46  *
    47  * This is a high level IPC communication wrapper. After the structure has been
    48  * initialized using devman handle of an USB host controller, it
    49  * will manage all communication to that host controller, including session
    50  * creation/destruction and proper IPC protocol.
    51  */
     46/** Connection to the host controller driver. */
    5247typedef struct {
    5348        /** Devman handle of the host controller. */
     
    5550        /** Session to the host controller. */
    5651        async_sess_t *hc_sess;
    57         /** Session guard. */
    58         fibril_mutex_t guard;
    59         /** Use counter. */
    60         unsigned ref_count;
    6152} usb_hc_connection_t;
    62 
    63 /** Initialize connection to USB host controller.
    64  *
    65  * @param connection Connection to be initialized.
    66  * @param hc_handle Devman handle of the host controller.
    67  * @return Error code.
    68  */
    69 static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection,
    70     devman_handle_t hc_handle)
    71 {
    72         assert(connection);
    73         connection->hc_handle = hc_handle;
    74         connection->hc_sess = NULL;
    75         connection->ref_count = 0;
    76         fibril_mutex_initialize(&connection->guard);
    77 }
    7853
    7954int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
    8055    const ddf_dev_t *);
    81 
    82 void usb_hc_connection_deinitialize(usb_hc_connection_t *);
     56int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
    8357
    8458int usb_hc_connection_open(usb_hc_connection_t *);
     59bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
    8560int usb_hc_connection_close(usb_hc_connection_t *);
    86 
    87 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool,
    88     usb_speed_t);
    89 int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t);
    9061int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
    9162    devman_handle_t *);
    92 int usb_hc_release_address(usb_hc_connection_t *, usb_address_t);
    9363
    94 int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t,
    95     usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    96 int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t,
    97     usb_endpoint_t, usb_direction_t);
     64usb_address_t usb_get_address_by_handle(devman_handle_t);
    9865
    99 int usb_hc_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
    100     uint64_t, void *, size_t, size_t *);
    101 int usb_hc_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
    102     uint64_t, const void *, size_t);
     66int usb_hc_find(devman_handle_t, devman_handle_t *);
    10367
    104 /** Get host controller handle by its class index.
    105  *
    106  * @param sid Service ID of the HC function.
    107  * @param hc_handle Where to store the HC handle
    108  *      (can be NULL for existence test only).
    109  * @return Error code.
    110  */
    111 static inline int usb_ddf_get_hc_handle_by_sid(
    112     service_id_t sid, devman_handle_t *handle)
    113 {
    114         devman_handle_t h;
    115         return devman_fun_sid_to_handle(sid, handle ? handle : &h);
    116 }
     68int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
     69    devman_handle_t *);
     70
     71int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
     72
    11773
    11874#endif
  • uspace/lib/usb/include/usb/usb.h

    r153cc76a r2f0dd2a  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusb
    2930 * @{
  • uspace/lib/usb/src/ddfiface.c

    r153cc76a r2f0dd2a  
    4444#include <assert.h>
    4545
    46 #include <usb/dev.h>
    47 
    4846/** DDF interface for USB device, implementation for typical hub. */
    4947usb_iface_t usb_iface_hub_impl = {
     
    6866{
    6967        assert(fun);
    70         return usb_get_hc_by_handle(fun->handle, handle);
     68        return usb_hc_find(fun->handle, handle);
    7169}
    7270
     
    9997{
    10098        assert(fun);
    101         return usb_get_address_by_handle(fun->handle, address);
     99
     100        async_sess_t *parent_sess =
     101            devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
     102            IPC_FLAG_BLOCKING);
     103        if (!parent_sess)
     104                return ENOMEM;
     105
     106        async_exch_t *exch = async_exchange_begin(parent_sess);
     107        if (!exch) {
     108                async_hangup(parent_sess);
     109                return ENOMEM;
     110        }
     111
     112        const int ret = usb_get_my_address(exch, address);
     113
     114        async_exchange_end(exch);
     115        async_hangup(parent_sess);
     116
     117        return ret;
    102118}
    103119
     
    118134        assert(fun);
    119135        assert(fun->driver_data);
    120         const usb_hub_attached_device_t *device = fun->driver_data;
     136        usb_hub_attached_device_t *device = fun->driver_data;
    121137        assert(device->fun == fun);
    122138        if (address)
  • uspace/lib/usb/src/hc.c

    r153cc76a r2f0dd2a  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libusb
    3030 * @{
     
    3333 * General communication with host controller driver (implementation).
    3434 */
     35#include <devman.h>
     36#include <async.h>
     37#include <dev_iface.h>
     38#include <usb_iface.h>
     39#include <usbhc_iface.h>
     40#include <usb/hc.h>
    3541#include <usb/debug.h>
    36 
     42#include <errno.h>
    3743#include <assert.h>
    38 #include <errno.h>
    39 #include <usbhc_iface.h>
    40 #include <usb/dev.h>
    41 #include <usb/hc.h>
    42 
    43 static int usb_hc_connection_add_ref(usb_hc_connection_t *connection)
    44 {
    45         assert(connection);
    46         fibril_mutex_lock(&connection->guard);
    47         if (connection->ref_count == 0) {
    48                 assert(connection->hc_sess == NULL);
    49                 /* Parallel exchange for us */
    50                 connection->hc_sess = devman_device_connect(EXCHANGE_PARALLEL,
    51                         connection->hc_handle, 0);
    52                 if (!connection->hc_sess) {
    53                         fibril_mutex_unlock(&connection->guard);
    54                         return ENOMEM;
    55                 }
    56         }
    57         ++connection->ref_count;
    58         fibril_mutex_unlock(&connection->guard);
    59         return EOK;
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 static int usb_hc_connection_del_ref(usb_hc_connection_t *connection)
    63 {
    64         assert(connection);
    65         fibril_mutex_lock(&connection->guard);
    66         if (connection->ref_count == 0) {
    67                 /* Closing already closed connection... */
    68                 assert(connection->hc_sess = NULL);
    69                 fibril_mutex_unlock(&connection->guard);
    70                 return EOK;
    71         }
    72         --connection->ref_count;
    73         int ret = EOK;
    74         if (connection->ref_count == 0) {
    75                 assert(connection->hc_sess);
    76                 ret = async_hangup(connection->hc_sess);
    77                 connection->hc_sess = NULL;
    78         }
    79         fibril_mutex_unlock(&connection->guard);
    80         return ret;
    81 }
    82 
    83 #define EXCH_INIT(connection, exch) \
    84 do { \
    85         exch = NULL; \
    86         if (!connection) \
    87                 return EBADMEM; \
    88         const int ret = usb_hc_connection_add_ref(connection); \
    89         if (ret != EOK) \
    90                 return ret; \
    91         exch = async_exchange_begin(connection->hc_sess); \
    92         if (exch == NULL) { \
    93                 usb_hc_connection_del_ref(connection); \
    94                 return ENOMEM; \
    95         } \
    96 } while (0)
    97 
    98 #define EXCH_FINI(connection, exch) \
    99 if (exch) { \
    100         async_exchange_end(exch); \
    101         usb_hc_connection_del_ref(connection); \
    102 } else (void)0
    10344
    10445/** Initialize connection to USB host controller.
     
    11859
    11960        devman_handle_t hc_handle;
    120         const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
    121         if (rc == EOK) {
    122                 usb_hc_connection_initialize(connection, hc_handle);
    123         }
     61        int rc = usb_hc_find(device->handle, &hc_handle);
     62        if (rc != EOK) {
     63                return rc;
     64        }
     65
     66        rc = usb_hc_connection_initialize(connection, hc_handle);
    12467
    12568        return rc;
    12669}
    127 /*----------------------------------------------------------------------------*/
    128 void usb_hc_connection_deinitialize(usb_hc_connection_t *connection)
    129 {
    130         assert(connection);
    131         fibril_mutex_lock(&connection->guard);
    132         if (connection->ref_count != 0) {
    133                 usb_log_warning("%u stale reference(s) to HC connection.\n",
    134                     connection->ref_count);
    135                 assert(connection->hc_sess);
    136                 async_hangup(connection->hc_sess);
    137                 connection->hc_sess = NULL;
    138                 connection->ref_count = 0;
    139         }
    140         fibril_mutex_unlock(&connection->guard);
    141 }
    142 /*----------------------------------------------------------------------------*/
     70
     71/** Manually initialize connection to USB host controller.
     72 *
     73 * @param connection Connection to be initialized.
     74 * @param hc_handle Devman handle of the host controller.
     75 * @return Error code.
     76 */
     77int usb_hc_connection_initialize(usb_hc_connection_t *connection,
     78    devman_handle_t hc_handle)
     79{
     80        assert(connection);
     81
     82        connection->hc_handle = hc_handle;
     83        connection->hc_sess = NULL;
     84
     85        return EOK;
     86}
     87
    14388/** Open connection to host controller.
    14489 *
     
    14893int usb_hc_connection_open(usb_hc_connection_t *connection)
    14994{
    150         return usb_hc_connection_add_ref(connection);
    151 }
    152 /*----------------------------------------------------------------------------*/
     95        assert(connection);
     96       
     97        if (usb_hc_connection_is_opened(connection))
     98                return EBUSY;
     99       
     100        async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
     101            connection->hc_handle, 0);
     102        if (!sess)
     103                return ENOMEM;
     104       
     105        connection->hc_sess = sess;
     106        return EOK;
     107}
     108
     109/** Tells whether connection to host controller is opened.
     110 *
     111 * @param connection Connection to the host controller.
     112 * @return Whether connection is opened.
     113 */
     114bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
     115{
     116        assert(connection);
     117        return (connection->hc_sess != NULL);
     118}
     119
    153120/** Close connection to the host controller.
    154121 *
     
    158125int usb_hc_connection_close(usb_hc_connection_t *connection)
    159126{
    160         return usb_hc_connection_del_ref(connection);
    161 }
    162 /*----------------------------------------------------------------------------*/
    163 /** Ask host controller for free address assignment.
    164  *
    165  * @param connection Opened connection to host controller.
    166  * @param preferred Preferred SUB address.
    167  * @param strict Fail if the preferred address is not avialable.
    168  * @param speed Speed of the new device (device that will be assigned
    169  *    the returned address).
    170  * @return Assigned USB address or negative error code.
    171  */
    172 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    173     usb_address_t preferred, bool strict, usb_speed_t speed)
    174 {
    175         async_exch_t *exch;
    176         EXCH_INIT(connection, exch);
    177 
    178         usb_address_t address = preferred;
    179         const int ret = usbhc_request_address(exch, &address, strict, speed);
    180 
    181         EXCH_FINI(connection, exch);
    182         return ret == EOK ? address : ret;
    183 }
    184 /*----------------------------------------------------------------------------*/
    185 int usb_hc_bind_address(usb_hc_connection_t * connection,
    186     usb_address_t address, devman_handle_t handle)
    187 {
    188         async_exch_t *exch;
    189         EXCH_INIT(connection, exch);
    190 
    191         const int ret = usbhc_bind_address(exch, address, handle);
    192 
    193         EXCH_FINI(connection, exch);
    194         return ret;
    195 }
    196 /*----------------------------------------------------------------------------*/
     127        assert(connection);
     128
     129        if (!usb_hc_connection_is_opened(connection)) {
     130                return ENOENT;
     131        }
     132
     133        int rc = async_hangup(connection->hc_sess);
     134        if (rc != EOK) {
     135                return rc;
     136        }
     137
     138        connection->hc_sess = NULL;
     139
     140        return EOK;
     141}
     142
    197143/** Get handle of USB device with given address.
    198144 *
     
    205151    usb_address_t address, devman_handle_t *handle)
    206152{
    207         async_exch_t *exch;
    208         EXCH_INIT(connection, exch);
    209 
     153        if (!usb_hc_connection_is_opened(connection))
     154                return ENOENT;
     155
     156        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     157        if (!exch)
     158                return ENOMEM;
    210159        const int ret = usbhc_get_handle(exch, address, handle);
    211 
    212         EXCH_FINI(connection, exch);
     160        async_exchange_end(exch);
    213161        return ret;
    214162}
    215 /*----------------------------------------------------------------------------*/
    216 int usb_hc_release_address(usb_hc_connection_t *connection,
    217     usb_address_t address)
    218 {
    219         async_exch_t *exch;
    220         EXCH_INIT(connection, exch);
    221 
    222         const int ret = usbhc_release_address(exch, address);
    223 
    224         EXCH_FINI(connection, exch);
    225         return ret;
    226 }
    227 /*----------------------------------------------------------------------------*/
    228 int usb_hc_register_endpoint(usb_hc_connection_t *connection,
    229     usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type,
    230     usb_direction_t direction, size_t packet_size, unsigned interval)
    231 {
    232         async_exch_t *exch;
    233         EXCH_INIT(connection, exch);
    234 
    235         const int ret = usbhc_register_endpoint(exch, address, endpoint,
    236             type, direction, packet_size, interval);
    237 
    238         EXCH_FINI(connection, exch);
    239         return ret;
    240 }
    241 /*----------------------------------------------------------------------------*/
    242 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection,
    243     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    244 {
    245         async_exch_t *exch;
    246         EXCH_INIT(connection, exch);
    247 
    248         const int ret =
    249             usbhc_unregister_endpoint(exch, address, endpoint, direction);
    250 
    251         EXCH_FINI(connection, exch);
    252         return ret;
    253 }
    254 /*----------------------------------------------------------------------------*/
    255 int usb_hc_read(usb_hc_connection_t *connection, usb_address_t address,
    256     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
    257     size_t *real_size)
    258 {
    259         async_exch_t *exch;
    260         EXCH_INIT(connection, exch);
    261 
    262         const int ret =
    263             usbhc_read(exch, address, endpoint, setup, data, size, real_size);
    264 
    265         EXCH_FINI(connection, exch);
    266         return ret;
    267 }
    268 /*----------------------------------------------------------------------------*/
    269 int usb_hc_write(usb_hc_connection_t *connection, usb_address_t address,
    270     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
    271 {
    272         async_exch_t *exch;
    273         EXCH_INIT(connection, exch);
    274 
    275         const int ret = usbhc_write(exch, address, endpoint, setup, data, size);
    276 
    277         EXCH_FINI(connection, exch);
     163
     164/** Tell USB address assigned to device with given handle.
     165 *
     166 * @param dev_handle Devman handle of the USB device in question.
     167 * @return USB address or negative error code.
     168 */
     169usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle)
     170{
     171        async_sess_t *parent_sess =
     172            devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
     173            IPC_FLAG_BLOCKING);
     174        if (!parent_sess)
     175                return ENOMEM;
     176
     177        async_exch_t *exch = async_exchange_begin(parent_sess);
     178        if (!exch) {
     179                async_hangup(parent_sess);
     180                return ENOMEM;
     181        }
     182        usb_address_t address;
     183        const int ret = usb_get_my_address(exch, &address);
     184
     185        async_exchange_end(exch);
     186        async_hangup(parent_sess);
     187
     188        if (ret != EOK)
     189                return ret;
     190
     191        return address;
     192}
     193
     194
     195/** Get host controller handle by its class index.
     196 *
     197 * @param sid Service ID of the HC function.
     198 * @param hc_handle Where to store the HC handle
     199 *      (can be NULL for existence test only).
     200 * @return Error code.
     201 */
     202int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
     203{
     204        devman_handle_t handle;
     205        int rc;
     206       
     207        rc = devman_fun_sid_to_handle(sid, &handle);
     208        if (hc_handle != NULL)
     209                *hc_handle = handle;
     210       
     211        return rc;
     212}
     213
     214/** Find host controller handle that is ancestor of given device.
     215 *
     216 * @param[in] device_handle Device devman handle.
     217 * @param[out] hc_handle Where to store handle of host controller
     218 *      controlling device with @p device_handle handle.
     219 * @return Error code.
     220 */
     221int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
     222{
     223        async_sess_t *parent_sess =
     224            devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
     225            IPC_FLAG_BLOCKING);
     226        if (!parent_sess)
     227                return ENOMEM;
     228
     229        async_exch_t *exch = async_exchange_begin(parent_sess);
     230        if (!exch) {
     231                async_hangup(parent_sess);
     232                return ENOMEM;
     233        }
     234        const int ret = usb_get_hc_handle(exch, hc_handle);
     235
     236        async_exchange_end(exch);
     237        async_hangup(parent_sess);
     238
    278239        return ret;
    279240}
  • uspace/lib/usb/src/usb.c

    r153cc76a r2f0dd2a  
    3939
    4040static const char *str_speed[] = {
    41         [USB_SPEED_LOW] = "low",
    42         [USB_SPEED_FULL] = "full",
    43         [USB_SPEED_HIGH] = "high",
     41        "low",
     42        "full",
     43        "high"
    4444};
    4545
    4646static const char *str_transfer_type[] = {
    47         [USB_TRANSFER_CONTROL] = "control",
    48         [USB_TRANSFER_ISOCHRONOUS] = "isochronous",
    49         [USB_TRANSFER_BULK] = "bulk",
    50         [USB_TRANSFER_INTERRUPT] = "interrupt",
     47        "control",
     48        "isochronous",
     49        "bulk",
     50        "interrupt"
    5151};
    5252
    5353static const char *str_transfer_type_short[] = {
    54         [USB_TRANSFER_CONTROL] = "ctrl",
    55         [USB_TRANSFER_ISOCHRONOUS] = "iso",
    56         [USB_TRANSFER_BULK] = "bulk",
    57         [USB_TRANSFER_INTERRUPT] = "intr",
     54        "ctrl",
     55        "iso",
     56        "bulk",
     57        "intr"
    5858};
    5959
    6060static const char *str_direction[] = {
    61         [USB_DIRECTION_IN] = "in",
    62         [USB_DIRECTION_OUT] = "out",
    63         [USB_DIRECTION_BOTH] = "both",
     61        "in",
     62        "out",
     63        "both"
    6464};
    6565
  • uspace/lib/usbdev/Makefile

    r153cc76a r2f0dd2a  
    4040        src/dp.c \
    4141        src/hub.c \
     42        src/pipepriv.c \
     43        src/pipepriv.h \
    4244        src/pipes.c \
    4345        src/pipesinit.c \
     46        src/pipesio.c \
    4447        src/recognise.c \
    4548        src/request.c
  • uspace/lib/usbdev/include/usb/dev/driver.h

    r153cc76a r2f0dd2a  
    3636#define LIBUSBDEV_DRIVER_H_
    3737
    38 #include <usb/hc.h>
    39 #include <usb/dev/usb_device_connection.h>
    4038#include <usb/dev/pipes.h>
    4139
     
    7472/** USB device structure. */
    7573typedef struct {
    76         /** Connection to USB hc, used by wire and arbitrary requests. */
    77         usb_hc_connection_t hc_conn;
    7874        /** Connection backing the pipes.
    7975         * Typically, you will not need to use this attribute at all.
     
    173169void usb_device_release_descriptors(usb_device_descriptors_t *);
    174170
    175 int usb_device_create_pipes(usb_device_connection_t *,
     171int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *,
    176172    const usb_endpoint_description_t **, const uint8_t *, size_t, int, int,
    177173    usb_endpoint_mapping_t **, size_t *);
    178 void usb_device_destroy_pipes(usb_endpoint_mapping_t *, size_t);
     174int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    179175
    180176void * usb_device_data_alloc(usb_device_t *, size_t);
  • uspace/lib/usbdev/include/usb/dev/hub.h

    r153cc76a r2f0dd2a  
    4040#include <ddf/driver.h>
    4141#include <sys/types.h>
    42 #include <errno.h>
    4342#include <usb/hc.h>
    4443
     
    6059} usb_hub_attached_device_t;
    6160
    62 int usb_hub_register_device(usb_hc_connection_t *,
     61usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t,
     62    bool, usb_speed_t);
     63int usb_hc_register_device(usb_hc_connection_t *,
    6364    const usb_hub_attached_device_t *);
    64 
    65 static inline int usb_hub_unregister_device(usb_hc_connection_t *conn,
    66     const usb_hub_attached_device_t *attached_device)
    67 {
    68         assert(conn);
    69         if (attached_device == NULL)
    70                 return EBADMEM;
    71         return usb_hc_release_address(conn, attached_device->address);
    72 }
     65int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
    7366
    7467#endif
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r153cc76a r2f0dd2a  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusbdev
    2930 * @{
     
    3637
    3738#include <sys/types.h>
     39#include <usb/usb.h>
     40#include <usb/hc.h>
     41#include <usb/descriptor.h>
    3842#include <ipc/devman.h>
    3943#include <ddf/driver.h>
    4044#include <fibril_synch.h>
    41 #include <usb/usb.h>
    42 #include <usb/descriptor.h>
    43 #include <usb/dev/usb_device_connection.h>
     45#include <async.h>
    4446
    45 #define CTRL_PIPE_MIN_PACKET_SIZE 8
     47/** Abstraction of a physical connection to the device.
     48 * This type is an abstraction of the USB wire that connects the host and
     49 * the function (device).
     50 */
     51typedef struct {
     52        /** Handle of the host controller device is connected to. */
     53        devman_handle_t hc_handle;
     54        /** Address of the device. */
     55        usb_address_t address;
     56} usb_device_connection_t;
     57
    4658/** Abstraction of a logical connection to USB device endpoint.
    47  * It encapsulates endpoint attributes (transfer type etc.).
     59 * It encapsulates endpoint attributes (transfer type etc.) as well
     60 * as information about currently running sessions.
    4861 * This endpoint must be bound with existing usb_device_connection_t
    4962 * (i.e. the wire to send data over).
     63 *
     64 * Locking order: if you want to lock both mutexes
     65 * (@c guard and @c hc_sess_mutex), lock @c guard first.
     66 * It is not necessary to lock @c guard if you want to lock @c hc_sess_mutex
     67 * only.
    5068 */
    5169typedef struct {
     70        /** Guard of the whole pipe. */
     71        fibril_mutex_t guard;
     72
    5273        /** The connection used for sending the data. */
    5374        usb_device_connection_t *wire;
     
    6586        size_t max_packet_size;
    6687
     88        /** Session to the host controller.
     89         * NULL when no session is active.
     90         * It is an error to access this member without @c hc_sess_mutex
     91         * being locked.
     92         * If call over the phone is to be made, it must be preceeded by
     93         * call to pipe_add_ref() [internal libusb function].
     94         */
     95        async_sess_t *hc_sess;
     96
     97        /** Guard for serialization of requests over the session. */
     98        fibril_mutex_t hc_sess_mutex;
     99
     100        /** Number of active transfers over the pipe. */
     101        int refcount;
     102        /** Number of failed attempts to open the HC phone.
     103         * When user requests usb_pipe_start_long_transfer() and the operation
     104         * fails, there is no way to report this to the user.
     105         * That the soft reference counter is increased to record the attempt.
     106         * When the user then request e.g. usb_pipe_read(), it will try to
     107         * add reference as well.
     108         * If that fails, it is reported to the user. If it is okay, the
     109         * real reference counter is incremented.
     110         * The problem might arise when ending the long transfer (since
     111         * the number of references would be only 1, but logically it shall be
     112         * two).
     113         * Decrementing the soft counter first shall solve this.
     114         */
     115        int refcount_soft;
     116
    67117        /** Whether to automatically reset halt on the endpoint.
    68118         * Valid only for control endpoint zero.
     
    70120        bool auto_reset_halt;
    71121} usb_pipe_t;
     122
    72123
    73124/** Description of endpoint characteristics. */
     
    105156} usb_endpoint_mapping_t;
    106157
     158int usb_device_connection_initialize_on_default_address(
     159    usb_device_connection_t *, usb_hc_connection_t *);
     160int usb_device_connection_initialize_from_device(usb_device_connection_t *,
     161    const ddf_dev_t *);
     162int usb_device_connection_initialize(usb_device_connection_t *,
     163    devman_handle_t, usb_address_t);
     164
     165int usb_device_get_assigned_interface(const ddf_dev_t *);
     166
    107167int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *,
    108168    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
    109169int usb_pipe_initialize_default_control(usb_pipe_t *,
    110170    usb_device_connection_t *);
    111 
    112171int usb_pipe_probe_default_control(usb_pipe_t *);
    113172int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    114173    size_t, const uint8_t *, size_t, usb_device_connection_t *);
     174int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
     175int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
    115176
    116 int usb_pipe_register(usb_pipe_t *, unsigned);
    117 int usb_pipe_unregister(usb_pipe_t *);
    118 
    119 int usb_pipe_start_long_transfer(usb_pipe_t *);
    120 int usb_pipe_end_long_transfer(usb_pipe_t *);
     177void usb_pipe_start_long_transfer(usb_pipe_t *);
     178void usb_pipe_end_long_transfer(usb_pipe_t *);
    121179
    122180int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usbdev/include/usb/dev/poll.h

    r153cc76a r2f0dd2a  
    3939#include <time.h>
    4040
    41 /** Parameters and callbacks for automated polling. */
    4241typedef struct {
    4342        /** Level of debugging messages from auto polling.
     
    8382         */
    8483        bool (*on_error)(usb_device_t *dev, int err_code, void *arg);
    85         /** Argument to pass to callbacks. */
    86         void *arg;
    8784} usb_device_auto_polling_t;
    8885
    8986int usb_device_auto_polling(usb_device_t *, size_t,
    90     const usb_device_auto_polling_t *, size_t);
     87    const usb_device_auto_polling_t *, size_t, void *);
    9188
    9289typedef bool (*usb_polling_callback_t)(usb_device_t *,
  • uspace/lib/usbdev/include/usb/dev/request.h

    r153cc76a r2f0dd2a  
    8383        uint8_t request_type;
    8484#define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7)
    85 #define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3)
    86 #define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f)
    87 #define SETUP_REQUEST_TO_HOST(type, recipient) \
    88     (uint8_t)((1 << 7) | ((type & 0x3) << 5) | (recipient & 0x1f))
    89 #define SETUP_REQUEST_TO_DEVICE(type, recipient) \
    90     (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f))
    9185
    9286        /** Request identification. */
  • uspace/lib/usbdev/src/altiface.c

    r153cc76a r2f0dd2a  
    167167}
    168168
    169 /** Clean initialized structure.
    170  * @param instance structure do deinitialize.
    171  */
    172 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *instance)
     169void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate)
    173170{
    174         if (!instance)
     171        if (!alternate)
    175172                return;
    176         free(instance->alternatives);
    177         instance->alternatives = NULL;
     173        free(alternate->alternatives);
    178174}
    179175/**
  • uspace/lib/usbdev/src/devdrv.c

    r153cc76a r2f0dd2a  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libusbdev
    3030 * @{
     
    3636#include <usb/dev/request.h>
    3737#include <usb/debug.h>
    38 #include <usb/dev.h>
     38#include <usb/dev/dp.h>
    3939#include <errno.h>
    4040#include <str_error.h>
     
    5656static const usb_driver_t *driver = NULL;
    5757
     58
    5859/** Main routine of USB device driver.
    5960 *
     
    7475        return ddf_driver_main(&generic_driver);
    7576}
    76 /*----------------------------------------------------------------------------*/
     77
    7778/** Count number of pipes the driver expects.
    7879 *
     
    8485{
    8586        size_t count;
    86         for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count);
     87        for (count = 0; endpoints && endpoints[count] != NULL; ++count);
    8788        return count;
     89}
     90
     91/** Initialize endpoint pipes, excluding default control one.
     92 *
     93 * @param drv The device driver.
     94 * @param dev Device to be initialized.
     95 * @return Error code.
     96 */
     97static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
     98    usb_device_t *dev, int alternate_setting)
     99{
     100        assert(dev);
     101
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
     105                return EOK;
     106        }
     107
     108        usb_endpoint_mapping_t *pipes;
     109        size_t pipes_count;
     110
     111        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
     112            dev->descriptors.configuration, dev->descriptors.configuration_size,
     113            dev->interface_no, alternate_setting, &pipes, &pipes_count);
     114
     115        if (rc != EOK) {
     116                return rc;
     117        }
     118
     119        dev->pipes = pipes;
     120        dev->pipes_count = pipes_count;
     121
     122        return EOK;
    88123}
    89124/*----------------------------------------------------------------------------*/
     
    101136        assert(driver->ops->device_add);
    102137
    103         /* Get place for driver data. */
    104138        usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
    105139        if (dev == NULL) {
     
    108142                return ENOMEM;
    109143        }
    110 
    111         /* Initialize generic USB driver data. */
    112144        const char *err_msg = NULL;
    113145        int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
     
    118150        }
    119151
    120         /* Start USB driver specific initialization. */
    121152        rc = driver->ops->device_add(dev);
    122153        if (rc != EOK)
     
    138169        if (driver->ops->device_rem == NULL)
    139170                return ENOTSUP;
    140         /* Just tell the driver to stop whatever it is doing */
    141         usb_device_t *usb_dev = gen_dev->driver_data;
    142         const int ret = driver->ops->device_rem(usb_dev);
    143         if (ret != EOK)
    144                 return ret;
    145         usb_device_deinit(usb_dev);
    146         return EOK;
     171        /* Just tell the driver to stop whatever it is doing, keep structures */
     172        return driver->ops->device_rem(gen_dev->driver_data);
    147173}
    148174/*----------------------------------------------------------------------------*/
     
    171197 *
    172198 * @param dev Device where to destroy the pipes.
    173  */
    174 static void destroy_current_pipes(usb_device_t *dev)
    175 {
    176         usb_device_destroy_pipes(dev->pipes, dev->pipes_count);
     199 * @return Error code.
     200 */
     201static int destroy_current_pipes(usb_device_t *dev)
     202{
     203        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     204            dev->pipes, dev->pipes_count);
     205        if (rc != EOK) {
     206                return rc;
     207        }
     208
    177209        dev->pipes = NULL;
    178210        dev->pipes_count = 0;
    179 }
    180 /*----------------------------------------------------------------------------*/
     211
     212        return EOK;
     213}
     214
    181215/** Change interface setting of a device.
    182216 * This function selects new alternate setting of an interface by issuing
     
    208242        }
    209243
     244        int rc;
     245
    210246        /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
     247        rc = destroy_current_pipes(dev);
     248        if (rc != EOK) {
     249                return rc;
     250        }
    212251
    213252        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
     253        rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215254            alternate_setting);
    216255        if (rc != EOK) {
     
    219258
    220259        /* Create new pipes. */
    221         rc = usb_device_create_pipes(&dev->wire, endpoints,
    222             dev->descriptors.configuration, dev->descriptors.configuration_size,
    223             dev->interface_no, (int)alternate_setting,
    224             &dev->pipes, &dev->pipes_count);
     260        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    225261
    226262        return rc;
     
    280316 * - registers endpoints with the host controller
    281317 *
     318 * @param[in] dev Generic DDF device backing the USB one.
    282319 * @param[in] wire Initialized backing connection to the host controller.
    283320 * @param[in] endpoints Endpoints description, NULL terminated.
     
    292329 * @return Error code.
    293330 */
    294 int usb_device_create_pipes(usb_device_connection_t *wire,
     331int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
    295332    const usb_endpoint_description_t **endpoints,
    296333    const uint8_t *config_descr, size_t config_descr_size,
     
    298335    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
    299336{
     337        assert(dev != NULL);
    300338        assert(wire != NULL);
     339        assert(endpoints != NULL);
    301340        assert(config_descr != NULL);
    302341        assert(config_descr_size > 0);
     
    320359        }
    321360
    322         /* Now initialize. */
     361        /* Now allocate and fully initialize. */
    323362        for (i = 0; i < pipe_count; i++) {
    324363                pipes[i].description = endpoints[i];
     
    331370            config_descr, config_descr_size, wire);
    332371        if (rc != EOK) {
    333                 free(pipes);
    334                 return rc;
    335         }
    336 
    337         /* Register created pipes. */
     372                goto rollback_free_only;
     373        }
     374
     375        /* Register the endpoints with HC. */
     376        usb_hc_connection_t hc_conn;
     377        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     378        if (rc != EOK) {
     379                goto rollback_free_only;
     380        }
     381
     382        rc = usb_hc_connection_open(&hc_conn);
     383        if (rc != EOK) {
     384                goto rollback_free_only;
     385        }
     386
    338387        for (i = 0; i < pipe_count; i++) {
    339388                if (pipes[i].present) {
    340389                        rc = usb_pipe_register(&pipes[i].pipe,
    341                             pipes[i].descriptor->poll_interval);
     390                            pipes[i].descriptor->poll_interval, &hc_conn);
    342391                        if (rc != EOK) {
    343392                                goto rollback_unregister_endpoints;
     
    345394                }
    346395        }
     396
     397        if (usb_hc_connection_close(&hc_conn) != EOK)
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    347400
    348401        *pipes_ptr = pipes;
     
    362415        for (i = 0; i < pipe_count; i++) {
    363416                if (pipes[i].present) {
    364                         usb_pipe_unregister(&pipes[i].pipe);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    365418                }
    366419        }
    367420
     421        if (usb_hc_connection_close(&hc_conn) != EOK)
     422                usb_log_warning("usb_device_create_pipes(): "
     423                    "Failed to close connection.\n");
     424
     425        /*
     426         * Jump here if something went wrong before some actual communication
     427         * with HC. Then the only thing that needs to be done is to free
     428         * allocated memory.
     429         */
     430rollback_free_only:
    368431        free(pipes);
     432
    369433        return rc;
    370434}
     
    372436/** Destroy pipes previously created by usb_device_create_pipes.
    373437 *
     438 * @param[in] dev Generic DDF device backing the USB one.
    374439 * @param[in] pipes Endpoint mapping to be destroyed.
    375440 * @param[in] pipes_count Number of endpoints.
    376441 */
    377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
    378 {
     442int usb_device_destroy_pipes(const ddf_dev_t *dev,
     443    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     444{
     445        assert(dev != NULL);
     446
     447        if (pipes_count == 0) {
     448                assert(pipes == NULL);
     449                return EOK;
     450        }
     451        assert(pipes != NULL);
     452
     453        int rc;
     454
     455        /* Prepare connection to HC to allow endpoint unregistering. */
     456        usb_hc_connection_t hc_conn;
     457        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     458        if (rc != EOK) {
     459                return rc;
     460        }
     461        rc = usb_hc_connection_open(&hc_conn);
     462        if (rc != EOK) {
     463                return rc;
     464        }
     465
    379466        /* Destroy the pipes. */
    380         for (size_t i = 0; i < pipes_count; ++i) {
    381                 assert(pipes);
    382                 usb_log_debug2("Unregistering pipe %zu: %spresent.\n",
     467        size_t i;
     468        for (i = 0; i < pipes_count; i++) {
     469                usb_log_debug2("Unregistering pipe %zu (%spresent).\n",
    383470                    i, pipes[i].present ? "" : "not ");
    384471                if (pipes[i].present)
    385                         usb_pipe_unregister(&pipes[i].pipe);
    386         }
     472                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
     473        }
     474
     475        if (usb_hc_connection_close(&hc_conn) != EOK)
     476                usb_log_warning("usb_device_destroy_pipes(): "
     477                    "Failed to close connection.\n");
     478
    387479        free(pipes);
     480
     481        return EOK;
    388482}
    389483
     
    411505        usb_dev->pipes = NULL;
    412506
    413         /* Get assigned params */
    414         devman_handle_t hc_handle;
    415         usb_address_t address;
    416 
    417         int rc = usb_get_info_by_handle(ddf_dev->handle,
    418             &hc_handle, &address, &usb_dev->interface_no);
    419         if (rc != EOK) {
    420                 *errstr_ptr = "device parameters retrieval";
    421                 return rc;
    422         }
    423 
    424         /* Initialize hc connection. */
    425         usb_hc_connection_initialize(&usb_dev->hc_conn, hc_handle);
    426 
    427507        /* Initialize backing wire and control pipe. */
    428         rc = usb_device_connection_initialize(
    429             &usb_dev->wire, &usb_dev->hc_conn, address);
     508        int rc = usb_device_connection_initialize_from_device(
     509            &usb_dev->wire, ddf_dev);
    430510        if (rc != EOK) {
    431511                *errstr_ptr = "device connection initialization";
     
    435515        /* This pipe was registered by the hub driver,
    436516         * during device initialization. */
    437         rc = usb_pipe_initialize_default_control(
    438             &usb_dev->ctrl_pipe, &usb_dev->wire);
     517        rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
     518            &usb_dev->wire);
    439519        if (rc != EOK) {
    440520                *errstr_ptr = "default control pipe initialization";
     
    442522        }
    443523
    444         /* Open hc connection for pipe registration. */
    445         rc = usb_hc_connection_open(&usb_dev->hc_conn);
    446         if (rc != EOK) {
    447                 *errstr_ptr = "hc connection open";
    448                 return rc;
    449         }
     524        /* Get our interface. */
     525        usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
    450526
    451527        /* Retrieve standard descriptors. */
    452         rc = usb_device_retrieve_descriptors(
    453             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
     528        rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
     529            &usb_dev->descriptors);
    454530        if (rc != EOK) {
    455531                *errstr_ptr = "descriptor retrieval";
    456                 usb_hc_connection_close(&usb_dev->hc_conn);
    457532                return rc;
    458533        }
     
    468543            (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
    469544
    470         /* Create and register other pipes than default control (EP 0) */
    471         rc = usb_device_create_pipes(&usb_dev->wire, endpoints,
    472             usb_dev->descriptors.configuration,
    473             usb_dev->descriptors.configuration_size,
    474             usb_dev->interface_no, (int)alternate_iface,
    475             &usb_dev->pipes, &usb_dev->pipes_count);
    476         if (rc != EOK) {
    477                 usb_hc_connection_close(&usb_dev->hc_conn);
     545        /* TODO Add comment here. */
     546        rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
     547        if (rc != EOK) {
    478548                /* Full configuration descriptor is allocated. */
    479549                usb_device_release_descriptors(&usb_dev->descriptors);
     
    484554        }
    485555
    486         usb_hc_connection_close(&usb_dev->hc_conn);
    487556        return EOK;
    488557}
     
    497566{
    498567        if (dev) {
    499                 /* Destroy existing pipes. */
     568                /* Ignore errors and hope for the best. */
    500569                destroy_current_pipes(dev);
    501                 /* Ignore errors and hope for the best. */
    502                 usb_hc_connection_deinitialize(&dev->hc_conn);
     570
    503571                usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
    504572                usb_device_release_descriptors(&dev->descriptors);
    505573                free(dev->driver_data);
    506                 dev->driver_data = NULL;
    507         }
    508 }
    509 
    510 /** Allocate driver specific data.
    511  * @param usb_dev usb_device structure.
    512  * @param size requested data size.
    513  * @return Pointer to the newly allocated space, NULL on failure.
    514  */
     574        }
     575}
     576
    515577void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
    516578{
  • uspace/lib/usbdev/src/devpoll.c

    r153cc76a r2f0dd2a  
    4646/** Data needed for polling. */
    4747typedef struct {
    48         /** Parameters for automated polling. */
    4948        usb_device_auto_polling_t auto_polling;
    5049
    51         /** USB device to poll. */
    5250        usb_device_t *dev;
    53         /** Device pipe to use for polling. */
    5451        size_t pipe_index;
    55         /** Size of the recieved data. */
    5652        size_t request_size;
    57         /** Data buffer. */
    5853        uint8_t *buffer;
     54        void *custom_arg;
    5955} polling_data_t;
    6056
     
    123119                        ++failed_attempts;
    124120                        const bool cont = (params->on_error == NULL) ? true :
    125                             params->on_error(data->dev, rc, params->arg);
     121                            params->on_error(data->dev, rc, data->custom_arg);
    126122                        if (!cont) {
    127123                                failed_attempts = params->max_failures;
     
    133129                assert(params->on_data);
    134130                const bool carry_on = params->on_data(
    135                     data->dev, data->buffer, actual_size, params->arg);
     131                    data->dev, data->buffer, actual_size, data->custom_arg);
    136132
    137133                if (!carry_on) {
     
    153149
    154150        if (params->on_polling_end != NULL) {
    155                 params->on_polling_end(data->dev, failed, params->arg);
     151                params->on_polling_end(data->dev, failed, data->custom_arg);
    156152        }
    157153
     
    203199                .on_polling_end = terminated_callback,
    204200                .on_error = NULL,
    205                 .arg = arg,
    206201        };
    207202
    208203        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    209            request_size);
     204           request_size, arg);
    210205}
    211206
     
    229224int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    230225    const usb_device_auto_polling_t *polling,
    231     size_t request_size)
     226    size_t request_size, void *arg)
    232227{
    233228        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     
    257252        polling_data->dev = dev;
    258253        polling_data->pipe_index = pipe_index;
     254        polling_data->custom_arg = arg;
    259255
    260256        /* Copy provided settings. */
  • uspace/lib/usbdev/src/hub.c

    r153cc76a r2f0dd2a  
    3838#include <usb/dev/recognise.h>
    3939#include <usb/debug.h>
     40#include <usbhc_iface.h>
    4041#include <errno.h>
    4142#include <assert.h>
     
    4445#include <async.h>
    4546
    46 /** How much time to wait between attempts to get the default address.
     47/** How much time to wait between attempts to register endpoint 0:0.
    4748 * The value is based on typical value for port reset + some overhead.
    4849 */
    49 #define DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     50#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     51
     52/** Check that HC connection is alright.
     53 *
     54 * @param conn Connection to be checked.
     55 */
     56#define CHECK_CONNECTION(conn) \
     57        do { \
     58                assert((conn)); \
     59                if (!usb_hc_connection_is_opened((conn))) { \
     60                        usb_log_error("Connection not open.\n"); \
     61                        return ENOTCONN; \
     62                } \
     63        } while (false)
     64
     65/** Ask host controller for free address assignment.
     66 *
     67 * @param connection Opened connection to host controller.
     68 * @param preferred Preferred SUB address.
     69 * @param strict Fail if the preferred address is not avialable.
     70 * @param speed Speed of the new device (device that will be assigned
     71 *    the returned address).
     72 * @return Assigned USB address or negative error code.
     73 */
     74usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
     75    usb_address_t preferred, bool strict, usb_speed_t speed)
     76{
     77        CHECK_CONNECTION(connection);
     78
     79        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     80        if (!exch)
     81                return (usb_address_t)ENOMEM;
     82
     83        usb_address_t address = preferred;
     84        const int ret = usbhc_request_address(exch, &address, strict, speed);
     85
     86        async_exchange_end(exch);
     87        return ret == EOK ? address : ret;
     88}
    5089
    5190/** Inform host controller about new device.
     
    5594 * @return Error code.
    5695 */
    57 int usb_hub_register_device(usb_hc_connection_t *connection,
     96int usb_hc_register_device(usb_hc_connection_t *connection,
    5897    const usb_hub_attached_device_t *attached_device)
    5998{
    60         assert(connection);
     99        CHECK_CONNECTION(connection);
    61100        if (attached_device == NULL || attached_device->fun == NULL)
    62                 return EBADMEM;
    63         return usb_hc_bind_address(connection,
     101                return EINVAL;
     102
     103        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     104        if (!exch)
     105                return ENOMEM;
     106        const int ret = usbhc_bind_address(exch,
    64107            attached_device->address, attached_device->fun->handle);
     108        async_exchange_end(exch);
     109
     110        return ret;
     111}
     112
     113/** Inform host controller about device removal.
     114 *
     115 * @param connection Opened connection to host controller.
     116 * @param address Address of the device that is being removed.
     117 * @return Error code.
     118 */
     119int usb_hc_unregister_device(usb_hc_connection_t *connection,
     120    usb_address_t address)
     121{
     122        CHECK_CONNECTION(connection);
     123
     124        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     125        if (!exch)
     126                return ENOMEM;
     127        const int ret = usbhc_release_address(exch, address);
     128        async_exchange_end(exch);
     129
     130        return ret;
    65131}
    66132
     
    79145 * @return Error code.
    80146 */
    81 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address)
     147static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
     148    usb_hc_connection_t *hc_conn)
    82149{
    83150        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     
    85152        }
    86153        assert(pipe);
     154        assert(hc_conn);
    87155        assert(pipe->wire != NULL);
    88156
     
    98166
    99167        /* TODO: prevent others from accessing the wire now. */
    100         if (usb_pipe_unregister(pipe) != EOK) {
     168        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
    101169                usb_log_warning(
    102170                    "Failed to unregister the old pipe on address change.\n");
    103171        }
    104         /* Address changed. We can release the old one, thus
    105          * allowing other to us it. */
    106         usb_hc_release_address(pipe->wire->hc_connection, pipe->wire->address);
    107 
    108172        /* The address is already changed so set it in the wire */
    109173        pipe->wire->address = new_address;
    110         rc = usb_pipe_register(pipe, 0);
     174        rc = usb_pipe_register(pipe, 0, hc_conn);
    111175        if (rc != EOK)
    112176                return EADDRNOTAVAIL;
     
    156220 */
    157221int usb_hc_new_device_wrapper(ddf_dev_t *parent,
    158     usb_hc_connection_t *hc_conn, usb_speed_t dev_speed,
     222    usb_hc_connection_t *connection, usb_speed_t dev_speed,
    159223    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    160224    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    161225{
    162         if (new_fun == NULL || hc_conn == NULL)
     226        if (new_fun == NULL || connection == NULL)
    163227                return EINVAL;
     228
     229        // TODO: Why not use provided connection?
     230        usb_hc_connection_t hc_conn;
     231        usb_hc_connection_initialize(&hc_conn, connection->hc_handle);
    164232
    165233        int rc;
     
    171239        }
    172240
    173         /* We are gona do a lot of communication better open it in advance. */
    174         rc = usb_hc_connection_open(hc_conn);
     241        rc = usb_hc_connection_open(&hc_conn);
    175242        if (rc != EOK) {
    176243                return rc;
    177244        }
    178245
    179         /* Request a new address. */
     246        /*
     247         * Request new address.
     248         */
    180249        usb_address_t dev_addr =
    181             usb_hc_request_address(hc_conn, 0, false, dev_speed);
     250            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    182251        if (dev_addr < 0) {
    183252                rc = EADDRNOTAVAIL;
     
    185254        }
    186255
    187         /* Initialize connection to device. */
     256        /*
     257         * We will not register control pipe on default address.
     258         * The registration might fail. That means that someone else already
     259         * registered that endpoint. We will simply wait and try again.
     260         * (Someone else already wants to add a new device.)
     261         */
    188262        usb_device_connection_t dev_conn;
    189         rc = usb_device_connection_initialize(
    190             &dev_conn, hc_conn, USB_ADDRESS_DEFAULT);
     263        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
     264            &hc_conn);
    191265        if (rc != EOK) {
    192266                rc = ENOTCONN;
     
    194268        }
    195269
    196         /* Initialize control pipe on default address. Don't register yet. */
    197270        usb_pipe_t ctrl_pipe;
    198271        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
     
    202275        }
    203276
    204         /*
    205          * The default address request might fail.
    206          * That means that someone else is already using that address.
    207          * We will simply wait and try again.
    208          * (Someone else already wants to add a new device.)
    209          */
    210277        do {
    211                 rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT,
     278                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
    212279                    true, dev_speed);
    213280                if (rc == ENOENT) {
    214281                        /* Do not overheat the CPU ;-). */
    215                         async_usleep(DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC);
     282                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    216283                }
    217284        } while (rc == ENOENT);
     
    220287        }
    221288
    222         /* Register control pipe on default address. 0 means no interval. */
    223         rc = usb_pipe_register(&ctrl_pipe, 0);
     289        /* Register control pipe on default address. */
     290        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    224291        if (rc != EOK) {
    225292                rc = ENOTCONN;
     
    228295
    229296        struct timeval end_time;
     297
    230298        rc = gettimeofday(&end_time, NULL);
    231299        if (rc != EOK) {
     
    262330        }
    263331
    264         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     332        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    265333        if (rc != EOK) {
    266334                rc = ESTALL;
     
    268336        }
    269337
     338        /* Address changed. We can release the default, thus
     339         * allowing other to access the default address. */
     340        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    270341
    271342        /* Register the device with devman. */
     
    285356
    286357        /* Inform the host controller about the handle. */
    287         rc = usb_hub_register_device(hc_conn, &new_device);
     358        rc = usb_hc_register_device(&hc_conn, &new_device);
    288359        if (rc != EOK) {
    289360                /* We know nothing about that data. */
     
    310381         */
    311382leave_release_default_address:
    312         if (usb_hc_release_address(hc_conn, USB_ADDRESS_DEFAULT) != EOK)
    313                 usb_log_warning("%s: Failed to release defaut address.\n",
    314                     __FUNCTION__);
     383        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    315384
    316385leave_release_free_address:
    317386        /* This might be either 0:0 or dev_addr:0 */
    318         if (usb_pipe_unregister(&ctrl_pipe) != EOK)
     387        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
    319388                usb_log_warning("%s: Failed to unregister default pipe.\n",
    320389                    __FUNCTION__);
    321390
    322         if (usb_hc_release_address(hc_conn, dev_addr) != EOK)
    323                 usb_log_warning("%s: Failed to release address: %d.\n",
    324                     __FUNCTION__, dev_addr);
     391        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
     392                usb_log_warning("%s: Failed to unregister device.\n",
     393                    __FUNCTION__);
    325394
    326395close_connection:
    327         if (usb_hc_connection_close(hc_conn) != EOK)
     396        if (usb_hc_connection_close(&hc_conn) != EOK)
    328397                usb_log_warning("%s: Failed to close hc connection.\n",
    329398                    __FUNCTION__);
  • uspace/lib/usbdev/src/pipes.c

    r153cc76a r2f0dd2a  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libusbdev
    3030 * @{
    3131 */
    3232/** @file
    33  * USB endpoint pipes functions.
    34  */
     33 * USB endpoint pipes miscellaneous functions.
     34 */
     35#include <usb/usb.h>
    3536#include <usb/dev/pipes.h>
    36 #include <usb/dev/request.h>
     37#include <usb/debug.h>
     38#include <usb/hc.h>
     39#include <usbhc_iface.h>
     40#include <usb_iface.h>
     41#include <devman.h>
    3742#include <errno.h>
    3843#include <assert.h>
    39 
    40 /** Prepare pipe for a long transfer.
    41  *
    42  * Long transfer is transfer consisting of several requests to the HC.
    43  * Calling this function is optional and it has positive effect of
    44  * improved performance because IPC session is initiated only once.
    45  *
    46  * @param pipe Pipe over which the transfer will happen.
    47  * @return Error code.
    48  */
    49 int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
    50 {
    51         assert(pipe);
    52         assert(pipe->wire);
    53         assert(pipe->wire->hc_connection);
    54         return usb_hc_connection_open(pipe->wire->hc_connection);
    55 }
    56 /*----------------------------------------------------------------------------*/
    57 /** Terminate a long transfer on a pipe.
    58  * @param pipe Pipe where to end the long transfer.
    59  * @return Error code.
    60  * @see usb_pipe_start_long_transfer
    61  */
    62 int usb_pipe_end_long_transfer(usb_pipe_t *pipe)
    63 {
    64         assert(pipe);
    65         assert(pipe->wire);
    66         assert(pipe->wire->hc_connection);
    67         return usb_hc_connection_close(pipe->wire->hc_connection);
    68 }
    69 /*----------------------------------------------------------------------------*/
    70 /** Try to clear endpoint halt of default control pipe.
    71  *
    72  * @param pipe Pipe for control endpoint zero.
    73  */
    74 static void clear_self_endpoint_halt(usb_pipe_t *pipe)
    75 {
    76         assert(pipe != NULL);
    77 
    78         if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
    79                 return;
     44#include "pipepriv.h"
     45
     46#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     47
     48/** Tell USB address assigned to given device.
     49 *
     50 * @param sess Session to parent device.
     51 * @param dev Device in question.
     52 * @return USB address or error code.
     53 */
     54static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
     55{
     56        assert(sess);
     57        async_exch_t *exch = async_exchange_begin(sess);
     58        if (!exch)
     59                return ENOMEM;
     60
     61        usb_address_t address;
     62        const int ret = usb_get_my_address(exch, &address);
     63
     64        async_exchange_end(exch);
     65
     66        return (ret == EOK) ? address : ret;
     67}
     68
     69/** Tell USB interface assigned to given device.
     70 *
     71 * @param device Device in question.
     72 * @return Error code (ENOTSUP means any).
     73 */
     74int usb_device_get_assigned_interface(const ddf_dev_t *device)
     75{
     76        assert(device);
     77        async_sess_t *parent_sess =
     78            devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
     79            IPC_FLAG_BLOCKING);
     80        if (!parent_sess)
     81                return ENOMEM;
     82
     83        async_exch_t *exch = async_exchange_begin(parent_sess);
     84        if (!exch) {
     85                async_hangup(parent_sess);
     86                return ENOMEM;
    8087        }
    8188
    82         /* Prevent infinite recursion. */
    83         pipe->auto_reset_halt = false;
    84         usb_request_clear_endpoint_halt(pipe, 0);
    85         pipe->auto_reset_halt = true;
    86 }
    87 /*----------------------------------------------------------------------------*/
    88 /** Request a control read transfer on an endpoint pipe.
    89  *
    90  * This function encapsulates all three stages of a control transfer.
    91  *
    92  * @param[in] pipe Pipe used for the transfer.
    93  * @param[in] setup_buffer Buffer with the setup packet.
    94  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    95  * @param[out] data_buffer Buffer for incoming data.
    96  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    97  * @param[out] data_transfered_size Number of bytes that were actually
    98  *                                  transfered during the DATA stage.
    99  * @return Error code.
    100  */
    101 int usb_pipe_control_read(usb_pipe_t *pipe,
    102     const void *setup_buffer, size_t setup_buffer_size,
    103     void *buffer, size_t buffer_size, size_t *transfered_size)
    104 {
    105         assert(pipe);
    106 
    107         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
     89        int iface_no;
     90        const int ret = usb_get_my_interface(exch, &iface_no);
     91
     92        return ret == EOK ? iface_no : ret;
     93}
     94
     95/** Initialize connection to USB device.
     96 *
     97 * @param connection Connection structure to be initialized.
     98 * @param dev Generic device backing the USB device.
     99 * @return Error code.
     100 */
     101int usb_device_connection_initialize_from_device(
     102    usb_device_connection_t *connection, const ddf_dev_t *dev)
     103{
     104        assert(connection);
     105        assert(dev);
     106       
     107        int rc;
     108        devman_handle_t hc_handle;
     109        usb_address_t my_address;
     110       
     111        rc = usb_hc_find(dev->handle, &hc_handle);
     112        if (rc != EOK)
     113                return rc;
     114       
     115        async_sess_t *parent_sess =
     116            devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
     117            IPC_FLAG_BLOCKING);
     118        if (!parent_sess)
     119                return ENOMEM;
     120       
     121        /*
     122         * Asking for "my" address may require several attempts.
     123         * That is because following scenario may happen:
     124         *  - parent driver (i.e. driver of parent device) announces new device
     125         *    and devman launches current driver
     126         *  - parent driver is preempted and thus does not send address-handle
     127         *    binding to HC driver
     128         *  - this driver gets here and wants the binding
     129         *  - the HC does not know the binding yet and thus it answers ENOENT
     130         *  So, we need to wait for the HC to learn the binding.
     131         */
     132       
     133        do {
     134                my_address = get_my_address(parent_sess, dev);
     135               
     136                if (my_address == ENOENT) {
     137                        /* Be nice, let other fibrils run and try again. */
     138                        async_usleep(IPC_AGAIN_DELAY);
     139                } else if (my_address < 0) {
     140                        /* Some other problem, no sense trying again. */
     141                        rc = my_address;
     142                        goto leave;
     143                }
     144       
     145        } while (my_address < 0);
     146       
     147        rc = usb_device_connection_initialize(connection,
     148            hc_handle, my_address);
     149       
     150leave:
     151        async_hangup(parent_sess);
     152        return rc;
     153}
     154
     155/** Initialize connection to USB device.
     156 *
     157 * @param connection Connection structure to be initialized.
     158 * @param host_controller_handle Devman handle of host controller device is
     159 *      connected to.
     160 * @param device_address Device USB address.
     161 * @return Error code.
     162 */
     163int usb_device_connection_initialize(usb_device_connection_t *connection,
     164    devman_handle_t host_controller_handle, usb_address_t device_address)
     165{
     166        assert(connection);
     167
     168        if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
    108169                return EINVAL;
    109170        }
    110171
    111         if ((buffer == NULL) || (buffer_size == 0)) {
    112                 return EINVAL;
     172        connection->hc_handle = host_controller_handle;
     173        connection->address = device_address;
     174
     175        return EOK;
     176}
     177
     178/** Initialize connection to USB device on default address.
     179 *
     180 * @param dev_connection Device connection structure to be initialized.
     181 * @param hc_connection Initialized connection to host controller.
     182 * @return Error code.
     183 */
     184int usb_device_connection_initialize_on_default_address(
     185    usb_device_connection_t *dev_connection,
     186    usb_hc_connection_t *hc_connection)
     187{
     188        assert(dev_connection);
     189
     190        if (hc_connection == NULL) {
     191                return EBADMEM;
    113192        }
    114193
    115         if ((pipe->direction != USB_DIRECTION_BOTH)
    116             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    117                 return EBADF;
    118         }
    119 
    120         uint64_t setup_packet;
    121         memcpy(&setup_packet, setup_buffer, 8);
    122 
    123         size_t act_size = 0;
    124         const int rc = usb_device_control_read(pipe->wire,
    125             pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size);
    126 
    127         if (rc == ESTALL) {
    128                 clear_self_endpoint_halt(pipe);
    129         }
    130 
    131         if (rc == EOK && transfered_size != NULL) {
    132                 *transfered_size = act_size;
    133         }
    134 
    135         return rc;
    136 }
    137 /*----------------------------------------------------------------------------*/
    138 /** Request a control write transfer on an endpoint pipe.
    139  *
    140  * This function encapsulates all three stages of a control transfer.
    141  *
    142  * @param[in] pipe Pipe used for the transfer.
    143  * @param[in] setup_buffer Buffer with the setup packet.
    144  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    145  * @param[in] data_buffer Buffer with data to be sent.
    146  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    147  * @return Error code.
    148  */
    149 int usb_pipe_control_write(usb_pipe_t *pipe,
    150     const void *setup_buffer, size_t setup_buffer_size,
    151     const void *buffer, size_t buffer_size)
    152 {
    153         assert(pipe);
    154 
    155         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    156                 return EINVAL;
    157         }
    158 
    159         if ((buffer == NULL) && (buffer_size > 0)) {
    160                 return EINVAL;
    161         }
    162 
    163         if ((buffer != NULL) && (buffer_size == 0)) {
    164                 return EINVAL;
    165         }
    166 
    167         if ((pipe->direction != USB_DIRECTION_BOTH)
    168             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    169                 return EBADF;
    170         }
    171 
    172         uint64_t setup_packet;
    173         memcpy(&setup_packet, setup_buffer, 8);
    174 
    175         const int rc = usb_device_control_write(pipe->wire,
    176             pipe->endpoint_no, setup_packet, buffer, buffer_size);
    177 
    178         if (rc == ESTALL) {
    179                 clear_self_endpoint_halt(pipe);
    180         }
    181 
    182         return rc;
    183 }
    184 /*----------------------------------------------------------------------------*/
    185 /** Request a read (in) transfer on an endpoint pipe.
    186  *
    187  * @param[in] pipe Pipe used for the transfer.
    188  * @param[out] buffer Buffer where to store the data.
    189  * @param[in] size Size of the buffer (in bytes).
    190  * @param[out] size_transfered Number of bytes that were actually transfered.
    191  * @return Error code.
    192  */
    193 int usb_pipe_read(usb_pipe_t *pipe,
    194     void *buffer, size_t size, size_t *size_transfered)
    195 {
    196         assert(pipe);
    197 
    198         if (buffer == NULL) {
    199                 return EINVAL;
    200         }
    201 
    202         if (size == 0) {
    203                 return EINVAL;
    204         }
    205 
    206         if (pipe->direction != USB_DIRECTION_IN) {
    207                 return EBADF;
    208         }
    209 
    210         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    211                 return EBADF;
    212         }
    213 
    214         /* Isochronous transfer are not supported (yet) */
    215         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    216             pipe->transfer_type != USB_TRANSFER_BULK)
    217             return ENOTSUP;
    218 
    219         size_t act_size = 0;
    220         const int rc = usb_device_read(pipe->wire,
    221             pipe->endpoint_no, buffer, size, &act_size);
    222 
    223         if (rc == EOK && size_transfered != NULL) {
    224                 *size_transfered = act_size;
    225         }
    226 
    227         return rc;
    228 }
    229 /*----------------------------------------------------------------------------*/
    230 /** Request a write (out) transfer on an endpoint pipe.
    231  *
    232  * @param[in] pipe Pipe used for the transfer.
    233  * @param[in] buffer Buffer with data to transfer.
    234  * @param[in] size Size of the buffer (in bytes).
    235  * @return Error code.
    236  */
    237 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
    238 {
    239         assert(pipe);
    240 
    241         if (buffer == NULL || size == 0) {
    242                 return EINVAL;
    243         }
    244 
    245         if (pipe->direction != USB_DIRECTION_OUT) {
    246                 return EBADF;
    247         }
    248 
    249         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    250                 return EBADF;
    251         }
    252 
    253         /* Isochronous transfer are not supported (yet) */
    254         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    255             pipe->transfer_type != USB_TRANSFER_BULK)
    256             return ENOTSUP;
    257 
    258         return usb_device_write(pipe->wire,
    259             pipe->endpoint_no, buffer, size);
    260 }
    261 /*----------------------------------------------------------------------------*/
    262 /** Initialize USB endpoint pipe.
    263  *
    264  * @param pipe Endpoint pipe to be initialized.
    265  * @param connection Connection to the USB device backing this pipe (the wire).
    266  * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
    267  * @param transfer_type Transfer type (e.g. interrupt or bulk).
    268  * @param max_packet_size Maximum packet size in bytes.
    269  * @param direction Endpoint direction (in/out).
    270  * @return Error code.
    271  */
    272 int usb_pipe_initialize(usb_pipe_t *pipe,
    273     usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
    274     usb_transfer_type_t transfer_type, size_t max_packet_size,
    275     usb_direction_t direction)
    276 {
    277         assert(pipe);
    278         assert(connection);
    279 
    280         pipe->wire = connection;
    281         pipe->endpoint_no = endpoint_no;
    282         pipe->transfer_type = transfer_type;
    283         pipe->max_packet_size = max_packet_size;
    284         pipe->direction = direction;
    285         pipe->auto_reset_halt = false;
    286 
    287         return EOK;
    288 }
    289 /*----------------------------------------------------------------------------*/
    290 /** Initialize USB endpoint pipe as the default zero control pipe.
    291  *
    292  * @param pipe Endpoint pipe to be initialized.
    293  * @param connection Connection to the USB device backing this pipe (the wire).
    294  * @return Error code.
    295  */
    296 int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
    297     usb_device_connection_t *connection)
    298 {
    299         assert(pipe);
    300         assert(connection);
    301 
    302         int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL,
    303             CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH);
    304 
    305         pipe->auto_reset_halt = true;
    306 
    307         return rc;
    308 }
    309 /*----------------------------------------------------------------------------*/
    310 /** Register endpoint with the host controller.
    311  *
    312  * @param pipe Pipe to be registered.
    313  * @param interval Polling interval.
    314  * @return Error code.
    315  */
    316 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
    317 {
    318         assert(pipe);
    319         assert(pipe->wire);
    320 
    321         return usb_device_register_endpoint(pipe->wire,
    322            pipe->endpoint_no, pipe->transfer_type,
    323            pipe->direction, pipe->max_packet_size, interval);
    324 }
    325 /*----------------------------------------------------------------------------*/
    326 /** Revert endpoint registration with the host controller.
    327  *
    328  * @param pipe Pipe to be unregistered.
    329  * @return Error code.
    330  */
    331 int usb_pipe_unregister(usb_pipe_t *pipe)
    332 {
    333         assert(pipe);
    334         assert(pipe->wire);
    335 
    336         return usb_device_unregister_endpoint(pipe->wire,
    337             pipe->endpoint_no, pipe->direction);
     194        return usb_device_connection_initialize(dev_connection,
     195            hc_connection->hc_handle, (usb_address_t) 0);
     196}
     197
     198/** Prepare pipe for a long transfer.
     199 *
     200 * By a long transfer is mean transfer consisting of several
     201 * requests to the HC.
     202 * Calling such function is optional and it has positive effect of
     203 * improved performance because IPC session is initiated only once.
     204 *
     205 * @param pipe Pipe over which the transfer will happen.
     206 * @return Error code.
     207 */
     208void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     209{
     210        (void) pipe_add_ref(pipe, true);
     211}
     212
     213/** Terminate a long transfer on a pipe.
     214 *
     215 * @see usb_pipe_start_long_transfer
     216 *
     217 * @param pipe Pipe where to end the long transfer.
     218 */
     219void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
     220{
     221        pipe_drop_ref(pipe);
    338222}
    339223
  • uspace/lib/usbdev/src/pipesinit.c

    r153cc76a r2f0dd2a  
    3131 */
    3232/** @file
    33  * Non trivial initialization of endpoint pipes.
     33 * Initialization of endpoint pipes.
    3434 *
    3535 */
     
    3838#include <usb/dev/dp.h>
    3939#include <usb/dev/request.h>
     40#include <usbhc_iface.h>
    4041#include <errno.h>
    4142#include <assert.h>
    4243
     44#define CTRL_PIPE_MIN_PACKET_SIZE 8
    4345#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
     46
    4447
    4548#define NESTING(parentname, childname) \
     
    324327
    325328        return EOK;
     329}
     330
     331/** Initialize USB endpoint pipe.
     332 *
     333 * @param pipe Endpoint pipe to be initialized.
     334 * @param connection Connection to the USB device backing this pipe (the wire).
     335 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
     336 * @param transfer_type Transfer type (e.g. interrupt or bulk).
     337 * @param max_packet_size Maximum packet size in bytes.
     338 * @param direction Endpoint direction (in/out).
     339 * @return Error code.
     340 */
     341int usb_pipe_initialize(usb_pipe_t *pipe,
     342    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
     343    usb_transfer_type_t transfer_type, size_t max_packet_size,
     344    usb_direction_t direction)
     345{
     346        assert(pipe);
     347        assert(connection);
     348
     349        fibril_mutex_initialize(&pipe->guard);
     350        pipe->wire = connection;
     351        pipe->hc_sess = NULL;
     352        fibril_mutex_initialize(&pipe->hc_sess_mutex);
     353        pipe->endpoint_no = endpoint_no;
     354        pipe->transfer_type = transfer_type;
     355        pipe->max_packet_size = max_packet_size;
     356        pipe->direction = direction;
     357        pipe->refcount = 0;
     358        pipe->refcount_soft = 0;
     359        pipe->auto_reset_halt = false;
     360
     361        return EOK;
     362}
     363
     364
     365/** Initialize USB endpoint pipe as the default zero control pipe.
     366 *
     367 * @param pipe Endpoint pipe to be initialized.
     368 * @param connection Connection to the USB device backing this pipe (the wire).
     369 * @return Error code.
     370 */
     371int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
     372    usb_device_connection_t *connection)
     373{
     374        assert(pipe);
     375        assert(connection);
     376
     377        int rc = usb_pipe_initialize(pipe, connection,
     378            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     379            USB_DIRECTION_BOTH);
     380
     381        pipe->auto_reset_halt = true;
     382
     383        return rc;
    326384}
    327385
     
    377435}
    378436
     437/** Register endpoint with the host controller.
     438 *
     439 * @param pipe Pipe to be registered.
     440 * @param interval Polling interval.
     441 * @param hc_connection Connection to the host controller (must be opened).
     442 * @return Error code.
     443 */
     444int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
     445    usb_hc_connection_t *hc_connection)
     446{
     447        assert(pipe);
     448        assert(pipe->wire);
     449        assert(hc_connection);
     450
     451        if (!usb_hc_connection_is_opened(hc_connection))
     452                return EBADF;
     453        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     454        if (!exch)
     455                return ENOMEM;
     456        const int ret = usbhc_register_endpoint(exch,
     457            pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
     458            pipe->direction, pipe->max_packet_size, interval);
     459
     460        async_exchange_end(exch);
     461        return ret;
     462}
     463
     464/** Revert endpoint registration with the host controller.
     465 *
     466 * @param pipe Pipe to be unregistered.
     467 * @param hc_connection Connection to the host controller (must be opened).
     468 * @return Error code.
     469 */
     470int usb_pipe_unregister(usb_pipe_t *pipe,
     471    usb_hc_connection_t *hc_connection)
     472{
     473        assert(pipe);
     474        assert(pipe->wire);
     475        assert(hc_connection);
     476
     477        if (!usb_hc_connection_is_opened(hc_connection))
     478                return EBADF;
     479
     480        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     481        if (!exch)
     482                return ENOMEM;
     483        const int ret = usbhc_unregister_endpoint(exch,
     484            pipe->wire->address, pipe->endpoint_no, pipe->direction);
     485        async_exchange_end(exch);
     486
     487        return ret;
     488}
     489
    379490/**
    380491 * @}
  • uspace/lib/usbdev/src/recognise.c

    r153cc76a r2f0dd2a  
    4545#include <errno.h>
    4646#include <assert.h>
     47
     48/** Index to append after device name for uniqueness. */
     49static size_t device_name_index = 0;
     50/** Mutex guard for device_name_index. */
     51static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
    4752
    4853/** DDF operations of child devices. */
     
    324329        }
    325330
    326         /** Index to append after device name for uniqueness. */
    327         static atomic_t device_name_index = {0};
    328         const size_t this_device_name_index =
    329             (size_t) atomic_preinc(&device_name_index);
     331        fibril_mutex_lock(&device_name_index_mutex);
     332        const size_t this_device_name_index = device_name_index++;
     333        fibril_mutex_unlock(&device_name_index_mutex);
    330334
    331335        ddf_fun_t *child = NULL;
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r153cc76a r2f0dd2a  
    9595/** list_get_instance wrapper.
    9696 * @param item Pointer to link member.
    97  * @return Pointer to endpoint_t structure.
     97 * @return Pointer to enpoint_t structure.
    9898 */
    9999static inline endpoint_t * endpoint_get_instance(link_t *item)
    100100{
    101         return item ? list_get_instance(item, endpoint_t, link) : NULL;
     101        return list_get_instance(item, endpoint_t, link);
    102102}
    103103#endif
  • uspace/lib/usbhost/include/usb/host/usb_device_manager.h

    r153cc76a r2f0dd2a  
    5959                devman_handle_t handle; /**< Devman handle of the device. */
    6060        } devices[USB_ADDRESS_COUNT];
    61         /** Maximum speed allowed. */
    6261        usb_speed_t max_speed;
    63         /** Protect access to members. */
    6462        fibril_mutex_t guard;
    6563        /** The last reserved address */
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r153cc76a r2f0dd2a  
    6565         */
    6666        size_t setup_size;
     67        /** Actually used portion of the buffer */
     68        size_t transfered_size;
     69        /** Indicates success/failure of the communication */
     70        int error;
    6771        /** Host controller function, passed to callback function */
    6872        ddf_fun_t *fun;
    69 
    70         /** Actually used portion of the buffer
    71          * This member is never accessed by functions provided in this header,
    72          * with the exception of usb_transfer_batch_finish. For external use.
    73          */
    74         size_t transfered_size;
    75         /** Indicates success/failure of the communication
    76          * This member is never accessed by functions provided in this header,
    77          * with the exception of usb_transfer_batch_finish. For external use.
    78          */
    79         int error;
    8073
    8174        /** Driver specific data */
     
    113106void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
    114107
    115 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    116     const void* data, size_t size, int error);
     108void usb_transfer_batch_finish(const usb_transfer_batch_t *instance,
     109    const void* data, size_t size);
    117110/*----------------------------------------------------------------------------*/
    118 /** Finish batch using stored error value and transferred size.
     111/** Override error value and finishes transfer.
    119112 *
    120113 * @param[in] instance Batch structure to use.
    121114 * @param[in] data Data to copy to the output buffer.
     115 * @param[in] size Size of @p data.
     116 * @param[in] error Set batch status to this error value.
    122117 */
    123 static inline void usb_transfer_batch_finish(
    124     const usb_transfer_batch_t *instance, const void* data)
     118static inline void usb_transfer_batch_finish_error(
     119    usb_transfer_batch_t *instance, const void* data, size_t size, int error)
    125120{
    126121        assert(instance);
    127         usb_transfer_batch_finish_error(
    128             instance, data, instance->transfered_size, instance->error);
     122        instance->error = error;
     123        usb_transfer_batch_finish(instance, data, size);
    129124}
    130125/*----------------------------------------------------------------------------*/
  • uspace/lib/usbhost/src/iface.c

    r153cc76a r2f0dd2a  
    3939#include <usb/host/hcd.h>
    4040
    41 /** Prepare generic usb_transfer_batch and schedule it.
    42  * @param fun DDF fun
    43  * @param target address and endpoint number.
    44  * @param setup_data Data to use in setup stage (Control communication type)
    45  * @param in Callback for device to host communication.
    46  * @param out Callback for host to device communication.
    47  * @param arg Callback parameter.
    48  * @param name Communication identifier (for nicer output).
    49  * @return Error code.
    50  */
    5141static inline int send_batch(
    5242    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     
    9989}
    10090/*----------------------------------------------------------------------------*/
    101 /** Calls ep_add_hook upon endpoint registration.
    102  * @param ep Endpoint to be registered.
    103  * @param arg hcd_t in disguise.
    104  * @return Error code.
    105  */
    10691static int register_helper(endpoint_t *ep, void *arg)
    10792{
     
    11499}
    115100/*----------------------------------------------------------------------------*/
    116 /** Calls ep_remove_hook upon endpoint removal.
    117  * @param ep Endpoint to be unregistered.
    118  * @param arg hcd_t in disguise.
    119  */
    120101static void unregister_helper(endpoint_t *ep, void *arg)
    121102{
     
    127108}
    128109/*----------------------------------------------------------------------------*/
    129 /** Calls ep_remove_hook upon endpoint removal. Prints warning.
    130  * @param ep Endpoint to be unregistered.
    131  * @param arg hcd_t in disguise.
    132  */
    133110static void unregister_helper_warn(endpoint_t *ep, void *arg)
    134111{
     
    142119}
    143120/*----------------------------------------------------------------------------*/
    144 /** Request address interface function.
    145  *
    146  * @param[in] fun DDF function that was called.
    147  * @param[in] address Pointer to preferred USB address.
     121/** Request address interface function
     122 *
     123 * @param[in] fun DDF function that was called.
     124 * @param[in] speed Speed to associate with the new default address.
    148125 * @param[out] address Place to write a new address.
    149  * @param[in] strict Fail if the preferred address is not available.
    150  * @param[in] speed Speed to associate with the new default address.
    151126 * @return Error code.
    152127 */
     
    165140}
    166141/*----------------------------------------------------------------------------*/
    167 /** Bind address interface function.
     142/** Bind address interface function
    168143 *
    169144 * @param[in] fun DDF function that was called.
     
    173148 */
    174149static int bind_address(
    175     ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     150  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    176151{
    177152        assert(fun);
     
    201176}
    202177/*----------------------------------------------------------------------------*/
    203 /** Release address interface function.
     178/** Release address interface function
    204179 *
    205180 * @param[in] fun DDF function that was called.
     
    219194}
    220195/*----------------------------------------------------------------------------*/
    221 /** Register endpoint interface function.
    222  * @param fun DDF function.
    223  * @param address USB address of the device.
    224  * @param endpoint USB endpoint number to be registered.
    225  * @param transfer_type Endpoint's transfer type.
    226  * @param direction USB communication direction the endpoint is capable of.
    227  * @param max_packet_size Maximu size of packets the endpoint accepts.
    228  * @param interval Preferred timeout between communication.
    229  * @return Error code.
    230  */
    231196static int register_endpoint(
    232197    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
    233198    usb_transfer_type_t transfer_type, usb_direction_t direction,
    234     size_t max_packet_size, unsigned interval)
     199    size_t max_packet_size, unsigned int interval)
    235200{
    236201        assert(fun);
     
    255220}
    256221/*----------------------------------------------------------------------------*/
    257 /** Unregister endpoint interface function.
    258  * @param fun DDF function.
    259  * @param address USB address of the endpoint.
    260  * @param endpoint USB endpoint number.
    261  * @param direction Communication direction of the enpdoint to unregister.
    262  * @return Error code.
    263  */
    264222static int unregister_endpoint(
    265223    ddf_fun_t *fun, usb_address_t address,
     
    275233}
    276234/*----------------------------------------------------------------------------*/
    277 /** Inbound communication interface function.
    278  * @param fun DDF function.
    279  * @param target Communication target.
    280  * @param setup_data Data to use in setup stage (control transfers).
    281  * @param data Pointer to data buffer.
    282  * @param size Size of the data buffer.
    283  * @param callback Function to call on communication end.
    284  * @param arg Argument passed to the callback function.
    285  * @return Error code.
    286  */
    287235static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
    288236    uint8_t *data, size_t size, usbhc_iface_transfer_in_callback_t callback,
     
    293241}
    294242/*----------------------------------------------------------------------------*/
    295 /** Outbound communication interface function.
    296  * @param fun DDF function.
    297  * @param target Communication target.
    298  * @param setup_data Data to use in setup stage (control transfers).
    299  * @param data Pointer to data buffer.
    300  * @param size Size of the data buffer.
    301  * @param callback Function to call on communication end.
    302  * @param arg Argument passed to the callback function.
    303  * @return Error code.
    304  */
    305243static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
    306244    const uint8_t *data, size_t size,
     
    311249}
    312250/*----------------------------------------------------------------------------*/
    313 /** usbhc Interface implementation using hcd_t from libusbhost library. */
    314251usbhc_iface_t hcd_iface = {
    315252        .request_address = request_address,
  • uspace/lib/usbhost/src/usb_device_manager.c

    r153cc76a r2f0dd2a  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusbhost
    2930 * @{
     
    4041 *
    4142 * @param[in] instance Device manager structure to use.
     43 * @param[in] speed Speed of the device requiring address.
    4244 * @return Free address, or error code.
    4345 */
     
    131133 * @param[in] handle Devman handle of the device.
    132134 * @return Error code.
    133  * @note Won't accept binding for default address.
    134135 */
    135136int usb_device_manager_bind_address(usb_device_manager_t *instance,
     
    183184}
    184185/*----------------------------------------------------------------------------*/
    185 /** Find USB address associated with the device.
     186/** Find USB address associated with the device
    186187 *
    187188 * @param[in] instance Device manager structure to use.
     
    207208/*----------------------------------------------------------------------------*/
    208209/** Find devman handle and speed assigned to USB address.
     210 * Intentionally refuse to work on default address.
    209211 *
    210212 * @param[in] instance Device manager structure to use.
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r153cc76a r2f0dd2a  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /**  @addtogroup libusbhost
    29  * @{
    30  */
    31 /** @file
    32  * HC Endpoint management.
    33  */
    3428
    3529#include <bool.h>
     
    6256}
    6357/*----------------------------------------------------------------------------*/
    64 /** Get list that holds endpoints for given address.
     58/** Get list that holds endpints for given address.
    6559 * @param instance usb_endpoint_manager structure, non-null.
    6660 * @param addr USB address, must be >= 0.
     
    8175 * @return Pointer to endpoint_t structure representing given communication
    8276 * target, NULL if there is no such endpoint registered.
    83  * @note Assumes that the internal mutex is locked.
    8477 */
    8578static endpoint_t * find_locked(usb_endpoint_manager_t *instance,
     
    176169 *
    177170 * Really ugly one. Resets toggle bit on all endpoints that need it.
    178  * @TODO Use tools from libusbdev requests.h
    179171 */
    180172void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
     
    192184        case 0x01: /* Clear Feature -- resets only cleared ep */
    193185                /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    194                 // TODO Use macros in libusbdev requests.h
    195186                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    196187                        fibril_mutex_lock(&instance->guard);
     
    211202                /* Recipient must be device, this resets all endpoints,
    212203                 * In fact there should be no endpoints but EP 0 registered
    213                  * as different interfaces use different endpoints,
    214                  * unless you're changing configuration or alternative
    215                  * interface of an already setup device. */
     204                 * as different interfaces use different endpoints. */
    216205                if ((data[0] & 0xf) == 0) {
    217206                        fibril_mutex_lock(&instance->guard);
     
    396385}
    397386/*----------------------------------------------------------------------------*/
    398 /** Unregister and destroy all endpoints using given address.
    399  * @param instance usb_endpoint_manager structure, non-null.
    400  * @param address USB address.
    401  * @param endpoint USB endpoint number.
    402  * @param direction Communication direction.
    403  * @param callback Function to call after unregister, before destruction.
    404  * @arg Argument to pass to the callback function.
    405  * @return Error code.
    406  */
    407387void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
    408388    usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
     
    423403        fibril_mutex_unlock(&instance->guard);
    424404}
    425 /**
    426  * @}
    427  */
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r153cc76a r2f0dd2a  
    3333 */
    3434#include <errno.h>
    35 #include <macros.h>
     35#include <str_error.h>
    3636
    3737#include <usb/usb.h>
     
    4848 * @param func_in callback on IN transfer completion.
    4949 * @param func_out callback on OUT transfer completion.
    50  * @param fun DDF function (passed to callback function).
    5150 * @param arg Argument to pass to the callback function.
    5251 * @param private_data driver specific per batch data.
     
    122121 * @param[in] data Data to copy to the output buffer.
    123122 * @param[in] size Size of @p data.
    124  * @param[in] error Error value to use.
    125123 */
    126 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    127     const void *data, size_t size, int error)
     124void usb_transfer_batch_finish(
     125    const usb_transfer_batch_t *instance, const void *data, size_t size)
    128126{
    129127        assert(instance);
     
    135133                /* Check for commands that reset toggle bit */
    136134                if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
    137                     && error == EOK) {
     135                    && instance->error == EOK) {
    138136                        const usb_target_t target =
    139137                            {{ instance->ep->address, instance->ep->endpoint }};
     
    141139                            instance->setup_buffer);
    142140                }
    143                 instance->callback_out(instance->fun, error, instance->arg);
     141                instance->callback_out(instance->fun,
     142                    instance->error, instance->arg);
    144143        }
    145144
    146145        if (instance->callback_in) {
    147146                /* We care about the data and there are some to copy */
    148                 const size_t safe_size = min(size, instance->buffer_size);
    149147                if (data) {
    150                         memcpy(instance->buffer, data, safe_size);
     148                        const size_t min_size = size < instance->buffer_size
     149                            ? size : instance->buffer_size;
     150                        memcpy(instance->buffer, data, min_size);
    151151                }
    152                 instance->callback_in(instance->fun, error,
    153                     safe_size, instance->arg);
     152                instance->callback_in(instance->fun, instance->error,
     153                    instance->transfered_size, instance->arg);
    154154        }
    155155}
Note: See TracChangeset for help on using the changeset viewer.