Changes in / [899f1a9:9c3bba0] in mainline


Ignore:
Location:
uspace
Files:
3 added
2 deleted
42 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/usbinfo/dev.c

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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/usbinfo.h

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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);
  • uspace/drv/bus/usb/usbhub/port.c

    r899f1a9 r9c3bba0  
    288288        port->attached_device.fun = NULL;
    289289
    290         ret = usb_hc_unregister_device(&hub->usb_device->hc_conn,
    291             port->attached_device.address);
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    3737        src/class.c \
    3838        src/ddfiface.c \
    39         src/dev.c \
    4039        src/debug.c \
    4140        src/dump.c \
  • uspace/lib/usb/include/usb/classes/hub.h

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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 * @{
     
    3636#define LIBUSB_HC_H_
    3737
    38 #include <devman.h>
     38#include <sys/types.h>
     39#include <ipc/devman.h>
     40#include <ipc/loc.h>
    3941#include <ddf/driver.h>
    4042#include <bool.h>
    41 #include <fibril_synch.h>
     43#include <async.h>
    4244#include <usb/usb.h>
    4345
     
    4850        /** Session to the host controller. */
    4951        async_sess_t *hc_sess;
    50         /** Session guard. */
    51         fibril_mutex_t guard;
    52         /** Use counter. */
    53         unsigned ref_count;
    5452} usb_hc_connection_t;
    55 
    56 /** Initialize connection to USB host controller.
    57  *
    58  * @param connection Connection to be initialized.
    59  * @param hc_handle Devman handle of the host controller.
    60  * @return Error code.
    61  */
    62 static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection,
    63     devman_handle_t hc_handle)
    64 {
    65         assert(connection);
    66         connection->hc_handle = hc_handle;
    67         connection->hc_sess = NULL;
    68         connection->ref_count = 0;
    69         fibril_mutex_initialize(&connection->guard);
    70 }
    7153
    7254int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
    7355    const ddf_dev_t *);
     56int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
    7457
    7558int usb_hc_connection_open(usb_hc_connection_t *);
     59bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
    7660int usb_hc_connection_close(usb_hc_connection_t *);
    77 
    78 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool,
    79     usb_speed_t);
    80 int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t);
    8161int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
    8262    devman_handle_t *);
    83 int usb_hc_release_address(usb_hc_connection_t *, usb_address_t);
    8463
    85 int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t,
    86     usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    87 int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t,
    88     usb_endpoint_t, usb_direction_t);
     64usb_address_t usb_get_address_by_handle(devman_handle_t);
    8965
    90 int usb_hc_control_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
    91     uint64_t, void *, size_t, size_t *);
    92 int usb_hc_control_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
    93     uint64_t, const void *, size_t);
     66int usb_hc_find(devman_handle_t, devman_handle_t *);
    9467
    95 static inline int usb_hc_read(usb_hc_connection_t *connection,
    96     usb_address_t address, usb_endpoint_t endpoint, void *data, size_t size,
    97     size_t *real_size)
    98 {
    99         return usb_hc_control_read(
    100             connection, address, endpoint, 0, data, size, real_size);
    101 }
    102 
    103 static inline int usb_hc_write(usb_hc_connection_t *connection,
    104     usb_address_t address, usb_endpoint_t endpoint, const void *data,
    105     size_t size)
    106 {
    107         return usb_hc_control_write(
    108              connection, address, endpoint, 0, data, size);
    109 }
     68int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
     69    devman_handle_t *);
    11070
    11171int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
     72
    11273
    11374#endif
  • uspace/lib/usb/include/usb/usb.h

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

    r899f1a9 r9c3bba0  
    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
     
    136134        assert(fun);
    137135        assert(fun->driver_data);
    138         const usb_hub_attached_device_t *device = fun->driver_data;
     136        usb_hub_attached_device_t *device = fun->driver_data;
    139137        assert(device->fun == fun);
    140138        if (address)
  • uspace/lib/usb/src/hc.c

    r899f1a9 r9c3bba0  
    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         --connection->ref_count;
    67         int ret = EOK;
    68         if (connection->ref_count == 0) {
    69                 assert(connection->hc_sess);
    70                 ret = async_hangup(connection->hc_sess);
    71                 connection->hc_sess = NULL;
    72         }
    73         fibril_mutex_unlock(&connection->guard);
    74         return ret;
    75 }
    76 
    77 #define EXCH_INIT(connection, exch) \
    78 do { \
    79         exch = NULL; \
    80         if (!connection) \
    81                 return EBADMEM; \
    82         const int ret = usb_hc_connection_add_ref(connection); \
    83         if (ret != EOK) \
    84                 return ret; \
    85         exch = async_exchange_begin(connection->hc_sess); \
    86         if (exch == NULL) { \
    87                 usb_hc_connection_del_ref(connection); \
    88                 return ENOMEM; \
    89         } \
    90 } while (0)
    91 
    92 #define EXCH_FINI(connection, exch) \
    93 if (exch) { \
    94         async_exchange_end(exch); \
    95         usb_hc_connection_del_ref(connection); \
    96 } else (void)0
    9744
    9845/** Initialize connection to USB host controller.
     
    11259
    11360        devman_handle_t hc_handle;
    114         const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
    115         if (rc == EOK) {
    116                 usb_hc_connection_initialize(connection, hc_handle);
    117         }
     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);
    11867
    11968        return rc;
    12069}
    121 /*----------------------------------------------------------------------------*/
     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
    12288/** Open connection to host controller.
    12389 *
     
    12793int usb_hc_connection_open(usb_hc_connection_t *connection)
    12894{
    129         return usb_hc_connection_add_ref(connection);
    130 }
    131 /*----------------------------------------------------------------------------*/
     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
    132120/** Close connection to the host controller.
    133121 *
     
    137125int usb_hc_connection_close(usb_hc_connection_t *connection)
    138126{
    139         return usb_hc_connection_del_ref(connection);
    140 }
    141 /*----------------------------------------------------------------------------*/
    142 /** Ask host controller for free address assignment.
    143  *
    144  * @param connection Opened connection to host controller.
    145  * @param preferred Preferred SUB address.
    146  * @param strict Fail if the preferred address is not avialable.
    147  * @param speed Speed of the new device (device that will be assigned
    148  *    the returned address).
    149  * @return Assigned USB address or negative error code.
    150  */
    151 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    152     usb_address_t preferred, bool strict, usb_speed_t speed)
    153 {
    154         async_exch_t *exch;
    155         EXCH_INIT(connection, exch);
    156 
    157         usb_address_t address = preferred;
    158         const int ret = usbhc_request_address(exch, &address, strict, speed);
    159 
    160         EXCH_FINI(connection, exch);
    161         return ret == EOK ? address : ret;
    162 }
    163 /*----------------------------------------------------------------------------*/
    164 int usb_hc_bind_address(usb_hc_connection_t * connection,
    165     usb_address_t address, devman_handle_t handle)
    166 {
    167         async_exch_t *exch;
    168         EXCH_INIT(connection, exch);
    169 
    170         const int ret = usbhc_bind_address(exch, address, handle);
    171 
    172         EXCH_FINI(connection, exch);
    173         return ret;
    174 }
    175 /*----------------------------------------------------------------------------*/
     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
    176143/** Get handle of USB device with given address.
    177144 *
     
    184151    usb_address_t address, devman_handle_t *handle)
    185152{
    186         async_exch_t *exch;
    187         EXCH_INIT(connection, exch);
    188 
     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;
    189159        const int ret = usbhc_get_handle(exch, address, handle);
    190 
    191         EXCH_FINI(connection, exch);
     160        async_exchange_end(exch);
    192161        return ret;
    193162}
    194 /*----------------------------------------------------------------------------*/
    195 int usb_hc_release_address(usb_hc_connection_t *connection,
    196     usb_address_t address)
    197 {
    198         async_exch_t *exch;
    199         EXCH_INIT(connection, exch);
    200 
    201         const int ret = usbhc_release_address(exch, address);
    202 
    203         EXCH_FINI(connection, exch);
    204         return ret;
    205 }
    206 /*----------------------------------------------------------------------------*/
    207 int usb_hc_register_endpoint(usb_hc_connection_t *connection,
    208     usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type,
    209     usb_direction_t direction, size_t packet_size, unsigned interval)
    210 {
    211         async_exch_t *exch;
    212         EXCH_INIT(connection, exch);
    213 
    214         const int ret = usbhc_register_endpoint(exch, address, endpoint,
    215             type, direction, packet_size, interval);
    216 
    217         EXCH_FINI(connection, exch);
    218         return ret;
    219 }
    220 /*----------------------------------------------------------------------------*/
    221 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection,
    222     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    223 {
    224         async_exch_t *exch;
    225         EXCH_INIT(connection, exch);
    226 
    227         const int ret =
    228             usbhc_unregister_endpoint(exch, address, endpoint, direction);
    229 
    230         EXCH_FINI(connection, exch);
    231         return ret;
    232 }
    233 /*----------------------------------------------------------------------------*/
    234 int usb_hc_control_read(usb_hc_connection_t *connection, usb_address_t address,
    235     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
    236     size_t *real_size)
    237 {
    238         async_exch_t *exch;
    239         EXCH_INIT(connection, exch);
    240 
    241         const int ret =
    242             usbhc_read(exch, address, endpoint, setup, data, size, real_size);
    243 
    244         EXCH_FINI(connection, exch);
    245         return ret;
    246 }
    247 /*----------------------------------------------------------------------------*/
    248 int usb_hc_control_write(usb_hc_connection_t *connection, usb_address_t address,
    249     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
    250 {
    251         async_exch_t *exch;
    252         EXCH_INIT(connection, exch);
    253 
    254         const int ret = usbhc_write(exch, address, endpoint, setup, data, size);
    255 
    256         EXCH_FINI(connection, exch);
    257         return ret;
    258 }
    259 /*----------------------------------------------------------------------------*/
     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
    260195/** Get host controller handle by its class index.
    261196 *
     
    268203{
    269204        devman_handle_t handle;
    270 
    271         const int ret = devman_fun_sid_to_handle(sid, &handle);
    272         if (ret == EOK && hc_handle != NULL)
     205        int rc;
     206       
     207        rc = devman_fun_sid_to_handle(sid, &handle);
     208        if (hc_handle != NULL)
    273209                *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);
    274238
    275239        return ret;
  • uspace/lib/usb/src/resolve.c

    r899f1a9 r9c3bba0  
    3434 */
    3535#include <inttypes.h>
    36 #include <usb/dev.h>
    3736#include <usb/hc.h>
    3837#include <devman.h>
     
    7877    devman_handle_t *dev_handle)
    7978{
     79        int rc;
    8080        usb_hc_connection_t conn;
     81
    8182        usb_hc_connection_initialize(&conn, hc_handle);
    82 
    83         const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
     83        rc = usb_hc_connection_open(&conn);
     84        if (rc != EOK) {
     85                return rc;
     86        }
     87
     88        rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
     89
     90        usb_hc_connection_close(&conn);
    8491
    8592        return rc;
     
    185192                /* Try to find its host controller. */
    186193                if (!found_hc) {
    187                         rc = usb_get_hc_by_handle(tmp_handle, &hc_handle);
     194                        rc = usb_hc_find(tmp_handle, &hc_handle);
    188195                        if (rc == EOK) {
    189196                                found_hc = true;
  • uspace/lib/usb/src/usb.c

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    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

    r899f1a9 r9c3bba0  
    7272/** USB device structure. */
    7373typedef struct {
    74         usb_hc_connection_t hc_conn;
    7574        /** Connection backing the pipes.
    7675         * Typically, you will not need to use this attribute at all.
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r899f1a9 r9c3bba0  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusbdev
    2930 * @{
     
    3738#include <sys/types.h>
    3839#include <usb/usb.h>
    39 #include <usb/dev.h>
     40#include <usb/hc.h>
    4041#include <usb/descriptor.h>
    4142#include <ipc/devman.h>
     
    4344#include <fibril_synch.h>
    4445#include <async.h>
     46
     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;
    4557
    4658/** Abstraction of a logical connection to USB device endpoint.
     
    7385        /** Maximum packet size for the endpoint. */
    7486        size_t max_packet_size;
     87
     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;
    75116
    76117        /** Whether to automatically reset halt on the endpoint.
     
    115156} usb_endpoint_mapping_t;
    116157
     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);
    117164
    118165int usb_device_get_assigned_interface(const ddf_dev_t *);
     
    122169int usb_pipe_initialize_default_control(usb_pipe_t *,
    123170    usb_device_connection_t *);
    124 
    125171int usb_pipe_probe_default_control(usb_pipe_t *);
    126172int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    127173    size_t, const uint8_t *, size_t, usb_device_connection_t *);
    128 int usb_pipe_register(usb_pipe_t *, unsigned);
    129 int usb_pipe_unregister(usb_pipe_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 *);
    130176
    131 int usb_pipe_start_long_transfer(usb_pipe_t *);
    132 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 *);
    133179
    134180int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usbdev/include/usb/dev/request.h

    r899f1a9 r9c3bba0  
    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/devdrv.c

    r899f1a9 r9c3bba0  
    170170                return ENOTSUP;
    171171        /* Just tell the driver to stop whatever it is doing, keep structures */
    172         const int ret = driver->ops->device_rem(gen_dev->driver_data);
    173         if (ret != EOK)
    174                 return ret;
    175         return ENOTSUP;
     172        return driver->ops->device_rem(gen_dev->driver_data);
    176173}
    177174/*----------------------------------------------------------------------------*/
     
    376373        }
    377374
     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
    378387        for (i = 0; i < pipe_count; i++) {
    379388                if (pipes[i].present) {
    380389                        rc = usb_pipe_register(&pipes[i].pipe,
    381                             pipes[i].descriptor->poll_interval);
     390                            pipes[i].descriptor->poll_interval, &hc_conn);
    382391                        if (rc != EOK) {
    383392                                goto rollback_unregister_endpoints;
     
    385394                }
    386395        }
     396
     397        if (usb_hc_connection_close(&hc_conn) != EOK)
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    387400
    388401        *pipes_ptr = pipes;
     
    402415        for (i = 0; i < pipe_count; i++) {
    403416                if (pipes[i].present) {
    404                         usb_pipe_unregister(&pipes[i].pipe);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    405418                }
    406419        }
     420
     421        if (usb_hc_connection_close(&hc_conn) != EOK)
     422                usb_log_warning("usb_device_create_pipes(): "
     423                    "Failed to close connection.\n");
    407424
    408425        /*
     
    453470                    i, pipes[i].present ? "" : "not ");
    454471                if (pipes[i].present)
    455                         usb_pipe_unregister(&pipes[i].pipe);
    456         }
     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");
    457478
    458479        free(pipes);
     
    484505        usb_dev->pipes = NULL;
    485506
    486         /* Initialize hc connection. */
    487         usb_hc_connection_initialize_from_device(&usb_dev->hc_conn, ddf_dev);
    488         const usb_address_t address =
    489             usb_get_address_by_handle(ddf_dev->handle);
    490 
    491507        /* Initialize backing wire and control pipe. */
    492         int rc = usb_device_connection_initialize(
    493             &usb_dev->wire, &usb_dev->hc_conn, address);
     508        int rc = usb_device_connection_initialize_from_device(
     509            &usb_dev->wire, ddf_dev);
    494510        if (rc != EOK) {
    495511                *errstr_ptr = "device connection initialization";
     
    499515        /* This pipe was registered by the hub driver,
    500516         * during device initialization. */
    501         rc = usb_pipe_initialize_default_control(
    502             &usb_dev->ctrl_pipe, &usb_dev->wire);
     517        rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
     518            &usb_dev->wire);
    503519        if (rc != EOK) {
    504520                *errstr_ptr = "default control pipe initialization";
    505                 return rc;
    506         }
    507 
    508         rc = usb_hc_connection_open(&usb_dev->hc_conn);
    509         if (rc != EOK) {
    510                 *errstr_ptr = "hc connection open";
    511521                return rc;
    512522        }
     
    514524        /* Get our interface. */
    515525        usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
     526
    516527        /* Retrieve standard descriptors. */
    517         rc = usb_device_retrieve_descriptors(
    518             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
     528        rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
     529            &usb_dev->descriptors);
    519530        if (rc != EOK) {
    520531                *errstr_ptr = "descriptor retrieval";
    521                 usb_hc_connection_close(&usb_dev->hc_conn);
    522532                return rc;
    523533        }
     
    536546        rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
    537547        if (rc != EOK) {
    538                 usb_hc_connection_close(&usb_dev->hc_conn);
    539548                /* Full configuration descriptor is allocated. */
    540549                usb_device_release_descriptors(&usb_dev->descriptors);
     
    545554        }
    546555
    547         usb_hc_connection_close(&usb_dev->hc_conn);
    548556        return EOK;
    549557}
  • uspace/lib/usbdev/src/hub.c

    r899f1a9 r9c3bba0  
    6363        } while (false)
    6464
     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}
    6589
    6690/** Inform host controller about new device.
     
    7397    const usb_hub_attached_device_t *attached_device)
    7498{
    75 //      CHECK_CONNECTION(connection);
     99        CHECK_CONNECTION(connection);
    76100        if (attached_device == NULL || attached_device->fun == NULL)
    77101                return EINVAL;
     
    96120    usb_address_t address)
    97121{
    98 //      CHECK_CONNECTION(connection);
     122        CHECK_CONNECTION(connection);
    99123
    100124        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     
    121145 * @return Error code.
    122146 */
    123 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)
    124149{
    125150        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     
    127152        }
    128153        assert(pipe);
     154        assert(hc_conn);
    129155        assert(pipe->wire != NULL);
    130156
     
    140166
    141167        /* TODO: prevent others from accessing the wire now. */
    142         if (usb_pipe_unregister(pipe) != EOK) {
     168        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
    143169                usb_log_warning(
    144170                    "Failed to unregister the old pipe on address change.\n");
    145171        }
    146         /* Address changed. We can release the default, thus
    147          * allowing other to access the default address. */
    148         usb_hc_unregister_device(pipe->wire->hc_connection,
    149             pipe->wire->address);
    150 
    151172        /* The address is already changed so set it in the wire */
    152173        pipe->wire->address = new_address;
    153         rc = usb_pipe_register(pipe, 0);
     174        rc = usb_pipe_register(pipe, 0, hc_conn);
    154175        if (rc != EOK)
    155176                return EADDRNOTAVAIL;
     
    199220 */
    200221int usb_hc_new_device_wrapper(ddf_dev_t *parent,
    201     usb_hc_connection_t *hc_conn, usb_speed_t dev_speed,
     222    usb_hc_connection_t *connection, usb_speed_t dev_speed,
    202223    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    203224    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    204225{
    205         if (new_fun == NULL || hc_conn == NULL)
     226        if (new_fun == NULL || connection == NULL)
    206227                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);
    207232
    208233        int rc;
     
    214239        }
    215240
    216         /* We are gona do a lot of communication better open it in advance. */
    217         rc = usb_hc_connection_open(hc_conn);
     241        rc = usb_hc_connection_open(&hc_conn);
    218242        if (rc != EOK) {
    219243                return rc;
    220244        }
    221245
    222         /* Request a new address. */
     246        /*
     247         * Request new address.
     248         */
    223249        usb_address_t dev_addr =
    224             usb_hc_request_address(hc_conn, 0, false, dev_speed);
     250            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    225251        if (dev_addr < 0) {
    226252                rc = EADDRNOTAVAIL;
    227253                goto close_connection;
    228         }
    229 
    230         /* Initialize connection to device. */
    231         usb_device_connection_t dev_conn;
    232         rc = usb_device_connection_initialize_on_default_address(
    233             &dev_conn, hc_conn);
    234         if (rc != EOK) {
    235                 rc = ENOTCONN;
    236                 goto leave_release_free_address;
    237254        }
    238255
     
    243260         * (Someone else already wants to add a new device.)
    244261         */
     262        usb_device_connection_t dev_conn;
     263        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
     264            &hc_conn);
     265        if (rc != EOK) {
     266                rc = ENOTCONN;
     267                goto leave_release_free_address;
     268        }
     269
    245270        usb_pipe_t ctrl_pipe;
    246271        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
     
    251276
    252277        do {
    253                 rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT,
     278                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
    254279                    true, dev_speed);
    255280                if (rc == ENOENT) {
     
    263288
    264289        /* Register control pipe on default address. */
    265         rc = usb_pipe_register(&ctrl_pipe, 0);
     290        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    266291        if (rc != EOK) {
    267292                rc = ENOTCONN;
     
    305330        }
    306331
    307         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     332        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    308333        if (rc != EOK) {
    309334                rc = ESTALL;
     
    311336        }
    312337
     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);
    313341
    314342        /* Register the device with devman. */
     
    328356
    329357        /* Inform the host controller about the handle. */
    330         rc = usb_hc_register_device(hc_conn, &new_device);
     358        rc = usb_hc_register_device(&hc_conn, &new_device);
    331359        if (rc != EOK) {
    332360                /* We know nothing about that data. */
     
    353381         */
    354382leave_release_default_address:
    355         usb_hc_unregister_device(hc_conn, USB_ADDRESS_DEFAULT);
     383        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    356384
    357385leave_release_free_address:
    358386        /* This might be either 0:0 or dev_addr:0 */
    359         if (usb_pipe_unregister(&ctrl_pipe) != EOK)
     387        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
    360388                usb_log_warning("%s: Failed to unregister default pipe.\n",
    361389                    __FUNCTION__);
    362390
    363         if (usb_hc_unregister_device(hc_conn, dev_addr) != EOK)
     391        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
    364392                usb_log_warning("%s: Failed to unregister device.\n",
    365393                    __FUNCTION__);
    366394
    367395close_connection:
    368         if (usb_hc_connection_close(hc_conn) != EOK)
     396        if (usb_hc_connection_close(&hc_conn) != EOK)
    369397                usb_log_warning("%s: Failed to close hc connection.\n",
    370398                    __FUNCTION__);
  • uspace/lib/usbdev/src/pipes.c

    r899f1a9 r9c3bba0  
    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 * @{
     
    3333 * USB endpoint pipes miscellaneous functions.
    3434 */
     35#include <usb/usb.h>
     36#include <usb/dev/pipes.h>
     37#include <usb/debug.h>
     38#include <usb/hc.h>
     39#include <usbhc_iface.h>
    3540#include <usb_iface.h>
    36 #include <usb/dev/pipes.h>
    37 #include <usb/dev/request.h>
     41#include <devman.h>
    3842#include <errno.h>
    3943#include <assert.h>
     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}
    4068
    4169/** Tell USB interface assigned to given device.
     
    6492        return ret == EOK ? iface_no : ret;
    6593}
    66 /*----------------------------------------------------------------------------*/
     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)) {
     169                return EINVAL;
     170        }
     171
     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;
     192        }
     193
     194        return usb_device_connection_initialize(dev_connection,
     195            hc_connection->hc_handle, (usb_address_t) 0);
     196}
     197
    67198/** Prepare pipe for a long transfer.
    68199 *
     
    75206 * @return Error code.
    76207 */
    77 int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
    78 {
    79         assert(pipe);
    80         assert(pipe->wire);
    81         assert(pipe->wire->hc_connection);
    82         return usb_hc_connection_open(pipe->wire->hc_connection);
    83 }
    84 /*----------------------------------------------------------------------------*/
     208void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     209{
     210        (void) pipe_add_ref(pipe, true);
     211}
     212
    85213/** Terminate a long transfer on a pipe.
    86214 *
     
    89217 * @param pipe Pipe where to end the long transfer.
    90218 */
    91 int usb_pipe_end_long_transfer(usb_pipe_t *pipe)
    92 {
    93         assert(pipe);
    94         assert(pipe->wire);
    95         assert(pipe->wire->hc_connection);
    96         return usb_hc_connection_close(pipe->wire->hc_connection);
    97 }
    98 /*----------------------------------------------------------------------------*/
    99 /** Request an in transfer, no checking of input parameters.
    100  *
    101  * @param[in] pipe Pipe used for the transfer.
    102  * @param[out] buffer Buffer where to store the data.
    103  * @param[in] size Size of the buffer (in bytes).
    104  * @param[out] size_transfered Number of bytes that were actually transfered.
    105  * @return Error code.
    106  */
    107 static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup,
    108     void *buffer, size_t size, size_t *size_transfered)
    109 {
    110         /* Isochronous transfer are not supported (yet) */
    111         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    112             pipe->transfer_type != USB_TRANSFER_BULK &&
    113             pipe->transfer_type != USB_TRANSFER_CONTROL)
    114             return ENOTSUP;
    115 
    116         return usb_hc_control_read(pipe->wire->hc_connection,
    117             pipe->wire->address, pipe->endpoint_no, setup, buffer, size,
    118             size_transfered);
    119 }
    120 /*----------------------------------------------------------------------------*/
    121 /** Request an out transfer, no checking of input parameters.
    122  *
    123  * @param[in] pipe Pipe used for the transfer.
    124  * @param[in] buffer Buffer with data to transfer.
    125  * @param[in] size Size of the buffer (in bytes).
    126  * @return Error code.
    127  */
    128 static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,
    129     const void *buffer, size_t size)
    130 {
    131         /* Only interrupt and bulk transfers are supported */
    132         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    133             pipe->transfer_type != USB_TRANSFER_BULK &&
    134             pipe->transfer_type != USB_TRANSFER_CONTROL)
    135             return ENOTSUP;
    136 
    137         return usb_hc_control_write(pipe->wire->hc_connection,
    138             pipe->wire->address, pipe->endpoint_no, setup, buffer, size);
    139 }
    140 /*----------------------------------------------------------------------------*/
    141 /** Try to clear endpoint halt of default control pipe.
    142  *
    143  * @param pipe Pipe for control endpoint zero.
    144  */
    145 static void clear_self_endpoint_halt(usb_pipe_t *pipe)
    146 {
    147         assert(pipe != NULL);
    148 
    149         if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
    150                 return;
    151         }
    152 
    153 
    154         /* Prevent infinite recursion. */
    155         pipe->auto_reset_halt = false;
    156         usb_request_clear_endpoint_halt(pipe, 0);
    157         pipe->auto_reset_halt = true;
    158 }
    159 /*----------------------------------------------------------------------------*/
    160 /** Request a control read transfer on an endpoint pipe.
    161  *
    162  * This function encapsulates all three stages of a control transfer.
    163  *
    164  * @param[in] pipe Pipe used for the transfer.
    165  * @param[in] setup_buffer Buffer with the setup packet.
    166  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    167  * @param[out] data_buffer Buffer for incoming data.
    168  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    169  * @param[out] data_transfered_size Number of bytes that were actually
    170  *                                  transfered during the DATA stage.
    171  * @return Error code.
    172  */
    173 int usb_pipe_control_read(usb_pipe_t *pipe,
    174     const void *setup_buffer, size_t setup_buffer_size,
    175     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    176 {
    177         assert(pipe);
    178 
    179         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    180                 return EINVAL;
    181         }
    182 
    183         if ((data_buffer == NULL) || (data_buffer_size == 0)) {
    184                 return EINVAL;
    185         }
    186 
    187         if ((pipe->direction != USB_DIRECTION_BOTH)
    188             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    189                 return EBADF;
    190         }
    191 
    192         uint64_t setup_packet;
    193         memcpy(&setup_packet, setup_buffer, 8);
    194 
    195         size_t act_size = 0;
    196         const int rc = usb_pipe_read_no_check(pipe, setup_packet,
    197             data_buffer, data_buffer_size, &act_size);
    198 
    199         if (rc == ESTALL) {
    200                 clear_self_endpoint_halt(pipe);
    201         }
    202 
    203         if (rc == EOK && data_transfered_size != NULL) {
    204                 *data_transfered_size = act_size;
    205         }
    206 
    207         return rc;
    208 }
    209 /*----------------------------------------------------------------------------*/
    210 /** Request a control write transfer on an endpoint pipe.
    211  *
    212  * This function encapsulates all three stages of a control transfer.
    213  *
    214  * @param[in] pipe Pipe used for the transfer.
    215  * @param[in] setup_buffer Buffer with the setup packet.
    216  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    217  * @param[in] data_buffer Buffer with data to be sent.
    218  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    219  * @return Error code.
    220  */
    221 int usb_pipe_control_write(usb_pipe_t *pipe,
    222     const void *setup_buffer, size_t setup_buffer_size,
    223     const void *data_buffer, size_t data_buffer_size)
    224 {
    225         assert(pipe);
    226 
    227         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    228                 return EINVAL;
    229         }
    230 
    231         if ((data_buffer == NULL) && (data_buffer_size > 0)) {
    232                 return EINVAL;
    233         }
    234 
    235         if ((data_buffer != NULL) && (data_buffer_size == 0)) {
    236                 return EINVAL;
    237         }
    238 
    239         if ((pipe->direction != USB_DIRECTION_BOTH)
    240             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    241                 return EBADF;
    242         }
    243 
    244         uint64_t setup_packet;
    245         memcpy(&setup_packet, setup_buffer, 8);
    246 
    247         const int rc = usb_pipe_write_no_check(pipe, setup_packet,
    248             data_buffer, data_buffer_size);
    249 
    250         if (rc == ESTALL) {
    251                 clear_self_endpoint_halt(pipe);
    252         }
    253 
    254         return rc;
    255 }
    256 /*----------------------------------------------------------------------------*/
    257 /** Request a read (in) transfer on an endpoint pipe.
    258  *
    259  * @param[in] pipe Pipe used for the transfer.
    260  * @param[out] buffer Buffer where to store the data.
    261  * @param[in] size Size of the buffer (in bytes).
    262  * @param[out] size_transfered Number of bytes that were actually transfered.
    263  * @return Error code.
    264  */
    265 int usb_pipe_read(usb_pipe_t *pipe,
    266     void *buffer, size_t size, size_t *size_transfered)
    267 {
    268         assert(pipe);
    269 
    270         if (buffer == NULL) {
    271                 return EINVAL;
    272         }
    273 
    274         if (size == 0) {
    275                 return EINVAL;
    276         }
    277 
    278         if (pipe->direction != USB_DIRECTION_IN) {
    279                 return EBADF;
    280         }
    281 
    282         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    283                 return EBADF;
    284         }
    285 
    286         size_t act_size = 0;
    287         const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size);
    288 
    289 
    290         if (rc == EOK && size_transfered != NULL) {
    291                 *size_transfered = act_size;
    292         }
    293 
    294         return rc;
    295 }
    296 /*----------------------------------------------------------------------------*/
    297 /** Request a write (out) transfer on an endpoint pipe.
    298  *
    299  * @param[in] pipe Pipe used for the transfer.
    300  * @param[in] buffer Buffer with data to transfer.
    301  * @param[in] size Size of the buffer (in bytes).
    302  * @return Error code.
    303  */
    304 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
    305 {
    306         assert(pipe);
    307 
    308         if (buffer == NULL || size == 0) {
    309                 return EINVAL;
    310         }
    311 
    312         if (pipe->direction != USB_DIRECTION_OUT) {
    313                 return EBADF;
    314         }
    315 
    316         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    317                 return EBADF;
    318         }
    319 
    320         return usb_pipe_write_no_check(pipe, 0, buffer, size);
    321 }
     219void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
     220{
     221        pipe_drop_ref(pipe);
     222}
     223
    322224/**
    323225 * @}
  • uspace/lib/usbdev/src/pipesinit.c

    r899f1a9 r9c3bba0  
    349349        fibril_mutex_initialize(&pipe->guard);
    350350        pipe->wire = connection;
     351        pipe->hc_sess = NULL;
     352        fibril_mutex_initialize(&pipe->hc_sess_mutex);
    351353        pipe->endpoint_no = endpoint_no;
    352354        pipe->transfer_type = transfer_type;
    353355        pipe->max_packet_size = max_packet_size;
    354356        pipe->direction = direction;
     357        pipe->refcount = 0;
     358        pipe->refcount_soft = 0;
    355359        pipe->auto_reset_halt = false;
    356360
     
    371375        assert(connection);
    372376
    373         int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL,
    374             CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH);
     377        int rc = usb_pipe_initialize(pipe, connection,
     378            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     379            USB_DIRECTION_BOTH);
    375380
    376381        pipe->auto_reset_halt = true;
     
    437442 * @return Error code.
    438443 */
    439 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
     444int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
     445    usb_hc_connection_t *hc_connection)
    440446{
    441447        assert(pipe);
    442448        assert(pipe->wire);
    443         assert(pipe->wire->hc_connection);
    444 
    445         return usb_hc_register_endpoint(pipe->wire->hc_connection,
    446            pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
    447            pipe->direction, pipe->max_packet_size, interval);
     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;
    448462}
    449463
     
    454468 * @return Error code.
    455469 */
    456 int usb_pipe_unregister(usb_pipe_t *pipe)
     470int usb_pipe_unregister(usb_pipe_t *pipe,
     471    usb_hc_connection_t *hc_connection)
    457472{
    458473        assert(pipe);
    459474        assert(pipe->wire);
    460         assert(pipe->wire->hc_connection);
    461 
    462         return usb_hc_unregister_endpoint(pipe->wire->hc_connection,
     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,
    463484            pipe->wire->address, pipe->endpoint_no, pipe->direction);
     485        async_exchange_end(exch);
     486
     487        return ret;
    464488}
    465489
  • uspace/lib/usbdev/src/recognise.c

    r899f1a9 r9c3bba0  
    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 
    327         /** Index to append after device name for uniqueness. */
    328         static atomic_t device_name_index = {0};
    329         const size_t this_device_name_index =
    330             (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);
    331334
    332335        ddf_fun_t *child = NULL;
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r899f1a9 r9c3bba0  
    106106void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
    107107
    108 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    109     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);
    110110/*----------------------------------------------------------------------------*/
    111 /** Finish batch using stored error value.
     111/** Override error value and finishes transfer.
    112112 *
    113113 * @param[in] instance Batch structure to use.
    114114 * @param[in] data Data to copy to the output buffer.
    115115 * @param[in] size Size of @p data.
     116 * @param[in] error Set batch status to this error value.
    116117 */
    117 static inline void usb_transfer_batch_finish(
    118     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)
    119120{
    120121        assert(instance);
    121         usb_transfer_batch_finish_error(
    122             instance, data, instance->transfered_size, instance->error);
     122        instance->error = error;
     123        usb_transfer_batch_finish(instance, data, size);
    123124}
    124125/*----------------------------------------------------------------------------*/
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r899f1a9 r9c3bba0  
    3333 */
    3434#include <errno.h>
    35 #include <macros.h>
     35#include <str_error.h>
    3636
    3737#include <usb/usb.h>
     
    121121 * @param[in] data Data to copy to the output buffer.
    122122 * @param[in] size Size of @p data.
    123  * @param[in] error Error value to use.
    124123 */
    125 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    126     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)
    127126{
    128127        assert(instance);
     
    134133                /* Check for commands that reset toggle bit */
    135134                if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
    136                     && error == EOK) {
     135                    && instance->error == EOK) {
    137136                        const usb_target_t target =
    138137                            {{ instance->ep->address, instance->ep->endpoint }};
     
    140139                            instance->setup_buffer);
    141140                }
    142                 instance->callback_out(instance->fun, error, instance->arg);
     141                instance->callback_out(instance->fun,
     142                    instance->error, instance->arg);
    143143        }
    144144
    145145        if (instance->callback_in) {
    146146                /* We care about the data and there are some to copy */
    147                 const size_t safe_size = min(size, instance->buffer_size);
    148147                if (data) {
    149                         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);
    150151                }
    151                 instance->callback_in(instance->fun, error,
    152                     safe_size, instance->arg);
     152                instance->callback_in(instance->fun, instance->error,
     153                    instance->transfered_size, instance->arg);
    153154        }
    154155}
Note: See TracChangeset for help on using the changeset viewer.