Changeset b4b534ac in mainline for uspace/drv/bus


Ignore:
Timestamp:
2016-07-22T08:24:47Z (10 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jan.vesely/helenos/usb

Location:
uspace/drv/bus/usb
Files:
17 added
16 deleted
68 edited
7 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/Makefile

    r5b18137 rb4b534ac  
    3131LIBS = \
    3232        $(LIBUSBHOST_PREFIX)/libusbhost.a \
     33        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
    3334        $(LIBUSB_PREFIX)/libusb.a \
    3435        $(LIBDRV_PREFIX)/libdrv.a
     
    3637EXTRA_CFLAGS += \
    3738        -I$(LIBUSB_PREFIX)/include \
     39        -I$(LIBUSBDEV_PREFIX)/include \
    3840        -I$(LIBUSBHOST_PREFIX)/include \
     41        -I$(LIBUSBVIRT_PREFIX)/include \
    3942        -I$(LIBDRV_PREFIX)/include
    4043
     
    4245
    4346SOURCES = \
     47        ehci_batch.c \
     48        ehci_endpoint.c \
     49        ehci_rh.c \
     50        endpoint_list.c \
     51        hc.c \
     52        hw_struct/queue_head.c \
     53        hw_struct/transfer_descriptor.c \
    4454        main.c \
    4555        res.c
  • uspace/drv/bus/usb/ehci/ehci_endpoint.h

    r5b18137 rb4b534ac  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup drvusbehci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief EHCI driver
    3333 */
    34 #ifndef DRV_UHCI_ROOT_HUB_H
    35 #define DRV_UHCI_ROOT_HUB_H
     34#ifndef DRV_EHCI_HCD_ENDPOINT_H
     35#define DRV_EHCI_HCD_ENDPOINT_H
    3636
    37 #include <ddf/driver.h>
    38 #include <device/hw_res_parsed.h>
     37#include <assert.h>
     38#include <adt/list.h>
     39#include <usb/host/endpoint.h>
     40#include <usb/host/hcd.h>
    3941
    40 #include "port.h"
     42#include "hw_struct/queue_head.h"
     43#include "hw_struct/transfer_descriptor.h"
    4144
    42 #define UHCI_ROOT_HUB_PORT_COUNT 2
    43 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
     45/** Connector structure linking ED to to prepared TD. */
     46typedef struct ehci_endpoint {
     47        /** EHCI endpoint descriptor */
     48        qh_t *qh;
     49        /** Linked list used by driver software */
     50        link_t link;
     51} ehci_endpoint_t;
    4452
    45 /** UHCI root hub drvier structure */
    46 typedef struct root_hub {
    47         /** Ports provided by the hub */
    48         uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
    49 } uhci_root_hub_t;
     53int ehci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
     54void ehci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);
    5055
    51 int uhci_root_hub_init(uhci_root_hub_t *instance, addr_range_t *regs,
    52     ddf_dev_t *rh);
     56/** Get and convert assigned ehci_endpoint_t structure
     57 * @param[in] ep USBD endpoint structure.
     58 * @return Pointer to assigned hcd endpoint structure
     59 */
     60static inline ehci_endpoint_t * ehci_endpoint_get(const endpoint_t *ep)
     61{
     62        assert(ep);
     63        return ep->hc_data.data;
     64}
    5365
    54 void uhci_root_hub_fini(uhci_root_hub_t *instance);
     66static inline ehci_endpoint_t * ehci_endpoint_list_instance(link_t *l)
     67{
     68        return list_get_instance(l, ehci_endpoint_t, link);
     69}
     70
    5571#endif
    5672/**
    5773 * @}
    5874 */
     75
  • uspace/drv/bus/usb/ehci/ehci_rh.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhci
     28/** @addtogroup drvusbehci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief EHCI driver
    3333 */
     34#ifndef DRV_EHCI_EHCI_RH_H
     35#define DRV_EHCI_EHCI_RH_H
     36
    3437#include <assert.h>
    35 #include <errno.h>
    36 #include <str_error.h>
    37 #include <stdio.h>
    38 #include <device/hw_res_parsed.h>
     38#include <sys/types.h>
    3939
    40 #include <usb/debug.h>
     40#include <usb/usb.h>
     41#include <usb/classes/hub.h>
     42#include <usb/host/usb_transfer_batch.h>
     43#include <usbvirt/virthub_base.h>
    4144
    42 #include "root_hub.h"
     45#include "ehci_regs.h"
    4346
    44 /** Root hub initialization
    45  * @param[in] instance RH structure to initialize
    46  * @param[in] fun DDF function representing UHCI root hub
    47  * @param[in] reg_addr Address of root hub status and control registers.
    48  * @param[in] reg_size Size of accessible address space.
    49  * @return Error code.
     47enum {
     48        EHCI_MAX_PORTS = 15,
     49};
     50
     51typedef struct {
     52        /** Virtual hub instance */
     53        virthub_base_t base;
     54        /** EHCI device registers */
     55        ehci_regs_t *registers;
     56        /** Number of downstream ports, EHCI limits this to 15 */
     57        unsigned port_count;
     58        /** USB hub descriptor describing the EHCI root hub */
     59        struct {
     60                usb_hub_descriptor_header_t header;
     61                uint8_t rempow[STATUS_BYTES(EHCI_MAX_PORTS) * 2];
     62        } __attribute__((packed)) hub_descriptor;
     63        /** interrupt transfer waiting for an actual interrupt to occur */
     64        usb_transfer_batch_t *unfinished_interrupt_transfer;
     65        bool reset_flag[EHCI_MAX_PORTS];
     66        bool resume_flag[EHCI_MAX_PORTS];
     67} ehci_rh_t;
     68
     69int ehci_rh_init(ehci_rh_t *instance, ehci_caps_regs_t *caps, ehci_regs_t *regs,
     70    const char *name);
     71int ehci_rh_schedule(ehci_rh_t *instance, usb_transfer_batch_t *batch);
     72int ehci_rh_interrupt(ehci_rh_t *instance);
     73
     74/** Get EHCI rh address.
     75 *
     76 * @param instance UHCI rh instance.
     77 * @return USB address assigned to the hub.
     78 * Wrapper for virtual hub address
    5079 */
    51 int
    52 rh_init(rh_t *instance, ddf_fun_t *fun, addr_range_t *regs, uintptr_t reg_addr,
    53     size_t reg_size)
     80static inline usb_address_t ehci_rh_get_address(ehci_rh_t *instance)
    5481{
    5582        assert(instance);
    56         assert(fun);
    57 
    58         /* Crop the PIO window to the absolute address range of UHCI I/O. */
    59         instance->pio_window.mem.base = 0;
    60         instance->pio_window.mem.size = 0;
    61         instance->pio_window.io.base = RNGABS(*regs);
    62         instance->pio_window.io.size = RNGSZ(*regs);
    63 
    64         /* Initialize resource structure */
    65         instance->resource_list.count = 1;
    66         instance->resource_list.resources = &instance->io_regs;
    67 
    68         instance->io_regs.type = IO_RANGE;
    69         instance->io_regs.res.io_range.address = reg_addr;
    70         instance->io_regs.res.io_range.size = reg_size;
    71         instance->io_regs.res.io_range.relative = true;
    72         instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
    73 
    74         const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    75         if (ret != EOK) {
    76                 usb_log_error("Failed to add root hub match id: %s\n",
    77                     str_error(ret));
    78         }
    79         return ret;
     83        return virthub_base_get_address(&instance->base);
    8084}
     85#endif
    8186/**
    8287 * @}
  • uspace/drv/bus/usb/ehci/hw_struct/fstn.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhci
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * @brief UHCI driver main structure for both host controller and root-hub.
     32 * @brief EHCI driver
    3433 */
    35 #ifndef DRV_UHCI_UHCI_H
    36 #define DRV_UHCI_UHCI_H
    37 #include <ddf/driver.h>
     34#ifndef DRV_EHCI_HW_STRUCT_FSTN_H
     35#define DRV_EHCI_HW_STRUCT_FSTN_H
    3836
    39 int device_setup_uhci(ddf_dev_t *device);
     37#include "link_pointer.h"
     38
     39typedef struct fstn {
     40        link_pointer_t normal_path;
     41        link_pointer_t back_path;
     42} fstn_t;
     43
    4044#endif
    4145/**
    4246 * @}
    4347 */
     48
  • uspace/drv/bus/usb/ehci/hw_struct/link_pointer.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup libusb
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * Implementations of DDF interfaces functions.
     32 * @brief EHCI driver
    3433 */
    35 
    36 #ifndef LIBUSB_DDFIFACE_H_
    37 #define LIBUSB_DDFIFACE_H_
     34#ifndef DRV_EHCI_HW_STRUCT_LINK_POINTER_H
     35#define DRV_EHCI_HW_STRUCT_LINK_POINTER_H
    3836
    3937#include <sys/types.h>
    40 #include <usb_iface.h>
    4138
    42 extern int usb_iface_get_hc_handle_device_impl(ddf_fun_t *, devman_handle_t *);
    43 extern int usb_iface_get_my_address_forward_impl(ddf_fun_t *, usb_address_t *);
    44 extern usb_iface_t usb_iface_hub_impl;
     39/** EHCI link pointer, used by many data structures */
     40typedef volatile uint32_t link_pointer_t;
    4541
    46 extern int usb_iface_get_my_address_from_device_data(ddf_fun_t *, usb_address_t *);
    47 extern usb_iface_t usb_iface_hub_child_impl;
     42#define LINK_POINTER_ADDRESS_MASK   0xfffffff0 /* upper 28 bits */
    4843
    49 extern int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
     44#define LINK_POINTER_TERMINATE_FLAG   (1 << 0)
     45
     46enum {
     47        LINK_POINTER_TYPE_iTD  = 0x0 << 1,
     48        LINK_POINTER_TYPE_QH   = 0x1 << 1,
     49        LINK_POINTER_TYPE_siTD = 0x2 << 1,
     50        LINK_POINTER_TYPE_FSTN = 0x3 << 1,
     51        LINK_POINTER_TYPE_MASK = 0x3 << 1,
     52};
     53
     54#define LINK_POINTER_QH(address) \
     55        ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_TYPE_QH)
     56
     57#define LINK_POINTER_TD(address) \
     58        (address & LINK_POINTER_ADDRESS_MASK)
     59
     60#define LINK_POINTER_TERM \
     61        ((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
    5062
    5163#endif
    52 
    5364/**
    5465 * @}
  • uspace/drv/bus/usb/ehci/hw_struct/mem_access.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhcihc
     28/** @addtogroup drvusbehci
    3029 * @{
    3130 */
    3231/** @file
    33  * @brief UHCI driver PCI helper functions
     32 * @brief EHCI driver
    3433 */
    35 #ifndef DRV_UHCI_PCI_H
    36 #define DRV_UHCI_PCI_H
     34#ifndef DRV_EHCI_HW_MEM_ACCESS_H
     35#define DRV_EHCI_HW_MEM_ACCESS_H
    3736
    38 #include <ddf/driver.h>
    39 #include <device/hw_res_parsed.h>
     37#include <byteorder.h>
     38#include <libarch/barrier.h>
    4039
    41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
    42 int enable_interrupts(ddf_dev_t *);
    43 int disable_legacy(ddf_dev_t *);
     40#define EHCI_MEM32_WR(reg, val) reg = host2uint32_t_le(val)
     41#define EHCI_MEM32_RD(reg) uint32_t_le2host(reg)
     42#define EHCI_MEM32_SET(reg, val) reg |= host2uint32_t_le(val)
     43#define EHCI_MEM32_CLR(reg, val) reg &= host2uint32_t_le(~val)
    4444
    4545#endif
    46 /**
     46
     47/*
    4748 * @}
    4849 */
  • uspace/drv/bus/usb/ehci/main.c

    r5b18137 rb4b534ac  
    3333 * Main routines of EHCI driver.
    3434 */
    35 
    3635#include <ddf/driver.h>
    3736#include <ddf/interrupt.h>
    3837#include <device/hw_res.h>
    3938#include <errno.h>
    40 #include <stdbool.h>
    4139#include <str_error.h>
     40#include <io/logctl.h>
    4241
    4342#include <usb_iface.h>
    44 #include <usb/ddfiface.h>
    4543#include <usb/debug.h>
    46 #include <usb/host/hcd.h>
     44#include <usb/host/ddf_helpers.h>
    4745
    4846#include "res.h"
     47#include "hc.h"
     48#include "ehci_endpoint.h"
    4949
    5050#define NAME "ehci"
    5151
    52 static int ehci_dev_add(ddf_dev_t *device);
     52static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     53static void ehci_driver_fini(hcd_t *);
    5354
    54 static driver_ops_t ehci_driver_ops = {
    55         .dev_add = ehci_dev_add,
     55static const ddf_hc_driver_t ehci_hc_driver = {
     56        .claim = disable_legacy,
     57        .hc_speed = USB_SPEED_HIGH,
     58        .irq_code_gen = ehci_hc_gen_irq_code,
     59        .init = ehci_driver_init,
     60        .fini = ehci_driver_fini,
     61        .name = "EHCI-PCI",
     62        .ops = {
     63                .schedule       = ehci_hc_schedule,
     64                .ep_add_hook    = ehci_endpoint_init,
     65                .ep_remove_hook = ehci_endpoint_fini,
     66                .irq_hook       = ehci_hc_interrupt,
     67                .status_hook    = ehci_hc_status,
     68        }
    5669};
    5770
    58 static driver_t ehci_driver = {
    59         .name = NAME,
    60         .driver_ops = &ehci_driver_ops
    61 };
    62 static ddf_dev_ops_t hc_ops = {
    63         .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    64 };
    6571
     72static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     73{
     74        assert(hcd);
     75        assert(hcd_get_driver_data(hcd) == NULL);
     76
     77        hc_t *instance = malloc(sizeof(hc_t));
     78        if (!instance)
     79                return ENOMEM;
     80
     81        const int ret = hc_init(instance, res, irq);
     82        if (ret == EOK) {
     83                hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops);
     84        } else {
     85                free(instance);
     86        }
     87        return ret;
     88}
     89
     90static void ehci_driver_fini(hcd_t *hcd)
     91{
     92        assert(hcd);
     93        hc_t *hc = hcd_get_driver_data(hcd);
     94        if (hc)
     95                hc_fini(hc);
     96
     97        free(hc);
     98        hcd_set_implementation(hcd, NULL, NULL);
     99}
    66100
    67101/** Initializes a new ddf driver instance of EHCI hcd.
     
    72106static int ehci_dev_add(ddf_dev_t *device)
    73107{
    74         ddf_fun_t *hc_fun = NULL;
    75         bool fun_bound = false;
    76 
     108        usb_log_debug("ehci_dev_add() called\n");
    77109        assert(device);
    78110
    79         addr_range_t reg_range;
    80         int irq = 0;
     111        return hcd_ddf_add_hc(device, &ehci_hc_driver);
    81112
    82         int rc = get_my_registers(device, &reg_range, &irq);
    83         if (rc != EOK) {
    84                 usb_log_error("Failed to get memory addresses for %" PRIun
    85                     ": %s.\n", ddf_dev_get_handle(device), str_error(rc));
    86                 goto error;
    87         }
     113}
    88114
    89         usb_log_info("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    90             RNGABSPTR(reg_range), RNGSZ(reg_range), irq);
    91115
    92         rc = disable_legacy(device, &reg_range);
    93         if (rc != EOK) {
    94                 usb_log_error("Failed to disable legacy USB: %s.\n",
    95                     str_error(rc));
    96                 goto error;
    97         }
     116static const driver_ops_t ehci_driver_ops = {
     117        .dev_add = ehci_dev_add,
     118};
    98119
    99         hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");
    100         if (hc_fun == NULL) {
    101                 usb_log_error("Failed to create EHCI function.\n");
    102                 rc = ENOMEM;
    103                 goto error;
    104         }
     120static const driver_t ehci_driver = {
     121        .name = NAME,
     122        .driver_ops = &ehci_driver_ops
     123};
    105124
    106         hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t));
    107         if (ehci_hc == NULL) {
    108                 usb_log_error("Failed to alloc generic HC driver.\n");
    109                 rc = ENOMEM;
    110                 goto error;
    111         }
    112 
    113         /* High Speed, no bandwidth */
    114         hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
    115         ddf_fun_set_ops(hc_fun,  &hc_ops);
    116 
    117         rc = ddf_fun_bind(hc_fun);
    118         if (rc != EOK) {
    119                 usb_log_error("Failed to bind EHCI function: %s.\n",
    120                     str_error(rc));
    121                 goto error;
    122         }
    123 
    124         fun_bound = true;
    125 
    126         rc = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY);
    127         if (rc != EOK) {
    128                 usb_log_error("Failed to add EHCI to HC class: %s.\n",
    129                     str_error(rc));
    130                 goto error;
    131         }
    132 
    133         usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
    134             ddf_dev_get_name(device), ddf_dev_get_handle(device));
    135 
    136         return EOK;
    137 error:
    138         if (fun_bound)
    139                 ddf_fun_unbind(hc_fun);
    140         if (hc_fun != NULL)
    141                 ddf_fun_destroy(hc_fun);
    142         return rc;
    143 }
    144125
    145126/** Initializes global driver structures (NONE).
     
    154135{
    155136        log_init(NAME);
     137        logctl_set_log_level(NAME, LVL_NOTE);
    156138        return ddf_driver_main(&ehci_driver);
    157139}
  • uspace/drv/bus/usb/ehci/res.c

    r5b18137 rb4b534ac  
    4646
    4747#include "res.h"
    48 
    49 #define HCC_PARAMS_OFFSET 0x8
    50 #define HCC_PARAMS_EECP_MASK 0xff
    51 #define HCC_PARAMS_EECP_OFFSET 8
    52 
    53 #define CMD_OFFSET 0x0
    54 #define STS_OFFSET 0x4
    55 #define INT_OFFSET 0x8
    56 #define CFG_OFFSET 0x40
    57 
    58 #define USBCMD_RUN 1
    59 #define USBSTS_HALTED (1 << 12)
     48#include "ehci_regs.h"
    6049
    6150#define USBLEGSUP_OFFSET 0
     
    6756#define WAIT_STEP 10
    6857
    69 
    70 /** Get address of registers and IRQ for given device.
    71  *
    72  * @param[in] dev Device asking for the addresses.
    73  * @param[out] mem_regs_p Pointer to the register range.
    74  * @param[out] irq_no IRQ assigned to the device.
    75  * @return Error code.
    76  */
    77 int get_my_registers(ddf_dev_t *dev,
    78     addr_range_t *mem_regs_p, int *irq_no)
    79 {
    80         assert(dev);
    81        
    82         async_sess_t *parent_sess = devman_parent_device_connect(
    83             ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
    84         if (!parent_sess)
    85                 return ENOMEM;
    86        
    87         hw_res_list_parsed_t hw_res;
    88         hw_res_list_parsed_init(&hw_res);
    89         const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
    90         async_hangup(parent_sess);
    91         if (ret != EOK) {
    92                 return ret;
    93         }
    94 
    95         if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
    96                 hw_res_list_parsed_clean(&hw_res);
    97                 return ENOENT;
    98         }
    99 
    100         if (mem_regs_p)
    101                 *mem_regs_p = hw_res.mem_ranges.ranges[0];
    102         if (irq_no)
    103                 *irq_no = hw_res.irqs.irqs[0];
    104 
    105         hw_res_list_parsed_clean(&hw_res);
    106         return EOK;
    107 }
    108 
    109 /** Calls the PCI driver with a request to enable interrupts
    110  *
    111  * @param[in] device Device asking for interrupts
    112  * @return Error code.
    113  */
    114 int enable_interrupts(ddf_dev_t *device)
    115 {
    116         async_sess_t *parent_sess = devman_parent_device_connect(
    117             ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
    118         if (!parent_sess)
    119                 return ENOMEM;
    120        
    121         const bool enabled = hw_res_enable_interrupt(parent_sess);
    122         async_hangup(parent_sess);
    123        
    124         return enabled ? EOK : EIO;
    125 }
    126 
    12758/** Implements BIOS hands-off routine as described in EHCI spec
    12859 *
     
    13162 * @return Error code.
    13263 */
    133 static int disable_extended_caps(ddf_dev_t *device, unsigned eecp)
     64static int disable_extended_caps(async_sess_t *parent_sess, unsigned eecp)
    13465{
    13566        /* nothing to do */
     
    13768                return EOK;
    13869
    139         async_sess_t *parent_sess = devman_parent_device_connect(
    140             ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
    141         if (!parent_sess)
    142                 return ENOMEM;
    143 
    14470        /* Read the first EEC. i.e. Legacy Support register */
    14571        uint32_t usblegsup;
    146         int rc = pci_config_space_read_32(parent_sess,
     72        int ret = pci_config_space_read_32(parent_sess,
    14773            eecp + USBLEGSUP_OFFSET, &usblegsup);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed to read USBLEGSUP: %s.\n",
    150                     str_error(rc));
    151                 goto error;
    152         }
    153 
    154         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     74        if (ret != EOK) {
     75                usb_log_error("Failed to read USBLEGSUP: %s.\n", str_error(ret));
     76                return ret;
     77        }
     78        usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    15579
    15680        /* Request control from firmware/BIOS by writing 1 to highest
    15781         * byte. (OS Control semaphore)*/
    15882        usb_log_debug("Requesting OS control.\n");
    159         rc = pci_config_space_write_8(parent_sess,
     83        ret = pci_config_space_write_8(parent_sess,
    16084            eecp + USBLEGSUP_OFFSET + 3, 1);
    161         if (rc != EOK) {
     85        if (ret != EOK) {
    16286                usb_log_error("Failed to request OS EHCI control: %s.\n",
    163                     str_error(rc));
    164                 goto error;
     87                    str_error(ret));
     88                return ret;
    16589        }
    16690
    16791        size_t wait = 0;
    16892        /* Wait for BIOS to release control. */
    169         rc = pci_config_space_read_32(
     93        ret = pci_config_space_read_32(
    17094            parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup);
    171         if (rc != EOK) {
    172                 usb_log_error("Failed reading PCI config space: %s.\n",
    173                     str_error(rc));
    174                 goto error;
    175         }
    176 
    177         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     95        while ((ret == EOK) && (wait < DEFAULT_WAIT)
     96            && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    17897                async_usleep(WAIT_STEP);
    179                 rc = pci_config_space_read_32(parent_sess,
     98                ret = pci_config_space_read_32(parent_sess,
    18099                    eecp + USBLEGSUP_OFFSET, &usblegsup);
    181                 if (rc != EOK) {
    182                         usb_log_error("Failed reading PCI config space: %s.\n",
    183                             str_error(rc));
    184                         goto error;
    185                 }
    186100                wait += WAIT_STEP;
    187101        }
     
    189103        if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
    190104                usb_log_info("BIOS released control after %zu usec.\n", wait);
    191                 async_hangup(parent_sess);
    192105                return EOK;
    193106        }
     
    196109        usb_log_warning( "BIOS failed to release control after "
    197110            "%zu usecs, force it.\n", wait);
    198         rc = pci_config_space_write_32(parent_sess,
     111        ret = pci_config_space_write_32(parent_sess,
    199112            eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    200         if (rc != EOK) {
    201                 usb_log_error("Failed to force OS control: "
    202                     "%s.\n", str_error(rc));
    203                 goto error;
     113        if (ret != EOK) {
     114                usb_log_error("Failed to force OS control: %s.\n",
     115                    str_error(ret));
     116                return ret;
    204117        }
    205118
     
    213126                /* Read the second EEC Legacy Support and Control register */
    214127                uint32_t usblegctlsts;
    215                 rc = pci_config_space_read_32(parent_sess,
     128                ret = pci_config_space_read_32(parent_sess,
    216129                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    217                 if (rc != EOK) {
     130                if (ret != EOK) {
    218131                        usb_log_error("Failed to get USBLEGCTLSTS: %s.\n",
    219                             str_error(rc));
    220                         goto error;
     132                            str_error(ret));
     133                        return ret;
    221134                }
    222 
    223                 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
     135                usb_log_debug2("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
    224136                /*
    225137                 * Zero SMI enables in legacy control register.
     
    227139                 * interfering. NOTE: Three upper bits are WC
    228140                 */
    229                 rc = pci_config_space_write_32(parent_sess,
     141                ret = pci_config_space_write_32(parent_sess,
    230142                    eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    231                 if (rc != EOK) {
    232                         usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc);
    233                         goto error;
     143                if (ret != EOK) {
     144                        usb_log_error("Failed to zero USBLEGCTLSTS: %s\n",
     145                            str_error(ret));
     146                        return ret;
    234147                }
    235148
    236149                udelay(10);
    237                 rc = pci_config_space_read_32(parent_sess,
     150                /* read again to amke sure it's zeroed */
     151                ret = pci_config_space_read_32(parent_sess,
    238152                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    239                 if (rc != EOK) {
     153                if (ret != EOK) {
    240154                        usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n",
    241                             str_error(rc));
    242                         goto error;
     155                            str_error(ret));
     156                        return ret;
    243157                }
    244 
    245                 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
     158                usb_log_debug2("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    246159                    usblegctlsts);
    247160        }
    248161
    249162        /* Read again Legacy Support register */
    250         rc = pci_config_space_read_32(parent_sess,
     163        ret = pci_config_space_read_32(parent_sess,
    251164            eecp + USBLEGSUP_OFFSET, &usblegsup);
    252         if (rc != EOK) {
     165        if (ret != EOK) {
    253166                usb_log_error("Failed to read USBLEGSUP: %s.\n",
    254                     str_error(rc));
    255                 goto error;
    256         }
    257 
    258         usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    259         async_hangup(parent_sess);
    260         return EOK;
    261 error:
    262         async_hangup(parent_sess);
    263         return rc;
     167                    str_error(ret));
     168                return ret;
     169        }
     170        usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
     171        return ret;
    264172}
    265173
    266 int disable_legacy(ddf_dev_t *device, addr_range_t *reg_range)
     174int disable_legacy(ddf_dev_t *device)
    267175{
    268176        assert(device);
     177
     178        async_sess_t *parent_sess = devman_parent_device_connect(
     179            ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
     180        if (!parent_sess)
     181                return ENOMEM;
     182
    269183        usb_log_debug("Disabling EHCI legacy support.\n");
     184
     185        hw_res_list_parsed_t res;
     186        hw_res_list_parsed_init(&res);
     187        int ret = hw_res_get_list_parsed(parent_sess, &res, 0);
     188        if (ret != EOK) {
     189                usb_log_error("Failed to get resource list: %s\n",
     190                    str_error(ret));
     191                goto clean;
     192        }
     193
     194        if (res.mem_ranges.count < 1) {
     195                usb_log_error("Incorrect mem range count: %zu",
     196                    res.mem_ranges.count);
     197                ret = EINVAL;
     198                goto clean;
     199        }
    270200
    271201        /* Map EHCI registers */
    272202        void *regs = NULL;
    273         int rc = pio_enable_range(reg_range, &regs);
    274         if (rc != EOK) {
     203        ret = pio_enable_range(&res.mem_ranges.ranges[0], &regs);
     204        if (ret != EOK) {
    275205                usb_log_error("Failed to map registers %p: %s.\n",
    276                     RNGABSPTR(*reg_range), str_error(rc));
    277                 return rc;
    278         }
    279 
    280         usb_log_debug2("Registers mapped at: %p.\n", regs);
    281 
    282         const uint32_t hcc_params =
    283             *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
    284         usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
     206                    RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret));
     207                goto clean;
     208        }
     209
     210        usb_log_debug("Registers mapped at: %p.\n", regs);
     211
     212        ehci_caps_regs_t *ehci_caps = regs;
     213
     214        const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
     215        usb_log_debug2("Value of hcc params register: %x.\n", hcc_params);
    285216
    286217        /* Read value of EHCI Extended Capabilities Pointer
    287218         * position of EEC registers (points to PCI config space) */
    288219        const uint32_t eecp =
    289             (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    290         usb_log_debug("Value of EECP: %x.\n", eecp);
    291 
    292         rc = disable_extended_caps(device, eecp);
    293         if (rc != EOK) {
     220            (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK;
     221        usb_log_debug2("Value of EECP: %x.\n", eecp);
     222
     223        ret = disable_extended_caps(parent_sess, eecp);
     224        if (ret != EOK) {
    294225                usb_log_error("Failed to disable extended capabilities: %s.\n",
    295                     str_error(rc));
    296                 return rc;
    297         }
    298 
    299         /*
    300          * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT IF NEEDED
    301          */
    302 
    303         /* Get size of capability registers in memory space. */
    304         const unsigned operation_offset = *(uint8_t*)regs;
    305         usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    306 
    307         /* Zero USBCMD register. */
    308         volatile uint32_t *usbcmd =
    309             (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
    310         volatile uint32_t *usbsts =
    311             (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
    312         volatile uint32_t *usbconf =
    313             (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
    314         volatile uint32_t *usbint =
    315             (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
    316         usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    317         if (*usbcmd & USBCMD_RUN) {
    318                 *usbsts = 0x3f; /* ack all interrupts */
    319                 *usbint = 0; /* disable all interrupts */
    320                 *usbconf = 0; /* release control of RH ports */
    321 
    322                 *usbcmd = 0;
    323                 /* Wait until hc is halted */
    324                 while ((*usbsts & USBSTS_HALTED) == 0);
    325                 usb_log_info("EHCI turned off.\n");
    326         } else {
    327                 usb_log_info("EHCI was not running.\n");
    328         }
    329         usb_log_debug("Registers: \n"
    330             "\t USBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)\n"
    331             "\t USBSTS(%p): %x(0x00001000 = HC halted)\n"
    332             "\t USBINT(%p): %x(0x0 = no interrupts).\n"
    333             "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n",
    334             usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf);
    335 
    336         return rc;
     226                    str_error(ret));
     227                    goto clean;
     228        }
     229clean:
     230        //TODO unmap registers
     231        hw_res_list_parsed_clean(&res);
     232        async_hangup(parent_sess);
     233        return ret;
    337234}
    338235
  • uspace/drv/bus/usb/ehci/res.h

    r5b18137 rb4b534ac  
    3939#include <device/hw_res_parsed.h>
    4040
    41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
    42 int enable_interrupts(ddf_dev_t *);
    43 int disable_legacy(ddf_dev_t *, addr_range_t *);
     41int disable_legacy(ddf_dev_t *);
    4442
    4543#endif
  • uspace/drv/bus/usb/ohci/Makefile

    r5b18137 rb4b534ac  
    3131LIBS = \
    3232        $(LIBUSBHOST_PREFIX)/libusbhost.a \
    33         $(LIBUSBDEV_PREFIX)/libusbdev.a \
     33        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
    3434        $(LIBUSB_PREFIX)/libusb.a \
    3535        $(LIBDRV_PREFIX)/libdrv.a
     
    3939        -I$(LIBUSBDEV_PREFIX)/include \
    4040        -I$(LIBUSBHOST_PREFIX)/include \
     41        -I$(LIBUSBVIRT_PREFIX)/include \
    4142        -I$(LIBDRV_PREFIX)/include
    4243
     
    4748        hc.c \
    4849        main.c \
    49         ohci.c \
    5050        ohci_batch.c \
    5151        ohci_endpoint.c \
    52         res.c \
    53         root_hub.c \
     52        ohci_rh.c \
    5453        hw_struct/endpoint_descriptor.c \
    5554        hw_struct/transfer_descriptor.c
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    r5b18137 rb4b534ac  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
     38#include <libarch/barrier.h>
     39
    3740#include <usb/debug.h>
    38 #include <libarch/barrier.h>
     41#include <usb/host/utils/malloc32.h>
     42
    3943#include "endpoint_list.h"
    4044
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_ENDPOINT_LIST_H
    3636
     37#include <adt/list.h>
     38#include <assert.h>
    3739#include <fibril_synch.h>
     40#include <sys/types.h>
     41#include <usb/host/utils/malloc32.h>
    3842
    3943#include "ohci_endpoint.h"
    4044#include "hw_struct/endpoint_descriptor.h"
    41 #include "utils/malloc32.h"
    4245
    4346/** Structure maintains both OHCI queue and software list of active endpoints.*/
     
    6568        assert(instance);
    6669        free32(instance->list_head);
     70        instance->list_head = NULL;
    6771}
    6872
  • uspace/drv/bus/usb/ohci/hc.c

    r5b18137 rb4b534ac  
    3434 */
    3535
     36#include <assert.h>
     37#include <async.h>
    3638#include <errno.h>
    37 #include <stdbool.h>
     39#include <macros.h>
     40#include <mem.h>
     41#include <stdlib.h>
    3842#include <str_error.h>
    39 #include <adt/list.h>
    40 #include <libarch/ddi.h>
     43#include <sys/types.h>
    4144
    4245#include <usb/debug.h>
    4346#include <usb/usb.h>
    44 #include <usb/ddfiface.h>
     47
     48#include "ohci_endpoint.h"
     49#include "ohci_batch.h"
    4550
    4651#include "hc.h"
    47 #include "ohci_endpoint.h"
    4852
    4953#define OHCI_USED_INTERRUPTS \
     
    8488};
    8589
    86 enum {
    87         /** Number of PIO ranges used in IRQ code */
    88         hc_irq_pio_range_count =
    89             sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),
    90 
    91         /** Number of commands used in IRQ code */
    92         hc_irq_cmd_count =
    93             sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)
    94 };
    95 
    9690static void hc_gain_control(hc_t *instance);
    9791static void hc_start(hc_t *instance);
    9892static int hc_init_transfer_lists(hc_t *instance);
    9993static int hc_init_memory(hc_t *instance);
    100 static int interrupt_emulator(hc_t *instance);
    101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    10294
    10395/** Generate IRQ code.
     
    10698 * @param[out] cmds Commands buffer.
    10799 * @param[in] cmds_size Size of the commands buffer (bytes).
    108  * @param[in] regs Device's register range.
     100 * @param[in] hw_res Device's resources.
    109101 *
    110102 * @return Error code.
    111103 */
    112 int
    113 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
    114     size_t cmds_size, addr_range_t *regs)
    115 {
    116         if ((ranges_size < sizeof(ohci_pio_ranges)) ||
    117             (cmds_size < sizeof(ohci_irq_commands)) ||
    118             (RNGSZ(*regs) < sizeof(ohci_regs_t)))
     104int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     105{
     106        assert(code);
     107        assert(hw_res);
     108
     109        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     110                return EINVAL;
     111
     112        const addr_range_t regs = hw_res->mem_ranges.ranges[0];
     113
     114        if (RNGSZ(regs) < sizeof(ohci_regs_t))
    119115                return EOVERFLOW;
    120116
    121         memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    122         ranges[0].base = RNGABS(*regs);
    123 
    124         memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    125         ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
    126         cmds[0].addr = (void *) &registers->interrupt_status;
    127         cmds[3].addr = (void *) &registers->interrupt_status;
    128         OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
    129 
    130         return EOK;
    131 }
    132 
    133 /** Register interrupt handler.
    134  *
    135  * @param[in] device Host controller DDF device
    136  * @param[in] regs Register range
    137  * @param[in] irq Interrupt number
    138  * @paran[in] handler Interrupt handler
    139  *
    140  * @return EOK on success or negative error code
    141  */
    142 int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,
    143     interrupt_handler_t handler)
    144 {
    145         int rc;
    146 
    147         irq_pio_range_t irq_ranges[hc_irq_pio_range_count];
    148         irq_cmd_t irq_cmds[hc_irq_cmd_count];
    149 
    150         irq_code_t irq_code = {
    151                 .rangecount = hc_irq_pio_range_count,
    152                 .ranges = irq_ranges,
    153                 .cmdcount = hc_irq_cmd_count,
    154                 .cmds = irq_cmds
    155         };
    156 
    157         rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
    158             sizeof(irq_cmds), regs);
    159         if (rc != EOK) {
    160                 usb_log_error("Failed to generate IRQ code: %s.\n",
    161                     str_error(rc));
    162                 return rc;
    163         }
    164 
    165         /* Register handler to avoid interrupt lockup */
    166         rc = register_interrupt_handler(device, irq, handler, &irq_code);
    167         if (rc != EOK) {
    168                 usb_log_error("Failed to register interrupt handler: %s.\n",
    169                     str_error(rc));
    170                 return rc;
    171         }
    172 
    173         return EOK;
    174 }
    175 
    176 /** Announce OHCI root hub to the DDF
    177  *
    178  * @param[in] instance OHCI driver intance
    179  * @param[in] hub_fun DDF fuction representing OHCI root hub
    180  * @return Error code
    181  */
    182 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
    183 {
    184         bool addr_reqd = false;
    185         bool ep_added = false;
    186         bool fun_bound = false;
    187         int rc;
    188 
    189         assert(instance);
    190         assert(hub_fun);
    191 
    192         /* Try to get address 1 for root hub. */
    193         instance->rh.address = 1;
    194         rc = usb_device_manager_request_address(
    195             &instance->generic->dev_manager, &instance->rh.address, false,
    196             USB_SPEED_FULL);
    197         if (rc != EOK) {
    198                 usb_log_error("Failed to get OHCI root hub address: %s\n",
    199                     str_error(rc));
    200                 goto error;
    201         }
    202 
    203         addr_reqd = true;
    204 
    205         rc = usb_endpoint_manager_add_ep(
    206             &instance->generic->ep_manager, instance->rh.address, 0,
    207             USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
    208             0, NULL, NULL);
    209         if (rc != EOK) {
    210                 usb_log_error("Failed to register root hub control endpoint: %s.\n",
    211                     str_error(rc));
    212                 goto error;
    213         }
    214 
    215         ep_added = true;
    216 
    217         rc = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
    218         if (rc != EOK) {
    219                 usb_log_error("Failed to add root hub match-id: %s.\n",
    220                     str_error(rc));
    221                 goto error;
    222         }
    223 
    224         rc = ddf_fun_bind(hub_fun);
    225         if (rc != EOK) {
    226                 usb_log_error("Failed to bind root hub function: %s.\n",
    227                     str_error(rc));
    228                 goto error;
    229         }
    230 
    231         fun_bound = true;
    232 
    233         rc = usb_device_manager_bind_address(&instance->generic->dev_manager,
    234             instance->rh.address, ddf_fun_get_handle(hub_fun));
    235         if (rc != EOK) {
    236                 usb_log_warning("Failed to bind root hub address: %s.\n",
    237                     str_error(rc));
    238         }
    239 
    240         return EOK;
    241 error:
    242         if (fun_bound)
    243                 ddf_fun_unbind(hub_fun);
    244         if (ep_added) {
    245                 usb_endpoint_manager_remove_ep(
    246                     &instance->generic->ep_manager, instance->rh.address, 0,
    247                     USB_DIRECTION_BOTH, NULL, NULL);
    248         }
    249         if (addr_reqd) {
    250                 usb_device_manager_release_address(
    251                     &instance->generic->dev_manager, instance->rh.address);
    252         }
    253         return rc;
     117        code->ranges = malloc(sizeof(ohci_pio_ranges));
     118        if (code->ranges == NULL)
     119                return ENOMEM;
     120
     121        code->cmds = malloc(sizeof(ohci_irq_commands));
     122        if (code->cmds == NULL) {
     123                free(code->ranges);
     124                return ENOMEM;
     125        }
     126
     127        code->rangecount = ARRAY_SIZE(ohci_pio_ranges);
     128        code->cmdcount = ARRAY_SIZE(ohci_irq_commands);
     129
     130        memcpy(code->ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
     131        code->ranges[0].base = RNGABS(regs);
     132
     133        memcpy(code->cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
     134        ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(regs);
     135        code->cmds[0].addr = (void *) &registers->interrupt_status;
     136        code->cmds[3].addr = (void *) &registers->interrupt_status;
     137        OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS);
     138
     139        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     140            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
     141
     142        return hw_res->irqs.irqs[0];
    254143}
    255144
     
    257146 *
    258147 * @param[in] instance Memory place for the structure.
    259  * @param[in] HC function node
    260  * @param[in] regs Device's I/O registers range.
     148 * @param[in] regs Device's resources
    261149 * @param[in] interrupts True if w interrupts should be used
    262150 * @return Error code
    263151 */
    264 int hc_init(hc_t *instance, ddf_fun_t *fun, addr_range_t *regs, bool interrupts)
    265 {
    266         assert(instance);
    267 
    268         int rc = pio_enable_range(regs, (void **) &instance->registers);
    269         if (rc != EOK) {
    270                 usb_log_error("Failed to gain access to device registers: %s.\n",
    271                     str_error(rc));
    272                 return rc;
    273         }
     152int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     153{
     154        assert(instance);
     155        assert(hw_res);
     156        if (hw_res->mem_ranges.count != 1 ||
     157            hw_res->mem_ranges.ranges[0].size < sizeof(ohci_regs_t))
     158            return EINVAL;
     159
     160        int ret = pio_enable_range(&hw_res->mem_ranges.ranges[0],
     161            (void **) &instance->registers);
     162        if (ret != EOK) {
     163                usb_log_error("Failed to gain access to registers: %s.\n",
     164                    str_error(ret));
     165                return ret;
     166        }
     167        usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n",
     168            hw_res->mem_ranges.ranges[0].address.absolute,
     169            hw_res->mem_ranges.ranges[0].size);
    274170
    275171        list_initialize(&instance->pending_batches);
    276 
    277         instance->generic = ddf_fun_data_alloc(fun, sizeof(hcd_t));
    278         if (instance->generic == NULL) {
    279                 usb_log_error("Out of memory.\n");
    280                 return ENOMEM;
    281         }
    282 
    283         hcd_init(instance->generic, USB_SPEED_FULL,
    284             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    285         instance->generic->private_data = instance;
    286         instance->generic->schedule = hc_schedule;
    287         instance->generic->ep_add_hook = ohci_endpoint_init;
    288         instance->generic->ep_remove_hook = ohci_endpoint_fini;
    289 
    290         rc = hc_init_memory(instance);
    291         if (rc != EOK) {
     172        fibril_mutex_initialize(&instance->guard);
     173        instance->hw_interrupts = interrupts;
     174
     175        ret = hc_init_memory(instance);
     176        if (ret != EOK) {
    292177                usb_log_error("Failed to create OHCI memory structures: %s.\n",
    293                     str_error(rc));
    294                 return rc;
    295         }
    296 
    297         fibril_mutex_initialize(&instance->guard);
     178                    str_error(ret));
     179                //TODO: We should disable pio access here
     180                return ret;
     181        }
    298182
    299183        hc_gain_control(instance);
    300184
    301         if (!interrupts) {
    302                 instance->interrupt_emulator =
    303                     fibril_create((int(*)(void*))interrupt_emulator, instance);
    304                 fibril_add_ready(instance->interrupt_emulator);
    305         }
    306 
    307         rh_init(&instance->rh, instance->registers);
     185        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    308186        hc_start(instance);
    309187
    310188        return EOK;
    311189}
     190
     191/** Safely dispose host controller internal structures
     192 *
     193 * @param[in] instance Host controller structure to use.
     194 */
     195void hc_fini(hc_t *instance)
     196{
     197        assert(instance);
     198        /* TODO: implement*/
     199};
    312200
    313201void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     
    379267}
    380268
     269int ohci_hc_status(hcd_t *hcd, uint32_t *status)
     270{
     271        assert(hcd);
     272        assert(status);
     273        hc_t *instance = hcd_get_driver_data(hcd);
     274        assert(instance);
     275
     276        if (instance->registers){
     277                *status = OHCI_RD(instance->registers->interrupt_status);
     278                OHCI_WR(instance->registers->interrupt_status, *status);
     279        }
     280        return EOK;
     281}
     282
    381283/** Add USB transfer to the schedule.
    382284 *
    383  * @param[in] instance OHCI hc driver structure.
     285 * @param[in] hcd HCD driver structure.
    384286 * @param[in] batch Batch representing the transfer.
    385287 * @return Error code.
    386288 */
    387 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     289int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    388290{
    389291        assert(hcd);
    390         hc_t *instance = hcd->private_data;
     292        hc_t *instance = hcd_get_driver_data(hcd);
    391293        assert(instance);
    392294
    393295        /* Check for root hub communication */
    394         if (batch->ep->address == instance->rh.address) {
     296        if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
    395297                usb_log_debug("OHCI root hub request.\n");
    396                 rh_request(&instance->rh, batch);
    397                 return EOK;
     298                return ohci_rh_schedule(&instance->rh, batch);
    398299        }
    399300        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     
    423324/** Interrupt handling routine
    424325 *
    425  * @param[in] instance OHCI hc driver structure.
     326 * @param[in] hcd HCD driver structure.
    426327 * @param[in] status Value of the status register at the time of interrupt.
    427328 */
    428 void hc_interrupt(hc_t *instance, uint32_t status)
    429 {
     329void ohci_hc_interrupt(hcd_t *hcd, uint32_t status)
     330{
     331        assert(hcd);
     332        hc_t *instance = hcd_get_driver_data(hcd);
    430333        status = OHCI_RD(status);
    431334        assert(instance);
     
    434337        usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
    435338        if (status & I_RHSC)
    436                 rh_interrupt(&instance->rh);
     339                ohci_rh_interrupt(&instance->rh);
    437340
    438341        if (status & I_WDH) {
     
    465368        }
    466369
    467 }
    468 
    469 /** Check status register regularly
    470  *
    471  * @param[in] instance OHCI hc driver structure.
    472  * @return Error code
    473  */
    474 int interrupt_emulator(hc_t *instance)
    475 {
    476         assert(instance);
    477         usb_log_info("Started interrupt emulator.\n");
    478         while (1) {
    479                 const uint32_t status = instance->registers->interrupt_status;
    480                 instance->registers->interrupt_status = status;
    481                 hc_interrupt(instance, status);
    482                 async_usleep(10000);
    483         }
    484         return EOK;
    485370}
    486371
     
    508393                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    509394                /* Zero everything but A20State */
     395                //TODO: should we ack interrupts before doing this?
    510396                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    511397                usb_log_debug(
     
    517403        if (OHCI_RD(instance->registers->control) & C_IR) {
    518404                usb_log_debug("SMM driver: request ownership change.\n");
     405                //TODO: should we ack interrupts before doing this?
    519406                OHCI_SET(instance->registers->command_status, CS_OCR);
    520407                /* Hope that SMM actually knows its stuff or we can hang here */
    521                 while (OHCI_RD(instance->registers->control & C_IR)) {
     408                while (OHCI_RD(instance->registers->control) & C_IR) {
    522409                        async_usleep(1000);
    523410                }
     
    603490
    604491        /* Enable interrupts */
    605         OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
    606         usb_log_debug("Enabled interrupts: %x.\n",
    607             OHCI_RD(instance->registers->interrupt_enable));
    608         OHCI_WR(instance->registers->interrupt_enable, I_MI);
     492        if (instance->hw_interrupts) {
     493                OHCI_WR(instance->registers->interrupt_enable,
     494                    OHCI_USED_INTERRUPTS);
     495                usb_log_debug("Enabled interrupts: %x.\n",
     496                    OHCI_RD(instance->registers->interrupt_enable));
     497                OHCI_WR(instance->registers->interrupt_enable, I_MI);
     498        }
    609499
    610500        /* Set periodic start to 90% */
     
    632522do { \
    633523        const char *name = usb_str_transfer_type(type); \
    634         int ret = endpoint_list_init(&instance->lists[type], name); \
     524        const int ret = endpoint_list_init(&instance->lists[type], name); \
    635525        if (ret != EOK) { \
    636526                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
  • uspace/drv/bus/usb/ohci/hc.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HC_H
    3636
     37#include <adt/list.h>
     38#include <ddi.h>
    3739#include <ddf/driver.h>
    38 #include <ddf/interrupt.h>
     40#include <device/hw_res_parsed.h>
    3941#include <fibril.h>
    4042#include <fibril_synch.h>
    41 #include <adt/list.h>
    42 #include <ddi.h>
     43#include <stdbool.h>
     44#include <sys/types.h>
    4345
    44 #include <usb/usb.h>
    4546#include <usb/host/hcd.h>
     47#include <usb/host/endpoint.h>
     48#include <usb/host/usb_transfer_batch.h>
    4649
    47 #include "ohci_batch.h"
    4850#include "ohci_regs.h"
    49 #include "root_hub.h"
     51#include "ohci_rh.h"
    5052#include "endpoint_list.h"
    5153#include "hw_struct/hcca.h"
     
    5355/** Main OHCI driver structure */
    5456typedef struct hc {
    55         /** Generic USB hc driver */
    56         hcd_t *generic;
    57 
    5857        /** Memory mapped I/O registers area */
    5958        ohci_regs_t *registers;
     
    7271        fibril_mutex_t guard;
    7372
     73        /** interrupts available */
     74        bool hw_interrupts;
     75
    7476        /** USB hub emulation structure */
    75         rh_t rh;
     77        ohci_rh_t rh;
    7678} hc_t;
    7779
    78 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t,
    79     addr_range_t *);
    80 int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int,
    81     interrupt_handler_t);
    82 int hc_register_hub(hc_t *, ddf_fun_t *);
    83 int hc_init(hc_t *, ddf_fun_t *, addr_range_t *, bool);
    84 
    85 /** Safely dispose host controller internal structures
    86  *
    87  * @param[in] instance Host controller structure to use.
    88  */
    89 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     80int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts);
     81void hc_fini(hc_t *instance);
    9082
    9183void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
    9284void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    9385
    94 void hc_interrupt(hc_t *instance, uint32_t status);
     86int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     87
     88void ohci_hc_interrupt(hcd_t *hcd, uint32_t status);
     89int ohci_hc_status(hcd_t *hcd, uint32_t *status);
     90int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    9591#endif
    9692/**
  • uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h

    r5b18137 rb4b534ac  
    3737#include <errno.h>
    3838
    39 #define CC_NOERROR (0x0)
    40 #define CC_CRC (0x1)
    41 #define CC_BITSTUFF (0x2)
    42 #define CC_TOGGLE (0x3)
    43 #define CC_STALL (0x4)
    44 #define CC_NORESPONSE (0x5)
    45 #define CC_PIDFAIL (0x6)
    46 #define CC_PIDUNEXPECTED (0x7)
    47 #define CC_DATAOVERRRUN (0x8)
    48 #define CC_DATAUNDERRRUN (0x9)
    49 #define CC_BUFFEROVERRRUN (0xc)
    50 #define CC_BUFFERUNDERRUN (0xd)
    51 #define CC_NOACCESS1 (0xe)
    52 #define CC_NOACCESS2 (0xf)
     39enum {
     40        CC_NOERROR = 0x0,
     41        CC_CRC = 0x1,
     42        CC_BITSTUFF = 0x2,
     43        CC_TOGGLE = 0x3,
     44        CC_STALL = 0x4,
     45        CC_NORESPONSE = 0x5,
     46        CC_PIDFAIL = 0x6,
     47        CC_PIDUNEXPECTED = 0x7,
     48        CC_DATAOVERRRUN = 0x8,
     49        CC_DATAUNDERRRUN = 0x9,
     50        CC_BUFFEROVERRRUN = 0xc,
     51        CC_BUFFERUNDERRUN = 0xd,
     52        CC_NOACCESS1 = 0xe,
     53        CC_NOACCESS2 = 0xf,
     54};
    5355
    54 inline static int cc_to_rc(int cc)
     56inline static unsigned cc_to_rc(unsigned cc)
    5557{
    5658        switch (cc) {
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
     34
     35#include <assert.h>
     36#include <macros.h>
     37#include <mem.h>
     38
     39#include <usb/usb.h>
     40#include <usb/host/utils/malloc32.h>
     41
     42#include "mem_access.h"
     43
    3444#include "endpoint_descriptor.h"
    3545
     
    4858 * @param td TD to put in the list.
    4959 *
    50  * If @param ep is NULL, dummy ED is initalized with only skip flag set.
     60 * If @param ep is NULL, dummy ED is initialized with only skip flag set.
    5161 */
    5262void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td)
    5363{
    5464        assert(instance);
    55         memset(instance, 0, sizeof(ed_t));
     65        memset(instance, 0, sizeof(*instance));
    5666
    5767        if (ep == NULL) {
     
    6171                return;
    6272        }
    63         /* Non-dummy ED must have TD assigned */
     73        /* Non-dummy ED must have corresponding EP and TD assigned */
    6474        assert(td);
     75        assert(ep);
     76        assert(ep->direction < ARRAY_SIZE(dir));
    6577
    6678        /* Status: address, endpoint nr, direction mask and max packet size. */
     
    7789
    7890        /* Isochronous format flag */
     91        // TODO: We need iTD instead of TD for iso transfers
    7992        if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    8093                OHCI_MEM32_SET(instance->status, ED_STATUS_F_FLAG);
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h

    r5b18137 rb4b534ac  
    3636
    3737#include <assert.h>
    38 #include <stdint.h>
     38#include <stdbool.h>
     39#include <sys/types.h>
    3940
    4041#include <usb/host/endpoint.h>
    41 
    42 #include "../utils/malloc32.h"
     42#include <usb/host/utils/malloc32.h>
     43
    4344#include "transfer_descriptor.h"
    4445
  • uspace/drv/bus/usb/ohci/hw_struct/hcca.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_HCCA_H
    3636
    37 #include <stdint.h>
    3837#include <malloc.h>
     38#include <sys/types.h>
     39#include <macros.h>
    3940
    4041#include "mem_access.h"
     
    5051        /** Frame number. */
    5152        uint16_t frame_number;
    52         uint16_t pad1;
     53        PADD16;
    5354        /** Pointer to the last completed TD. (useless) */
    5455        uint32_t done_head;
    5556        /** Padding to make the size 256B */
    56         uint32_t reserved[30];
     57        PADD32[30];
    5758} hcca_t;
     59
     60STATIC_ASSERT(sizeof(hcca_t) == 256);
    5861
    5962/** Allocate properly aligned structure.
     
    6568static inline hcca_t * hcca_get(void)
    6669{
    67         static_assert(sizeof(hcca_t) == 256);
    68         hcca_t *hcca = memalign(256, sizeof(hcca_t));
     70        hcca_t *hcca = memalign(sizeof(hcca_t), sizeof(hcca_t));
    6971        if (hcca)
    7072                memset(hcca, 0, sizeof(hcca_t));
     
    8082{
    8183        assert(hcca);
    82         assert(index < HCCA_INT_EP_COUNT);
     84        assert(index < ARRAY_SIZE(hcca->int_ep));
    8385        OHCI_MEM32_WR(hcca->int_ep[index], pa);
    84 
    8586}
    8687#endif
  • uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
    3636
    37 #include <stdint.h>
     37#include <sys/types.h>
    3838
    3939#include "completion_codes.h"
  • uspace/drv/bus/usb/ohci/hw_struct/mem_access.h

    r5b18137 rb4b534ac  
    4747 * @}
    4848 */
    49 
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
     34
     35#include <assert.h>
     36#include <mem.h>
     37
    3438#include <usb/usb.h>
    35 #include <mem.h>
    36 #include "../utils/malloc32.h"
     39#include <usb/host/utils/malloc32.h>
     40
     41#include "completion_codes.h"
     42#include "mem_access.h"
    3743#include "transfer_descriptor.h"
    3844
     
    7076        }
    7177
    72         /* Alow less data on input. */
     78        /* Allow less data on input. */
    7379        if (dir == USB_DIRECTION_IN) {
    7480                OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG);
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h

    r5b18137 rb4b534ac  
    3535#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
     37#include <assert.h>
    3738#include <stdbool.h>
    3839#include <stdint.h>
  • uspace/drv/bus/usb/ohci/main.c

    r5b18137 rb4b534ac  
    3333 * Main routines of OHCI driver.
    3434 */
     35
     36#include <assert.h>
    3537#include <ddf/driver.h>
    3638#include <errno.h>
     39#include <io/log.h>
    3740#include <str_error.h>
    3841
    3942#include <usb/debug.h>
     43#include <usb/host/ddf_helpers.h>
    4044
    41 #include "ohci.h"
     45#include "hc.h"
    4246
    4347#define NAME "ohci"
     48static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     49static void ohci_driver_fini(hcd_t *);
     50
     51static const ddf_hc_driver_t ohci_hc_driver = {
     52        .hc_speed = USB_SPEED_FULL,
     53        .irq_code_gen = ohci_hc_gen_irq_code,
     54        .init = ohci_driver_init,
     55        .fini = ohci_driver_fini,
     56        .name = "OHCI",
     57        .ops = {
     58                .schedule       = ohci_hc_schedule,
     59                .ep_add_hook    = ohci_endpoint_init,
     60                .ep_remove_hook = ohci_endpoint_fini,
     61                .irq_hook       = ohci_hc_interrupt,
     62                .status_hook    = ohci_hc_status,
     63        },
     64};
     65
     66
     67static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     68{
     69        assert(hcd);
     70        assert(hcd_get_driver_data(hcd) == NULL);
     71
     72        hc_t *instance = malloc(sizeof(hc_t));
     73        if (!instance)
     74                return ENOMEM;
     75
     76        const int ret = hc_init(instance, res, irq);
     77        if (ret == EOK) {
     78                hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops);
     79        } else {
     80                free(instance);
     81        }
     82        return ret;
     83}
     84
     85static void ohci_driver_fini(hcd_t *hcd)
     86{
     87        assert(hcd);
     88        hc_t *hc = hcd_get_driver_data(hcd);
     89        if (hc)
     90                hc_fini(hc);
     91
     92        hcd_set_implementation(hcd, NULL, NULL);
     93        free(hc);
     94}
    4495
    4596/** Initializes a new ddf driver instance of OHCI hcd.
     
    52103        usb_log_debug("ohci_dev_add() called\n");
    53104        assert(device);
    54 
    55         int ret = device_setup_ohci(device);
    56         if (ret != EOK) {
    57                 usb_log_error("Failed to initialize OHCI driver: %s.\n",
    58                     str_error(ret));
    59                 return ret;
    60         }
    61         usb_log_info("Controlling new OHCI device '%s'.\n", ddf_dev_get_name(device));
    62 
    63         return EOK;
     105        return hcd_ddf_add_hc(device, &ohci_hc_driver);
    64106}
    65107
    66 static driver_ops_t ohci_driver_ops = {
     108static const driver_ops_t ohci_driver_ops = {
    67109        .dev_add = ohci_dev_add,
    68110};
    69111
    70 static driver_t ohci_driver = {
     112static const driver_t ohci_driver = {
    71113        .name = NAME,
    72114        .driver_ops = &ohci_driver_ops
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver USB transaction structure
    3333 */
     34
     35#include <assert.h>
    3436#include <errno.h>
    35 #include <str_error.h>
    3637#include <macros.h>
     38#include <mem.h>
     39#include <stdbool.h>
    3740
    3841#include <usb/usb.h>
    3942#include <usb/debug.h>
     43#include <usb/host/utils/malloc32.h>
    4044
    4145#include "ohci_batch.h"
    4246#include "ohci_endpoint.h"
    43 #include "utils/malloc32.h"
    4447
    4548static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t);
     
    9497{
    9598        assert(usb_batch);
    96 #define CHECK_NULL_DISPOSE_RET(ptr, message...) \
    97 if (ptr == NULL) { \
    98         usb_log_error(message); \
    99         ohci_transfer_batch_dispose(ohci_batch); \
    100         return NULL; \
    101 } else (void)0
    10299
    103100        ohci_transfer_batch_t *ohci_batch =
    104101            calloc(1, sizeof(ohci_transfer_batch_t));
    105         CHECK_NULL_DISPOSE_RET(ohci_batch,
    106             "Failed to allocate OHCI batch data.\n");
     102        if (!ohci_batch) {
     103                usb_log_error("Failed to allocate OHCI batch data.");
     104                goto dispose;
     105        }
    107106        link_initialize(&ohci_batch->link);
    108107        ohci_batch->td_count =
     
    116115        /* We need an extra place for TD that was left at ED */
    117116        ohci_batch->tds = calloc(ohci_batch->td_count + 1, sizeof(td_t*));
    118         CHECK_NULL_DISPOSE_RET(ohci_batch->tds,
    119             "Failed to allocate OHCI transfer descriptors.\n");
     117        if (!ohci_batch->tds) {
     118                usb_log_error("Failed to allocate OHCI transfer descriptors.");
     119                goto dispose;
     120        }
    120121
    121122        /* Add TD left over by the previous transfer */
     
    125126        for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
    126127                ohci_batch->tds[i] = malloc32(sizeof(td_t));
    127                 CHECK_NULL_DISPOSE_RET(ohci_batch->tds[i],
    128                     "Failed to allocate TD %d.\n", i );
     128                if (!ohci_batch->tds[i]) {
     129                        usb_log_error("Failed to allocate TD %d.", i);
     130                        goto dispose;
     131                }
    129132        }
    130133
     
    138141                ohci_batch->device_buffer =
    139142                    malloc32(usb_batch->setup_size + usb_batch->buffer_size);
    140                 CHECK_NULL_DISPOSE_RET(ohci_batch->device_buffer,
    141                     "Failed to allocate device accessible buffer.\n");
     143                if (!ohci_batch->device_buffer) {
     144                        usb_log_error("Failed to allocate device buffer");
     145                        goto dispose;
     146                }
    142147                /* Copy setup data */
    143148                memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer,
     
    156161
    157162        return ohci_batch;
    158 #undef CHECK_NULL_DISPOSE_RET
     163dispose:
     164        ohci_transfer_batch_dispose(ohci_batch);
     165        return NULL;
    159166}
    160167
  • uspace/drv/bus/usb/ohci/ohci_batch.h

    r5b18137 rb4b534ac  
    3636
    3737#include <adt/list.h>
    38 #include <usbhc_iface.h>
    39 #include <usb/usb.h>
     38#include <assert.h>
     39#include <stdbool.h>
    4040#include <usb/host/usb_transfer_batch.h>
    4141
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    r5b18137 rb4b534ac  
    3232 * @brief OHCI driver
    3333 */
    34 #include "utils/malloc32.h"
     34
     35#include <assert.h>
     36#include <stdlib.h>
     37#include <usb/host/utils/malloc32.h>
     38
    3539#include "ohci_endpoint.h"
    3640#include "hc.h"
     
    8791        }
    8892
     93        link_initialize(&ohci_ep->link);
    8994        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    9095        endpoint_set_hc_data(
    9196            ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set);
    92         hc_enqueue_endpoint(hcd->private_data, ep);
     97        hc_enqueue_endpoint(hcd_get_driver_data(hcd), ep);
    9398        return EOK;
    9499}
     
    104109        assert(ep);
    105110        ohci_endpoint_t *instance = ohci_endpoint_get(ep);
    106         hc_dequeue_endpoint(hcd->private_data, ep);
     111        hc_dequeue_endpoint(hcd_get_driver_data(hcd), ep);
     112        endpoint_clear_hc_data(ep);
    107113        if (instance) {
    108114                free32(instance->ed);
     
    110116                free(instance);
    111117        }
    112         endpoint_clear_hc_data(ep);
    113118}
    114119/**
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r5b18137 rb4b534ac  
    3434#ifndef DRV_OHCI_OHCI_REGS_H
    3535#define DRV_OHCI_OHCI_REGS_H
     36#include <ddi.h>
    3637#include <sys/types.h>
    3738#include <byteorder.h>
    3839
    39 #define OHCI_WR(reg, val) reg = host2uint32_t_le(val)
    40 #define OHCI_RD(reg) uint32_t_le2host(reg)
    41 #define OHCI_SET(reg, val) reg |= host2uint32_t_le(val)
    42 #define OHCI_CLR(reg, val) reg &= host2uint32_t_le(~val)
    43 
     40#define OHCI_WR(reg, val) pio_write_32(&(reg), host2uint32_t_le(val))
     41#define OHCI_RD(reg) uint32_t_le2host(pio_read_32(&(reg)))
     42#define OHCI_SET(reg, val) pio_set_32(&(reg), host2uint32_t_le(val), 1)
     43#define OHCI_CLR(reg, val) pio_clear_32(&(reg), host2uint32_t_le(val), 1)
    4444
    4545#define LEGACY_REGS_OFFSET 0x100
     
    215215        /** Root hub per port status */
    216216        ioport32_t rh_port_status[];
    217 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
     217#define RHPS_CCS_FLAG (1 << 0)                /* r: current connect status,
    218218                                               * w: 1-clear port enable, 0-N/S*/
    219219#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
    220 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status
     220#define RHPS_PES_FLAG (1 << 1)               /* r: port enable status
    221221                                              * w: 1-set port enable, 0-N/S */
    222222#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
    223 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
     223#define RHPS_PSS_FLAG (1 << 2)                /* r: port suspend status
    224224                                               * w: 1-set port suspend, 0-N/S */
    225225#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
    226 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current
     226#define RHPS_POCI_FLAG (1 << 3)                /* r: port over-current
    227227                                                * (if reports are per-port
    228228                                                * w: 1-clear port suspend
     
    230230                                                *    0-nothing */
    231231#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
    232 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
     232#define RHPS_PRS_FLAG (1 << 4)                /* r: port reset status
    233233                                               * w: 1-set port reset, 0-N/S */
    234234#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
    235 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status
     235#define RHPS_PPS_FLAG (1 << 8)               /* r: port power status
    236236                                              * w: 1-set port power, 0-N/S */
    237237#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
    238 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
     238#define RHPS_LSDA_FLAG (1 << 9)                /* r: low speed device attached
    239239                                                * w: 1-clear port power, 0-N/S*/
    240240#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
  • uspace/drv/bus/usb/ohci/ohci_rh.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3232 * @brief OHCI driver
    3333 */
    34 #ifndef DRV_OHCI_ROOT_HUB_H
    35 #define DRV_OHCI_ROOT_HUB_H
     34#ifndef DRV_OHCI_OHCI_RH_H
     35#define DRV_OHCI_OHCI_RH_H
     36
     37#include <assert.h>
     38#include <sys/types.h>
    3639
    3740#include <usb/usb.h>
    38 #include <usb/dev/driver.h>
     41#include <usb/classes/hub.h>
    3942#include <usb/host/usb_transfer_batch.h>
     43#include <usbvirt/virthub_base.h>
    4044
    4145#include "ohci_regs.h"
    4246
    43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
     47enum {
     48        OHCI_MAX_PORTS = 15,
     49};
    4450
    45 /**
    46  * ohci root hub representation
    47  */
    48 typedef struct rh {
    49         fibril_mutex_t guard;
    50         /** pointer to ohci driver registers */
     51typedef struct {
     52        /** Virtual hub instance */
     53        virthub_base_t base;
     54        /** OHCI device registers */
    5155        ohci_regs_t *registers;
    52         /** usb address of the root hub */
    53         usb_address_t address;
    54         /** hub port count */
    55         size_t port_count;
     56        /** Number of downstream ports, OHCI limits this to 15 */
     57        unsigned port_count;
     58        /** USB hub descriptor describing the OHCI root hub */
     59        struct {
     60                usb_hub_descriptor_header_t header;
     61                uint8_t rempow[STATUS_BYTES(OHCI_MAX_PORTS) * 2];
     62        } __attribute__((packed)) hub_descriptor;
    5663        /** interrupt transfer waiting for an actual interrupt to occur */
    5764        usb_transfer_batch_t *unfinished_interrupt_transfer;
    58         /** size of interrupt buffer */
    59         size_t interrupt_mask_size;
    60         /** Descriptors */
    61         struct {
    62                 usb_standard_configuration_descriptor_t configuration;
    63                 usb_standard_interface_descriptor_t interface;
    64                 usb_standard_endpoint_descriptor_t endpoint;
    65                 uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE];
    66         } __attribute__ ((packed)) descriptors;
    67         /** size of hub descriptor */
    68         size_t hub_descriptor_size;
    69 } rh_t;
     65} ohci_rh_t;
    7066
    71 void rh_init(rh_t *instance, ohci_regs_t *regs);
     67int ohci_rh_init(ohci_rh_t *instance, ohci_regs_t *regs, const char *name);
     68int ohci_rh_schedule(ohci_rh_t *instance, usb_transfer_batch_t *batch);
     69int ohci_rh_interrupt(ohci_rh_t *instance);
    7270
    73 void rh_request(rh_t *instance, usb_transfer_batch_t *request);
    74 
    75 void rh_interrupt(rh_t *instance);
     71/** Get OHCI rh address.
     72 *
     73 * @param instance UHCI rh instance.
     74 * @return USB address assigned to the hub.
     75 * Wrapper for virtual hub address
     76 */
     77static inline usb_address_t ohci_rh_get_address(ohci_rh_t *instance)
     78{
     79        assert(instance);
     80        return virthub_base_get_address(&instance->base);
     81}
    7682#endif
    7783/**
  • uspace/drv/bus/usb/uhci/Makefile

    r5b18137 rb4b534ac  
    3131LIBS = \
    3232        $(LIBUSBHOST_PREFIX)/libusbhost.a \
     33        $(LIBUSBVIRT_PREFIX)/libusbvirt.a \
    3334        $(LIBUSB_PREFIX)/libusb.a \
    3435        $(LIBDRV_PREFIX)/libdrv.a
     
    3637EXTRA_CFLAGS += \
    3738        -I$(LIBUSB_PREFIX)/include \
     39        -I$(LIBUSBDEV_PREFIX)/include \
    3840        -I$(LIBUSBHOST_PREFIX)/include \
     41        -I$(LIBUSBVIRT_PREFIX)/include \
    3942        -I$(LIBDRV_PREFIX)/include
    4043
     
    4447        hc.c \
    4548        main.c \
    46         res.c \
    47         root_hub.c \
    4849        transfer_list.c \
    49         uhci.c \
    5050        uhci_batch.c \
     51        uhci_rh.c \
    5152        hw_struct/transfer_descriptor.c
    5253
  • uspace/drv/bus/usb/uhci/hc.c

    r5b18137 rb4b534ac  
    3232 * @brief UHCI Host controller driver routines
    3333 */
     34
     35#include <adt/list.h>
     36#include <assert.h>
     37#include <async.h>
     38#include <ddi.h>
     39#include <device/hw_res_parsed.h>
     40#include <fibril.h>
    3441#include <errno.h>
     42#include <macros.h>
     43#include <mem.h>
     44#include <stdlib.h>
    3545#include <str_error.h>
    36 #include <adt/list.h>
    37 #include <ddi.h>
     46#include <sys/types.h>
    3847
    3948#include <usb/debug.h>
    4049#include <usb/usb.h>
    41 
     50#include <usb/host/utils/malloc32.h>
     51
     52#include "uhci_batch.h"
    4253#include "hc.h"
    43 #include "uhci_batch.h"
    4454
    4555#define UHCI_INTR_ALLOW_INTERRUPTS \
     
    8595static int hc_init_mem_structures(hc_t *instance);
    8696static int hc_init_transfer_lists(hc_t *instance);
    87 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    88 
    89 static int hc_interrupt_emulator(void *arg);
     97
    9098static int hc_debug_checker(void *arg);
    9199
    92 enum {
    93         /** Number of PIO ranges used in IRQ code */
    94         hc_irq_pio_range_count =
    95             sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t),
    96 
    97         /* Number of commands used in IRQ code */
    98         hc_irq_cmd_count =
    99             sizeof(uhci_irq_commands) / sizeof(irq_cmd_t)
    100 };
    101100
    102101/** Generate IRQ code.
    103  * @param[out] ranges PIO ranges buffer.
    104  * @param[in] ranges_size Size of the ranges buffer (bytes).
    105  * @param[out] cmds Commands buffer.
    106  * @param[in] cmds_size Size of the commands buffer (bytes).
    107  * @param[in] regs Device's register range.
     102 * @param[out] code IRQ code structure.
     103 * @param[in] hw_res Device's resources.
    108104 *
    109105 * @return Error code.
    110106 */
    111 int
    112 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
    113     size_t cmds_size, addr_range_t *regs)
    114 {
    115         if ((ranges_size < sizeof(uhci_irq_pio_ranges)) ||
    116             (cmds_size < sizeof(uhci_irq_commands)) ||
    117             (RNGSZ(*regs) < sizeof(uhci_regs_t)))
     107int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     108{
     109        assert(code);
     110        assert(hw_res);
     111
     112        if (hw_res->irqs.count != 1 || hw_res->io_ranges.count != 1)
     113                return EINVAL;
     114        const addr_range_t regs = hw_res->io_ranges.ranges[0];
     115
     116        if (RNGSZ(regs) < sizeof(uhci_regs_t))
    118117                return EOVERFLOW;
    119118
    120         memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges));
    121         ranges[0].base = RNGABS(*regs);
    122 
    123         memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
    124         uhci_regs_t *registers = (uhci_regs_t *) RNGABSPTR(*regs);
    125         cmds[0].addr = (void *) &registers->usbsts;
    126         cmds[3].addr = (void *) &registers->usbsts;
    127 
    128         return EOK;
    129 }
    130 
    131 /** Register interrupt handler.
    132  *
    133  * @param[in] device Host controller DDF device
    134  * @param[in] regs Register range
    135  * @param[in] irq Interrupt number
    136  * @paran[in] handler Interrupt handler
    137  *
    138  * @return EOK on success or negative error code
    139  */
    140 int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,
    141     interrupt_handler_t handler)
    142 {
    143         int rc;
    144         irq_pio_range_t irq_ranges[hc_irq_pio_range_count];
    145         irq_cmd_t irq_cmds[hc_irq_cmd_count];
    146         rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
    147             sizeof(irq_cmds), regs);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed to generate IRQ commands: %s.\n",
    150                     str_error(rc));
    151                 return rc;
    152         }
    153        
    154         irq_code_t irq_code = {
    155                 .rangecount = hc_irq_pio_range_count,
    156                 .ranges = irq_ranges,
    157                 .cmdcount = hc_irq_cmd_count,
    158                 .cmds = irq_cmds
    159         };
    160        
    161         /* Register handler to avoid interrupt lockup */
    162         rc = register_interrupt_handler(device, irq, handler, &irq_code);
    163         if (rc != EOK) {
    164                 usb_log_error("Failed to register interrupt handler: %s.\n",
    165                     str_error(rc));
    166                 return rc;
    167         }
    168        
    169         return EOK;
     119        code->ranges = malloc(sizeof(uhci_irq_pio_ranges));
     120        if (code->ranges == NULL)
     121                return ENOMEM;
     122
     123        code->cmds = malloc(sizeof(uhci_irq_commands));
     124        if (code->cmds == NULL) {
     125                free(code->ranges);
     126                return ENOMEM;
     127        }
     128
     129        code->rangecount = ARRAY_SIZE(uhci_irq_pio_ranges);
     130        code->cmdcount = ARRAY_SIZE(uhci_irq_commands);
     131
     132        memcpy(code->ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges));
     133        code->ranges[0].base = RNGABS(regs);
     134
     135        memcpy(code->cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
     136        uhci_regs_t *registers = (uhci_regs_t *) RNGABSPTR(regs);
     137        code->cmds[0].addr = (void*)&registers->usbsts;
     138        code->cmds[3].addr = (void*)&registers->usbsts;
     139
     140        usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n",
     141            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
     142
     143        return hw_res->irqs.irqs[0];
    170144}
    171145
    172146/** Take action based on the interrupt cause.
    173147 *
    174  * @param[in] instance UHCI structure to use.
     148 * @param[in] hcd HCD structure to use.
    175149 * @param[in] status Value of the status register at the time of interrupt.
    176150 *
     
    180154 * - resume from suspend state (not implemented)
    181155 */
    182 void hc_interrupt(hc_t *instance, uint16_t status)
    183 {
     156void uhci_hc_interrupt(hcd_t *hcd, uint32_t status)
     157{
     158        assert(hcd);
     159        hc_t *instance = hcd_get_driver_data(hcd);
    184160        assert(instance);
    185161        /* Lower 2 bits are transaction error and transaction complete */
     
    195171                    &instance->transfers_bulk_full, &done);
    196172
    197                 while (!list_empty(&done)) {
    198                         link_t *item = list_first(&done);
    199                         list_remove(item);
     173                list_foreach_safe(done, current, next) {
     174                        list_remove(current);
    200175                        uhci_transfer_batch_t *batch =
    201                             uhci_transfer_batch_from_link(item);
     176                            uhci_transfer_batch_from_link(current);
    202177                        uhci_transfer_batch_finish_dispose(batch);
    203178                }
     
    230205 *
    231206 * @param[in] instance Memory place to initialize.
    232  * @param[in] HC function node
    233207 * @param[in] regs Range of device's I/O control registers.
    234208 * @param[in] interrupts True if hw interrupts should be used.
     
    239213 * interrupt fibrils.
    240214 */
    241 int hc_init(hc_t *instance, ddf_fun_t *fun, addr_range_t *regs, bool interrupts)
    242 {
    243         assert(regs->size >= sizeof(uhci_regs_t));
    244         int rc;
     215int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     216{
     217        assert(instance);
     218        assert(hw_res);
     219        if (hw_res->io_ranges.count != 1 ||
     220            hw_res->io_ranges.ranges[0].size < sizeof(uhci_regs_t))
     221            return EINVAL;
    245222
    246223        instance->hw_interrupts = interrupts;
     
    248225
    249226        /* allow access to hc control registers */
    250         uhci_regs_t *io;
    251         rc = pio_enable_range(regs, (void **) &io);
    252         if (rc != EOK) {
    253                 usb_log_error("Failed to gain access to registers at %p: %s.\n",
    254                     io, str_error(rc));
    255                 return rc;
    256         }
    257 
    258         instance->registers = io;
    259         usb_log_debug(
    260             "Device registers at %p (%zuB) accessible.\n", io, regs->size);
    261 
    262         rc = hc_init_mem_structures(instance);
    263         if (rc != EOK) {
    264                 usb_log_error("Failed to initialize UHCI memory structures: %s.\n",
    265                     str_error(rc));
    266                 return rc;
    267         }
    268 
    269         instance->generic = ddf_fun_data_alloc(fun, sizeof(hcd_t));
    270         if (instance->generic == NULL) {
    271                 usb_log_error("Out of memory.\n");
    272                 return ENOMEM;
    273         }
    274 
    275         hcd_init(instance->generic, USB_SPEED_FULL,
    276             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    277 
    278         instance->generic->private_data = instance;
    279         instance->generic->schedule = hc_schedule;
    280         instance->generic->ep_add_hook = NULL;
     227        int ret = pio_enable_range(&hw_res->io_ranges.ranges[0],
     228            (void **) &instance->registers);
     229        if (ret != EOK) {
     230                usb_log_error("Failed to gain access to registers: %s.\n",
     231                    str_error(ret));
     232                return ret;
     233        }
     234
     235        usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n",
     236            hw_res->io_ranges.ranges[0].address.absolute,
     237            hw_res->io_ranges.ranges[0].size);
     238
     239        ret = hc_init_mem_structures(instance);
     240        if (ret != EOK) {
     241                usb_log_error("Failed to init UHCI memory structures: %s.\n",
     242                    str_error(ret));
     243                // TODO: we should disable pio here
     244                return ret;
     245        }
    281246
    282247        hc_init_hw(instance);
    283         if (!interrupts) {
    284                 instance->interrupt_emulator =
    285                     fibril_create(hc_interrupt_emulator, instance);
    286                 fibril_add_ready(instance->interrupt_emulator);
    287         }
    288248        (void)hc_debug_checker;
    289249
     250        uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
     251
    290252        return EOK;
     253}
     254
     255/** Safely dispose host controller internal structures
     256 *
     257 * @param[in] instance Host controller structure to use.
     258 */
     259void hc_fini(hc_t *instance)
     260{
     261        assert(instance);
     262        //TODO Implement
    291263}
    292264
     
    432404        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
    433405          &instance->transfers_bulk_full;
    434         instance->transfers[USB_SPEED_LOW][USB_TRANSFER_BULK] =
    435           &instance->transfers_bulk_full;
    436 
     406
     407        return EOK;
     408}
     409
     410int uhci_hc_status(hcd_t *hcd, uint32_t *status)
     411{
     412        assert(hcd);
     413        assert(status);
     414        hc_t *instance = hcd_get_driver_data(hcd);
     415        assert(instance);
     416
     417        *status = 0;
     418        if (instance->registers) {
     419                uint16_t s = pio_read_16(&instance->registers->usbsts);
     420                pio_write_16(&instance->registers->usbsts, s);
     421                *status = s;
     422        }
    437423        return EOK;
    438424}
     
    446432 * Checks for bandwidth availability and appends the batch to the proper queue.
    447433 */
    448 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     434int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    449435{
    450436        assert(hcd);
    451         hc_t *instance = hcd->private_data;
     437        hc_t *instance = hcd_get_driver_data(hcd);
    452438        assert(instance);
    453439        assert(batch);
     440
     441        if (batch->ep->address == uhci_rh_get_address(&instance->rh))
     442                return uhci_rh_schedule(&instance->rh, batch);
     443
    454444        uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
    455445        if (!uhci_batch) {
     
    463453        transfer_list_add_batch(list, uhci_batch);
    464454
    465         return EOK;
    466 }
    467 
    468 /** Polling function, emulates interrupts.
    469  *
    470  * @param[in] arg UHCI hc structure to use.
    471  * @return EOK (should never return)
    472  */
    473 int hc_interrupt_emulator(void* arg)
    474 {
    475         usb_log_debug("Started interrupt emulator.\n");
    476         hc_t *instance = arg;
    477         assert(instance);
    478 
    479         while (1) {
    480                 /* Read and clear status register */
    481                 uint16_t status = pio_read_16(&instance->registers->usbsts);
    482                 pio_write_16(&instance->registers->usbsts, status);
    483                 if (status != 0)
    484                         usb_log_debug2("UHCI status: %x.\n", status);
    485                 hc_interrupt(instance, status);
    486                 async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
    487         }
    488455        return EOK;
    489456}
  • uspace/drv/bus/usb/uhci/hc.h

    r5b18137 rb4b534ac  
    3636#define DRV_UHCI_HC_H
    3737
    38 #include <ddf/driver.h>
    39 #include <ddf/interrupt.h>
    4038#include <device/hw_res_parsed.h>
    4139#include <fibril.h>
     40#include <macros.h>
     41#include <stdbool.h>
     42#include <sys/types.h>
    4243#include <usb/host/hcd.h>
     44#include <usb/host/usb_transfer_batch.h>
    4345
     46#include "uhci_rh.h"
    4447#include "transfer_list.h"
     48#include "hw_struct/link_pointer.h"
    4549
    4650/** UHCI I/O registers layout */
     
    8387        /** SOF modification to match external timers */
    8488        ioport8_t sofmod;
     89
     90        PADD8[3];
     91        ioport16_t ports[];
    8592} uhci_regs_t;
    8693
    8794#define UHCI_FRAME_LIST_COUNT 1024
    88 #define UHCI_INT_EMULATOR_TIMEOUT 10000
    8995#define UHCI_DEBUGER_TIMEOUT 5000000
    9096#define UHCI_ALLOWED_HW_FAIL 5
    91 #define UHCI_NEEDED_IRQ_COMMANDS 5
    9297
    9398/** Main UHCI driver structure */
    9499typedef struct hc {
    95         /** Generic HCD driver structure */
    96         hcd_t *generic;
    97 
     100        uhci_rh_t rh;
    98101        /** Addresses of I/O registers */
    99102        uhci_regs_t *registers;
     
    113116        /** Pointer table to the above lists, helps during scheduling */
    114117        transfer_list_t *transfers[2][4];
    115         /** Fibril periodically checking status register*/
    116         fid_t interrupt_emulator;
    117118        /** Indicator of hw interrupts availability */
    118119        bool hw_interrupts;
     
    122123} hc_t;
    123124
    124 int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int,
    125     interrupt_handler_t);
    126 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t,
    127     addr_range_t *);
    128 void hc_interrupt(hc_t *instance, uint16_t status);
    129 int hc_init(hc_t *, ddf_fun_t *, addr_range_t *, bool);
     125int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interupts);
     126void hc_fini(hc_t *instance);
    130127
    131 /** Safely dispose host controller internal structures
    132  *
    133  * @param[in] instance Host controller structure to use.
    134  */
    135 static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/
     128int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     129
     130void uhci_hc_interrupt(hcd_t *hcd, uint32_t status);
     131int uhci_hc_status(hcd_t *hcd, uint32_t *status);
     132int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     133
    136134#endif
    137135
  • uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h

    r5b18137 rb4b534ac  
    3535#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
    3636
     37#include <sys/types.h>
     38
    3739/** UHCI link pointer, used by many data structures */
    3840typedef uint32_t link_pointer_t;
  • uspace/drv/bus/usb/uhci/hw_struct/queue_head.h

    r5b18137 rb4b534ac  
    3434#ifndef DRV_UHCI_HW_STRUCT_QH_H
    3535#define DRV_UHCI_HW_STRUCT_QH_H
     36
    3637#include <assert.h>
     38#include <sys/types.h>
     39#include <usb/host/utils/malloc32.h>
    3740
    3841#include "link_pointer.h"
    3942#include "transfer_descriptor.h"
    40 #include "../utils/malloc32.h"
    4143
    4244/** This structure is defined in UHCI design guide p. 31 */
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c

    r5b18137 rb4b534ac  
    3232 * @brief UHCI driver
    3333 */
     34
     35#include <assert.h>
    3436#include <errno.h>
     37
    3538#include <usb/debug.h>
     39#include <usb/usb.h>
     40#include <usb/host/utils/malloc32.h>
    3641
     42#include "link_pointer.h"
    3743#include "transfer_descriptor.h"
    38 #include "../utils/malloc32.h"
    3944
    4045/** Initialize Transfer Descriptor
  • uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h

    r5b18137 rb4b534ac  
    3535#define DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
    37 #include <mem.h>
     37#include <assert.h>
    3838#include <usb/usb.h>
     39#include <stdbool.h>
     40#include <sys/types.h>
    3941
    4042#include "link_pointer.h"
  • uspace/drv/bus/usb/uhci/main.c

    r5b18137 rb4b534ac  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup drvusbuhci
    2929 * @{
    3030 */
     
    3232 * @brief UHCI driver initialization
    3333 */
     34
     35#include <assert.h>
    3436#include <ddf/driver.h>
     37#include <devman.h>
    3538#include <errno.h>
     39#include <io/log.h>
     40#include <io/logctl.h>
     41#include <pci_dev_iface.h>
     42#include <stdio.h>
    3643#include <str_error.h>
     44#include <usb/debug.h>
     45#include <usb/host/ddf_helpers.h>
    3746
    38 #include <usb/ddfiface.h>
    39 #include <usb/debug.h>
    40 
    41 #include "uhci.h"
     47#include "hc.h"
    4248
    4349#define NAME "uhci"
    4450
    45 static int uhci_dev_add(ddf_dev_t *device);
     51static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     52static void uhci_driver_fini(hcd_t *);
     53static int disable_legacy(ddf_dev_t *);
    4654
    47 static driver_ops_t uhci_driver_ops = {
    48         .dev_add = uhci_dev_add,
     55static const ddf_hc_driver_t uhci_hc_driver = {
     56        .claim = disable_legacy,
     57        .hc_speed = USB_SPEED_FULL,
     58        .irq_code_gen = uhci_hc_gen_irq_code,
     59        .init = uhci_driver_init,
     60        .fini = uhci_driver_fini,
     61        .name = "UHCI",
     62        .ops = {
     63                .schedule    = uhci_hc_schedule,
     64                .irq_hook    = uhci_hc_interrupt,
     65                .status_hook = uhci_hc_status,
     66        },
    4967};
    5068
    51 static driver_t uhci_driver = {
    52         .name = NAME,
    53         .driver_ops = &uhci_driver_ops
    54 };
     69static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     70{
     71        assert(hcd);
     72        assert(hcd_get_driver_data(hcd) == NULL);
     73
     74        hc_t *instance = malloc(sizeof(hc_t));
     75        if (!instance)
     76                return ENOMEM;
     77
     78        const int ret = hc_init(instance, res, irq);
     79        if (ret == EOK) {
     80                hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops);
     81        } else {
     82                free(instance);
     83        }
     84        return ret;
     85}
     86
     87static void uhci_driver_fini(hcd_t *hcd)
     88{
     89        assert(hcd);
     90        hc_t *hc = hcd_get_driver_data(hcd);
     91        if (hc)
     92                hc_fini(hc);
     93
     94        hcd_set_implementation(hcd, NULL, NULL);
     95        free(hc);
     96}
     97
     98/** Call the PCI driver with a request to clear legacy support register
     99 *
     100 * @param[in] device Device asking to disable interrupts
     101 * @return Error code.
     102 */
     103static int disable_legacy(ddf_dev_t *device)
     104{
     105        assert(device);
     106
     107        async_sess_t *parent_sess = devman_parent_device_connect(
     108            ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
     109        if (!parent_sess)
     110                return ENOMEM;
     111
     112        /* See UHCI design guide page 45 for these values.
     113         * Write all WC bits in USB legacy register */
     114        const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
     115
     116        async_hangup(parent_sess);
     117        return rc;
     118}
    55119
    56120/** Initialize a new ddf driver instance for uhci hc and hub.
     
    59123 * @return Error code.
    60124 */
    61 int uhci_dev_add(ddf_dev_t *device)
     125static int uhci_dev_add(ddf_dev_t *device)
    62126{
    63127        usb_log_debug2("uhci_dev_add() called\n");
    64128        assert(device);
     129        return hcd_ddf_add_hc(device, &uhci_hc_driver);
     130}
    65131
    66         const int ret = device_setup_uhci(device);
    67         if (ret != EOK) {
    68                 usb_log_error("Failed to initialize UHCI driver: %s.\n",
    69                     str_error(ret));
    70         } else {
    71                 usb_log_info("Controlling new UHCI device '%s'.\n",
    72                     ddf_dev_get_name(device));
    73         }
     132static const driver_ops_t uhci_driver_ops = {
     133        .dev_add = uhci_dev_add,
     134};
    74135
    75         return ret;
    76 }
     136static const driver_t uhci_driver = {
     137        .name = NAME,
     138        .driver_ops = &uhci_driver_ops
     139};
     140
    77141
    78142/** Initialize global driver structures (NONE).
     
    88152        printf(NAME ": HelenOS UHCI driver.\n");
    89153        log_init(NAME);
    90 
     154        logctl_set_log_level(NAME, LVL_NOTE);
    91155        return ddf_driver_main(&uhci_driver);
    92156}
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r5b18137 rb4b534ac  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
     38#include <libarch/barrier.h>
     39#include <sys/types.h>
    3740#include <usb/debug.h>
    38 #include <libarch/barrier.h>
    39 
     41#include <usb/host/usb_transfer_batch.h>
     42#include <usb/host/utils/malloc32.h>
     43
     44#include "hw_struct/link_pointer.h"
    4045#include "transfer_list.h"
    4146
  • uspace/drv/bus/usb/uhci/transfer_list.h

    r5b18137 rb4b534ac  
    3535#define DRV_UHCI_TRANSFER_LIST_H
    3636
     37#include <adt/list.h>
    3738#include <fibril_synch.h>
    3839
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r5b18137 rb4b534ac  
    3232 * @brief UHCI driver USB transfer structure
    3333 */
     34
     35#include <assert.h>
    3436#include <errno.h>
    35 #include <str_error.h>
    3637#include <macros.h>
     38#include <mem.h>
     39#include <stdlib.h>
    3740
    3841#include <usb/usb.h>
    3942#include <usb/debug.h>
     43#include <usb/host/endpoint.h>
     44#include <usb/host/utils/malloc32.h>
    4045
    4146#include "uhci_batch.h"
    42 #include "transfer_list.h"
    4347#include "hw_struct/transfer_descriptor.h"
    44 #include "utils/malloc32.h"
    4548
    4649#define DEFAULT_ERROR_COUNT 3
     
    6770        assert(uhci_batch);
    6871        assert(uhci_batch->usb_batch);
     72        assert(!link_in_use(&uhci_batch->link));
    6973        usb_transfer_batch_finish(uhci_batch->usb_batch,
    7074            uhci_transfer_batch_data_buffer(uhci_batch));
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    r5b18137 rb4b534ac  
    3535#define DRV_UHCI_BATCH_H
    3636
     37#include <adt/list.h>
     38#include <assert.h>
     39#include <errno.h>
     40#include <stdbool.h>
     41#include <sys/types.h>
    3742#include <usb/host/usb_transfer_batch.h>
    38 #include <adt/list.h>
    3943
    4044#include "hw_struct/queue_head.h"
  • uspace/drv/bus/usb/uhci/uhci_rh.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief UHCI host controller driver structure
    3434 */
    35 #ifndef DRV_UHCI_RH_H
    36 #define DRV_UHCI_RH_H
     35#ifndef DRV_UHCI_UHCI_RH_H
     36#define DRV_UHCI_UHCI_RH_H
    3737
    38 #include <ddf/driver.h>
    39 #include <ops/hw_res.h>
    40 #include <ops/pio_window.h>
     38#include <usbvirt/virthub_base.h>
     39#include <usb/host/usb_transfer_batch.h>
     40#include <usb/usb.h>
    4141
    42 /** DDF support structure for uhci_rhd driver, provides I/O resources */
    43 typedef struct rh {
    44         /** List of resources available to the root hub. */
    45         hw_resource_list_t resource_list;
    46         /** The only resource in the RH resource list */
    47         hw_resource_t io_regs;
    48         /** PIO window in which the RH will operate. */
    49         pio_window_t pio_window;       
    50 } rh_t;
     42#include <stdbool.h>
     43#include <sys/types.h>
    5144
    52 extern int rh_init(rh_t *, ddf_fun_t *, addr_range_t *, uintptr_t, size_t);
     45/** Endpoint number for status change pipe. */
     46#define HUB_STATUS_CHANGE_PIPE   1
     47
     48/** Virtual to UHCI hub connector */
     49typedef struct {
     50        /** Virtual hub software implementation */
     51        virthub_base_t base;
     52        /** UHCI root hub port io registers */
     53        ioport16_t *ports[2];
     54        /** Reset change indicator, it is not reported by regs */
     55        bool reset_changed[2];
     56} uhci_rh_t;
     57
     58int uhci_rh_init(uhci_rh_t *instance, ioport16_t *ports, const char *name);
     59int uhci_rh_schedule(uhci_rh_t *instance, usb_transfer_batch_t *batch);
     60
     61/** Get UHCI rh address.
     62 *
     63 * @param instance UHCI rh instance.
     64 * @return USB address assigned to the hub.
     65 * Wrapper for virtual hub address
     66 */
     67static inline usb_address_t uhci_rh_get_address(uhci_rh_t *instance)
     68{
     69        return virthub_base_get_address(&instance->base);
     70}
    5371
    5472#endif
  • uspace/drv/bus/usb/usbflbk/main.c

    r5b18137 rb4b534ac  
    4848static int usbfallback_device_add(usb_device_t *dev)
    4949{
    50         int rc;
    51         const char *fun_name = "ctl";
    52 
    53         ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    54             fun_name);
    55         if (ctl_fun == NULL) {
    56                 usb_log_error("Failed to create control function.\n");
    57                 return ENOMEM;
    58         }
    59         rc = ddf_fun_bind(ctl_fun);
    60         if (rc != EOK) {
    61                 usb_log_error("Failed to bind control function: %s.\n",
    62                     str_error(rc));
    63                 return rc;
    64         }
    65 
    66         dev->driver_data = ctl_fun;
    67 
    68         usb_log_info("Pretending to control %s `%s'" \
    69             " (node `%s', handle %" PRIun ").\n",
    70             dev->interface_no < 0 ? "device" : "interface",
    71             ddf_dev_get_name(dev->ddf_dev), fun_name, ddf_dev_get_handle(dev->ddf_dev));
    72 
     50        usb_log_info("Pretending to control %s `%s'.\n",
     51            usb_device_get_iface_number(dev) < 0 ? "device" : "interface",
     52            usb_device_get_name(dev));
    7353        return EOK;
    7454}
     
    8262{
    8363        assert(dev);
    84         ddf_fun_t *ctl_fun = dev->driver_data;
    85         const int ret = ddf_fun_unbind(ctl_fun);
    86         if (ret != EOK) {
    87                 usb_log_error("Failed to unbind %s.\n", ddf_fun_get_name(ctl_fun));
    88                 return ret;
    89         }
    90         ddf_fun_destroy(ctl_fun);
    91         dev->driver_data = NULL;
    92 
    9364        return EOK;
    9465}
  • uspace/drv/bus/usb/usbhid/blink1/blink1.c

    r5b18137 rb4b534ac  
    3535 */
    3636
     37#include <errno.h>
    3738#include <str_error.h>
    3839#include <usb/debug.h>
     
    7879        report.arg5 = 0;
    7980       
    80         return usbhid_req_set_report(&blink1_dev->hid_dev->usb_dev->ctrl_pipe,
    81             blink1_dev->hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_FEATURE,
    82             (uint8_t *) &report, sizeof(report));
     81        return usbhid_req_set_report(
     82            usb_device_get_default_pipe(blink1_dev->hid_dev->usb_dev),
     83            usb_device_get_iface_number(blink1_dev->hid_dev->usb_dev),
     84            USB_HID_REPORT_TYPE_FEATURE, (uint8_t *) &report, sizeof(report));
    8385}
    8486
     
    100102       
    101103        /* Create the exposed function. */
    102         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    103             HID_BLINK1_FUN_NAME);
     104        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
     105            fun_exposed, HID_BLINK1_FUN_NAME);
    104106        if (fun == NULL) {
    105107                usb_log_error("Could not create DDF function node `%s'.\n",
  • uspace/drv/bus/usb/usbhid/generic/hiddev.c

    r5b18137 rb4b534ac  
    190190        /* Create the exposed function. */
    191191        usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
    192         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    193             HID_GENERIC_FUN_NAME);
     192        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
     193            fun_exposed, HID_GENERIC_FUN_NAME);
    194194        if (fun == NULL) {
    195195                usb_log_error("Could not create DDF function node.\n");
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.c

    r5b18137 rb4b534ac  
    100100
    101101const char *HID_KBD_FUN_NAME = "keyboard";
    102 const char *HID_KBD_CATEGORY = "keyboard";
     102const char *HID_KBD_CATEGORY_NAME = "keyboard";
    103103
    104104static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
     
    261261
    262262        if (rc != EOK) {
    263                 usb_log_warning("Error translating LED output to output report"
    264                     ".\n");
     263                usb_log_warning("Could not translate LED output to output"
     264                    "report.\n");
    265265                return;
    266266        }
     
    270270                0));
    271271
    272         rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    273             hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
     272        rc = usbhid_req_set_report(
     273            usb_device_get_default_pipe(hid_dev->usb_dev),
     274            usb_device_get_iface_number(hid_dev->usb_dev),
     275            USB_HID_REPORT_TYPE_OUTPUT,
    274276            kbd_dev->output_buffer, kbd_dev->output_size);
    275277        if (rc != EOK) {
     
    476478}
    477479
    478 /* API functions                                                              */
    479 
    480 /**
    481  * Initialization of the USB/HID keyboard structure.
    482  *
    483  * This functions initializes required structures from the device's descriptors.
    484  *
    485  * During initialization, the keyboard is switched into boot protocol, the idle
    486  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    487  * when a key is pressed or released. Finally, the LED lights are turned on
    488  * according to the default setup of lock keys.
    489  *
    490  * @note By default, the keyboards is initialized with Num Lock turned on and
    491  *       other locks turned off.
    492  *
    493  * @param kbd_dev Keyboard device structure to be initialized.
    494  * @param dev DDF device structure of the keyboard.
    495  *
    496  * @retval EOK if successful.
    497  * @retval EINVAL if some parameter is not given.
    498  * @return Other value inherited from function usbhid_dev_init().
    499  */
    500 int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
    501 {
    502         ddf_fun_t *fun = NULL;
    503         usb_kbd_t *kbd_dev = NULL;
    504         usb_hid_report_path_t *path = NULL;
    505         bool bound = false;
    506         fid_t fid = 0;
    507         int rc;
    508 
    509         usb_log_debug("Initializing HID/KBD structure...\n");
    510 
    511         if (hid_dev == NULL) {
    512                 usb_log_error(
    513                     "Failed to init keyboard structure: no structure given.\n");
    514                 rc = EINVAL;
    515                 goto error;
    516         }
    517 
    518         /* Create the exposed function. */
    519         usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    520         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    521             HID_KBD_FUN_NAME);
    522         if (fun == NULL) {
    523                 usb_log_error("Could not create DDF function node.\n");
    524                 rc = ENOMEM;
    525                 goto error;
    526         }
    527 
    528         /* Store the initialized HID device and HID ops
    529          * to the DDF function. */
    530         ddf_fun_set_ops(fun, &kbdops);
    531 
    532         kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t));
    533         if (kbd_dev == NULL) {
    534                 usb_log_error("Failed to allocate KBD device structure.\n");
    535                 rc = ENOMEM;
    536                 goto error;
    537         }
    538 
    539         kbd_dev->fun = fun;
     480/* HID/KBD structure manipulation                                             */
     481
     482static int kbd_dev_init(usb_kbd_t *kbd_dev, usb_hid_dev_t *hid_dev)
     483{
     484        assert(kbd_dev);
     485        assert(hid_dev);
    540486
    541487        /* Default values */
     
    554500
    555501        // TODO: make more general
    556         path = usb_hid_report_path();
     502        usb_hid_report_path_t *path = usb_hid_report_path();
    557503        if (path == NULL) {
    558504                usb_log_error("Failed to create kbd report path.\n");
    559                 rc = ENOMEM;
    560                 goto error;
    561         }
    562 
    563         rc = usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    564         if (rc != EOK) {
     505                usb_kbd_destroy(kbd_dev);
     506                return ENOMEM;
     507        }
     508
     509        int ret =
     510            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     511        if (ret != EOK) {
    565512                usb_log_error("Failed to append item to kbd report path.\n");
    566                 goto error;
     513                usb_hid_report_path_free(path);
     514                usb_kbd_destroy(kbd_dev);
     515                return ret;
    567516        }
    568517
     
    573522
    574523        usb_hid_report_path_free(path);
    575         path = NULL;
    576524
    577525        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     
    580528        if (kbd_dev->keys == NULL) {
    581529                usb_log_error("Failed to allocate key buffer.\n");
    582                 rc = ENOMEM;
    583                 goto error;
     530                usb_kbd_destroy(kbd_dev);
     531                return ENOMEM;
    584532        }
    585533
     
    587535        if (kbd_dev->keys_old == NULL) {
    588536                usb_log_error("Failed to allocate old_key buffer.\n");
    589                 rc = ENOMEM;
    590                 goto error;
     537                usb_kbd_destroy(kbd_dev);
     538                return ENOMEM;
    591539        }
    592540
     
    597545        if (kbd_dev->output_buffer == NULL) {
    598546                usb_log_error("Error creating output report buffer.\n");
    599                 rc = ENOMEM;
    600                 goto error;
     547                usb_kbd_destroy(kbd_dev);
     548                return ENOMEM;
    601549        }
    602550
     
    606554        if (kbd_dev->led_path == NULL) {
    607555                usb_log_error("Failed to create kbd led report path.\n");
    608                 rc = ENOMEM;
    609                 goto error;
    610         }
    611 
    612         rc = usb_hid_report_path_append_item(
     556                usb_kbd_destroy(kbd_dev);
     557                return ENOMEM;
     558        }
     559
     560        ret = usb_hid_report_path_append_item(
    613561            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    614         if (rc != EOK) {
     562        if (ret != EOK) {
    615563                usb_log_error("Failed to append to kbd/led report path.\n");
    616                 goto error;
     564                usb_kbd_destroy(kbd_dev);
     565                return ret;
    617566        }
    618567
     
    626575        if (kbd_dev->led_data == NULL) {
    627576                usb_log_error("Error creating buffer for LED output report.\n");
    628                 rc = ENOMEM;
    629                 goto error;
     577                usb_kbd_destroy(kbd_dev);
     578                return ENOMEM;
    630579        }
    631580
     
    634583        usb_kbd_set_led(hid_dev, kbd_dev);
    635584
    636         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    637             hid_dev->usb_dev->interface_no, IDLE_RATE);
     585        usbhid_req_set_idle(usb_device_get_default_pipe(hid_dev->usb_dev),
     586            usb_device_get_iface_number(hid_dev->usb_dev), IDLE_RATE);
     587
     588
     589        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
     590        usb_log_debug("HID/KBD device structure initialized.\n");
     591
     592        return EOK;
     593}
     594
     595
     596/* API functions                                                              */
     597
     598/**
     599 * Initialization of the USB/HID keyboard structure.
     600 *
     601 * This functions initializes required structures from the device's descriptors.
     602 *
     603 * During initialization, the keyboard is switched into boot protocol, the idle
     604 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     605 * when a key is pressed or released. Finally, the LED lights are turned on
     606 * according to the default setup of lock keys.
     607 *
     608 * @note By default, the keyboards is initialized with Num Lock turned on and
     609 *       other locks turned off.
     610 *
     611 * @param kbd_dev Keyboard device structure to be initialized.
     612 * @param dev DDF device structure of the keyboard.
     613 *
     614 * @retval EOK if successful.
     615 * @retval EINVAL if some parameter is not given.
     616 * @return Other value inherited from function usbhid_dev_init().
     617 */
     618int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
     619{
     620        usb_log_debug("Initializing HID/KBD structure...\n");
     621
     622        if (hid_dev == NULL) {
     623                usb_log_error(
     624                    "Failed to init keyboard structure: no structure given.\n");
     625                return EINVAL;
     626        }
     627
     628        /* Create the exposed function. */
     629        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
     630        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
     631            fun_exposed, HID_KBD_FUN_NAME);
     632        if (fun == NULL) {
     633                usb_log_error("Could not create DDF function node.\n");
     634                return ENOMEM;
     635        }
     636
     637        usb_kbd_t *kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t));
     638        if (kbd_dev == NULL) {
     639                usb_log_error("Failed to allocate KBD device structure.\n");
     640                ddf_fun_destroy(fun);
     641                return ENOMEM;
     642        }
     643
     644        int ret = kbd_dev_init(kbd_dev, hid_dev);
     645        if (ret != EOK) {
     646                usb_log_error("Failed to initialize KBD device  structure.\n");
     647                ddf_fun_destroy(fun);
     648                return ret;
     649        }
     650
     651        /* Store the initialized HID device and HID ops
     652         * to the DDF function. */
     653        ddf_fun_set_ops(fun, &kbdops);
     654
     655        ret = ddf_fun_bind(fun);
     656        if (ret != EOK) {
     657                usb_log_error("Could not bind DDF function: %s.\n",
     658                    str_error(ret));
     659                usb_kbd_destroy(kbd_dev);
     660                ddf_fun_destroy(fun);
     661                return ret;
     662        }
     663
     664        usb_log_debug("%s function created. Handle: %" PRIun "\n",
     665            HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
     666
     667        usb_log_debug("Adding DDF function to category %s...\n",
     668            HID_KBD_CATEGORY_NAME);
     669        ret = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
     670        if (ret != EOK) {
     671                usb_log_error(
     672                    "Could not add DDF function to category %s: %s.\n",
     673                    HID_KBD_CATEGORY_NAME, str_error(ret));
     674                usb_kbd_destroy(kbd_dev);
     675                if (ddf_fun_unbind(fun) == EOK) {
     676                        ddf_fun_destroy(fun);
     677                } else {
     678                        usb_log_error(
     679                            "Failed to unbind `%s', will not destroy.\n",
     680                            ddf_fun_get_name(fun));
     681                }
     682                return ret;
     683        }
    638684
    639685        /* Create new fibril for auto-repeat. */
    640         fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
     686        fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
    641687        if (fid == 0) {
    642688                usb_log_error("Failed to start fibril for KBD auto-repeat");
    643                 rc = ENOMEM;
    644                 goto error;
    645         }
    646 
    647         kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    648         usb_log_debug("HID/KBD device structure initialized.\n");
    649 
    650         rc = ddf_fun_bind(fun);
    651         if (rc != EOK) {
    652                 usb_log_error("Could not bind DDF function: %s.\n",
    653                     str_error(rc));
    654                 goto error;
    655         }
    656 
    657         bound = true;
    658 
    659         usb_log_debug("%s function created. Handle: %" PRIun "\n",
    660             HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
    661 
    662         usb_log_debug("Adding DDF function to category %s...\n",
    663             HID_KBD_CATEGORY);
    664         rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY);
    665         if (rc != EOK) {
    666                 usb_log_error(
    667                     "Could not add DDF function to category %s: %s.\n",
    668                     HID_KBD_CATEGORY, str_error(rc));
    669                 goto error;
    670         }
    671 
     689                usb_kbd_destroy(kbd_dev);
     690                return ENOMEM;
     691        }
    672692        fibril_add_ready(fid);
    673 
     693        kbd_dev->fun = fun;
    674694        /* Save the KBD device structure into the HID device structure. */
    675695        *data = kbd_dev;
    676696
    677697        return EOK;
    678 error:
    679         if (bound)
    680                 ddf_fun_unbind(fun);
    681         if (fid != 0)
    682                 fibril_destroy(fid);
    683         if (kbd_dev != NULL) {
    684                 free(kbd_dev->led_data);
    685                 if (kbd_dev->led_path != NULL)
    686                         usb_hid_report_path_free(kbd_dev->led_path);
    687                 if (kbd_dev->output_buffer != NULL)
    688                         usb_hid_report_output_free(kbd_dev->output_buffer);
    689                 free(kbd_dev->keys_old);
    690                 free(kbd_dev->keys);
    691         }
    692         if (path != NULL)
    693                 usb_hid_report_path_free(path);
    694         if (fun != NULL)
    695                 ddf_fun_destroy(fun);
    696         return rc;
    697698}
    698699
     
    749750        usb_hid_report_output_free(kbd_dev->output_buffer);
    750751
    751         ddf_fun_unbind(kbd_dev->fun);
    752         ddf_fun_destroy(kbd_dev->fun);
     752        if (kbd_dev->fun) {
     753                if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     754                        usb_log_warning("Failed to unbind %s.\n",
     755                            ddf_fun_get_name(kbd_dev->fun));
     756                } else {
     757                        usb_log_debug2("%s unbound.\n",
     758                            ddf_fun_get_name(kbd_dev->fun));
     759                        ddf_fun_destroy(kbd_dev->fun);
     760                }
     761        }
    753762}
    754763
     
    779788        }
    780789
    781         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    782             hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
     790        rc = usbhid_req_set_protocol(
     791            usb_device_get_default_pipe(hid_dev->usb_dev),
     792            usb_device_get_iface_number(hid_dev->usb_dev),
     793            USB_HID_PROTOCOL_BOOT);
    783794
    784795        if (rc != EOK) {
  • uspace/drv/bus/usb/usbhid/main.c

    r5b18137 rb4b534ac  
    6565        }
    6666
    67         if (dev->interface_no < 0) {
     67        if (usb_device_get_iface_number(dev) < 0) {
    6868                usb_log_error("Failed to add HID device: endpoints not found."
    6969                    "\n");
     
    8989         * This will create a separate fibril that will query the device
    9090         * for the data continuously. */
    91        rc = usb_device_auto_poll(dev,
     91        rc = usb_device_auto_poll_desc(dev,
    9292           /* Index of the polling pipe. */
    93            hid_dev->poll_pipe_index,
     93           hid_dev->poll_pipe_mapping->description,
    9494           /* Callback when data arrives. */
    9595           usb_hid_polling_callback,
    9696           /* How much data to request. */
    97            dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size,
     97           hid_dev->poll_pipe_mapping->pipe.max_packet_size,
     98           /* Delay */
     99           -1,
    98100           /* Callback when the polling ends. */
    99101           usb_hid_polling_ended_callback,
     
    103105        if (rc != EOK) {
    104106                usb_log_error("Failed to start polling fibril for `%s'.\n",
    105                     ddf_dev_get_name(dev->ddf_dev));
     107                    usb_device_get_name(dev));
    106108                usb_hid_deinit(hid_dev);
    107109                return rc;
     
    109111        hid_dev->running = true;
    110112
    111         usb_log_info("HID device `%s' ready to use.\n",
    112             ddf_dev_get_name(dev->ddf_dev));
     113        usb_log_info("HID device `%s' ready.\n", usb_device_get_name(dev));
    113114
    114115        return EOK;
     
    137138{
    138139        assert(dev);
    139         assert(dev->driver_data);
    140         usb_hid_dev_t *hid_dev = dev->driver_data;
     140        usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
     141        assert(hid_dev);
    141142        unsigned tries = 100;
    142143        /* Wait for fail. */
     
    150151
    151152        usb_hid_deinit(hid_dev);
    152         usb_log_debug2("%s destruction complete.\n", ddf_dev_get_name(dev->ddf_dev));
     153        usb_log_debug2("%s destruction complete.\n", usb_device_get_name(dev));
    153154        return EOK;
    154155}
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.c

    r5b18137 rb4b534ac  
    246246}
    247247
     248#define FUN_UNBIND_DESTROY(fun) \
     249if (fun) { \
     250        if (ddf_fun_unbind((fun)) == EOK) { \
     251                ddf_fun_destroy((fun)); \
     252        } else { \
     253                usb_log_error("Could not unbind function `%s', it " \
     254                    "will not be destroyed.\n", ddf_fun_get_name(fun)); \
     255        } \
     256} else (void)0
     257
    248258/** Get highest index of a button mentioned in given report.
    249259 *
     
    286296}
    287297
    288 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    289 {
    290         ddf_fun_t *fun = NULL;
    291         usb_mouse_t *mouse_dev = NULL;
    292         bool bound = false;
    293         int rc;
    294 
    295         usb_log_debug("Initializing HID/Mouse structure...\n");
    296 
    297         if (hid_dev == NULL) {
    298                 usb_log_error("Failed to init mouse structure: no structure"
    299                     " given.\n");
    300                 rc = EINVAL;
    301                 goto error;
    302         }
    303 
    304         /* Create the exposed function. */
    305         usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    306         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    307             HID_MOUSE_FUN_NAME);
    308         if (fun == NULL) {
    309                 usb_log_error("Could not create DDF function node `%s'.\n",
    310                     HID_MOUSE_FUN_NAME);
    311                 rc = ENOMEM;
    312                 goto error;
    313         }
    314 
    315         ddf_fun_set_ops(fun, &ops);
    316 
    317         mouse_dev = ddf_fun_data_alloc(fun, sizeof(usb_mouse_t));
    318         if (mouse_dev == NULL) {
    319                 usb_log_error("Error while creating USB/HID Mouse device "
    320                     "structure.\n");
    321                 rc = ENOMEM;
    322                 goto error;
    323         }
    324 
     298static int mouse_dev_init(usb_mouse_t *mouse_dev, usb_hid_dev_t *hid_dev)
     299{
    325300        // FIXME: This may not be optimal since stupid hardware vendor may
    326301        // use buttons 1, 2, 3 and 6000 and we would allocate array of
     
    335310        if (mouse_dev->buttons == NULL) {
    336311                usb_log_error(NAME ": out of memory, giving up on device!\n");
    337                 rc = ENOMEM;
    338                 goto error;
     312                free(mouse_dev);
     313                return ENOMEM;
    339314        }
    340315
    341316        // TODO: how to know if the device supports the request???
    342         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    343             hid_dev->usb_dev->interface_no, IDLE_RATE);
    344 
    345         rc = ddf_fun_bind(fun);
    346         if (rc != EOK) {
     317        usbhid_req_set_idle(usb_device_get_default_pipe(hid_dev->usb_dev),
     318            usb_device_get_iface_number(hid_dev->usb_dev), IDLE_RATE);
     319        return EOK;
     320}
     321
     322int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
     323{
     324        usb_log_debug("Initializing HID/Mouse structure...\n");
     325
     326        if (hid_dev == NULL) {
     327                usb_log_error("Failed to init keyboard structure: no structure"
     328                    " given.\n");
     329                return EINVAL;
     330        }
     331
     332        /* Create the exposed function. */
     333        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
     334        ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev,
     335            fun_exposed, HID_MOUSE_FUN_NAME);
     336        if (fun == NULL) {
     337                usb_log_error("Could not create DDF function node `%s'.\n",
     338                    HID_MOUSE_FUN_NAME);
     339                return ENOMEM;
     340        }
     341
     342        usb_mouse_t *mouse_dev = ddf_fun_data_alloc(fun, sizeof(usb_mouse_t));
     343        if (mouse_dev == NULL) {
     344                usb_log_error("Failed to alloc HID mouse device structure.\n");
     345                ddf_fun_destroy(fun);
     346                return ENOMEM;
     347        }
     348
     349        int ret = mouse_dev_init(mouse_dev, hid_dev);
     350        if (ret != EOK) {
     351                usb_log_error("Failed to init HID mouse device structure.\n");
     352                return ret;
     353        }
     354
     355        ddf_fun_set_ops(fun, &ops);
     356
     357        ret = ddf_fun_bind(fun);
     358        if (ret != EOK) {
    347359                usb_log_error("Could not bind DDF function `%s': %s.\n",
    348                     ddf_fun_get_name(fun), str_error(rc));
    349                 goto error;
    350         }
    351 
    352         bound = true;
     360                    ddf_fun_get_name(fun), str_error(ret));
     361                ddf_fun_destroy(fun);
     362                return ret;
     363        }
    353364
    354365        usb_log_debug("Adding DDF function `%s' to category %s...\n",
    355366            ddf_fun_get_name(fun), HID_MOUSE_CATEGORY);
    356         rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
    357         if (rc != EOK) {
    358                 usb_log_error("Could not add DDF function to category %s: "
    359                     "%s.\n", HID_MOUSE_CATEGORY, str_error(rc));
    360                 goto error;
    361         }
    362 
     367        ret = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
     368        if (ret != EOK) {
     369                usb_log_error(
     370                    "Could not add DDF function to category %s: %s.\n",
     371                    HID_MOUSE_CATEGORY, str_error(ret));
     372                FUN_UNBIND_DESTROY(fun);
     373                return ret;
     374        }
    363375        mouse_dev->mouse_fun = fun;
    364376
    365377        /* Save the Mouse device structure into the HID device structure. */
    366378        *data = mouse_dev;
     379
    367380        return EOK;
    368 error:
    369         if (bound)
    370                 ddf_fun_unbind(fun);
    371         if (mouse_dev != NULL)
    372                 free(mouse_dev->buttons);
    373         if (fun != NULL)
    374                 ddf_fun_destroy(fun);
    375         return rc;
    376381}
    377382
     
    404409        }
    405410
    406         ddf_fun_unbind(mouse_dev->mouse_fun);
    407411        free(mouse_dev->buttons);
    408         ddf_fun_destroy(mouse_dev->mouse_fun);
     412        FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
    409413}
    410414
     
    421425        }
    422426
    423         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    424             hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
     427        rc = usbhid_req_set_protocol(
     428            usb_device_get_default_pipe(hid_dev->usb_dev),
     429            usb_device_get_iface_number(hid_dev->usb_dev),
     430            USB_HID_PROTOCOL_BOOT);
    425431
    426432        if (rc != EOK) {
  • uspace/drv/bus/usb/usbhid/multimedia/multimedia.c

    r5b18137 rb4b534ac  
    162162
    163163        /* Create the exposed function. */
    164         ddf_fun_t *fun = ddf_fun_create(
    165             hid_dev->usb_dev->ddf_dev, fun_exposed, NAME);
     164        ddf_fun_t *fun = usb_device_ddf_fun_create(
     165            hid_dev->usb_dev, fun_exposed, NAME);
    166166        if (fun == NULL) {
    167167                usb_log_error("Could not create DDF function node.\n");
  • uspace/drv/bus/usb/usbhid/usbhid.c

    r5b18137 rb4b534ac  
    4141#include <usb/hid/hidreport.h>
    4242#include <usb/hid/request.h>
     43
    4344#include <errno.h>
     45#include <macros.h>
    4446#include <str_error.h>
    4547
     
    114116    const usb_hid_subdriver_mapping_t *mapping)
    115117{
    116         assert(hid_dev != NULL);
    117         assert(hid_dev->usb_dev != NULL);
    118 
    119         return (hid_dev->usb_dev->descriptors.device.vendor_id
    120             == mapping->vendor_id
    121             && hid_dev->usb_dev->descriptors.device.product_id
    122             == mapping->product_id);
     118        assert(hid_dev);
     119        assert(hid_dev->usb_dev);
     120        assert(mapping);
     121        const usb_standard_device_descriptor_t *d =
     122            &usb_device_descriptors(hid_dev->usb_dev)->device;
     123
     124        return (d->vendor_id == mapping->vendor_id)
     125            && (d->product_id == mapping->product_id);
    123126}
    124127
     
    264267}
    265268
    266 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
     269static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    267270{
    268271        assert(hid_dev);
     
    270273
    271274        static const struct {
    272                 unsigned ep_number;
     275                const usb_endpoint_description_t *desc;
    273276                const char* description;
    274277        } endpoints[] = {
    275                 {USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"},
    276                 {USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"},
    277                 {USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"},
     278                {&usb_hid_kbd_poll_endpoint_description, "Keyboard endpoint"},
     279                {&usb_hid_mouse_poll_endpoint_description, "Mouse endpoint"},
     280                {&usb_hid_generic_poll_endpoint_description, "Generic HID endpoint"},
    278281        };
    279282
    280         for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) {
    281                 if (endpoints[i].ep_number >= dev->pipes_count) {
    282                         return EINVAL;
    283                 }
    284                 if (dev->pipes[endpoints[i].ep_number].present) {
     283        for (unsigned i = 0; i < ARRAY_SIZE(endpoints); ++i) {
     284                usb_endpoint_mapping_t *epm =
     285                    usb_device_get_mapped_ep_desc(dev, endpoints[i].desc);
     286                if (epm && epm->present) {
    285287                        usb_log_debug("Found: %s.\n", endpoints[i].description);
    286                         hid_dev->poll_pipe_index = endpoints[i].ep_number;
     288                        hid_dev->poll_pipe_mapping = epm;
    287289                        return EOK;
    288290                }
     
    351353        /* The USB device should already be initialized, save it in structure */
    352354        hid_dev->usb_dev = dev;
    353         hid_dev->poll_pipe_index = -1;
     355        hid_dev->poll_pipe_mapping = NULL;
    354356
    355357        int rc = usb_hid_check_pipes(hid_dev, dev);
     
    381383                    "boot protocol.\n");
    382384
    383                 switch (hid_dev->poll_pipe_index) {
    384                 case USB_HID_KBD_POLL_EP_NO:
     385                switch (hid_dev->poll_pipe_mapping->interface->interface_protocol) {
     386                case USB_HID_PROTOCOL_KEYBOARD:
    385387                        usb_log_info("Falling back to kbd boot protocol.\n");
    386388                        rc = usb_kbd_set_boot_protocol(hid_dev);
     
    389391                        }
    390392                        break;
    391                 case USB_HID_MOUSE_POLL_EP_NO:
     393                case USB_HID_PROTOCOL_MOUSE:
    392394                        usb_log_info("Falling back to mouse boot protocol.\n");
    393395                        rc = usb_mouse_set_boot_protocol(hid_dev);
     
    397399                        break;
    398400                default:
    399                         assert(hid_dev->poll_pipe_index
    400                             == USB_HID_GENERIC_POLL_EP_NO);
    401401                        usb_log_info("Falling back to generic HID driver.\n");
    402402                        usb_hid_set_generic_hid_subdriver(hid_dev);
     
    476476            &hid_dev->report, buffer, buffer_size, &hid_dev->report_id);
    477477        if (rc != EOK) {
    478                 usb_log_warning("Error in usb_hid_parse_report():"
     478                usb_log_warning("Failure in usb_hid_parse_report():"
    479479                    "%s\n", str_error(rc));
    480480        }
  • uspace/drv/bus/usb/usbhid/usbhid.h

    r5b18137 rb4b534ac  
    103103        usb_device_t *usb_dev;
    104104
    105         /** Index of the polling pipe in usb_hid_endpoints array. */
    106         unsigned poll_pipe_index;
     105        /** Endpont mapping of the polling pipe. */
     106        usb_endpoint_mapping_t *poll_pipe_mapping;
    107107
    108108        /** Subdrivers. */
     
    132132};
    133133
    134 
    135 
    136 enum {
    137         USB_HID_KBD_POLL_EP_NO = 0,
    138         USB_HID_MOUSE_POLL_EP_NO = 1,
    139         USB_HID_GENERIC_POLL_EP_NO = 2,
    140         USB_HID_POLL_EP_COUNT = 3
    141 };
    142 
    143134extern const usb_endpoint_description_t *usb_hid_endpoints[];
    144 
    145 
    146135
    147136int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
  • uspace/drv/bus/usb/usbhub/main.c

    r5b18137 rb4b534ac  
    3636#include <async.h>
    3737#include <stdio.h>
     38#include <io/logctl.h>
    3839
    3940#include <usb/dev/driver.h>
     
    4344#include "usbhub.h"
    4445
    45 /** Hub status-change endpoint description.
    46  *
    47  * For more information see section 11.15.1 of USB 1.1 specification.
    48  */
    49 static const usb_endpoint_description_t hub_status_change_endpoint_description =
    50 {
    51         .transfer_type = USB_TRANSFER_INTERRUPT,
    52         .direction = USB_DIRECTION_IN,
    53         .interface_class = USB_CLASS_HUB,
    54         .interface_subclass = 0,
    55         .interface_protocol = 0,
    56         .flags = 0
    57 };
    5846
    5947/** USB hub driver operations. */
     
    8068        printf(NAME ": HelenOS USB hub driver.\n");
    8169        log_init(NAME);
    82 
     70        logctl_set_log_level(NAME, LVL_NOTE);
    8371        return usb_driver_main(&usb_hub_driver);
    8472}
  • uspace/drv/bus/usb/usbhub/port.c

    r5b18137 rb4b534ac  
    4141
    4242#include <usb/debug.h>
    43 #include <usb/dev/hub.h>
    4443
    4544#include "port.h"
     
    5655static int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub);
    5756static void usb_hub_port_reset_completed(usb_hub_port_t *port,
    58     usb_port_status_t status);
     57    usb_hub_dev_t *hub, usb_port_status_t status);
    5958static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status);
    60 static int enable_port_callback(void *arg);
    6159static int add_device_phase1_worker_fibril(void *arg);
    6260static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub,
     
    6664{
    6765        assert(port);
    68         if (port->attached_device.fun)
     66        if (port->device_attached)
    6967                return usb_hub_port_device_gone(port, hub);
    7068        return EOK;
     
    124122        assert(port);
    125123        fibril_mutex_lock(&port->mutex);
    126         port->reset_completed = true;
    127         port->reset_okay = false;
     124        if (port->reset_status == IN_RESET)
     125                port->reset_status = RESET_FAIL;
    128126        fibril_condvar_broadcast(&port->reset_cv);
    129127        fibril_mutex_unlock(&port->mutex);
     
    141139        assert(port);
    142140        assert(hub);
    143         usb_log_debug("Interrupt at port %zu\n", port->port_number);
     141        usb_log_debug2("(%p-%u): Interrupt.\n", hub, port->port_number);
    144142
    145143        usb_port_status_t status = 0;
    146144        const int opResult = get_port_status(port, &status);
    147145        if (opResult != EOK) {
    148                 usb_log_error("Failed to get port %zu status: %s.\n",
     146                usb_log_error("(%p-%u): Failed to get port status: %s.\n", hub,
    149147                    port->port_number, str_error(opResult));
    150148                return;
     
    155153                const bool connected =
    156154                    (status & USB_HUB_PORT_STATUS_CONNECTION) != 0;
    157                 usb_log_debug("Connection change on port %zu: device %s.\n",
     155                usb_log_debug("(%p-%u): Connection change: device %s.\n", hub,
    158156                    port->port_number, connected ? "attached" : "removed");
    159157
     
    162160                    USB_HUB_FEATURE_C_PORT_CONNECTION);
    163161                if (opResult != EOK) {
    164                         usb_log_warning("Failed to clear port-change-connection"
    165                             " flag: %s.\n", str_error(opResult));
     162                        usb_log_warning("(%p-%u): Failed to clear "
     163                            "port-change-connection flag: %s.\n", hub,
     164                            port->port_number, str_error(opResult));
    166165                }
    167166
     
    170169                            usb_port_speed(status));
    171170                        if (opResult != EOK) {
    172                                 usb_log_error(
    173                                     "Cannot handle change on port %zu: %s.\n",
    174                                     port->port_number, str_error(opResult));
     171                                usb_log_error("(%p-%u): Cannot handle change on"
     172                                   " port: %s.\n", hub, port->port_number,
     173                                   str_error(opResult));
    175174                        }
    176175                } else {
     176                        /* Handle the case we were in reset */
     177                        //usb_hub_port_reset_fail(port);
    177178                        /* If enabled change was reported leave the removal
    178179                         * to that handler, it shall ACK the change too. */
     
    185186        /* Enable change, ports are automatically disabled on errors. */
    186187        if (status & USB_HUB_PORT_C_STATUS_ENABLED) {
    187                 usb_log_info("Port %zu, disabled because of errors.\n",
     188                //TODO: maybe HS reset failed?
     189                usb_log_info("(%p-%u): Port disabled because of errors.\n", hub,
    188190                   port->port_number);
    189191                usb_hub_port_device_gone(port, hub);
     
    191193                        USB_HUB_FEATURE_C_PORT_ENABLE);
    192194                if (rc != EOK) {
    193                         usb_log_error(
    194                             "Failed to clear port %zu enable change feature: "
    195                             "%s.\n", port->port_number, str_error(rc));
     195                        usb_log_error("(%p-%u): Failed to clear port enable "
     196                            "change feature: %s.", hub, port->port_number,
     197                            str_error(rc));
    196198                }
    197199
     
    200202        /* Suspend change */
    201203        if (status & USB_HUB_PORT_C_STATUS_SUSPEND) {
    202                 usb_log_error("Port %zu went to suspend state, this should"
    203                     "NOT happen as we do not support suspend state!",
     204                usb_log_error("(%p-%u): Port went to suspend state, this should"
     205                    " NOT happen as we do not support suspend state!", hub,
    204206                    port->port_number);
    205207                const int rc = usb_hub_port_clear_feature(port,
    206208                        USB_HUB_FEATURE_C_PORT_SUSPEND);
    207209                if (rc != EOK) {
    208                         usb_log_error(
    209                             "Failed to clear port %zu suspend change feature: "
    210                             "%s.\n", port->port_number, str_error(rc));
     210                        usb_log_error("(%p-%u): Failed to clear port suspend "
     211                            "change feature: %s.", hub, port->port_number,
     212                            str_error(rc));
    211213                }
    212214        }
     
    214216        /* Over current */
    215217        if (status & USB_HUB_PORT_C_STATUS_OC) {
     218                usb_log_debug("(%p-%u): Port OC reported!.", hub,
     219                    port->port_number);
    216220                /* According to the USB specs:
    217221                 * 11.13.5 Over-current Reporting and Recovery
     
    222226                    USB_HUB_FEATURE_C_PORT_OVER_CURRENT);
    223227                if (rc != EOK) {
    224                         usb_log_error(
    225                             "Failed to clear port %zu OC change feature: %s.\n",
    226                             port->port_number, str_error(rc));
     228                        usb_log_error("(%p-%u): Failed to clear port OC change "
     229                            "feature: %s.\n", hub, port->port_number,
     230                            str_error(rc));
    227231                }
    228232                if (!(status & ~USB_HUB_PORT_STATUS_OC)) {
     
    230234                            port, USB_HUB_FEATURE_PORT_POWER);
    231235                        if (rc != EOK) {
    232                                 usb_log_error(
    233                                     "Failed to set port %zu power after OC:"
    234                                     " %s.\n", port->port_number, str_error(rc));
     236                                usb_log_error("(%p-%u): Failed to set port "
     237                                    "power after OC: %s.", hub,
     238                                    port->port_number, str_error(rc));
    235239                        }
    236240                }
     
    239243        /* Port reset, set on port reset complete. */
    240244        if (status & USB_HUB_PORT_C_STATUS_RESET) {
    241                 usb_hub_port_reset_completed(port, status);
    242         }
    243 
    244         usb_log_debug("Port %zu status 0x%08" PRIx32 "\n",
     245                usb_hub_port_reset_completed(port, hub, status);
     246        }
     247
     248        usb_log_debug2("(%p-%u): Port status %#08" PRIx32, hub,
    245249            port->port_number, status);
    246250}
     
    259263        assert(port);
    260264        assert(hub);
    261         if (port->attached_device.address < 0) {
    262                 usb_log_warning(
    263                     "Device on port %zu removed before being registered.\n",
    264                     port->port_number);
    265 
    266                 /*
    267                  * Device was removed before port reset completed.
    268                  * We will announce a failed port reset to unblock the
    269                  * port reset callback from new device wrapper.
    270                  */
    271                 usb_hub_port_reset_fail(port);
    272                 return EOK;
    273         }
    274 
    275         fibril_mutex_lock(&port->mutex);
    276         assert(port->attached_device.fun);
    277         usb_log_debug("Removing device on port %zu.\n", port->port_number);
    278         int ret = ddf_fun_unbind(port->attached_device.fun);
    279         if (ret != EOK) {
    280                 usb_log_error("Failed to unbind child function on port"
    281                     " %zu: %s.\n", port->port_number, str_error(ret));
    282                 fibril_mutex_unlock(&port->mutex);
    283                 return ret;
    284         }
    285 
    286         ddf_fun_destroy(port->attached_device.fun);
    287         port->attached_device.fun = NULL;
    288 
    289         ret = usb_hub_unregister_device(&hub->usb_device->hc_conn,
    290             &port->attached_device);
    291         if (ret != EOK) {
    292                 usb_log_warning("Failed to unregister address of the "
    293                     "removed device: %s.\n", str_error(ret));
    294         }
    295 
    296         port->attached_device.address = -1;
    297         fibril_mutex_unlock(&port->mutex);
    298         usb_log_info("Removed device on port %zu.\n", port->port_number);
    299         return EOK;
     265        async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device);
     266        if (!exch)
     267                return ENOMEM;
     268        const int rc = usb_device_remove(exch, port->port_number);
     269        usb_device_bus_exchange_end(exch);
     270        if (rc == EOK)
     271                port->device_attached = false;
     272        return rc;
     273
    300274}
    301275
     
    308282 * @param status Port status mask
    309283 */
    310 void usb_hub_port_reset_completed(usb_hub_port_t *port,
     284void usb_hub_port_reset_completed(usb_hub_port_t *port, usb_hub_dev_t *hub,
    311285    usb_port_status_t status)
    312286{
    313287        assert(port);
    314288        fibril_mutex_lock(&port->mutex);
     289        const bool enabled = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;
    315290        /* Finalize device adding. */
    316         port->reset_completed = true;
    317         port->reset_okay = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;
    318 
    319         if (port->reset_okay) {
    320                 usb_log_debug("Port %zu reset complete.\n", port->port_number);
     291
     292        if (enabled) {
     293                port->reset_status = RESET_OK;
     294                usb_log_debug("(%p-%u): Port reset complete.\n", hub,
     295                    port->port_number);
    321296        } else {
    322                 usb_log_warning(
    323                     "Port %zu reset complete but port not enabled.\n",
    324                     port->port_number);
     297                port->reset_status = RESET_FAIL;
     298                usb_log_warning("(%p-%u): Port reset complete but port not "
     299                    "enabled.", hub, port->port_number);
    325300        }
    326301        fibril_condvar_broadcast(&port->reset_cv);
     
    330305        int rc = usb_hub_port_clear_feature(port, USB_HUB_FEATURE_C_PORT_RESET);
    331306        if (rc != EOK) {
    332                 usb_log_error(
    333                     "Failed to clear port %zu reset change feature: %s.\n",
    334                     port->port_number, str_error(rc));
     307                usb_log_error("(%p-%u): Failed to clear port reset change: %s.",
     308                    hub, port->port_number, str_error(rc));
    335309        }
    336310}
     
    376350}
    377351
    378 /** Callback for enabling a specific port.
    379  *
    380  * We wait on a CV until port is reseted.
    381  * That is announced via change on interrupt pipe.
    382  *
    383  * @param port_no Port number (starting at 1).
    384  * @param arg Custom argument, points to @c usb_hub_dev_t.
    385  * @return Error code.
    386  */
    387 static int enable_port_callback(void *arg)
    388 {
    389         usb_hub_port_t *port = arg;
    390         assert(port);
    391         const int rc =
    392             usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
    393         if (rc != EOK) {
    394                 usb_log_warning("Port reset failed: %s.\n", str_error(rc));
     352static int port_enable(usb_hub_port_t *port, usb_hub_dev_t *hub, bool enable)
     353{
     354        if (enable) {
     355                int rc =
     356                    usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
     357                if (rc != EOK) {
     358                        usb_log_error("(%p-%u): Port reset request failed: %s.",
     359                            hub, port->port_number, str_error(rc));
     360                        return rc;
     361                }
     362                /* Wait until reset completes. */
     363                fibril_mutex_lock(&port->mutex);
     364                port->reset_status = IN_RESET;
     365                while (port->reset_status == IN_RESET)
     366                        fibril_condvar_wait(&port->reset_cv, &port->mutex);
     367                rc = port->reset_status == RESET_OK ? EOK : ESTALL;
     368                fibril_mutex_unlock(&port->mutex);
    395369                return rc;
    396         }
    397 
    398         /*
    399          * Wait until reset completes.
    400          */
    401         fibril_mutex_lock(&port->mutex);
    402         while (!port->reset_completed) {
    403                 fibril_condvar_wait(&port->reset_cv, &port->mutex);
    404         }
    405         fibril_mutex_unlock(&port->mutex);
    406 
    407         return port->reset_okay ? EOK : ESTALL;
     370        } else {
     371                return usb_hub_port_clear_feature(port,
     372                                USB_HUB_FEATURE_PORT_ENABLE);
     373        }
    408374}
    409375
     
    418384int add_device_phase1_worker_fibril(void *arg)
    419385{
    420         struct add_device_phase1 *data = arg;
    421         assert(data);
    422 
    423         usb_address_t new_address;
    424         ddf_fun_t *child_fun;
    425 
    426         child_fun = ddf_fun_create(data->hub->usb_device->ddf_dev,
    427             fun_inner, NULL);
    428         if (child_fun == NULL)
    429                 return ENOMEM;
    430 
    431         const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    432             child_fun, &data->hub->usb_device->hc_conn, data->speed,
    433             enable_port_callback, data->port, &new_address, NULL);
    434 
    435         if (rc == EOK) {
    436                 fibril_mutex_lock(&data->port->mutex);
    437                 data->port->attached_device.fun = child_fun;
    438                 data->port->attached_device.address = new_address;
    439                 fibril_mutex_unlock(&data->port->mutex);
    440 
    441                 usb_log_info("Detected new device on `%s' (port %zu), "
    442                     "address %d (handle %" PRIun ").\n",
    443                     ddf_dev_get_name(data->hub->usb_device->ddf_dev),
    444                     data->port->port_number, new_address,
    445                     ddf_fun_get_handle(child_fun));
     386        struct add_device_phase1 *params = arg;
     387        assert(params);
     388
     389        int ret = EOK;
     390        usb_hub_dev_t *hub = params->hub;
     391        usb_hub_port_t *port = params->port;
     392        const usb_speed_t speed = params->speed;
     393        free(arg);
     394
     395        usb_log_debug("(%p-%u): New device sequence.", hub, port->port_number);
     396
     397        async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device);
     398        if (!exch) {
     399                usb_log_error("(%p-%u): Failed to begin bus exchange.", hub,
     400                    port->port_number);
     401                ret = ENOMEM;
     402                goto out;
     403        }
     404
     405        /* Reserve default address */
     406        while ((ret = usb_reserve_default_address(exch, speed)) == ENOENT) {
     407                async_usleep(1000000);
     408        }
     409        if (ret != EOK) {
     410                usb_log_error("(%p-%u): Failed to reserve default address: %s",
     411                    hub, port->port_number, str_error(ret));
     412                goto out;
     413        }
     414
     415        usb_log_debug("(%p-%u): Got default address reseting port.", hub,
     416            port->port_number);
     417        /* Reset port */
     418        ret = port_enable(port, hub, true);
     419        if (ret != EOK) {
     420                usb_log_error("(%p-%u): Failed to reset port.", hub,
     421                    port->port_number);
     422                if (usb_release_default_address(exch) != EOK)
     423                        usb_log_warning("(%p-%u): Failed to release default "
     424                            "address.", hub, port->port_number);
     425                ret = EIO;
     426                goto out;
     427        }
     428        usb_log_debug("(%p-%u): Port reset, enumerating device", hub,
     429            port->port_number);
     430
     431        ret = usb_device_enumerate(exch, port->port_number);
     432        if (ret != EOK) {
     433                usb_log_error("(%p-%u): Failed to enumerate device: %s", hub,
     434                    port->port_number, str_error(ret));
     435                const int ret = port_enable(port, hub, false);
     436                if (ret != EOK) {
     437                        usb_log_warning("(%p-%u)Failed to disable port (%s), "
     438                            "NOT releasing default address.", hub,
     439                            port->port_number, str_error(ret));
     440                } else {
     441                        const int ret = usb_release_default_address(exch);
     442                        if (ret != EOK)
     443                                usb_log_warning("(%p-%u): Failed to release "
     444                                    "default address: %s", hub,
     445                                    port->port_number, str_error(ret));
     446                }
    446447        } else {
    447                 ddf_fun_destroy(child_fun);
    448                 usb_log_error("Failed registering device on port %zu: %s.\n",
    449                     data->port->port_number, str_error(rc));
    450         }
    451 
    452 
    453         fibril_mutex_lock(&data->hub->pending_ops_mutex);
    454         assert(data->hub->pending_ops_count > 0);
    455         --data->hub->pending_ops_count;
    456         fibril_condvar_signal(&data->hub->pending_ops_cv);
    457         fibril_mutex_unlock(&data->hub->pending_ops_mutex);
    458 
    459         free(arg);
    460 
    461         return rc;
     448                usb_log_debug("(%p-%u): Device enumerated", hub,
     449                    port->port_number);
     450                port->device_attached = true;
     451                if (usb_release_default_address(exch) != EOK)
     452                        usb_log_warning("(%p-%u): Failed to release default "
     453                            "address", hub, port->port_number);
     454        }
     455out:
     456        usb_device_bus_exchange_end(exch);
     457
     458        fibril_mutex_lock(&hub->pending_ops_mutex);
     459        assert(hub->pending_ops_count > 0);
     460        --hub->pending_ops_count;
     461        fibril_condvar_signal(&hub->pending_ops_cv);
     462        fibril_mutex_unlock(&hub->pending_ops_mutex);
     463
     464        return ret;
    462465}
    463466
     
    485488        data->speed = speed;
    486489
    487         fibril_mutex_lock(&port->mutex);
    488         port->reset_completed = false;
    489         fibril_mutex_unlock(&port->mutex);
    490 
    491490        fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
    492491        if (fibril == 0) {
  • uspace/drv/bus/usb/usbhub/port.h

    r5b18137 rb4b534ac  
    3737
    3838#include <usb/dev/driver.h>
    39 #include <usb/dev/hub.h>
    4039#include <usb/classes/hub.h>
     40#include <usb_iface.h>
    4141
    4242typedef struct usb_hub_dev usb_hub_dev_t;
     
    4444/** Information about single port on a hub. */
    4545typedef struct {
    46         /* Port number as reported in descriptors. */
    47         size_t port_number;
     46        /** Port number as reported in descriptors. */
     47        unsigned port_number;
    4848        /** Device communication pipe. */
    4949        usb_pipe_t *control_pipe;
     
    5252        /** CV for waiting to port reset completion. */
    5353        fibril_condvar_t reset_cv;
    54         /** Whether port reset is completed.
     54        /** Port reset status.
    5555         * Guarded by @c reset_mutex.
    5656         */
    57         bool reset_completed;
    58         /** Whether to announce the port reset as successful. */
    59         bool reset_okay;
    60 
    61         /** Information about attached device. */
    62         usb_hub_attached_device_t attached_device;
     57        enum {
     58                NO_RESET,
     59                IN_RESET,
     60                RESET_OK,
     61                RESET_FAIL,
     62        } reset_status;
     63        /** Device reported to USB bus driver */
     64        bool device_attached;
    6365} usb_hub_port_t;
    6466
     
    6769 * @param port Port to be initialized.
    6870 */
    69 static inline void usb_hub_port_init(usb_hub_port_t *port, size_t port_number,
     71static inline void usb_hub_port_init(usb_hub_port_t *port, unsigned port_number,
    7072    usb_pipe_t *control_pipe)
    7173{
    7274        assert(port);
    73         port->attached_device.address = -1;
    74         port->attached_device.fun = NULL;
    7575        port->port_number = port_number;
    7676        port->control_pipe = control_pipe;
     77        port->reset_status = NO_RESET;
     78        port->device_attached = false;
    7779        fibril_mutex_initialize(&port->mutex);
    7880        fibril_condvar_initialize(&port->reset_cv);
  • uspace/drv/bus/usb/usbhub/status.h

    r5b18137 rb4b534ac  
    6464#define USB_HUB_PORT_STATUS_HIGH_SPEED \
    6565    (uint32_usb2host(1 << 10))
     66#define USB_HUB_PORT_STATUS_TEST_MODE \
     67    (uint32_usb2host(1 << 11))
     68#define USB_HUB_PORT_INDICATOR_CONTROL \
     69    (uint32_usb2host(1 << 12))
    6670
    6771#define USB_HUB_PORT_C_STATUS_CONNECTION \
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r5b18137 rb4b534ac  
    4545#include <usb/dev/pipes.h>
    4646#include <usb/classes/classes.h>
    47 #include <usb/ddfiface.h>
    4847#include <usb/descriptor.h>
    4948#include <usb/dev/recognise.h>
     
    5756
    5857#define HUB_FNC_NAME "hub"
     58/** Hub status-change endpoint description.
     59 *
     60 * For more information see section 11.15.1 of USB 1.1 specification.
     61 */
     62const usb_endpoint_description_t hub_status_change_endpoint_description =
     63{
     64        .transfer_type = USB_TRANSFER_INTERRUPT,
     65        .direction = USB_DIRECTION_IN,
     66        .interface_class = USB_CLASS_HUB,
     67        .interface_subclass = 0,
     68        .interface_protocol = 0,
     69        .flags = 0
     70};
    5971
    6072/** Standard get hub global status request */
     
    99111        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
    100112
    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",
    105                     str_error(opResult));
    106                 return opResult;
    107         }
    108 
    109113        /* Set hub's first configuration. (There should be only one) */
    110         opResult = usb_set_first_configuration(usb_dev);
    111         if (opResult != EOK) {
    112                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     114        int opResult = usb_set_first_configuration(usb_dev);
     115        if (opResult != EOK) {
    113116                usb_log_error("Could not set hub configuration: %s\n",
    114117                    str_error(opResult));
     
    119122        opResult = usb_hub_process_hub_specific_info(hub_dev);
    120123        if (opResult != EOK) {
    121                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    122124                usb_log_error("Could process hub specific info, %s\n",
    123125                    str_error(opResult));
     
    127129        /* Create hub control function. */
    128130        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    129         hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
     131        hub_dev->hub_fun = usb_device_ddf_fun_create(hub_dev->usb_device,
    130132            fun_exposed, HUB_FNC_NAME);
    131133        if (hub_dev->hub_fun == NULL) {
    132                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    133134                usb_log_error("Failed to create hub function.\n");
    134135                return ENOMEM;
     
    138139        opResult = ddf_fun_bind(hub_dev->hub_fun);
    139140        if (opResult != EOK) {
    140                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
    141141                usb_log_error("Failed to bind hub function: %s.\n",
    142142                   str_error(opResult));
     
    146146
    147147        /* Start hub operation. */
    148         opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
    149             hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
    150             usb_hub_polling_terminated_callback, hub_dev);
    151         if (opResult != EOK) {
    152                 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     148        opResult = usb_device_auto_poll_desc(hub_dev->usb_device,
     149            &hub_status_change_endpoint_description,
     150            hub_port_changes_callback, ((hub_dev->port_count + 1 + 7) / 8),
     151            -1, usb_hub_polling_terminated_callback, hub_dev);
     152        if (opResult != EOK) {
    153153                /* Function is already bound */
    154154                ddf_fun_unbind(hub_dev->hub_fun);
     
    159159        }
    160160        hub_dev->running = true;
    161         usb_log_info("Controlling hub '%s' (%zu ports).\n",
    162             ddf_dev_get_name(hub_dev->usb_device->ddf_dev), hub_dev->port_count);
    163 
    164         usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
     161        usb_log_info("Controlling hub '%s' (%p: %zu ports).\n",
     162            usb_device_get_name(hub_dev->usb_device), hub_dev,
     163            hub_dev->port_count);
     164
    165165        return EOK;
    166166}
     
    185185{
    186186        assert(usb_dev);
    187         usb_hub_dev_t *hub = usb_dev->driver_data;
     187        usb_hub_dev_t *hub = usb_device_data_get(usb_dev);
    188188        assert(hub);
    189189        unsigned tries = 10;
     
    191191                async_usleep(100000);
    192192                if (!tries--) {
    193                         usb_log_error("Can't remove hub, still running.\n");
     193                        usb_log_error("(%p): Can't remove hub, still running.",
     194                            hub);
    194195                        return EBUSY;
    195196                }
     
    199200
    200201        for (size_t port = 0; port < hub->port_count; ++port) {
    201                 if (hub->ports[port].attached_device.fun) {
    202                         const int ret =
    203                             usb_hub_port_fini(&hub->ports[port], hub);
    204                         if (ret != EOK)
    205                                 return ret;
    206                 }
     202                const int ret = usb_hub_port_fini(&hub->ports[port], hub);
     203                if (ret != EOK)
     204                        return ret;
    207205        }
    208206        free(hub->ports);
     
    210208        const int ret = ddf_fun_unbind(hub->hub_fun);
    211209        if (ret != EOK) {
    212                 usb_log_error("Failed to unbind '%s' function: %s.\n",
    213                    HUB_FNC_NAME, str_error(ret));
     210                usb_log_error("(%p) Failed to unbind '%s' function: %s.",
     211                   hub, HUB_FNC_NAME, str_error(ret));
    214212                return ret;
    215213        }
    216214        ddf_fun_destroy(hub->hub_fun);
    217215
    218         usb_log_info("USB hub driver, stopped and cleaned.\n");
     216        usb_log_info("(%p) USB hub driver stopped and cleaned.", hub);
    219217        return EOK;
    220218}
     
    231229    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
    232230{
    233         usb_log_debug("hub_port_changes_callback\n");
     231//      usb_log_debug("hub_port_changes_callback\n");
    234232        usb_hub_dev_t *hub = arg;
    235233        assert(hub);
     
    247245
    248246        /* N + 1 bit indicates change on port N */
    249         for (size_t port = 0; port < hub->port_count + 1; port++) {
     247        for (size_t port = 0; port < hub->port_count; ++port) {
    250248                const size_t bit = port + 1;
    251249                const bool change = (change_bitmap[bit / 8] >> (bit % 8)) & 1;
     
    272270
    273271        /* Get hub descriptor. */
    274         usb_log_debug("Retrieving descriptor\n");
    275         usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe;
     272        usb_log_debug("(%p): Retrieving descriptor.", hub_dev);
     273        usb_pipe_t *control_pipe =
     274            usb_device_get_default_pipe(hub_dev->usb_device);
    276275
    277276        usb_hub_descriptor_header_t descriptor;
     
    282281            sizeof(usb_hub_descriptor_header_t), &received_size);
    283282        if (opResult != EOK) {
    284                 usb_log_error("Failed to receive hub descriptor: %s.\n",
    285                     str_error(opResult));
     283                usb_log_error("(%p): Failed to receive hub descriptor: %s.\n",
     284                    hub_dev, str_error(opResult));
    286285                return opResult;
    287286        }
    288287
    289         usb_log_debug("Setting port count to %d.\n", descriptor.port_count);
     288        usb_log_debug("(%p): Setting port count to %d.\n", hub_dev,
     289            descriptor.port_count);
    290290        hub_dev->port_count = descriptor.port_count;
    291291
     
    306306
    307307        if (!hub_dev->power_switched) {
    308                 usb_log_info(
    309                    "Power switching not supported, ports always powered.\n");
     308                usb_log_info("(%p): Power switching not supported, "
     309                    "ports always powered.", hub_dev);
    310310                return EOK;
    311311        }
    312312
    313         usb_log_info("Hub port power switching enabled.\n");
    314 
    315         for (size_t port = 0; port < hub_dev->port_count; ++port) {
    316                 usb_log_debug("Powering port %zu.\n", port);
     313        usb_log_info("(%p): Hub port power switching enabled (%s).\n", hub_dev,
     314            hub_dev->per_port_power ? "per port" : "ganged");
     315
     316        for (unsigned port = 0; port < hub_dev->port_count; ++port) {
     317                usb_log_debug("(%p): Powering port %u.", hub_dev, port);
    317318                const int ret = usb_hub_port_set_feature(
    318319                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    319320
    320321                if (ret != EOK) {
    321                         usb_log_error("Cannot power on port %zu: %s.\n",
    322                             hub_dev->ports[port].port_number, str_error(ret));
     322                        usb_log_error("(%p-%u): Cannot power on port: %s.\n",
     323                            hub_dev, hub_dev->ports[port].port_number,
     324                            str_error(ret));
    323325                } else {
    324326                        if (!hub_dev->per_port_power) {
    325                                 usb_log_debug("Ganged power switching, "
    326                                     "one port is enough.\n");
     327                                usb_log_debug("(%p) Ganged power switching, "
     328                                    "one port is enough.", hub_dev);
    327329                                break;
    328330                        }
     
    345347        /* Get number of possible configurations from device descriptor */
    346348        const size_t configuration_count =
    347             usb_device->descriptors.device.configuration_count;
     349            usb_device_descriptors(usb_device)->device.configuration_count;
    348350        usb_log_debug("Hub has %zu configurations.\n", configuration_count);
    349351
     
    353355        }
    354356
    355         if (usb_device->descriptors.configuration_size
    356             < sizeof(usb_standard_configuration_descriptor_t)) {
     357        const size_t config_size =
     358            usb_device_descriptors(usb_device)->full_config_size;
     359        const usb_standard_configuration_descriptor_t *config_descriptor =
     360            usb_device_descriptors(usb_device)->full_config;
     361
     362        if (config_size < sizeof(usb_standard_configuration_descriptor_t)) {
    357363            usb_log_error("Configuration descriptor is not big enough"
    358364                " to fit standard configuration descriptor.\n");
     
    360366        }
    361367
    362         // TODO: Make sure that the cast is correct
    363         usb_standard_configuration_descriptor_t *config_descriptor
    364             = (usb_standard_configuration_descriptor_t *)
    365             usb_device->descriptors.configuration;
    366 
    367368        /* Set configuration. Use the configuration that was in
    368369         * usb_device->descriptors.configuration i.e. The first one. */
    369370        const int opResult = usb_request_set_configuration(
    370             &usb_device->ctrl_pipe, config_descriptor->configuration_number);
     371            usb_device_get_default_pipe(usb_device),
     372            config_descriptor->configuration_number);
    371373        if (opResult != EOK) {
    372374                usb_log_error("Failed to set hub configuration: %s.\n",
     
    392394        if (status & USB_HUB_STATUS_OVER_CURRENT) {
    393395                /* Hub should remove power from all ports if it detects OC */
    394                 usb_log_warning("Detected hub over-current condition, "
    395                     "all ports should be powered off.");
     396                usb_log_warning("(%p) Detected hub over-current condition, "
     397                    "all ports should be powered off.", hub_dev);
    396398                return;
    397399        }
     
    406408                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    407409                if (ret != EOK) {
    408                         usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on"
    409                             " port %zu: %s\n", hub_dev->ports[port].port_number,
    410                             str_error(ret));
     410                        usb_log_warning("(%p-%u): HUB OVER-CURRENT GONE: Cannot"
     411                            " power on port: %s\n", hub_dev,
     412                            hub_dev->ports[port].port_number, str_error(ret));
    411413                } else {
    412414                        if (!hub_dev->per_port_power)
     
    427429        assert(hub_dev);
    428430        assert(hub_dev->usb_device);
    429         usb_log_debug("Global interrupt on a hub\n");
    430         usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe;
     431        usb_log_debug("(%p): Global interrupt on th hub.",  hub_dev);
     432        usb_pipe_t *control_pipe =
     433            usb_device_get_default_pipe(hub_dev->usb_device);
    431434
    432435        usb_hub_status_t status;
     
    438441            &status, sizeof(usb_hub_status_t), &rcvd_size);
    439442        if (opResult != EOK) {
    440                 usb_log_error("Could not get hub status: %s\n",
     443                usb_log_error("(%p): Could not get hub status: %s.", hub_dev,
    441444                    str_error(opResult));
    442445                return;
    443446        }
    444447        if (rcvd_size != sizeof(usb_hub_status_t)) {
    445                 usb_log_error("Received status has incorrect size\n");
     448                usb_log_error("(%p): Received status has incorrect size: "
     449                    "%zu != %zu", hub_dev, rcvd_size, sizeof(usb_hub_status_t));
    446450                return;
    447451        }
     
    452456                /* Ack change in hub OC flag */
    453457                const int ret = usb_request_clear_feature(
    454                     &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     458                    control_pipe, USB_REQUEST_TYPE_CLASS,
    455459                    USB_REQUEST_RECIPIENT_DEVICE,
    456460                    USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0);
    457461                if (ret != EOK) {
    458                         usb_log_error("Failed to clear hub over-current "
    459                             "change flag: %s.\n", str_error(opResult));
     462                        usb_log_error("(%p): Failed to clear hub over-current "
     463                            "change flag: %s.\n", hub_dev, str_error(opResult));
    460464                }
    461465        }
     
    480484                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    481485                if (opResult != EOK) {
    482                         usb_log_error("Failed to clear hub power change "
    483                             "flag: %s.\n", str_error(ret));
     486                        usb_log_error("(%p): Failed to clear hub power change "
     487                            "flag: %s.\n", hub_dev, str_error(ret));
    484488                }
    485489        }
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r5b18137 rb4b534ac  
    3939#include <ddf/driver.h>
    4040
    41 #include <usb/dev/hub.h>
    4241#include <usb/classes/hub.h>
    4342
     
    8180};
    8281
     82extern const usb_endpoint_description_t hub_status_change_endpoint_description;
     83
    8384int usb_hub_device_add(usb_device_t *usb_dev);
    8485int usb_hub_device_remove(usb_device_t *usb_dev);
  • uspace/drv/bus/usb/usbmast/bo_trans.c

    r5b18137 rb4b534ac  
    4444#include "usbmast.h"
    4545
    46 bool usb_mast_verbose = false;
    4746
    4847#define MASTLOG(format, ...) \
    49         do { \
    50                 if (usb_mast_verbose) { \
    51                         usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \
    52                 } \
    53         } while (false)
     48        usb_log_debug2("USB cl08: " format, ##__VA_ARGS__)
    5449
    5550/** Send command via bulk-only transport.
     
    6560{
    6661        int rc;
    67         int retval = EOK;
    68         size_t act_size;
    69         usb_pipe_t *bulk_in_pipe = &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
    70         usb_pipe_t *bulk_out_pipe = &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
    71         usb_direction_t ddir;
    72         void *dbuf;
    73         size_t dbuf_size;
    74 
    75         if (cmd->data_out != NULL && cmd->data_in == NULL) {
    76                 ddir = USB_DIRECTION_OUT;
    77                 dbuf = (void *)cmd->data_out;
    78                 dbuf_size = cmd->data_out_size;
    79         } else if (cmd->data_out == NULL && cmd->data_in != NULL) {
     62
     63        if (cmd->data_in && cmd->data_out)
     64                return EINVAL;
     65
     66        usb_pipe_t *bulk_in_pipe = mfun->mdev->bulk_in_pipe;
     67        usb_pipe_t *bulk_out_pipe = mfun->mdev->bulk_out_pipe;
     68
     69        usb_pipe_t *dpipe = bulk_out_pipe;
     70        usb_direction_t ddir = USB_DIRECTION_OUT;
     71        size_t dbuf_size = cmd->data_out_size;
     72
     73        if (cmd->data_in) {
    8074                ddir = USB_DIRECTION_IN;
    81                 dbuf = cmd->data_in;
    8275                dbuf_size = cmd->data_in_size;
    83         } else {
    84                 assert(false);
     76                dpipe = bulk_in_pipe;
    8577        }
    8678
     
    9688            usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
    9789            str_error(rc));
    98         if (rc != EOK)
    99                 return EIO;
     90        if (rc != EOK) {
     91                usb_log_error("Bulk out write failed: %s\n", str_error(rc));
     92                return EIO;
     93        }
    10094
    10195        MASTLOG("Transferring data.\n");
    102         if (ddir == USB_DIRECTION_IN) {
     96        if (cmd->data_in) {
     97                size_t act_size;
    10398                /* Recieve data from the device. */
    104                 rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size);
     99                rc = usb_pipe_read(dpipe, cmd->data_in, cmd->data_in_size,
     100                    &act_size);
    105101                MASTLOG("Received %zu bytes (%s): %s.\n", act_size,
    106                     usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
     102                    usb_debug_str_buffer(cmd->data_in, act_size, 0),
    107103                    str_error(rc));
    108         } else {
     104        }
     105        if (cmd->data_out) {
    109106                /* Send data to the device. */
    110                 rc = usb_pipe_write(bulk_out_pipe, dbuf, dbuf_size);
    111                 MASTLOG("Sent %zu bytes (%s): %s.\n", act_size,
    112                     usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
     107                rc = usb_pipe_write(dpipe, cmd->data_out, cmd->data_out_size);
     108                MASTLOG("Sent %zu bytes (%s): %s.\n", cmd->data_out_size,
     109                    usb_debug_str_buffer(cmd->data_out, cmd->data_out_size, 0),
    113110                    str_error(rc));
    114111        }
     
    116113        if (rc == ESTALL) {
    117114                /* Clear stall condition and continue below to read CSW. */
    118                 if (ddir == USB_DIRECTION_IN) {
    119                         usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
    120                             &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
    121                 } else {
    122                         usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
    123                             &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
    124                 }
     115                usb_pipe_clear_halt(
     116                    usb_device_get_default_pipe(mfun->mdev->usb_dev), dpipe);
    125117        } else if (rc != EOK) {
     118                usb_log_error("Failed to transfer data: %s", str_error(rc));
    126119                return EIO;
    127120        }
     
    136129            str_error(rc));
    137130        if (rc != EOK) {
    138                 MASTLOG("rc != EOK\n");
     131                usb_log_error("Failed to read CSW: %s", str_error(rc));
    139132                return EIO;
    140133        }
    141134
    142135        if (csw_size != sizeof(csw)) {
    143                 MASTLOG("csw_size != sizeof(csw)\n");
     136                usb_log_error("Received CSW of incorrect size.");
    144137                return EIO;
    145138        }
    146139
    147140        if (csw.dCSWTag != tag) {
    148                 MASTLOG("csw.dCSWTag != tag\n");
     141                usb_log_error("Received CSW with incorrect tag. (expected: %"
     142                    PRIX32" received: %"PRIx32, tag, csw.dCSWTag);
    149143                return EIO;
    150144        }
     
    158152                break;
    159153        case cbs_failed:
    160                 MASTLOG("Command failed\n");
    161154                cmd->status = CMDS_FAILED;
     155                usb_log_error("CBS Failed.\n");
    162156                break;
    163157        case cbs_phase_error:
    164                 MASTLOG("Phase error\n");
    165                 retval = EIO;
     158                usb_log_error("CBS phase error.\n");
     159                rc = EIO;
    166160                break;
    167161        default:
    168                 retval = EIO;
    169                 break;
    170         }
    171 
    172         size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
     162                usb_log_error("CBS other error.\n");
     163                rc = EIO;
     164                break;
     165        }
     166
     167        const size_t residue = uint32_usb2host(csw.dCSWDataResidue);
    173168        if (residue > dbuf_size) {
    174                 MASTLOG("residue > dbuf_size\n");
     169                usb_log_error("Residue > buffer size (%zu > %zu).\n",
     170                    residue, dbuf_size);
    175171                return EIO;
    176172        }
     
    184180         */
    185181
    186         if (ddir == USB_DIRECTION_IN)
     182        if (cmd->data_in)
    187183                cmd->rcvd_size = dbuf_size - residue;
    188184
    189         return retval;
     185        return rc;
    190186}
    191187
     
    197193int usb_massstor_reset(usbmast_dev_t *mdev)
    198194{
    199         return usb_control_request_set(&mdev->usb_dev->ctrl_pipe,
     195        return usb_control_request_set(
     196            usb_device_get_default_pipe(mdev->usb_dev),
    200197            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    201             0xFF, 0, mdev->usb_dev->interface_no, NULL, 0);
     198            0xFF, 0, usb_device_get_iface_number(mdev->usb_dev), NULL, 0);
    202199}
    203200
     
    215212         */
    216213        usb_massstor_reset(mdev);
    217         usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
    218             &mdev->usb_dev->pipes[BULK_IN_EP].pipe);
    219         usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
    220             &mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
     214        usb_pipe_clear_halt(usb_device_get_default_pipe(mdev->usb_dev),
     215            mdev->bulk_in_pipe);
     216        usb_pipe_clear_halt(usb_device_get_default_pipe(mdev->usb_dev),
     217            mdev->bulk_out_pipe);
    221218}
    222219
     
    236233        uint8_t max_lun;
    237234        size_t data_recv_len;
    238         int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe,
     235        int rc = usb_control_request_get(
     236            usb_device_get_default_pipe(mdev->usb_dev),
    239237            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    240             0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len);
     238            0xFE, 0, usb_device_get_iface_number(mdev->usb_dev), &max_lun, 1,
     239            &data_recv_len);
    241240        if (rc != EOK) {
    242241                return rc;
  • uspace/drv/bus/usb/usbmast/bo_trans.h

    r5b18137 rb4b534ac  
    4444#include "usbmast.h"
    4545
    46 #define BULK_IN_EP 0
    47 #define BULK_OUT_EP 1
    48 
    4946typedef enum cmd_status {
    5047        CMDS_GOOD,
     
    6360
    6461        /** Command Descriptor Block */
    65         void *cdb;
     62        const void *cdb;
    6663        /** CDB size in bytes */
    6764        size_t cdb_size;
  • uspace/drv/bus/usb/usbmast/main.c

    r5b18137 rb4b534ac  
    4444#include <usb/classes/massstor.h>
    4545#include <errno.h>
     46#include <io/logctl.h>
    4647#include <str_error.h>
    4748#include "cmdw.h"
     
    5152
    5253#define NAME "usbmast"
    53 
    54 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
    55 #define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
    5654
    5755static const usb_endpoint_description_t bulk_in_ep = {
     
    112110static int usbmast_device_gone(usb_device_t *dev)
    113111{
    114         usbmast_dev_t *mdev = dev->driver_data;
     112        usbmast_dev_t *mdev = usb_device_data_get(dev);
    115113        assert(mdev);
    116114
     
    152150        unsigned i;
    153151
     152        usb_endpoint_mapping_t *epm_in =
     153            usb_device_get_mapped_ep_desc(dev, &bulk_in_ep);
     154        usb_endpoint_mapping_t *epm_out =
     155            usb_device_get_mapped_ep_desc(dev, &bulk_out_ep);
     156        if (!epm_in || !epm_out || !epm_in->present || !epm_out->present) {
     157                usb_log_error("Required EPs were not mapped.\n");
     158                return ENOENT;
     159        }
     160
    154161        /* Allocate softstate */
    155162        mdev = usb_device_data_alloc(dev, sizeof(usbmast_dev_t));
     
    159166        }
    160167
    161         mdev->ddf_dev = dev->ddf_dev;
    162168        mdev->usb_dev = dev;
    163169
    164         usb_log_info("Initializing mass storage `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
     170        usb_log_info("Initializing mass storage `%s'.\n",
     171            usb_device_get_name(dev));
    165172        usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
    166             dev->pipes[BULK_IN_EP].pipe.endpoint_no,
    167             dev->pipes[BULK_IN_EP].pipe.max_packet_size);
     173            epm_in->pipe.endpoint_no, epm_in->pipe.max_packet_size);
    168174        usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
    169             dev->pipes[BULK_OUT_EP].pipe.endpoint_no,
    170             dev->pipes[BULK_OUT_EP].pipe.max_packet_size);
     175            epm_out->pipe.endpoint_no, epm_out->pipe.max_packet_size);
    171176
    172177        usb_log_debug("Get LUN count...\n");
     
    179184        }
    180185
     186        mdev->bulk_in_pipe = &epm_in->pipe;
     187        mdev->bulk_out_pipe = &epm_out->pipe;
    181188        for (i = 0; i < mdev->lun_count; i++) {
    182189                rc = usbmast_fun_create(mdev, i);
     
    223230        }
    224231
    225         fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
     232        fun = usb_device_ddf_fun_create(mdev->usb_dev, fun_exposed, fun_name);
    226233        if (fun == NULL) {
    227234                usb_log_error("Failed to create DDF function %s.\n", fun_name);
     
    254261        if (rc != EOK) {
    255262                usb_log_warning("Failed to inquire device `%s': %s.\n",
    256                     ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
     263                    usb_device_get_name(mdev->usb_dev), str_error(rc));
    257264                rc = EIO;
    258265                goto error;
     
    261268        usb_log_info("Mass storage `%s' LUN %u: " \
    262269            "%s by %s rev. %s is %s (%s).\n",
    263             ddf_dev_get_name(mdev->ddf_dev),
     270            usb_device_get_name(mdev->usb_dev),
    264271            lun,
    265272            inquiry.product,
     
    274281        if (rc != EOK) {
    275282                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    276                     ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
     283                    usb_device_get_name(mdev->usb_dev), str_error(rc));
    277284                rc = EIO;
    278285                goto error;
     
    396403{
    397404        log_init(NAME);
    398 
     405        logctl_set_log_level(NAME, LVL_NOTE);
    399406        return usb_driver_main(&usbmast_driver);
    400407}
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    r5b18137 rb4b534ac  
    6363static void usbmast_dump_sense(scsi_sense_data_t *sense_buf)
    6464{
    65         unsigned sense_key;
    66 
    67         sense_key = sense_buf->flags_key & 0x0f;
     65        const unsigned sense_key = sense_buf->flags_key & 0x0f;
    6866        printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, "
    6967            "ASCQ 0x%02x.\n", sense_key,
     
    7371}
    7472
     73static int usb_massstor_unit_ready(usbmast_fun_t *mfun)
     74{
     75        scsi_cmd_t cmd;
     76        scsi_cdb_test_unit_ready_t cdb;
     77        int rc;
     78
     79        memset(&cdb, 0, sizeof(cdb));
     80        cdb.op_code = SCSI_CMD_TEST_UNIT_READY;
     81
     82        memset(&cmd, 0, sizeof(cmd));
     83        cmd.cdb = &cdb;
     84        cmd.cdb_size = sizeof(cdb);
     85
     86        rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
     87
     88        if (rc != EOK) {
     89                usb_log_error("Test Unit Ready failed on device %s: %s.",
     90                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
     91                return rc;
     92        }
     93        /* Ignore command error here. If there's something wrong
     94         * with the device the following commands will fail too.
     95         */
     96        if (cmd.status != CMDS_GOOD)
     97                usb_log_warning("Test Unit Ready command failed on device %s.",
     98                   usb_device_get_name(mfun->mdev->usb_dev));
     99
     100        return EOK;
     101}
     102
    75103/** Run SCSI command.
    76104 *
     
    85113
    86114        do {
     115                rc = usb_massstor_unit_ready(mfun);
     116                if (rc != EOK) {
     117                        usb_log_error("Inquiry transport failed, device %s: %s.\n",
     118                           usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
     119                        return rc;
     120                }
     121
    87122                rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd);
    88123                if (rc != EOK) {
    89124                        usb_log_error("Inquiry transport failed, device %s: %s.\n",
    90                            ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     125                           usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    91126                        return rc;
    92127                }
     
    96131
    97132                usb_log_error("SCSI command failed, device %s.\n",
    98                     ddf_dev_get_name(mfun->mdev->ddf_dev));
     133                    usb_device_get_name(mfun->mdev->usb_dev));
    99134
    100135                rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
     
    147182        if (rc != EOK) {
    148183                usb_log_error("Inquiry transport failed, device %s: %s.\n",
    149                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     184                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    150185                return rc;
    151186        }
     
    153188        if (cmd.status != CMDS_GOOD) {
    154189                usb_log_error("Inquiry command failed, device %s.\n",
    155                    ddf_dev_get_name(mfun->mdev->ddf_dev));
     190                   usb_device_get_name(mfun->mdev->usb_dev));
    156191                return EIO;
    157192        }
     
    215250        if (rc != EOK || cmd.status != CMDS_GOOD) {
    216251                usb_log_error("Request Sense failed, device %s: %s.\n",
    217                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     252                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    218253                return rc;
    219254        }
     
    257292        if (rc != EOK) {
    258293                usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
    259                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     294                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    260295                return rc;
    261296        }
     
    263298        if (cmd.status != CMDS_GOOD) {
    264299                usb_log_error("Read Capacity (10) command failed, device %s.\n",
    265                    ddf_dev_get_name(mfun->mdev->ddf_dev));
     300                   usb_device_get_name(mfun->mdev->usb_dev));
    266301                return EIO;
    267302        }
     
    314349        if (rc != EOK) {
    315350                usb_log_error("Read (10) transport failed, device %s: %s.\n",
    316                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     351                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    317352                return rc;
    318353        }
     
    320355        if (cmd.status != CMDS_GOOD) {
    321356                usb_log_error("Read (10) command failed, device %s.\n",
    322                    ddf_dev_get_name(mfun->mdev->ddf_dev));
     357                   usb_device_get_name(mfun->mdev->usb_dev));
    323358                return EIO;
    324359        }
     
    370405        if (rc != EOK) {
    371406                usb_log_error("Write (10) transport failed, device %s: %s.\n",
    372                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     407                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    373408                return rc;
    374409        }
     
    376411        if (cmd.status != CMDS_GOOD) {
    377412                usb_log_error("Write (10) command failed, device %s.\n",
    378                    ddf_dev_get_name(mfun->mdev->ddf_dev));
     413                   usb_device_get_name(mfun->mdev->usb_dev));
    379414                return EIO;
    380415        }
     
    394429int usbmast_sync_cache(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks)
    395430{
    396         scsi_cmd_t cmd;
    397         scsi_cdb_sync_cache_10_t cdb;
    398         int rc;
    399 
    400431        if (ba > UINT32_MAX)
    401432                return ELIMIT;
     
    404435                return ELIMIT;
    405436
    406         memset(&cdb, 0, sizeof(cdb));
    407         cdb.op_code = SCSI_CMD_SYNC_CACHE_10;
    408         cdb.lba = host2uint32_t_be(ba);
    409         cdb.numlb = host2uint16_t_be(nblocks);
    410 
    411         memset(&cmd, 0, sizeof(cmd));
    412         cmd.cdb = &cdb;
    413         cmd.cdb_size = sizeof(cdb);
    414 
    415         rc = usbmast_run_cmd(mfun, &cmd);
     437        const scsi_cdb_sync_cache_10_t cdb = {
     438                .op_code = SCSI_CMD_SYNC_CACHE_10,
     439                .lba = host2uint32_t_be(ba),
     440                .numlb = host2uint16_t_be(nblocks),
     441        };
     442
     443        scsi_cmd_t cmd = {
     444                .cdb = &cdb,
     445                .cdb_size = sizeof(cdb),
     446        };
     447
     448        const int rc = usbmast_run_cmd(mfun, &cmd);
    416449
    417450        if (rc != EOK) {
    418451                usb_log_error("Synchronize Cache (10) transport failed, device %s: %s.\n",
    419                    ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
     452                   usb_device_get_name(mfun->mdev->usb_dev), str_error(rc));
    420453                return rc;
    421454        }
     
    423456        if (cmd.status != CMDS_GOOD) {
    424457                usb_log_error("Synchronize Cache (10) command failed, device %s.\n",
    425                    ddf_dev_get_name(mfun->mdev->ddf_dev));
     458                   usb_device_get_name(mfun->mdev->usb_dev));
    426459                return EIO;
    427460        }
  • uspace/drv/bus/usb/usbmast/usbmast.h

    r5b18137 rb4b534ac  
    4343/** Mass storage device. */
    4444typedef struct usbmast_dev {
    45         /** DDF device */
    46         ddf_dev_t *ddf_dev;
    4745        /** USB device */
    4846        usb_device_t *usb_dev;
     
    5149        /** LUN functions */
    5250        ddf_fun_t **luns;
     51        /** Data read pipe */
     52        usb_pipe_t *bulk_in_pipe;
     53        /** Data write pipe */
     54        usb_pipe_t *bulk_out_pipe;
    5355} usbmast_dev_t;
    5456
  • uspace/drv/bus/usb/usbmid/explore.c

    r5b18137 rb4b534ac  
    3434 * Exploration of available interfaces in the USB device.
    3535 */
    36 #include <ddf/driver.h>
    3736#include <errno.h>
    3837#include <str_error.h>
     
    4140#include <usb/dev/request.h>
    4241#include <usb/dev/dp.h>
    43 #include <usb/ddfiface.h>
    4442#include "usbmid.h"
    45 
    46 /** Operations of the device itself. */
    47 static ddf_dev_ops_t mid_device_ops = {
    48         .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
    49 };
    5043
    5144/** Tell whether given interface is already in the list.
     
    5750static bool interface_in_list(const list_t *list, int interface_no)
    5851{
    59         list_foreach(*list, link, usbmid_interface_t, iface) {
     52        list_foreach(*list, link, const usbmid_interface_t, iface) {
    6053                if (iface->interface_no == interface_no) {
    6154                        return true;
     
    7164 * @param config_descriptor_size Size of configuration descriptor in bytes.
    7265 * @param list List where to add the interfaces.
    73  * @return EOK on success, ENOMEM if out of memory.
    7466 */
    75 static int create_interfaces(usb_mid_t *mid, const uint8_t *config_descriptor,
    76     size_t config_descriptor_size)
     67static int create_interfaces(const uint8_t *config_descriptor,
     68    size_t config_descriptor_size, list_t *list, usb_device_t *usb_dev)
    7769{
     70        assert(config_descriptor);
     71        assert(usb_dev);
     72
    7873        const usb_dp_parser_data_t data = {
    7974                .data = config_descriptor,
     
    9186        /* Walk all descriptors nested in the current configuration decriptor;
    9287         * i.e. all interface descriptors. */
    93         for (;interface_ptr != NULL;
     88        for (; interface_ptr != NULL;
    9489            interface_ptr = usb_dp_get_sibling_descriptor(
    9590                &parser, &data, config_descriptor, interface_ptr))
     
    10398
    10499                /* Skip alternate interfaces. */
    105                 if (interface_in_list(&mid->interface_list,
    106                     interface->interface_number)) {
     100                if (interface_in_list(list, interface->interface_number)) {
    107101                        /* TODO: add the alternatives and create match ids
    108102                         * for them. */
     
    110104                }
    111105
    112                 /* Create the function */
    113                 ddf_fun_t *fun = ddf_fun_create(mid->dev, fun_inner, NULL);
    114                 if (fun == NULL)
    115                         goto error;
    116106
    117                 usbmid_interface_t *iface = ddf_fun_data_alloc(fun,
    118                     sizeof(usbmid_interface_t));
    119                 if (iface == NULL)
    120                         goto error;
     107                usb_log_info("Creating child for interface %d (%s).\n",
     108                    interface->interface_number,
     109                    usb_str_class(interface->interface_class));
    121110
    122                 link_initialize(&iface->link);
    123                 iface->fun = fun;
    124                 iface->interface_no = interface->interface_number;
    125                 iface->interface = interface;
    126 
    127                 list_append(&iface->link, &mid->interface_list);
     111                usbmid_interface_t *iface = NULL;
     112                const int rc = usbmid_spawn_interface_child(usb_dev, &iface,
     113                        &usb_device_descriptors(usb_dev)->device, interface);
     114                if (rc != EOK) {
     115                        //TODO: Do something about that failure.
     116                        usb_log_error("Failed to create interface child for "
     117                            "%d (%s): %s.\n", interface->interface_number,
     118                            usb_str_class(interface->interface_class),
     119                            str_error(rc));
     120                } else {
     121                        list_append(&iface->link, list);
     122                }
    128123        }
    129 
    130124        return EOK;
    131 error:
    132         while (!list_empty(&mid->interface_list)) {
    133                 link_t *link = list_first(&mid->interface_list);
    134                 usbmid_interface_t *iface = list_get_instance(link,
    135                     usbmid_interface_t, link);
    136 
    137                 ddf_fun_destroy(iface->fun);
    138         }
    139 
    140         return ENOMEM;
    141125}
    142126
     
    149133 * @return Whether to accept this device from devman.
    150134 */
    151 bool usbmid_explore_device(usb_device_t *dev)
     135int usbmid_explore_device(usb_device_t *dev)
    152136{
    153         int rc;
    154 
    155         unsigned dev_class = dev->descriptors.device.device_class;
     137        assert(dev);
     138        const unsigned dev_class =
     139            usb_device_descriptors(dev)->device.device_class;
    156140        if (dev_class != USB_CLASS_USE_INTERFACE) {
    157141                usb_log_warning(
     
    159143                    dev_class, usb_str_class(dev_class),
    160144                    USB_CLASS_USE_INTERFACE);
    161                 usb_log_error("Not multi interface device, refusing.\n");
    162                 return false;
     145                usb_log_error("Not a multi-interface device, refusing.\n");
     146                return ENOTSUP;
    163147        }
    164148
    165         /* Shortcuts to save on typing ;-). */
    166         const void *config_descriptor_raw = dev->descriptors.configuration;
    167         size_t config_descriptor_size = dev->descriptors.configuration_size;
     149        /* Get coonfiguration descriptor. */
     150        const size_t config_descriptor_size =
     151            usb_device_descriptors(dev)->full_config_size;
     152        const void *config_descriptor_raw =
     153            usb_device_descriptors(dev)->full_config;
    168154        const usb_standard_configuration_descriptor_t *config_descriptor =
    169155            config_descriptor_raw;
    170156
    171157        /* Select the first configuration */
    172         rc = usb_request_set_configuration(&dev->ctrl_pipe,
     158        int rc = usb_request_set_configuration(usb_device_get_default_pipe(dev),
    173159            config_descriptor->configuration_number);
    174160        if (rc != EOK) {
    175161                usb_log_error("Failed to set device configuration: %s.\n",
    176162                    str_error(rc));
    177                 return false;
     163                return rc;
    178164        }
    179 
     165       
    180166        /* Create driver soft-state. */
    181167        usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t));
    182168        if (!usb_mid) {
    183169                usb_log_error("Failed to create USB MID structure.\n");
    184                 return false;
     170                return ENOMEM;
    185171        }
    186172
    187         usb_mid->dev = dev->ddf_dev;
    188 
    189173        /* Create control function. */
    190         usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
     174        usb_mid->ctl_fun = usb_device_ddf_fun_create(dev, fun_exposed, "ctl");
    191175        if (usb_mid->ctl_fun == NULL) {
    192176                usb_log_error("Failed to create control function.\n");
    193                 return false;
     177                return ENOMEM;
    194178        }
    195         ddf_fun_set_ops(usb_mid->ctl_fun, &mid_device_ops);
    196179
    197180        /* Bind control function. */
     
    201184                    str_error(rc));
    202185                ddf_fun_destroy(usb_mid->ctl_fun);
    203                 return false;
     186                return rc;
    204187        }
    205188
    206189        /* Create interface children. */
    207190        list_initialize(&usb_mid->interface_list);
    208         create_interfaces(usb_mid, config_descriptor_raw, config_descriptor_size);
     191        create_interfaces(config_descriptor_raw, config_descriptor_size,
     192            &usb_mid->interface_list, dev);
    209193
    210         /* Start child function for every interface. */
    211         list_foreach(usb_mid->interface_list, link, usbmid_interface_t, iface) {
    212                 usb_log_info("Creating child for interface %d (%s).\n",
    213                     iface->interface_no,
    214                     usb_str_class(iface->interface->interface_class));
    215 
    216                 rc = usbmid_spawn_interface_child(dev, iface,
    217                     &dev->descriptors.device, iface->interface);
    218                 if (rc != EOK) {
    219                         usb_log_error("Failed to create interface child: %s.\n",
    220                             str_error(rc));
    221                 }
    222         }
    223 
    224         return true;
     194        return EOK;
    225195}
    226196
  • uspace/drv/bus/usb/usbmid/main.c

    r5b18137 rb4b534ac  
    5151static int usbmid_device_add(usb_device_t *dev)
    5252{
    53         usb_log_info("Taking care of new MID `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
     53        usb_log_info("Taking care of new MID `%s'.\n", usb_device_get_name(dev));
    5454
    55         const bool accept = usbmid_explore_device(dev);
    56 
    57         if (!accept) {
    58                 return ENOTSUP;
    59         }
    60 
    61         return EOK;
     55        return usbmid_explore_device(dev);
    6256}
    6357
     
    7064{
    7165        assert(dev);
    72         usb_mid_t *usb_mid = dev->driver_data;
     66        usb_mid_t *usb_mid = usb_device_data_get(dev);
    7367        assert(usb_mid);
    7468
     
    8983                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    9084
    91                 usb_log_info("Removing child for interface %d (%s).\n",
    92                     iface->interface_no,
    93                     usb_str_class(iface->interface->interface_class));
     85                usb_log_info("Removing child `%s'.\n",
     86                    ddf_fun_get_name(iface->fun));
    9487
    9588                /* Tell the child to go off-line. */
    9689                int pret = ddf_fun_offline(iface->fun);
    9790                if (pret != EOK) {
    98                         usb_log_warning("Failed to turn off child for interface"
    99                             " %d (%s): %s\n", iface->interface_no,
    100                             usb_str_class(iface->interface->interface_class),
    101                             str_error(pret));
     91                        usb_log_warning("Failed to turn off child `%s': %s\n",
     92                            ddf_fun_get_name(iface->fun), str_error(pret));
    10293                        ret = pret;
    10394                }
     
    10697                pret = usbmid_interface_destroy(iface);
    10798                if (pret != EOK) {
    108                         usb_log_error("Failed to destroy child for interface "
    109                             "%d (%s): %s\n", iface->interface_no,
    110                             usb_str_class(iface->interface->interface_class),
    111                             str_error(pret));
     99                        usb_log_error("Failed to destroy child `%s': %s\n",
     100                            ddf_fun_get_name(iface->fun), str_error(pret));
    112101                        ret = pret;
    113102                }
     
    124113{
    125114        assert(dev);
    126         usb_mid_t *usb_mid = dev->driver_data;
     115        usb_mid_t *usb_mid = usb_device_data_get(dev);
    127116        assert(usb_mid);
    128117
    129         usb_log_info("USB MID gone: `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
     118        usb_log_info("USB MID gone: `%s'.\n", usb_device_get_name(dev));
    130119
    131120        /* Remove ctl function */
     
    145134                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    146135
    147                 usb_log_info("Child for interface %d (%s) gone.\n",
    148                     iface->interface_no,
    149                     usb_str_class(iface->interface->interface_class));
     136                usb_log_info("Child `%s' is gone.\n",
     137                    ddf_fun_get_name(iface->fun));
    150138
    151139                const int pret = usbmid_interface_destroy(iface);
    152140                if (pret != EOK) {
    153                         usb_log_error("Failed to remove child for interface "
    154                             "%d (%s): %s\n",
    155                             iface->interface_no,
    156                             usb_str_class(iface->interface->interface_class),
    157                             str_error(pret));
     141                        usb_log_error("Failed to remove child `%s': %s\n",
     142                            ddf_fun_get_name(iface->fun), str_error(pret));
    158143                        ret = pret;
    159144                }
  • uspace/drv/bus/usb/usbmid/usbmid.c

    r5b18137 rb4b534ac  
    3939#include <stdlib.h>
    4040#include <usb_iface.h>
    41 #include <usb/ddfiface.h>
    4241#include <usb/dev/pipes.h>
    4342#include <usb/classes/classes.h>
     
    4544#include "usbmid.h"
    4645
    47 /** Callback for DDF USB interface. */
    48 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no)
     46/** Get USB device handle by calling the parent usb_device_t.
     47 *
     48 * @param[in] fun Device function the operation is running on.
     49 * @param[out] handle Device handle.
     50 * @return Error code.
     51 */
     52static int usb_iface_device_handle(ddf_fun_t *fun, devman_handle_t *handle)
     53{
     54        assert(fun);
     55        assert(handle);
     56        usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
     57        *handle = usb_device_get_devman_handle(usb_dev);
     58        return EOK;
     59}
     60
     61/** Callback for DDF USB get interface. */
     62static int usb_iface_iface_no(ddf_fun_t *fun, int *iface_no)
    4963{
    5064        usbmid_interface_t *iface = ddf_fun_data_get(fun);
    5165        assert(iface);
    5266
    53         if (iface_no != NULL) {
     67        if (iface_no)
    5468                *iface_no = iface->interface_no;
    55         }
    5669
    5770        return EOK;
    5871}
    5972
    60 /** DDF interface of the child - interface function. */
     73/** DDF interface of the child - USB functions. */
    6174static usb_iface_t child_usb_iface = {
    62         .get_hc_handle = usb_iface_get_hc_handle_device_impl,
    63         .get_my_address = usb_iface_get_my_address_forward_impl,
    64         .get_my_interface = usb_iface_get_interface_impl,
     75        .get_my_device_handle = usb_iface_device_handle,
     76        .get_my_interface = usb_iface_iface_no,
    6577};
    6678
     
    7890                return ret;
    7991        }
    80         /* NOTE: usbmid->interface points somewhere, but we did not
    81          * allocate that space, so don't touch */
    8292        ddf_fun_destroy(mid_iface->fun);
    83         /* NOTE: mid_iface is invalid at this point, it was assigned to
    84          * mid_iface->fun->driver_data and freed in ddf_fun_destroy */
    8593        return EOK;
    8694}
     
    95103 */
    96104int usbmid_spawn_interface_child(usb_device_t *parent,
    97     usbmid_interface_t *iface,
     105    usbmid_interface_t **iface_ret,
    98106    const usb_standard_device_descriptor_t *device_descriptor,
    99107    const usb_standard_interface_descriptor_t *interface_descriptor)
    100108{
     109        ddf_fun_t *child = NULL;
    101110        char *child_name = NULL;
    102111        int rc;
     
    110119            usb_str_class(interface_descriptor->interface_class),
    111120            interface_descriptor->interface_number);
    112         if (rc < 0)
     121        if (rc < 0) {
    113122                return ENOMEM;
     123        }
    114124
    115         rc = ddf_fun_set_name(iface->fun, child_name);
     125        /* Create the device. */
     126        child = usb_device_ddf_fun_create(parent, fun_inner, child_name);
    116127        free(child_name);
    117         if (rc != EOK)
     128        if (child == NULL) {
    118129                return ENOMEM;
     130        }
    119131
    120132        match_id_list_t match_ids;
     
    123135        rc = usb_device_create_match_ids_from_interface(device_descriptor,
    124136            interface_descriptor, &match_ids);
    125         if (rc != EOK)
     137        if (rc != EOK) {
     138                ddf_fun_destroy(child);
    126139                return rc;
     140        }
    127141
    128142        list_foreach(match_ids.ids, link, match_id_t, match_id) {
    129                 rc = ddf_fun_add_match_id(iface->fun, match_id->id, match_id->score);
     143                rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
    130144                if (rc != EOK) {
    131145                        clean_match_ids(&match_ids);
     146                        ddf_fun_destroy(child);
    132147                        return rc;
    133148                }
    134149        }
    135150        clean_match_ids(&match_ids);
     151        ddf_fun_set_ops(child, &child_device_ops);
    136152
    137         ddf_fun_set_ops(iface->fun, &child_device_ops);
     153        usbmid_interface_t *iface = ddf_fun_data_alloc(child, sizeof(*iface));
    138154
    139         rc = ddf_fun_bind(iface->fun);
    140         if (rc != EOK)
     155        iface->fun = child;
     156        iface->interface_no = interface_descriptor->interface_number;
     157        link_initialize(&iface->link);
     158
     159        rc = ddf_fun_bind(child);
     160        if (rc != EOK) {
     161                /* This takes care of match_id deallocation as well. */
     162                ddf_fun_destroy(child);
    141163                return rc;
     164        }
     165        *iface_ret = iface;
    142166
    143167        return EOK;
  • uspace/drv/bus/usb/usbmid/usbmid.h

    r5b18137 rb4b534ac  
    5050        /** Function container. */
    5151        ddf_fun_t *fun;
    52         /** Interface descriptor. */
    53         const usb_standard_interface_descriptor_t *interface;
    5452        /** Interface number. */
    5553        int interface_no;
     
    6058/** Container to hold all the function pointers */
    6159typedef struct usb_mid {
    62         ddf_dev_t *dev;
    6360        ddf_fun_t *ctl_fun;
    6461        list_t interface_list;
    6562} usb_mid_t;
    6663
    67 bool usbmid_explore_device(usb_device_t *);
    68 int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
     64int usbmid_explore_device(usb_device_t *);
     65int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t **,
    6966    const usb_standard_device_descriptor_t *,
    7067    const usb_standard_interface_descriptor_t *);
  • uspace/drv/bus/usb/usbmid/usbmid.ma

    r5b18137 rb4b534ac  
     1100 usb&class=use-interface
    12100 usb&mid
  • uspace/drv/bus/usb/vhc/Makefile

    r5b18137 rb4b534ac  
    4949        hub/virthubops.c \
    5050        conndev.c \
    51         connhost.c \
    5251        devconn.c \
    53         hub.c \
    5452        main.c \
    5553        transfer.c
  • uspace/drv/bus/usb/vhc/conndev.c

    r5b18137 rb4b534ac  
    3838#include <ddf/driver.h>
    3939#include <usbvirt/ipc.h>
     40#include <usb/debug.h>
    4041#include <async.h>
    41 #include "conn.h"
     42
     43#include "vhcd.h"
    4244
    4345static fibril_local uintptr_t plugged_device_handle = 0;
     
    9496    ipc_call_t *icall)
    9597{
    96         vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
     98        vhc_data_t *vhc = ddf_fun_data_get(fun);
    9799       
    98100        async_sess_t *callback =
     
    125127void on_client_close(ddf_fun_t *fun)
    126128{
    127         vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
     129        vhc_data_t *vhc = ddf_fun_data_get(fun);
    128130
    129131        if (plugged_device_handle != 0) {
  • uspace/drv/bus/usb/vhc/devconn.c

    r5b18137 rb4b534ac  
    5151static int vhc_virtdev_plug_generic(vhc_data_t *vhc,
    5252    async_sess_t *sess, usbvirt_device_t *virtdev,
    53     uintptr_t *handle, bool connect)
     53    uintptr_t *handle, bool connect, usb_address_t address)
    5454{
    5555        vhc_virtdev_t *dev = vhc_virtdev_create();
     
    6060        dev->dev_sess = sess;
    6161        dev->dev_local = virtdev;
     62        dev->address = address;
    6263
    6364        fibril_mutex_lock(&vhc->guard);
     
    7879        if (connect) {
    7980                // FIXME: check status
    80                 (void) virthub_connect_device(vhc->hub, dev);
     81                (void) virthub_connect_device(&vhc->hub, dev);
    8182        }
    8283
     
    8687int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle)
    8788{
    88         return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true);
     89        return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true, 0);
    8990}
    9091
    9192int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
    9293{
    93         return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true);
     94        return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true, 0);
    9495}
    9596
    96 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
     97int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle, usb_address_t address)
    9798{
    98         return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false);
     99        return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false, address);
    99100}
    100101
     
    104105
    105106        // FIXME: check status
    106         (void) virthub_disconnect_device(vhc->hub, dev);
     107        (void) virthub_disconnect_device(&vhc->hub, dev);
    107108
    108109        fibril_mutex_lock(&vhc->guard);
  • uspace/drv/bus/usb/vhc/hub/virthub.c

    r5b18137 rb4b534ac  
    3434 */
    3535#include <usb/classes/classes.h>
     36#include <usb/classes/hub.h>
    3637#include <usbvirt/device.h>
    3738#include <assert.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     41#include <stdio.h>
    4042#include <stdlib.h>
    4143#include <ddf/driver.h>
     
    7577        .type = USB_DESCTYPE_HUB,
    7678        .port_count = HUB_PORT_COUNT,
    77         .characteristics = 0,
     79        .characteristics = HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG,
    7880        .power_on_warm_up = 50, /* Huh? */
    7981        .max_current = 100, /* Huh again. */
     
    9698        .length = sizeof(usb_standard_configuration_descriptor_t),
    9799        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    98         .total_length = 
     100        .total_length =
    99101                sizeof(usb_standard_configuration_descriptor_t)
    100102                + sizeof(std_interface_descriptor)
     
    144146 * @return Error code.
    145147 */
    146 int virthub_init(usbvirt_device_t *dev)
     148int virthub_init(usbvirt_device_t *dev, const char* name)
    147149{
    148150        if (dev == NULL) {
     
    151153        dev->ops = &hub_ops;
    152154        dev->descriptors = &descriptors;
     155        dev->address = 0;
     156        dev->name = str_dup(name);
     157        if (!dev->name)
     158                return ENOMEM;
    153159
    154160        hub_t *hub = malloc(sizeof(hub_t));
    155161        if (hub == NULL) {
     162                free(dev->name);
    156163                return ENOMEM;
    157164        }
  • uspace/drv/bus/usb/vhc/hub/virthub.h

    r5b18137 rb4b534ac  
    7979extern hub_descriptor_t hub_descriptor;
    8080
    81 int virthub_init(usbvirt_device_t *);
     81int virthub_init(usbvirt_device_t *, const char *name);
    8282int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *);
    8383int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *);
  • uspace/drv/bus/usb/vhc/hub/virthubops.c

    r5b18137 rb4b534ac  
    340340
    341341
    342 /** IN class request. */
    343 #define CLASS_REQ_IN(recipient) \
    344         USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
    345         USBVIRT_REQUEST_TYPE_CLASS, recipient)
    346 /** OUT class request. */
    347 #define CLASS_REQ_OUT(recipient) \
    348         USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
    349         USBVIRT_REQUEST_TYPE_CLASS, recipient)
    350342
    351343/** Recipient: other. */
     
    353345/** Recipient: device. */
    354346#define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
    355 /** Direction: in. */
    356 #define DIR_IN USB_DIRECTION_IN
    357 /** Direction: out. */
    358 #define DIR_OUT USB_DIRECTION_OUT
    359 
    360 
    361 /** Create a class request.
    362  *
    363  * @param direction Request direction.
    364  * @param recipient Request recipient.
    365  * @param req Request code.
    366  */
    367 #define CLASS_REQ(direction, recipient, req) \
    368         .req_direction = direction, \
    369         .req_recipient = recipient, \
    370         .req_type = USB_REQUEST_TYPE_CLASS, \
    371         .request = req
    372 
    373 /** Create a standard request.
    374  *
    375  * @param direction Request direction.
    376  * @param recipient Request recipient.
    377  * @param req Request code.
    378  */
    379 #define STD_REQ(direction, recipient, req) \
    380         .req_direction = direction, \
    381         .req_recipient = recipient, \
    382         .req_type = USB_REQUEST_TYPE_STANDARD, \
    383         .request = req
     347
    384348
    385349/** Hub operations on control endpoint zero. */
    386350static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
    387351        {
    388                 STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
    389                 .name = "GetDescriptor",
     352                STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     353                .name = "GetStdDescriptor",
    390354                .callback = req_get_descriptor
    391355        },
    392356        {
    393                 CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
    394                 .name = "GetDescriptor",
     357                CLASS_REQ_IN(REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     358                .name = "GetClassDescriptor",
    395359                .callback = req_get_descriptor
    396360        },
    397361        {
    398                 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
     362                CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
    399363                .name = "GetPortStatus",
    400364                .callback = req_get_port_status
    401365        },
    402366        {
    403                 CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
     367                CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
    404368                .name = "ClearHubFeature",
    405369                .callback = req_clear_hub_feature
    406370        },
    407371        {
    408                 CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
     372                CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
    409373                .name = "ClearPortFeature",
    410374                .callback = req_clear_port_feature
    411375        },
    412376        {
    413                 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
     377                CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATE),
    414378                .name = "GetBusState",
    415379                .callback = req_get_bus_state
    416380        },
    417381        {
    418                 CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
     382                CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
    419383                .name = "GetHubDescriptor",
    420384                .callback = req_get_descriptor
    421385        },
    422386        {
    423                 CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
     387                CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
    424388                .name = "GetHubStatus",
    425389                .callback = req_get_hub_status
    426390        },
    427391        {
    428                 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
     392                CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
    429393                .name = "GetPortStatus",
    430394                .callback = req_get_port_status
    431395        },
    432396        {
    433                 CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
     397                CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
    434398                .name = "SetHubFeature",
    435399                .callback = req_set_hub_feature
    436400        },
    437401        {
    438                 CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
     402                CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
    439403                .name = "SetPortFeature",
    440404                .callback = req_set_port_feature
  • uspace/drv/bus/usb/vhc/main.c

    r5b18137 rb4b534ac  
    3434 */
    3535
    36 #include <loc.h>
    37 #include <async.h>
    38 #include <unistd.h>
    39 #include <stdlib.h>
    40 #include <sysinfo.h>
    4136#include <stdio.h>
    4237#include <errno.h>
     
    4439#include <ddf/driver.h>
    4540
    46 #include <usb/usb.h>
    47 #include <usb/ddfiface.h>
    48 #include <usb_iface.h>
     41#include <usb/host/ddf_helpers.h>
     42
     43#include <usb/debug.h>
    4944#include "vhcd.h"
    50 #include "hub.h"
    51 #include "conn.h"
     45
    5246
    5347static ddf_dev_ops_t vhc_ops = {
    54         .interfaces[USBHC_DEV_IFACE] = &vhc_iface,
    55         .interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
    5648        .close = on_client_close,
    5749        .default_handler = default_connection_handler
    5850};
    5951
     52static int vhc_control_node(ddf_dev_t *dev, ddf_fun_t **fun)
     53{
     54        assert(dev);
     55        assert(fun);
     56
     57        *fun = ddf_fun_create(dev, fun_exposed, "virtual");
     58        if (!*fun)
     59                return ENOMEM;
     60
     61        vhc_data_t *vhc = ddf_fun_data_alloc(*fun, sizeof(vhc_data_t));
     62        if (!vhc) {
     63                ddf_fun_destroy(*fun);
     64        }
     65        ddf_fun_set_ops(*fun, &vhc_ops);
     66        const int ret = ddf_fun_bind(*fun);
     67        if (ret != EOK) {
     68                ddf_fun_destroy(*fun);
     69                *fun = NULL;
     70                return ret;
     71        }
     72        vhc_init(vhc);
     73        return EOK;
     74}
     75
     76hcd_ops_t vhc_hc_ops = {
     77        .schedule = vhc_schedule,
     78};
     79
    6080static int vhc_dev_add(ddf_dev_t *dev)
    6181{
    62         static int vhc_count = 0;
    63         int rc;
     82        /* Initialize virtual structure */
     83        ddf_fun_t *ctl_fun = NULL;
     84        int ret = vhc_control_node(dev, &ctl_fun);
     85        if (ret != EOK) {
     86                usb_log_error("Failed to setup control node.\n");
     87                return ret;
     88        }
     89        vhc_data_t *data = ddf_fun_data_get(ctl_fun);
    6490
    65         if (vhc_count > 0) {
    66                 return ELIMIT;
     91        /* Initialize generic structures */
     92        ret = hcd_ddf_setup_hc(dev, USB_SPEED_FULL,
     93            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
     94        if (ret != EOK) {
     95                usb_log_error("Failed to init HCD structures: %s.\n",
     96                   str_error(ret));
     97                ddf_fun_destroy(ctl_fun);
     98                return ret;
    6799        }
    68100
    69         vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t));
    70         if (data == NULL) {
    71                 usb_log_fatal("Failed to allocate memory.\n");
    72                 return ENOMEM;
    73         }
    74         data->magic = 0xDEADBEEF;
    75         rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1,
    76             bandwidth_count_usb11);
    77         if (rc != EOK) {
    78                 usb_log_fatal("Failed to initialize endpoint manager.\n");
    79                 free(data);
    80                 return rc;
    81         }
    82         usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX);
     101        hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops);
    83102
    84         ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
    85         if (hc == NULL) {
    86                 usb_log_fatal("Failed to create device function.\n");
    87                 free(data);
    88                 return ENOMEM;
     103        /* Add virtual hub device */
     104        ret = vhc_virtdev_plug_hub(data, &data->hub, NULL, 0);
     105        if (ret != EOK) {
     106                usb_log_error("Failed to plug root hub: %s.\n", str_error(ret));
     107                ddf_fun_destroy(ctl_fun);
     108                return ret;
    89109        }
    90110
    91         ddf_fun_set_ops(hc, &vhc_ops);
    92         list_initialize(&data->devices);
    93         fibril_mutex_initialize(&data->guard);
    94         data->hub = &virtual_hub_device;
    95         data->hc_fun = hc;
    96 
    97         rc = ddf_fun_bind(hc);
    98         if (rc != EOK) {
    99                 usb_log_fatal("Failed to bind HC function: %s.\n",
    100                     str_error(rc));
    101                 free(data);
    102                 return rc;
     111        /*
     112         * Creating root hub registers a new USB device so HC
     113         * needs to be ready at this time.
     114         */
     115        ret = hcd_ddf_setup_root_hub(dev);
     116        if (ret != EOK) {
     117                usb_log_error("Failed to init VHC root hub: %s\n",
     118                        str_error(ret));
     119                // TODO do something here...
    103120        }
    104121
    105         rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY);
    106         if (rc != EOK) {
    107                 usb_log_fatal("Failed to add function to HC class: %s.\n",
    108                     str_error(rc));
    109                 free(data);
    110                 return rc;
    111         }
    112 
    113         virtual_hub_device_init(hc);
    114 
    115         usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
    116             (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc));
    117 
    118         rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
    119         if (rc != EOK) {
    120                 usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
    121                 free(data);
    122                 return rc;
    123         }
    124 
    125         return EOK;
     122        return ret;
    126123}
    127124
     
    135132};
    136133
    137 
    138134int main(int argc, char * argv[])
    139 {       
     135{
    140136        log_init(NAME);
    141 
    142137        printf(NAME ": virtual USB host controller driver.\n");
    143138
     
    145140}
    146141
    147 
    148142/**
    149143 * @}
  • uspace/drv/bus/usb/vhc/transfer.c

    r5b18137 rb4b534ac  
    2929#include <errno.h>
    3030#include <str_error.h>
     31#include <usb/debug.h>
    3132#include <usbvirt/device.h>
    3233#include <usbvirt/ipc.h>
    3334#include "vhcd.h"
    34 
    35 vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep,
    36     usb_direction_t dir, usb_transfer_type_t tr_type,
    37     ddf_fun_t *fun, void *callback_arg)
    38 {
    39         vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t));
    40         if (result == NULL) {
    41                 return NULL;
    42         }
    43         link_initialize(&result->link);
    44         result->address = address;
    45         result->endpoint = ep;
    46         result->direction = dir;
    47         result->transfer_type = tr_type;
    48         result->setup_buffer = NULL;
    49         result->setup_buffer_size = 0;
    50         result->data_buffer = NULL;
    51         result->data_buffer_size = 0;
    52         result->ddf_fun = fun;
    53         result->callback_arg = callback_arg;
    54         result->callback_in = NULL;
    55         result->callback_out = NULL;
    56 
    57         usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result,
    58             address, ep, usb_str_transfer_type_short(tr_type),
    59             dir == USB_DIRECTION_IN ? "in" : "out");
    60 
    61         return result;
    62 }
     35#include "hub/virthub.h"
    6336
    6437static bool is_set_address_transfer(vhc_transfer_t *transfer)
    6538{
    66         if (transfer->endpoint != 0) {
    67                 return false;
    68         }
    69         if (transfer->transfer_type != USB_TRANSFER_CONTROL) {
    70                 return false;
    71         }
    72         if (transfer->direction != USB_DIRECTION_OUT) {
    73                 return false;
    74         }
    75         if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) {
    76                 return false;
    77         }
    78         usb_device_request_setup_packet_t *setup = transfer->setup_buffer;
     39        if (transfer->batch->ep->endpoint != 0) {
     40                return false;
     41        }
     42        if (transfer->batch->ep->transfer_type != USB_TRANSFER_CONTROL) {
     43                return false;
     44        }
     45        if (usb_transfer_batch_direction(transfer->batch) != USB_DIRECTION_OUT) {
     46                return false;
     47        }
     48        const usb_device_request_setup_packet_t *setup =
     49            (void*)transfer->batch->setup_buffer;
    7950        if (setup->request_type != 0) {
    8051                return false;
     
    8758}
    8859
    89 int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer)
    90 {
    91         fibril_mutex_lock(&vhc->guard);
    92 
    93         bool target_found = false;
    94         list_foreach(vhc->devices, link, vhc_virtdev_t, dev) {
    95                 fibril_mutex_lock(&dev->guard);
    96                 if (dev->address == transfer->address) {
    97                         if (target_found) {
    98                                 usb_log_warning("Transfer would be accepted by more devices!\n");
    99                                 goto next;
    100                         }
    101                         target_found = true;
    102                         list_append(&transfer->link, &dev->transfer_queue);
    103                 }
    104 next:
    105                 fibril_mutex_unlock(&dev->guard);
    106         }
    107 
    108         fibril_mutex_unlock(&vhc->guard);
    109 
    110         if (target_found) {
    111                 return EOK;
     60static int process_transfer_local(usb_transfer_batch_t *batch,
     61    usbvirt_device_t *dev, size_t *actual_data_size)
     62{
     63        int rc;
     64       
     65        const usb_direction_t dir = usb_transfer_batch_direction(batch);
     66
     67        if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
     68                if (dir == USB_DIRECTION_IN) {
     69                        rc = usbvirt_control_read(dev,
     70                            batch->setup_buffer, batch->setup_size,
     71                            batch->buffer, batch->buffer_size,
     72                            actual_data_size);
     73                } else {
     74                        assert(dir == USB_DIRECTION_OUT);
     75                        rc = usbvirt_control_write(dev,
     76                            batch->setup_buffer, batch->setup_size,
     77                            batch->buffer, batch->buffer_size);
     78                }
    11279        } else {
    113                 return ENOENT;
    114         }
    115 }
    116 
    117 static int process_transfer_local(vhc_transfer_t *transfer,
    118     usbvirt_device_t *dev, size_t *actual_data_size)
     80                if (dir == USB_DIRECTION_IN) {
     81                        rc = usbvirt_data_in(dev, batch->ep->transfer_type,
     82                            batch->ep->endpoint,
     83                            batch->buffer, batch->buffer_size,
     84                            actual_data_size);
     85                } else {
     86                        assert(dir == USB_DIRECTION_OUT);
     87                        rc = usbvirt_data_out(dev, batch->ep->transfer_type,
     88                            batch->ep->endpoint,
     89                            batch->buffer, batch->buffer_size);
     90                }
     91        }
     92
     93        return rc;
     94}
     95
     96static int process_transfer_remote(usb_transfer_batch_t *batch,
     97    async_sess_t *sess, size_t *actual_data_size)
    11998{
    12099        int rc;
    121100
    122         if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
    123                 if (transfer->direction == USB_DIRECTION_IN) {
    124                         rc = usbvirt_control_read(dev,
    125                             transfer->setup_buffer, transfer->setup_buffer_size,
    126                             transfer->data_buffer, transfer->data_buffer_size,
    127                             actual_data_size);
    128                 } else {
    129                         assert(transfer->direction == USB_DIRECTION_OUT);
    130                         rc = usbvirt_control_write(dev,
    131                             transfer->setup_buffer, transfer->setup_buffer_size,
    132                             transfer->data_buffer, transfer->data_buffer_size);
     101        const usb_direction_t dir = usb_transfer_batch_direction(batch);
     102
     103        if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
     104                if (dir == USB_DIRECTION_IN) {
     105                        rc = usbvirt_ipc_send_control_read(sess,
     106                            batch->setup_buffer, batch->setup_size,
     107                            batch->buffer, batch->buffer_size,
     108                            actual_data_size);
     109                } else {
     110                        assert(dir == USB_DIRECTION_OUT);
     111                        rc = usbvirt_ipc_send_control_write(sess,
     112                            batch->setup_buffer, batch->setup_size,
     113                            batch->buffer, batch->buffer_size);
    133114                }
    134115        } else {
    135                 if (transfer->direction == USB_DIRECTION_IN) {
    136                         rc = usbvirt_data_in(dev, transfer->transfer_type,
    137                             transfer->endpoint,
    138                             transfer->data_buffer, transfer->data_buffer_size,
    139                             actual_data_size);
    140                 } else {
    141                         assert(transfer->direction == USB_DIRECTION_OUT);
    142                         rc = usbvirt_data_out(dev, transfer->transfer_type,
    143                             transfer->endpoint,
    144                             transfer->data_buffer, transfer->data_buffer_size);
    145                 }
    146         }
    147 
    148         return rc;
    149 }
    150 
    151 static int process_transfer_remote(vhc_transfer_t *transfer,
    152     async_sess_t *sess, size_t *actual_data_size)
    153 {
    154         int rc;
    155 
    156         if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
    157                 if (transfer->direction == USB_DIRECTION_IN) {
    158                         rc = usbvirt_ipc_send_control_read(sess,
    159                             transfer->setup_buffer, transfer->setup_buffer_size,
    160                             transfer->data_buffer, transfer->data_buffer_size,
    161                             actual_data_size);
    162                 } else {
    163                         assert(transfer->direction == USB_DIRECTION_OUT);
    164                         rc = usbvirt_ipc_send_control_write(sess,
    165                             transfer->setup_buffer, transfer->setup_buffer_size,
    166                             transfer->data_buffer, transfer->data_buffer_size);
    167                 }
    168         } else {
    169                 if (transfer->direction == USB_DIRECTION_IN) {
    170                         rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint,
    171                             transfer->transfer_type,
    172                             transfer->data_buffer, transfer->data_buffer_size,
    173                             actual_data_size);
    174                 } else {
    175                         assert(transfer->direction == USB_DIRECTION_OUT);
    176                         rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint,
    177                             transfer->transfer_type,
    178                             transfer->data_buffer, transfer->data_buffer_size);
     116                if (dir == USB_DIRECTION_IN) {
     117                        rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint,
     118                            batch->ep->transfer_type,
     119                            batch->buffer, batch->buffer_size,
     120                            actual_data_size);
     121                } else {
     122                        assert(dir == USB_DIRECTION_OUT);
     123                        rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint,
     124                            batch->ep->transfer_type,
     125                            batch->buffer, batch->buffer_size);
    179126                }
    180127        }
     
    195142}
    196143
    197 
    198144static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
    199145    size_t data_transfer_size, int outcome)
    200146{
    201147        assert(outcome != ENAK);
    202 
    203         usb_log_debug2("Transfer %p ended: %s.\n",
    204             transfer, str_error(outcome));
    205 
    206         if (transfer->direction == USB_DIRECTION_IN) {
    207                 transfer->callback_in(transfer->ddf_fun, outcome,
    208                     data_transfer_size, transfer->callback_arg);
    209         } else {
    210                 assert(transfer->direction == USB_DIRECTION_OUT);
    211                 transfer->callback_out(transfer->ddf_fun, outcome,
    212                     transfer->callback_arg);
    213         }
    214 
     148        assert(transfer);
     149        assert(transfer->batch);
     150        usb_transfer_batch_finish_error(transfer->batch, NULL,
     151            data_transfer_size, outcome);
     152        usb_transfer_batch_destroy(transfer->batch);
    215153        free(transfer);
     154}
     155
     156int vhc_init(vhc_data_t *instance)
     157{
     158        assert(instance);
     159        list_initialize(&instance->devices);
     160        fibril_mutex_initialize(&instance->guard);
     161        instance->magic = 0xDEADBEEF;
     162        return virthub_init(&instance->hub, "root hub");
     163}
     164
     165int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     166{
     167        assert(hcd);
     168        assert(batch);
     169        vhc_data_t *vhc = hcd_get_driver_data(hcd);
     170        assert(vhc);
     171
     172        vhc_transfer_t *transfer = malloc(sizeof(vhc_transfer_t));
     173        if (!transfer)
     174                return ENOMEM;
     175        link_initialize(&transfer->link);
     176        transfer->batch = batch;
     177
     178        fibril_mutex_lock(&vhc->guard);
     179
     180        int targets = 0;
     181
     182        list_foreach(vhc->devices, link, vhc_virtdev_t, dev) {
     183                fibril_mutex_lock(&dev->guard);
     184                if (dev->address == transfer->batch->ep->address) {
     185                        if (!targets) {
     186                                list_append(&transfer->link, &dev->transfer_queue);
     187                        }
     188                        ++targets;
     189                }
     190                fibril_mutex_unlock(&dev->guard);
     191        }
     192
     193        fibril_mutex_unlock(&vhc->guard);
     194       
     195        if (targets > 1)
     196                usb_log_warning("Transfer would be accepted by more devices!\n");
     197
     198        return targets ? EOK : ENOENT;
    216199}
    217200
     
    234217                size_t data_transfer_size = 0;
    235218                if (dev->dev_sess) {
    236                         rc = process_transfer_remote(transfer, dev->dev_sess,
    237                             &data_transfer_size);
     219                        rc = process_transfer_remote(transfer->batch,
     220                            dev->dev_sess, &data_transfer_size);
    238221                } else if (dev->dev_local != NULL) {
    239                         rc = process_transfer_local(transfer, dev->dev_local,
    240                             &data_transfer_size);
     222                        rc = process_transfer_local(transfer->batch,
     223                            dev->dev_local, &data_transfer_size);
    241224                } else {
    242225                        usb_log_warning("Device has no remote phone nor local node.\n");
     
    251234                        if (is_set_address_transfer(transfer)) {
    252235                                usb_device_request_setup_packet_t *setup
    253                                     = transfer->setup_buffer;
     236                                    = (void*)transfer->batch->setup_buffer;
    254237                                dev->address = setup->value;
    255238                                usb_log_debug2("Address changed to %d\n",
     
    284267        return EOK;
    285268}
    286 
  • uspace/drv/bus/usb/vhc/vhcd.h

    r5b18137 rb4b534ac  
    3636#define VHCD_VHCD_H_
    3737
    38 #include <usb/debug.h>
    3938#include <usbvirt/device.h>
    40 #include <usb/host/usb_endpoint_manager.h>
    41 #include <usb/host/usb_device_manager.h>
    4239#include <usbhc_iface.h>
    4340#include <async.h>
     41
     42#include <usb/host/hcd.h>
     43
    4444
    4545#define NAME "vhc"
     
    5959        list_t devices;
    6060        fibril_mutex_t guard;
    61         usb_endpoint_manager_t ep_manager;
    62         usb_device_manager_t dev_manager;
    63         usbvirt_device_t *hub;
    64         ddf_fun_t *hc_fun;
     61        usbvirt_device_t hub;
    6562} vhc_data_t;
    6663
    6764typedef struct {
    6865        link_t link;
    69         usb_address_t address;
    70         usb_endpoint_t endpoint;
    71         usb_direction_t direction;
    72         usb_transfer_type_t transfer_type;
    73         void *setup_buffer;
    74         size_t setup_buffer_size;
    75         void *data_buffer;
    76         size_t data_buffer_size;
    77         ddf_fun_t *ddf_fun;
    78         void *callback_arg;
    79         usbhc_iface_transfer_in_callback_t callback_in;
    80         usbhc_iface_transfer_out_callback_t callback_out;
     66        usb_transfer_batch_t *batch;
    8167} vhc_transfer_t;
    8268
    83 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
    84     usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
     69
     70void on_client_close(ddf_fun_t *fun);
     71void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
     72    ipc_call_t *icall);
     73
    8574int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *);
    8675int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
    87 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
     76int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *, usb_address_t address);
    8877void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
    89 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
    9078
     79int vhc_init(vhc_data_t *instance);
     80int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    9181int vhc_transfer_queue_processor(void *arg);
    92 
    9382
    9483#endif
Note: See TracChangeset for help on using the changeset viewer.