Changeset 361e61b in mainline for uspace/drv


Ignore:
Timestamp:
2011-03-21T14:23:15Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
55e388a1
Parents:
c32688d (diff), 48fe0c9 (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 with development

Location:
uspace/drv
Files:
20 added
1 deleted
43 edited
4 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/ehci-hcd/Makefile

    rc32688d r361e61b  
    3333
    3434SOURCES = \
     35        hc_iface.c \
    3536        main.c \
    3637        pci.c
  • uspace/drv/ehci-hcd/main.c

    rc32688d r361e61b  
    2727 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2828 */
    29 /** @addtogroup usbdrvehci
     29/** @addtogroup drvusbehci
    3030 * @{
    3131 */
     
    4444
    4545#include "pci.h"
    46 
    47 #define NAME "ehci-hcd"
     46#include "ehci.h"
    4847
    4948static int ehci_add_device(ddf_dev_t *device);
     
    5756        .driver_ops = &ehci_driver_ops
    5857};
     58static ddf_dev_ops_t hc_ops = {
     59        .interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
     60};
     61
    5962/*----------------------------------------------------------------------------*/
    6063/** Initializes a new ddf driver instance of EHCI hcd.
     
    7174        return ret; \
    7275}
    73 
    74         usb_log_info("uhci_add_device() called\n");
    7576
    7677        uintptr_t mem_reg_base = 0;
     
    8990            "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
    9091
     92        ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci-hc");
     93        if (hc_fun == NULL) {
     94                usb_log_error("Failed to create EHCI function.\n");
     95                return ENOMEM;
     96        }
     97        hc_fun->ops = &hc_ops;
     98        ret = ddf_fun_bind(hc_fun);
     99
     100        CHECK_RET_RETURN(ret,
     101            "Failed to bind EHCI function: %s.\n",
     102            str_error(ret));
     103
     104        usb_log_info("Controlling new EHCI device `%s' (handle %llu).\n",
     105            device->name, device->handle);
     106
    91107        return EOK;
    92108#undef CHECK_RET_RETURN
     
    103119int main(int argc, char *argv[])
    104120{
    105         usb_log_enable(USB_LOG_LEVEL_ERROR, NAME);
     121        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    106122        return ddf_driver_main(&ehci_driver);
    107123}
  • uspace/drv/ehci-hcd/pci.c

    rc32688d r361e61b  
    247247
    248248
    249         if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {
     249        if ((value & USBLEGSUP_BIOS_CONTROL) == 0) {
    250250                usb_log_info("BIOS released control after %d usec.\n", wait);
    251251        } else {
    252252                /* BIOS failed to hand over control, this should not happen. */
    253                 usb_log_warning( "BIOS failed to release control after"
     253                usb_log_warning( "BIOS failed to release control after "
    254254                    "%d usecs, force it.\n", wait);
    255255                ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     
    258258                CHECK_RET_HANGUP_RETURN(ret,
    259259                    "Failed(%d) to force OS EHCI control.\n", ret);
    260                 /* TODO: This does not seem to work on my machine */
    261260        }
    262261
     
    280279        usb_log_debug2("USBLEGSUP: %x.\n", value);
    281280
    282 /*
    283  * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED
    284  */
     281        /*
     282         * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
     283        */
    285284
    286285        /* Get size of capability registers in memory space. */
  • uspace/drv/ohci/Makefile

    rc32688d r361e61b  
    11#
    2 # Copyright (c) 2011 Jiri Svoboda
     2# Copyright (c) 2011 Jan Vesely
    33# All rights reserved.
    44#
     
    2727#
    2828
    29 -include ../version
    30 -include ../Makefile.config
    31 -include ../boot/arch/$(BARCH)/Makefile.inc
    32 -include ../boot/Makefile.common
     29USPACE_PREFIX = ../..
     30LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
     31EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
     32BINARY = ohci
    3333
    34 PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \
    35     ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \
    36     sparc64/serengeti sparc64/ultra
     34SOURCES = \
     35        iface.c \
     36        batch.c \
     37        main.c \
     38        hc.c \
     39        root_hub.c \
     40        pci.c
    3741
    38 ifdef POST_OUTPUT
    39         IMGFILE = $(POST_OUTPUT)
    40 else
    41         IMGFILE = $(BOOT_OUTPUT)
    42 endif
    43 
    44 SUFFIX = $(suffix $(IMGFILE))
    45 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
    46 
    47 .PHONY: all clean dist distfile
    48 
    49 all: distfile
    50 distfile: $(DISTFILE)
    51 
    52 $(DISTFILE): $(IMGFILE)
    53         cp $< $@
    54 
    55 dist:
    56         for profile in $(PROFILES); do \
    57                 $(MAKE) -C .. clean ; \
    58                 $(MAKE) -C .. PROFILE=$$profile distfile ; \
    59         done
    60 
    61 clean:
    62         rm -f $(DISTFILE)
     42include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/ohci/root_hub.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbohci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief OHCI driver
    3333 */
    3434#include <assert.h>
    35 #include <stdio.h>
     35#include <errno.h>
     36#include <str_error.h>
    3637
    3738#include <usb/debug.h>
    3839
    39 #include "port_status.h"
     40#include "root_hub.h"
    4041
    41 struct flag_name
    42 {
    43         uint16_t flag;
    44         const char *name;
    45 };
    46 
    47 static const struct flag_name flags[] =
    48 {
    49         { STATUS_SUSPEND, "suspended" },
    50         { STATUS_IN_RESET, "in reset" },
    51         { STATUS_LOW_SPEED, "low speed device" },
    52         { STATUS_ALWAYS_ONE, "always 1 bit" },
    53         { STATUS_RESUME, "resume" },
    54         { STATUS_LINE_D_MINUS, "line D- value" },
    55         { STATUS_LINE_D_PLUS, "line D+ value" },
    56         { STATUS_ENABLED_CHANGED, "enabled changed" },
    57         { STATUS_ENABLED, "enabled" },
    58         { STATUS_CONNECTED_CHANGED, "connected changed" },
    59         { STATUS_CONNECTED, "connected" }
    60 };
    61 
    62 /** Prints portr status in a human readable way.
    63  *
    64  * @param[in] value Port value to print.
     42/** Root hub initialization
    6543 * @return Error code.
    6644 */
    67 void print_port_status(port_status_t value)
     45int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
    6846{
    69         unsigned i = 0;
    70         for (;i < sizeof(flags)/sizeof(struct flag_name); ++i) {
    71                 usb_log_debug2("\t%s status: %s.\n", flags[i].name,
    72                   ((value & flags[i].flag) != 0) ? "YES" : "NO");
     47        assert(instance);
     48        instance->address = -1;
     49        instance->registers = regs;
     50        instance->device = dev;
     51
     52        usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff);
     53
     54        /* TODO: implement */
     55        return EOK;
     56}
     57/*----------------------------------------------------------------------------*/
     58int rh_request(rh_t *instance, batch_t *request)
     59{
     60        assert(instance);
     61        assert(request);
     62        /* TODO: implement */
     63        if (request->setup_buffer) {
     64                usb_log_info("Root hub got SETUP packet: %s.\n",
     65                    usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
    7366        }
     67        usb_log_error("Root hub request processing not implemented.\n");
     68        batch_finish(request, ENOTSUP);
     69        return EOK;
     70}
     71/*----------------------------------------------------------------------------*/
     72void rh_interrupt(rh_t *instance)
     73{
     74        usb_log_error("Root hub interrupt not implemented.\n");
     75        /* TODO: implement */
    7476}
    7577/**
  • uspace/drv/ohci/root_hub.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup drvusbohci
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief OHCI driver
    3434 */
    35 #ifndef DRV_UHCI_ROOT_HUB_H
    36 #define DRV_UHCI_ROOT_HUB_H
     35#ifndef DRV_OHCI_ROOT_HUB_H
     36#define DRV_OHCI_ROOT_HUB_H
    3737
    38 #include <ddf/driver.h>
     38#include <usb/usb.h>
    3939
    40 int setup_root_hub(ddf_fun_t **device, ddf_dev_t *hc);
     40#include "ohci_regs.h"
     41#include "batch.h"
    4142
     43typedef struct rh {
     44        ohci_regs_t *registers;
     45        usb_address_t address;
     46        ddf_dev_t *device;
     47} rh_t;
     48
     49int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs);
     50
     51int rh_request(rh_t *instance, batch_t *request);
     52
     53void rh_interrupt(rh_t *instance);
    4254#endif
    4355/**
  • uspace/drv/pciintel/pci.c

    rc32688d r361e61b  
    9292        pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
    9393
    94   sysarg_t apic;
    95   sysarg_t i8259;
     94        sysarg_t apic;
     95        sysarg_t i8259;
    9696
    9797        int irc_phone = -1;
    98         int irc_service = 0;
    99 
    100   if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
    101     irc_service = SERVICE_APIC;
     98        int irc_service = -1;
     99
     100        if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
     101                irc_service = SERVICE_APIC;
    102102        } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
    103     irc_service = SERVICE_I8259;
    104         }
    105 
    106   if (irc_service == 0)
     103                irc_service = SERVICE_I8259;
     104        }
     105
     106        if (irc_service == -1) {
    107107                return false;
     108        }
    108109
    109110        irc_phone = service_connect_blocking(irc_service, 0, 0);
    110         if (irc_phone < 0)
     111        if (irc_phone < 0) {
    111112                return false;
     113        }
    112114
    113115        size_t i;
    114   for (i = 0; i < dev_data->hw_resources.count; i++) {
     116        for (i = 0; i < dev_data->hw_resources.count; i++) {
    115117                if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    116118                        int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
  • uspace/drv/uhci-hcd/Makefile

    rc32688d r361e61b  
    3535        iface.c \
    3636        main.c \
    37         root_hub.c \
    3837        transfer_list.c \
    3938        uhci.c \
     39        uhci_hc.c \
     40        uhci_rh.c \
    4041        uhci_struct/transfer_descriptor.c \
    41         utils/device_keeper.c \
    4242        pci.c \
    4343        batch.c
  • uspace/drv/uhci-hcd/batch.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver USB transaction structure
    3333 */
    3434#include <errno.h>
     
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "uhci.h"
     42#include "uhci_hc.h"
    4343#include "utils/malloc32.h"
     44#include "uhci_struct/transfer_descriptor.h"
    4445
    4546#define DEFAULT_ERROR_COUNT 3
    4647
    47 static int batch_schedule(batch_t *instance);
     48typedef struct uhci_batch {
     49        qh_t *qh;
     50        td_t *tds;
     51        size_t packets;
     52        device_keeper_t *manager;
     53} uhci_batch_t;
    4854
    4955static void batch_control(batch_t *instance,
    5056    usb_packet_id data_stage, usb_packet_id status_stage);
    5157static void batch_data(batch_t *instance, usb_packet_id pid);
    52 static void batch_call_in(batch_t *instance);
    53 static void batch_call_out(batch_t *instance);
    5458static void batch_call_in_and_dispose(batch_t *instance);
    5559static void batch_call_out_and_dispose(batch_t *instance);
    56 static void batch_dispose(batch_t *instance);
    57 
    58 
    59 /** Allocates memory and initializes internal data structures.
     60
     61
     62/** Allocate memory and initialize internal data structure.
    6063 *
    6164 * @param[in] fun DDF function to pass to callback.
     
    7275 * @param[in] arg additional parameter to func_in or func_out
    7376 * @param[in] manager Pointer to toggle management structure.
    74  * @return False, if there is an active TD, true otherwise.
     77 * @return Valid pointer if all substructures were successfully created,
     78 * NULL otherwise.
     79 *
     80 * Determines the number of needed packets (TDs). Prepares a transport buffer
     81 * (that is accessible by the hardware). Initializes parameters needed for the
     82 * transaction and callback.
    7583 */
    7684batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7785    usb_transfer_type_t transfer_type, size_t max_packet_size,
    78     usb_speed_t speed, char *buffer, size_t size,
     86    usb_speed_t speed, char *buffer, size_t buffer_size,
    7987    char* setup_buffer, size_t setup_size,
    8088    usbhc_iface_transfer_in_callback_t func_in,
     
    98106        CHECK_NULL_DISPOSE_RETURN(instance,
    99107            "Failed to allocate batch instance.\n");
    100         bzero(instance, sizeof(batch_t));
    101 
    102         instance->qh = malloc32(sizeof(queue_head_t));
    103         CHECK_NULL_DISPOSE_RETURN(instance->qh,
     108        batch_init(instance, target, transfer_type, speed, max_packet_size,
     109            buffer, NULL, buffer_size, NULL, setup_size, func_in,
     110            func_out, arg, fun, NULL);
     111
     112
     113        uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
     114        CHECK_NULL_DISPOSE_RETURN(instance,
     115            "Failed to allocate batch instance.\n");
     116        bzero(data, sizeof(uhci_batch_t));
     117        data->manager = manager;
     118        instance->private_data = data;
     119
     120        data->packets = (buffer_size + max_packet_size - 1) / max_packet_size;
     121        if (transfer_type == USB_TRANSFER_CONTROL) {
     122                data->packets += 2;
     123        }
     124
     125        data->tds = malloc32(sizeof(td_t) * data->packets);
     126        CHECK_NULL_DISPOSE_RETURN(
     127            data->tds, "Failed to allocate transfer descriptors.\n");
     128        bzero(data->tds, sizeof(td_t) * data->packets);
     129
     130        data->qh = malloc32(sizeof(qh_t));
     131        CHECK_NULL_DISPOSE_RETURN(data->qh,
    104132            "Failed to allocate batch queue head.\n");
    105         queue_head_init(instance->qh);
    106 
    107         instance->packets = (size + max_packet_size - 1) / max_packet_size;
    108         if (transfer_type == USB_TRANSFER_CONTROL) {
    109                 instance->packets += 2;
    110         }
    111 
    112         instance->tds = malloc32(sizeof(td_t) * instance->packets);
    113         CHECK_NULL_DISPOSE_RETURN(
    114             instance->tds, "Failed to allocate transfer descriptors.\n");
    115         bzero(instance->tds, sizeof(td_t) * instance->packets);
    116 
    117 //      const size_t transport_size = max_packet_size * instance->packets;
    118 
    119         if (size > 0) {
    120                 instance->transport_buffer = malloc32(size);
     133        qh_init(data->qh);
     134        qh_set_element_td(data->qh, addr_to_phys(data->tds));
     135
     136        if (buffer_size > 0) {
     137                instance->transport_buffer = malloc32(buffer_size);
    121138                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    122139                    "Failed to allocate device accessible buffer.\n");
     
    130147        }
    131148
    132 
    133         link_initialize(&instance->link);
    134 
    135         instance->max_packet_size = max_packet_size;
    136         instance->target = target;
    137         instance->transfer_type = transfer_type;
    138         instance->buffer = buffer;
    139         instance->buffer_size = size;
    140         instance->setup_size = setup_size;
    141         instance->fun = fun;
    142         instance->arg = arg;
    143         instance->speed = speed;
    144         instance->manager = manager;
    145 
    146         if (func_out)
    147                 instance->callback_out = func_out;
    148         if (func_in)
    149                 instance->callback_in = func_in;
    150 
    151         queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
    152 
    153149        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    154150            instance, target.address, target.endpoint);
     
    156152}
    157153/*----------------------------------------------------------------------------*/
    158 /** Checks batch TDs for activity.
     154/** Check batch TDs for activity.
    159155 *
    160156 * @param[in] instance Batch structure to use.
    161157 * @return False, if there is an active TD, true otherwise.
     158 *
     159 * Walk all TDs. Stop with false if there is an active one (it is to be
     160 * processed). Stop with true if an error is found. Return true if the last TS
     161 * is reached.
    162162 */
    163163bool batch_is_complete(batch_t *instance)
    164164{
    165165        assert(instance);
     166        uhci_batch_t *data = instance->private_data;
     167        assert(data);
     168
    166169        usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
    167             instance, instance->packets);
     170            instance, data->packets);
    168171        instance->transfered_size = 0;
    169172        size_t i = 0;
    170         for (;i < instance->packets; ++i) {
    171                 if (td_is_active(&instance->tds[i])) {
     173        for (;i < data->packets; ++i) {
     174                if (td_is_active(&data->tds[i])) {
    172175                        return false;
    173176                }
    174177
    175                 instance->error = td_status(&instance->tds[i]);
     178                instance->error = td_status(&data->tds[i]);
    176179                if (instance->error != EOK) {
    177180                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    178                             instance, i, instance->tds[i].status);
    179 
    180                         device_keeper_set_toggle(instance->manager,
    181                             instance->target, td_toggle(&instance->tds[i]));
     181                            instance, i, data->tds[i].status);
     182                        td_print_status(&data->tds[i]);
     183
     184                        device_keeper_set_toggle(data->manager,
     185                            instance->target, instance->direction,
     186                            td_toggle(&data->tds[i]));
    182187                        if (i > 0)
    183188                                goto substract_ret;
     
    185190                }
    186191
    187                 instance->transfered_size += td_act_size(&instance->tds[i]);
    188                 if (td_is_short(&instance->tds[i]))
     192                instance->transfered_size += td_act_size(&data->tds[i]);
     193                if (td_is_short(&data->tds[i]))
    189194                        goto substract_ret;
    190195        }
     
    197202 *
    198203 * @param[in] instance Batch structure to use.
     204 *
     205 * Uses genercir control function with pids OUT and IN.
    199206 */
    200207void batch_control_write(batch_t *instance)
    201208{
    202209        assert(instance);
    203         /* we are data out, we are supposed to provide data */
     210        /* We are data out, we are supposed to provide data */
    204211        memcpy(instance->transport_buffer, instance->buffer,
    205212            instance->buffer_size);
     
    207214        instance->next_step = batch_call_out_and_dispose;
    208215        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    209         batch_schedule(instance);
    210216}
    211217/*----------------------------------------------------------------------------*/
     
    213219 *
    214220 * @param[in] instance Batch structure to use.
     221 *
     222 * Uses generic control with pids IN and OUT.
    215223 */
    216224void batch_control_read(batch_t *instance)
     
    220228        instance->next_step = batch_call_in_and_dispose;
    221229        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    222         batch_schedule(instance);
    223 }
    224 /*----------------------------------------------------------------------------*/
    225 /** Prepares interrupt in transaction.
    226  *
    227  * @param[in] instance Batch structure to use.
     230}
     231/*----------------------------------------------------------------------------*/
     232/** Prepare interrupt in transaction.
     233 *
     234 * @param[in] instance Batch structure to use.
     235 *
     236 * Data transaction with PID_IN.
    228237 */
    229238void batch_interrupt_in(batch_t *instance)
    230239{
    231240        assert(instance);
     241        instance->direction = USB_DIRECTION_IN;
    232242        batch_data(instance, USB_PID_IN);
    233243        instance->next_step = batch_call_in_and_dispose;
    234244        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    235         batch_schedule(instance);
    236 }
    237 /*----------------------------------------------------------------------------*/
    238 /** Prepares interrupt out transaction.
    239  *
    240  * @param[in] instance Batch structure to use.
     245}
     246/*----------------------------------------------------------------------------*/
     247/** Prepare interrupt out transaction.
     248 *
     249 * @param[in] instance Batch structure to use.
     250 *
     251 * Data transaction with PID_OUT.
    241252 */
    242253void batch_interrupt_out(batch_t *instance)
    243254{
    244255        assert(instance);
    245         /* we are data out, we are supposed to provide data */
    246         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     256        instance->direction = USB_DIRECTION_OUT;
     257        /* We are data out, we are supposed to provide data */
     258        memcpy(instance->transport_buffer, instance->buffer,
     259            instance->buffer_size);
    247260        batch_data(instance, USB_PID_OUT);
    248261        instance->next_step = batch_call_out_and_dispose;
    249262        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    250         batch_schedule(instance);
    251 }
    252 /*----------------------------------------------------------------------------*/
    253 /** Prepares bulk in transaction.
    254  *
    255  * @param[in] instance Batch structure to use.
     263}
     264/*----------------------------------------------------------------------------*/
     265/** Prepare bulk in transaction.
     266 *
     267 * @param[in] instance Batch structure to use.
     268 *
     269 * Data transaction with PID_IN.
    256270 */
    257271void batch_bulk_in(batch_t *instance)
     
    259273        assert(instance);
    260274        batch_data(instance, USB_PID_IN);
     275        instance->direction = USB_DIRECTION_IN;
    261276        instance->next_step = batch_call_in_and_dispose;
    262277        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    263         batch_schedule(instance);
    264 }
    265 /*----------------------------------------------------------------------------*/
    266 /** Prepares bulk out transaction.
    267  *
    268  * @param[in] instance Batch structure to use.
     278}
     279/*----------------------------------------------------------------------------*/
     280/** Prepare bulk out transaction.
     281 *
     282 * @param[in] instance Batch structure to use.
     283 *
     284 * Data transaction with PID_OUT.
    269285 */
    270286void batch_bulk_out(batch_t *instance)
    271287{
    272288        assert(instance);
    273         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     289        instance->direction = USB_DIRECTION_OUT;
     290        /* We are data out, we are supposed to provide data */
     291        memcpy(instance->transport_buffer, instance->buffer,
     292            instance->buffer_size);
    274293        batch_data(instance, USB_PID_OUT);
    275294        instance->next_step = batch_call_out_and_dispose;
    276295        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    277         batch_schedule(instance);
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 /** Prepares generic data transaction
     296}
     297/*----------------------------------------------------------------------------*/
     298/** Prepare generic data transaction
    281299 *
    282300 * @param[in] instance Batch structure to use.
    283301 * @param[in] pid to use for data packets.
     302 *
     303 * Packets with alternating toggle bit and supplied pid value.
     304 * The last packet is marked with IOC flag.
    284305 */
    285306void batch_data(batch_t *instance, usb_packet_id pid)
    286307{
    287308        assert(instance);
     309        uhci_batch_t *data = instance->private_data;
     310        assert(data);
     311
    288312        const bool low_speed = instance->speed == USB_SPEED_LOW;
    289         int toggle =
    290             device_keeper_get_toggle(instance->manager, instance->target);
     313        int toggle = device_keeper_get_toggle(
     314            data->manager, instance->target, instance->direction);
    291315        assert(toggle == 0 || toggle == 1);
    292316
     
    294318        size_t remain_size = instance->buffer_size;
    295319        while (remain_size > 0) {
    296                 char *data =
     320                char *trans_data =
    297321                    instance->transport_buffer + instance->buffer_size
    298322                    - remain_size;
     
    302326                    remain_size : instance->max_packet_size;
    303327
    304                 td_t *next_packet = (packet + 1 < instance->packets)
    305                     ? &instance->tds[packet + 1] : NULL;
    306 
    307                 assert(packet < instance->packets);
     328                td_t *next_packet = (packet + 1 < data->packets)
     329                    ? &data->tds[packet + 1] : NULL;
     330
     331                assert(packet < data->packets);
    308332                assert(packet_size <= remain_size);
    309333
    310334                td_init(
    311                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    312                     toggle, false, low_speed, instance->target, pid, data,
     335                    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     336                    toggle, false, low_speed, instance->target, pid, trans_data,
    313337                    next_packet);
    314338
     
    318342                ++packet;
    319343        }
    320         device_keeper_set_toggle(instance->manager, instance->target, toggle);
    321 }
    322 /*----------------------------------------------------------------------------*/
    323 /** Prepares generic control transaction
     344        td_set_ioc(&data->tds[packet - 1]);
     345        device_keeper_set_toggle(data->manager, instance->target,
     346            instance->direction, toggle);
     347}
     348/*----------------------------------------------------------------------------*/
     349/** Prepare generic control transaction
    324350 *
    325351 * @param[in] instance Batch structure to use.
    326352 * @param[in] data_stage to use for data packets.
    327353 * @param[in] status_stage to use for data packets.
     354 *
     355 * Setup stage with toggle 0 and USB_PID_SETUP.
     356 * Data stage with alternating toggle and pid supplied by parameter.
     357 * Status stage with toggle 1 and pid supplied by parameter.
     358 * The last packet is marked with IOC.
    328359 */
    329360void batch_control(batch_t *instance,
     
    331362{
    332363        assert(instance);
     364        uhci_batch_t *data = instance->private_data;
     365        assert(data);
     366        assert(data->packets >= 2);
    333367
    334368        const bool low_speed = instance->speed == USB_SPEED_LOW;
    335369        int toggle = 0;
    336370        /* setup stage */
    337         td_init(instance->tds, DEFAULT_ERROR_COUNT,
    338             instance->setup_size, toggle, false, low_speed, instance->target,
    339             USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     371        td_init(
     372            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
     373            low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
     374            &data->tds[1]);
    340375
    341376        /* data stage */
     
    343378        size_t remain_size = instance->buffer_size;
    344379        while (remain_size > 0) {
    345                 char *data =
     380                char *control_data =
    346381                    instance->transport_buffer + instance->buffer_size
    347382                    - remain_size;
     
    354389
    355390                td_init(
    356                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     391                    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    357392                    toggle, false, low_speed, instance->target, data_stage,
    358                     data, &instance->tds[packet + 1]);
     393                    control_data, &data->tds[packet + 1]);
    359394
    360395                ++packet;
    361                 assert(packet < instance->packets);
     396                assert(packet < data->packets);
    362397                assert(packet_size <= remain_size);
    363398                remain_size -= packet_size;
     
    365400
    366401        /* status stage */
    367         assert(packet == instance->packets - 1);
    368         td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
    369             0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    370 
    371 
    372         instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     402        assert(packet == data->packets - 1);
     403
     404        td_init(
     405            &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     406            instance->target, status_stage, NULL, NULL);
     407        td_set_ioc(&data->tds[packet]);
     408
    373409        usb_log_debug2("Control last TD status: %x.\n",
    374             instance->tds[packet].status);
    375 }
    376 /*----------------------------------------------------------------------------*/
    377 /** Prepares data, gets error status and calls callback in.
    378  *
    379  * @param[in] instance Batch structure to use.
    380  */
    381 void batch_call_in(batch_t *instance)
    382 {
    383         assert(instance);
    384         assert(instance->callback_in);
    385 
    386         /* we are data in, we need data */
    387         memcpy(instance->buffer, instance->transport_buffer,
    388             instance->buffer_size);
    389 
    390         int err = instance->error;
    391         usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
    392             instance, instance->transfer_type, str_error(err), err,
    393             instance->transfered_size);
    394 
    395         instance->callback_in(
    396             instance->fun, err, instance->transfered_size, instance->arg);
    397 }
    398 /*----------------------------------------------------------------------------*/
    399 /** Gets error status and calls callback out.
    400  *
    401  * @param[in] instance Batch structure to use.
    402  */
    403 void batch_call_out(batch_t *instance)
    404 {
    405         assert(instance);
    406         assert(instance->callback_out);
    407 
    408         int err = instance->error;
    409         usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
    410             instance, instance->transfer_type, str_error(err), err);
    411         instance->callback_out(instance->fun,
    412             err, instance->arg);
    413 }
    414 /*----------------------------------------------------------------------------*/
    415 /** Prepares data, gets error status, calls callback in and dispose.
     410            data->tds[packet].status);
     411}
     412/*----------------------------------------------------------------------------*/
     413qh_t * batch_qh(batch_t *instance)
     414{
     415        assert(instance);
     416        uhci_batch_t *data = instance->private_data;
     417        assert(data);
     418        return data->qh;
     419}
     420/*----------------------------------------------------------------------------*/
     421/** Helper function calls callback and correctly disposes of batch structure.
    416422 *
    417423 * @param[in] instance Batch structure to use.
     
    424430}
    425431/*----------------------------------------------------------------------------*/
    426 /** Gets error status, calls callback out and dispose.
     432/** Helper function calls callback and correctly disposes of batch structure.
    427433 *
    428434 * @param[in] instance Batch structure to use.
     
    435441}
    436442/*----------------------------------------------------------------------------*/
    437 /** Correctly disposes all used data structures.
     443/** Correctly dispose all used data structures.
    438444 *
    439445 * @param[in] instance Batch structure to use.
     
    442448{
    443449        assert(instance);
     450        uhci_batch_t *data = instance->private_data;
     451        assert(data);
    444452        usb_log_debug("Batch(%p) disposing.\n", instance);
    445453        /* free32 is NULL safe */
    446         free32(instance->tds);
    447         free32(instance->qh);
     454        free32(data->tds);
     455        free32(data->qh);
    448456        free32(instance->setup_buffer);
    449457        free32(instance->transport_buffer);
     458        free(data);
    450459        free(instance);
    451 }
    452 /*----------------------------------------------------------------------------*/
    453 int batch_schedule(batch_t *instance)
    454 {
    455         assert(instance);
    456         uhci_t *hc = fun_to_uhci(instance->fun);
    457         assert(hc);
    458         return uhci_schedule(hc, instance);
    459460}
    460461/**
  • uspace/drv/uhci-hcd/batch.h

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver USB transaction structure
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
     
    3939#include <usbhc_iface.h>
    4040#include <usb/usb.h>
     41#include <usb/host/device_keeper.h>
     42#include <usb/host/batch.h>
    4143
    42 #include "uhci_struct/transfer_descriptor.h"
    4344#include "uhci_struct/queue_head.h"
    44 #include "utils/device_keeper.h"
    4545
    46 typedef struct batch
    47 {
    48         link_t link;
    49         usb_speed_t speed;
    50         usb_target_t target;
    51         usb_transfer_type_t transfer_type;
    52         union {
    53                 usbhc_iface_transfer_in_callback_t callback_in;
    54                 usbhc_iface_transfer_out_callback_t callback_out;
    55         };
    56         void *arg;
    57         char *transport_buffer;
    58         char *setup_buffer;
    59         size_t setup_size;
    60         char *buffer;
    61         size_t buffer_size;
    62         size_t max_packet_size;
    63         size_t packets;
    64         size_t transfered_size;
    65         int error;
    66         ddf_fun_t *fun;
    67         queue_head_t *qh;
    68         td_t *tds;
    69         void (*next_step)(struct batch*);
    70         device_keeper_t *manager;
    71 } batch_t;
    72 
    73 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    74     usb_transfer_type_t transfer_type, size_t max_packet_size,
    75     usb_speed_t speed, char *buffer, size_t size,
    76                 char *setup_buffer, size_t setup_size,
     46batch_t * batch_get(
     47    ddf_fun_t *fun,
     48                usb_target_t target,
     49    usb_transfer_type_t transfer_type,
     50                size_t max_packet_size,
     51    usb_speed_t speed,
     52                char *buffer,
     53                size_t size,
     54                char *setup_buffer,
     55                size_t setup_size,
    7756    usbhc_iface_transfer_in_callback_t func_in,
    78     usbhc_iface_transfer_out_callback_t func_out, void *arg,
     57    usbhc_iface_transfer_out_callback_t func_out,
     58                void *arg,
    7959                device_keeper_t *manager
    8060                );
     61
     62void batch_dispose(batch_t *instance);
    8163
    8264bool batch_is_complete(batch_t *instance);
     
    9375
    9476void batch_bulk_out(batch_t *instance);
     77
     78qh_t * batch_qh(batch_t *instance);
    9579#endif
    9680/**
  • uspace/drv/uhci-hcd/iface.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver hc interface implementation
    3333 */
    3434#include <ddf/driver.h>
     
    4040
    4141#include "iface.h"
    42 #include "uhci.h"
    43 #include "utils/device_keeper.h"
     42#include "uhci_hc.h"
    4443
    4544/** Reserve default address interface function
     
    5352{
    5453        assert(fun);
    55         uhci_t *hc = fun_to_uhci(fun);
     54        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    5655        assert(hc);
    5756        usb_log_debug("Default address request with speed %d.\n", speed);
     
    6867{
    6968        assert(fun);
    70         uhci_t *hc = fun_to_uhci(fun);
     69        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    7170        assert(hc);
    7271        usb_log_debug("Default address release.\n");
     
    8685{
    8786        assert(fun);
    88         uhci_t *hc = fun_to_uhci(fun);
     87        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    8988        assert(hc);
    9089        assert(address);
     
    109108{
    110109        assert(fun);
    111         uhci_t *hc = fun_to_uhci(fun);
     110        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    112111        assert(hc);
    113112        usb_log_debug("Address bind %d-%d.\n", address, handle);
     
    125124{
    126125        assert(fun);
    127         uhci_t *hc = fun_to_uhci(fun);
     126        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    128127        assert(hc);
    129128        usb_log_debug("Address release %d.\n", address);
     
    148147{
    149148        assert(fun);
    150         uhci_t *hc = fun_to_uhci(fun);
     149        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    151150        assert(hc);
    152151        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    161160                return ENOMEM;
    162161        batch_interrupt_out(batch);
     162        const int ret = uhci_hc_schedule(hc, batch);
     163        if (ret != EOK) {
     164                batch_dispose(batch);
     165                return ret;
     166        }
    163167        return EOK;
    164168}
     
    180184{
    181185        assert(fun);
    182         uhci_t *hc = fun_to_uhci(fun);
     186        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    183187        assert(hc);
    184188        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    192196                return ENOMEM;
    193197        batch_interrupt_in(batch);
     198        const int ret = uhci_hc_schedule(hc, batch);
     199        if (ret != EOK) {
     200                batch_dispose(batch);
     201                return ret;
     202        }
    194203        return EOK;
    195204}
     
    211220{
    212221        assert(fun);
    213         uhci_t *hc = fun_to_uhci(fun);
     222        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    214223        assert(hc);
    215224        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    224233                return ENOMEM;
    225234        batch_bulk_out(batch);
     235        const int ret = uhci_hc_schedule(hc, batch);
     236        if (ret != EOK) {
     237                batch_dispose(batch);
     238                return ret;
     239        }
    226240        return EOK;
    227241}
     
    243257{
    244258        assert(fun);
    245         uhci_t *hc = fun_to_uhci(fun);
     259        uhci_hc_t *hc = fun_to_uhci_hc(fun);
    246260        assert(hc);
    247261        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    255269                return ENOMEM;
    256270        batch_bulk_in(batch);
     271        const int ret = uhci_hc_schedule(hc, batch);
     272        if (ret != EOK) {
     273                batch_dispose(batch);
     274                return ret;
     275        }
    257276        return EOK;
    258277}
     
    277296{
    278297        assert(fun);
    279         uhci_t *hc = fun_to_uhci(fun);
    280         assert(hc);
    281         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    282         usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",
    283             target.address, target.endpoint, size, max_packet_size);
     298        uhci_hc_t *hc = fun_to_uhci_hc(fun);
     299        assert(hc);
     300        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     301        usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
     302            speed, target.address, target.endpoint, size, max_packet_size);
    284303
    285304        if (setup_size != 8)
     
    293312        device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
    294313        batch_control_write(batch);
     314        const int ret = uhci_hc_schedule(hc, batch);
     315        if (ret != EOK) {
     316                batch_dispose(batch);
     317                return ret;
     318        }
    295319        return EOK;
    296320}
     
    315339{
    316340        assert(fun);
    317         uhci_t *hc = fun_to_uhci(fun);
    318         assert(hc);
    319         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    320 
    321         usb_log_debug("Control READ %d:%d %zu(%zu).\n",
    322             target.address, target.endpoint, size, max_packet_size);
     341        uhci_hc_t *hc = fun_to_uhci_hc(fun);
     342        assert(hc);
     343        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     344
     345        usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
     346            speed, target.address, target.endpoint, size, max_packet_size);
    323347        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    324348            max_packet_size, speed, data, size, setup_data, setup_size, callback,
     
    327351                return ENOMEM;
    328352        batch_control_read(batch);
    329         return EOK;
    330 }
    331 /*----------------------------------------------------------------------------*/
    332 usbhc_iface_t uhci_iface = {
     353        const int ret = uhci_hc_schedule(hc, batch);
     354        if (ret != EOK) {
     355                batch_dispose(batch);
     356                return ret;
     357        }
     358        return EOK;
     359}
     360/*----------------------------------------------------------------------------*/
     361usbhc_iface_t uhci_hc_iface = {
    333362        .reserve_default_address = reserve_default_address,
    334363        .release_default_address = release_default_address,
  • uspace/drv/uhci-hcd/iface.h

    rc32688d r361e61b  
    2727 */
    2828
    29 /** @addtogroup usb
     29/** @addtogroup drvusbuhcihc
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief UHCI driver iface
    3434 */
    3535#ifndef DRV_UHCI_IFACE_H
     
    3838#include <usbhc_iface.h>
    3939
    40 extern usbhc_iface_t uhci_iface;
     40extern usbhc_iface_t uhci_hc_iface;
    4141
    4242#endif
  • uspace/drv/uhci-hcd/main.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver initialization
    3333 */
    3434#include <ddf/driver.h>
    35 #include <ddf/interrupt.h>
    36 #include <device/hw_res.h>
    3735#include <errno.h>
    3836#include <str_error.h>
    3937
    40 #include <usb_iface.h>
    4138#include <usb/ddfiface.h>
    4239#include <usb/debug.h>
    4340
    4441#include "iface.h"
    45 #include "pci.h"
    46 #include "root_hub.h"
    4742#include "uhci.h"
    4843
     
    6055};
    6156/*----------------------------------------------------------------------------*/
    62 /** IRQ handling callback, identifies devic
    63  *
    64  * @param[in] dev DDF instance of the device to use.
    65  * @param[in] iid (Unused).
    66  * @param[in] call Pointer to the call that represents interrupt.
    67  */
    68 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    69 {
    70         assert(dev);
    71         uhci_t *hc = dev_to_uhci(dev);
    72         uint16_t status = IPC_GET_ARG1(*call);
    73         assert(hc);
    74         uhci_interrupt(hc, status);
    75 }
    76 /*----------------------------------------------------------------------------*/
    77 /** Initializes a new ddf driver instance of UHCI hcd.
     57/** Initialize a new ddf driver instance for uhci hc and hub.
    7858 *
    7959 * @param[in] device DDF instance of the device to initialize.
    8060 * @return Error code.
    81  *
    82  * Gets and initialies hardware resources, disables any legacy support,
    83  * and reports root hub device.
    8461 */
    8562int uhci_add_device(ddf_dev_t *device)
    8663{
     64        usb_log_info("uhci_add_device() called\n");
    8765        assert(device);
    88         uhci_t *hcd = NULL;
    89 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \
    90 if (ret != EOK) { \
    91         usb_log_error(message); \
    92         if (hcd != NULL) \
    93                 free(hcd); \
    94         return ret; \
    95 }
     66        uhci_t *uhci = malloc(sizeof(uhci_t));
     67        if (uhci == NULL) {
     68                usb_log_error("Failed to allocate UHCI driver.\n");
     69                return ENOMEM;
     70        }
    9671
    97         usb_log_info("uhci_add_device() called\n");
    98 
    99         uintptr_t io_reg_base = 0;
    100         size_t io_reg_size = 0;
    101         int irq = 0;
    102 
    103         int ret =
    104             pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
    105         CHECK_RET_FREE_HC_RETURN(ret,
    106             "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    107         usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    108             io_reg_base, io_reg_size, irq);
    109 
    110         ret = pci_disable_legacy(device);
    111         CHECK_RET_FREE_HC_RETURN(ret,
    112             "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
    113 
    114 #if 0
    115         ret = pci_enable_interrupts(device);
     72        int ret = uhci_init(uhci, device);
    11673        if (ret != EOK) {
    117                 usb_log_warning(
    118                     "Failed(%d) to enable interrupts, fall back to polling.\n",
    119                     ret);
     74                usb_log_error("Failed to initialzie UHCI driver.\n");
     75                return ret;
    12076        }
    121 #endif
    122 
    123         hcd = malloc(sizeof(uhci_t));
    124         ret = (hcd != NULL) ? EOK : ENOMEM;
    125         CHECK_RET_FREE_HC_RETURN(ret,
    126             "Failed(%d) to allocate memory for uhci hcd.\n", ret);
    127 
    128         ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
    129         CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
    130 #undef CHECK_RET_FREE_HC_RETURN
    131 
    132         /*
    133          * We might free hcd, but that does not matter since no one
    134          * else would access driver_data anyway.
    135          */
    136         device->driver_data = hcd;
    137 
    138         ddf_fun_t *rh = NULL;
    139 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
    140 if (ret != EOK) { \
    141         usb_log_error(message); \
    142         if (hcd != NULL) {\
    143                 uhci_fini(hcd); \
    144                 free(hcd); \
    145         } \
    146         if (rh != NULL) \
    147                 free(rh); \
    148         return ret; \
    149 }
    150 
    151         /* It does no harm if we register this on polling */
    152         ret = register_interrupt_handler(device, irq, irq_handler,
    153             &hcd->interrupt_code);
    154         CHECK_RET_FINI_FREE_RETURN(ret,
    155             "Failed(%d) to register interrupt handler.\n", ret);
    156 
    157         ret = setup_root_hub(&rh, device);
    158         CHECK_RET_FINI_FREE_RETURN(ret,
    159             "Failed(%d) to setup UHCI root hub.\n", ret);
    160         rh->driver_data = hcd->ddf_instance;
    161 
    162         ret = ddf_fun_bind(rh);
    163         CHECK_RET_FINI_FREE_RETURN(ret,
    164             "Failed(%d) to register UHCI root hub.\n", ret);
    165 
     77        device->driver_data = uhci;
    16678        return EOK;
    167 #undef CHECK_RET_FINI_FREE_RETURN
    16879}
    16980/*----------------------------------------------------------------------------*/
    170 /** Initializes global driver structures (NONE).
     81/** Initialize global driver structures (NONE).
    17182 *
    17283 * @param[in] argc Nmber of arguments in argv vector (ignored).
     
    17889int main(int argc, char *argv[])
    17990{
    180         sleep(3);
     91        sleep(3); /* TODO: remove in final version */
    18192        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    18293
  • uspace/drv/uhci-hcd/pci.c

    rc32688d r361e61b  
    2727 */
    2828/**
    29  * @addtogroup drvusbuhci
     29 * @addtogroup drvusbuhcihc
    3030 * @{
    3131 */
     
    117117}
    118118/*----------------------------------------------------------------------------*/
    119 /** Calls the PCI driver with a request to enable interrupts
     119/** Call the PCI driver with a request to enable interrupts
    120120 *
    121121 * @param[in] device Device asking for interrupts
     
    131131}
    132132/*----------------------------------------------------------------------------*/
    133 /** Calls the PCI driver with a request to clear legacy support register
     133/** Call the PCI driver with a request to clear legacy support register
    134134 *
    135135 * @param[in] device Device asking to disable interrupts
  • uspace/drv/uhci-hcd/pci.h

    rc32688d r361e61b  
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup drvusbuhcihc
    3030 * @{
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief UHCI driver PCI helper functions
    3434 */
    3535#ifndef DRV_UHCI_PCI_H
  • uspace/drv/uhci-hcd/transfer_list.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver transfer list implementation
    3333 */
    3434#include <errno.h>
    35 
    3635#include <usb/debug.h>
    3736
     
    4140    transfer_list_t *instance, batch_t *batch);
    4241/*----------------------------------------------------------------------------*/
    43 /** Initializes transfer list structures.
     42/** Initialize transfer list structures.
    4443 *
    4544 * @param[in] instance Memory place to use.
    46  * @param[in] name Name of te new list.
    47  * @return Error code
    48  *
    49  * Allocates memory for internat queue_head_t structure.
     45 * @param[in] name Name of the new list.
     46 * @return Error code
     47 *
     48 * Allocates memory for internal qh_t structure.
    5049 */
    5150int transfer_list_init(transfer_list_t *instance, const char *name)
    5251{
    5352        assert(instance);
    54         instance->next = NULL;
    5553        instance->name = name;
    56         instance->queue_head = malloc32(sizeof(queue_head_t));
     54        instance->queue_head = malloc32(sizeof(qh_t));
    5755        if (!instance->queue_head) {
    5856                usb_log_error("Failed to allocate queue head.\n");
     
    6159        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    6260
    63         queue_head_init(instance->queue_head);
     61        qh_init(instance->queue_head);
    6462        list_initialize(&instance->batch_list);
    6563        fibril_mutex_initialize(&instance->guard);
     
    6765}
    6866/*----------------------------------------------------------------------------*/
    69 /** Set the next list in chain.
     67/** Set the next list in transfer list chain.
    7068 *
    7169 * @param[in] instance List to lead.
    7270 * @param[in] next List to append.
    7371 * @return Error code
     72 *
     73 * Does not check whether this replaces an existing list .
    7474 */
    7575void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
     
    7979        if (!instance->queue_head)
    8080                return;
    81         queue_head_append_qh(instance->queue_head, next->queue_head_pa);
    82         instance->queue_head->element = instance->queue_head->next_queue;
    83 }
    84 /*----------------------------------------------------------------------------*/
    85 /** Submits a new transfer batch to list and queue.
     81        /* Set both next and element to point to the same QH */
     82        qh_set_next_qh(instance->queue_head, next->queue_head_pa);
     83        qh_set_element_qh(instance->queue_head, next->queue_head_pa);
     84}
     85/*----------------------------------------------------------------------------*/
     86/** Submit transfer batch to the list and queue.
    8687 *
    8788 * @param[in] instance List to use.
    8889 * @param[in] batch Transfer batch to submit.
    8990 * @return Error code
     91 *
     92 * The batch is added to the end of the list and queue.
    9093 */
    9194void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
     
    9396        assert(instance);
    9497        assert(batch);
    95         usb_log_debug2(
    96             "Adding batch(%p) to queue %s.\n", batch, instance->name);
    97 
    98         uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     98        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     99
     100        const uint32_t pa = addr_to_phys(batch_qh(batch));
    99101        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    100         pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    101 
    102         batch->qh->next_queue = instance->queue_head->next_queue;
     102
     103        /* New batch will be added to the end of the current list
     104         * so set the link accordingly */
     105        qh_set_next_qh(batch_qh(batch), instance->queue_head->next);
    103106
    104107        fibril_mutex_lock(&instance->guard);
    105108
    106         if (instance->queue_head->element == instance->queue_head->next_queue) {
    107                 /* there is nothing scheduled */
    108                 list_append(&batch->link, &instance->batch_list);
    109                 instance->queue_head->element = pa;
    110                 usb_log_debug("Batch(%p) added to queue %s first.\n",
    111                         batch, instance->name);
    112                 fibril_mutex_unlock(&instance->guard);
    113                 return;
    114         }
    115         /* now we can be sure that there is someting scheduled */
    116         assert(!list_empty(&instance->batch_list));
     109        /* Add to the hardware queue. */
     110        if (list_empty(&instance->batch_list)) {
     111                /* There is nothing scheduled */
     112                qh_t *qh = instance->queue_head;
     113                assert(qh->element == qh->next);
     114                qh_set_element_qh(qh, pa);
     115        } else {
     116                /* There is something scheduled */
     117                batch_t *last = list_get_instance(
     118                    instance->batch_list.prev, batch_t, link);
     119                qh_set_next_qh(batch_qh(last), pa);
     120        }
     121        /* Add to the driver list */
     122        list_append(&batch->link, &instance->batch_list);
     123
    117124        batch_t *first = list_get_instance(
    118                   instance->batch_list.next, batch_t, link);
    119         batch_t *last = list_get_instance(
    120             instance->batch_list.prev, batch_t, link);
    121         queue_head_append_qh(last->qh, pa);
    122         list_append(&batch->link, &instance->batch_list);
    123 
    124         usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
     125            instance->batch_list.next, batch_t, link);
     126        usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
    125127                batch, instance->name, first);
    126128        fibril_mutex_unlock(&instance->guard);
    127129}
    128130/*----------------------------------------------------------------------------*/
    129 /** Removes a transfer batch from list and queue.
    130  *
    131  * @param[in] instance List to use.
    132  * @param[in] batch Transfer batch to remove.
    133  * @return Error code
    134  */
    135 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
    136 {
    137         assert(instance);
    138         assert(batch);
    139         assert(instance->queue_head);
    140         assert(batch->qh);
    141         usb_log_debug2(
    142             "Removing batch(%p) from queue %s.\n", batch, instance->name);
    143 
    144         if (batch->link.prev == &instance->batch_list) {
    145                 /* I'm the first one here */
    146                 usb_log_debug(
    147                     "Batch(%p) removed (FIRST) from %s, next element %x.\n",
    148                     batch, instance->name, batch->qh->next_queue);
    149                 instance->queue_head->element = batch->qh->next_queue;
    150         } else {
    151                 usb_log_debug(
    152                     "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
    153                     batch, instance->name, batch->qh->next_queue);
    154                 batch_t *prev =
    155                     list_get_instance(batch->link.prev, batch_t, link);
    156                 prev->qh->next_queue = batch->qh->next_queue;
    157         }
    158         list_remove(&batch->link);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Checks list for finished transfers.
    162  *
    163  * @param[in] instance List to use.
    164  * @return Error code
     131/** Check list for finished batches.
     132 *
     133 * @param[in] instance List to use.
     134 * @return Error code
     135 *
     136 * Creates a local list of finished batches and calls next_step on each and
     137 * every one. This is safer because next_step may theoretically access
     138 * this transfer list leading to the deadlock if its done inline.
    165139 */
    166140void transfer_list_remove_finished(transfer_list_t *instance)
     
    177151
    178152                if (batch_is_complete(batch)) {
     153                        /* Save for post-processing */
    179154                        transfer_list_remove_batch(instance, batch);
    180155                        list_append(current, &done);
     
    191166        }
    192167}
     168/*----------------------------------------------------------------------------*/
     169/** Walk the list and abort all batches.
     170 *
     171 * @param[in] instance List to use.
     172 */
     173void transfer_list_abort_all(transfer_list_t *instance)
     174{
     175        fibril_mutex_lock(&instance->guard);
     176        while (list_empty(&instance->batch_list)) {
     177                link_t *current = instance->batch_list.next;
     178                batch_t *batch = list_get_instance(current, batch_t, link);
     179                transfer_list_remove_batch(instance, batch);
     180                batch_finish(batch, EIO);
     181        }
     182        fibril_mutex_unlock(&instance->guard);
     183}
     184/*----------------------------------------------------------------------------*/
     185/** Remove a transfer batch from the list and queue.
     186 *
     187 * @param[in] instance List to use.
     188 * @param[in] batch Transfer batch to remove.
     189 * @return Error code
     190 *
     191 * Does not lock the transfer list, caller is responsible for that.
     192 */
     193void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
     194{
     195        assert(instance);
     196        assert(instance->queue_head);
     197        assert(batch);
     198        assert(batch_qh(batch));
     199        usb_log_debug2(
     200            "Queue %s: removing batch(%p).\n", instance->name, batch);
     201
     202        const char * pos = NULL;
     203        /* Remove from the hardware queue */
     204        if (batch->link.prev == &instance->batch_list) {
     205                /* I'm the first one here */
     206                qh_set_element_qh(instance->queue_head, batch_qh(batch)->next);
     207                pos = "FIRST";
     208        } else {
     209                batch_t *prev =
     210                    list_get_instance(batch->link.prev, batch_t, link);
     211                qh_set_next_qh(batch_qh(prev), batch_qh(batch)->next);
     212                pos = "NOT FIRST";
     213        }
     214        /* Remove from the driver list */
     215        list_remove(&batch->link);
     216        usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
     217            batch, pos, instance->name, batch_qh(batch)->next);
     218}
    193219/**
    194220 * @}
  • uspace/drv/uhci-hcd/transfer_list.h

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver transfer list structure
    3333 */
    3434#ifndef DRV_UHCI_TRANSFER_LIST_H
     
    4444{
    4545        fibril_mutex_t guard;
    46         queue_head_t *queue_head;
     46        qh_t *queue_head;
    4747        uint32_t queue_head_pa;
    48         struct transfer_list *next;
    4948        const char *name;
    5049        link_t batch_list;
    5150} transfer_list_t;
     51
     52/** Dispose transfer list structures.
     53 *
     54 * @param[in] instance Memory place to use.
     55 *
     56 * Frees memory for internal qh_t structure.
     57 */
     58static inline void transfer_list_fini(transfer_list_t *instance)
     59{
     60        assert(instance);
     61        free32(instance->queue_head);
     62}
    5263
    5364int transfer_list_init(transfer_list_t *instance, const char *name);
     
    5566void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    5667
    57 static inline void transfer_list_fini(transfer_list_t *instance)
    58 {
    59         assert(instance);
    60         free32(instance->queue_head);
    61 }
     68void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
     69
    6270void transfer_list_remove_finished(transfer_list_t *instance);
    6371
    64 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
     72void transfer_list_abort_all(transfer_list_t *instance);
    6573#endif
    6674/**
  • uspace/drv/uhci-hcd/uhci.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28
     29/** @addtogroup drvusbuhci
    2930 * @{
    3031 */
     
    3435#include <errno.h>
    3536#include <str_error.h>
    36 #include <adt/list.h>
    37 #include <libarch/ddi.h>
    38 
     37#include <ddf/interrupt.h>
     38#include <usb_iface.h>
     39#include <usb/ddfiface.h>
    3940#include <usb/debug.h>
    40 #include <usb/usb.h>
    41 #include <usb/ddfiface.h>
    42 #include <usb_iface.h>
    4341
    4442#include "uhci.h"
    4543#include "iface.h"
    46 
    47 static irq_cmd_t uhci_cmds[] = {
    48         {
    49                 .cmd = CMD_PIO_READ_16,
    50                 .addr = NULL, /* patched for every instance */
    51                 .dstarg = 1
    52         },
    53         {
    54                 .cmd = CMD_PIO_WRITE_16,
    55                 .addr = NULL, /* pathed for every instance */
    56                 .value = 0x1f
    57         },
    58         {
    59                 .cmd = CMD_ACCEPT
    60         }
    61 };
    62 
    63 /** Gets USB address of the calling device.
    64  *
    65  * @param[in] fun UHCI hc function.
    66  * @param[in] handle Handle of the device seeking address.
    67  * @param[out] address Place to store found address.
    68  * @return Error code.
     44#include "pci.h"
     45
     46
     47/** IRQ handling callback, identifies device
     48 *
     49 * @param[in] dev DDF instance of the device to use.
     50 * @param[in] iid (Unused).
     51 * @param[in] call Pointer to the call that represents interrupt.
     52 */
     53static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     54{
     55        assert(dev);
     56        uhci_hc_t *hc = &((uhci_t*)dev->driver_data)->hc;
     57        uint16_t status = IPC_GET_ARG1(*call);
     58        assert(hc);
     59        uhci_hc_interrupt(hc, status);
     60}
     61/*----------------------------------------------------------------------------*/
     62/** Get address of the device identified by handle.
     63 *
     64 * @param[in] dev DDF instance of the device to use.
     65 * @param[in] iid (Unused).
     66 * @param[in] call Pointer to the call that represents interrupt.
    6967 */
    7068static int usb_iface_get_address(
     
    7270{
    7371        assert(fun);
    74         uhci_t *hc = fun_to_uhci(fun);
    75         assert(hc);
    76 
    77         usb_address_t addr = device_keeper_find(&hc->device_manager,
    78             handle);
     72        device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.device_manager;
     73
     74        usb_address_t addr = device_keeper_find(manager, handle);
    7975        if (addr < 0) {
    8076                return addr;
     
    8884}
    8985/*----------------------------------------------------------------------------*/
    90 static usb_iface_t hc_usb_iface = {
    91         .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     86/** Gets handle of the respective hc (this or parent device).
     87 *
     88 * @param[in] root_hub_fun Root hub function seeking hc handle.
     89 * @param[out] handle Place to write the handle.
     90 * @return Error code.
     91 */
     92static int usb_iface_get_hc_handle(
     93    ddf_fun_t *fun, devman_handle_t *handle)
     94{
     95        assert(handle);
     96        ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun;
     97        assert(hc_fun != NULL);
     98
     99        *handle = hc_fun->handle;
     100        return EOK;
     101}
     102/*----------------------------------------------------------------------------*/
     103/** This iface is generic for both RH and HC. */
     104static usb_iface_t usb_iface = {
     105        .get_hc_handle = usb_iface_get_hc_handle,
    92106        .get_address = usb_iface_get_address
    93107};
    94108/*----------------------------------------------------------------------------*/
    95 static ddf_dev_ops_t uhci_ops = {
    96         .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    97         .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    98 };
    99 /*----------------------------------------------------------------------------*/
    100 static int uhci_init_transfer_lists(uhci_t *instance);
    101 static int uhci_init_mem_structures(uhci_t *instance);
    102 static void uhci_init_hw(uhci_t *instance);
    103 
    104 static int uhci_interrupt_emulator(void *arg);
    105 static int uhci_debug_checker(void *arg);
    106 
    107 static bool allowed_usb_packet(
    108     bool low_speed, usb_transfer_type_t transfer, size_t size);
    109 /*----------------------------------------------------------------------------*/
    110 /** Initializes UHCI hcd driver structure
    111  *
    112  * @param[in] instance Memory place to initialize.
    113  * @param[in] dev DDF device.
    114  * @param[in] regs Address of I/O control registers.
    115  * @param[in] size Size of I/O control registers.
    116  * @return Error code.
    117  * @note Should be called only once on any structure.
    118  */
    119 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
    120 {
    121         assert(reg_size >= sizeof(regs_t));
    122         int ret;
    123 
     109static ddf_dev_ops_t uhci_hc_ops = {
     110        .interfaces[USB_DEV_IFACE] = &usb_iface,
     111        .interfaces[USBHC_DEV_IFACE] = &uhci_hc_iface, /* see iface.h/c */
     112};
     113/*----------------------------------------------------------------------------*/
     114/** Get root hub hw resources (I/O registers).
     115 *
     116 * @param[in] fun Root hub function.
     117 * @return Pointer to the resource list used by the root hub.
     118 */
     119static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
     120{
     121        assert(fun);
     122        return &((uhci_rh_t*)fun->driver_data)->resource_list;
     123}
     124/*----------------------------------------------------------------------------*/
     125static hw_res_ops_t hw_res_iface = {
     126        .get_resource_list = get_resource_list,
     127        .enable_interrupt = NULL
     128};
     129/*----------------------------------------------------------------------------*/
     130static ddf_dev_ops_t uhci_rh_ops = {
     131        .interfaces[USB_DEV_IFACE] = &usb_iface,
     132        .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
     133};
     134/*----------------------------------------------------------------------------*/
     135/** Initialize hc and rh ddf structures and their respective drivers.
     136 *
     137 * @param[in] instance UHCI structure to use.
     138 * @param[in] device DDF instance of the device to use.
     139 *
     140 * This function does all the preparatory work for hc and rh drivers:
     141 *  - gets device hw resources
     142 *  - disables UHCI legacy support
     143 *  - asks for interrupt
     144 *  - registers interrupt handler
     145 */
     146int uhci_init(uhci_t *instance, ddf_dev_t *device)
     147{
     148        assert(instance);
     149        instance->hc_fun = NULL;
     150        instance->rh_fun = NULL;
    124151#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
    125         if (ret != EOK) { \
    126                 usb_log_error(message); \
    127                 if (instance->ddf_instance) \
    128                         ddf_fun_destroy(instance->ddf_instance); \
    129                 return ret; \
    130         } else (void) 0
    131 
    132         /* Create UHCI function. */
    133         instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
    134         ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    135         CHECK_RET_DEST_FUN_RETURN(ret,
    136             "Failed to create UHCI device function.\n");
    137 
    138         instance->ddf_instance->ops = &uhci_ops;
    139         instance->ddf_instance->driver_data = instance;
    140 
    141         ret = ddf_fun_bind(instance->ddf_instance);
     152if (ret != EOK) { \
     153        usb_log_error(message); \
     154        if (instance->hc_fun) \
     155                ddf_fun_destroy(instance->hc_fun); \
     156        if (instance->rh_fun) \
     157                ddf_fun_destroy(instance->rh_fun); \
     158        return ret; \
     159}
     160
     161        uintptr_t io_reg_base = 0;
     162        size_t io_reg_size = 0;
     163        int irq = 0;
     164
     165        int ret =
     166            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     167        CHECK_RET_DEST_FUN_RETURN(ret,
     168            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
     169        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
     170            io_reg_base, io_reg_size, irq);
     171
     172        ret = pci_disable_legacy(device);
     173        CHECK_RET_DEST_FUN_RETURN(ret,
     174            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
     175
     176        bool interrupts = false;
     177        ret = pci_enable_interrupts(device);
     178        if (ret != EOK) {
     179                usb_log_warning(
     180                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     181                    ret);
     182        } else {
     183                usb_log_debug("Hw interrupts enabled.\n");
     184                interrupts = true;
     185        }
     186
     187        instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
     188        ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
     189        CHECK_RET_DEST_FUN_RETURN(ret,
     190            "Failed(%d) to create HC function.\n", ret);
     191
     192        ret = uhci_hc_init(&instance->hc, instance->hc_fun,
     193            (void*)io_reg_base, io_reg_size, interrupts);
     194        CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     195        instance->hc_fun->ops = &uhci_hc_ops;
     196        instance->hc_fun->driver_data = &instance->hc;
     197        ret = ddf_fun_bind(instance->hc_fun);
    142198        CHECK_RET_DEST_FUN_RETURN(ret,
    143199            "Failed(%d) to bind UHCI device function: %s.\n",
    144200            ret, str_error(ret));
    145 
    146         /* allow access to hc control registers */
    147         regs_t *io;
    148         ret = pio_enable(regs, reg_size, (void**)&io);
    149         CHECK_RET_DEST_FUN_RETURN(ret,
    150             "Failed(%d) to gain access to registers at %p: %s.\n",
    151             ret, str_error(ret), io);
    152         instance->registers = io;
    153         usb_log_debug("Device registers at %p(%u) accessible.\n",
    154             io, reg_size);
    155 
    156         ret = uhci_init_mem_structures(instance);
    157         CHECK_RET_DEST_FUN_RETURN(ret,
    158             "Failed to initialize UHCI memory structures.\n");
    159 
    160         uhci_init_hw(instance);
    161         instance->cleaner =
    162             fibril_create(uhci_interrupt_emulator, instance);
    163         fibril_add_ready(instance->cleaner);
    164 
    165         instance->debug_checker = fibril_create(uhci_debug_checker, instance);
    166         fibril_add_ready(instance->debug_checker);
    167 
    168         usb_log_info("Started UHCI driver.\n");
     201#undef CHECK_RET_HC_RETURN
     202
     203#define CHECK_RET_FINI_RETURN(ret, message...) \
     204if (ret != EOK) { \
     205        usb_log_error(message); \
     206        if (instance->hc_fun) \
     207                ddf_fun_destroy(instance->hc_fun); \
     208        if (instance->rh_fun) \
     209                ddf_fun_destroy(instance->rh_fun); \
     210        uhci_hc_fini(&instance->hc); \
     211        return ret; \
     212}
     213
     214        /* It does no harm if we register this on polling */
     215        ret = register_interrupt_handler(device, irq, irq_handler,
     216            &instance->hc.interrupt_code);
     217        CHECK_RET_FINI_RETURN(ret,
     218            "Failed(%d) to register interrupt handler.\n", ret);
     219
     220        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
     221        ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
     222        CHECK_RET_FINI_RETURN(ret,
     223            "Failed(%d) to create root hub function.\n", ret);
     224
     225        ret = uhci_rh_init(&instance->rh, instance->rh_fun,
     226            (uintptr_t)instance->hc.registers + 0x10, 4);
     227        CHECK_RET_FINI_RETURN(ret,
     228            "Failed(%d) to setup UHCI root hub.\n", ret);
     229
     230        instance->rh_fun->ops = &uhci_rh_ops;
     231        instance->rh_fun->driver_data = &instance->rh;
     232        ret = ddf_fun_bind(instance->rh_fun);
     233        CHECK_RET_FINI_RETURN(ret,
     234            "Failed(%d) to register UHCI root hub.\n", ret);
     235
    169236        return EOK;
    170 #undef CHECK_RET_DEST_FUN_RETURN
    171 }
    172 /*----------------------------------------------------------------------------*/
    173 /** Initializes UHCI hcd hw resources.
    174  *
    175  * @param[in] instance UHCI structure to use.
    176  */
    177 void uhci_init_hw(uhci_t *instance)
    178 {
    179         assert(instance);
    180         regs_t *registers = instance->registers;
    181 
    182         /* Reset everything, who knows what touched it before us */
    183         pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    184         async_usleep(10000); /* 10ms according to USB spec */
    185         pio_write_16(&registers->usbcmd, 0);
    186 
    187         /* Reset hc, all states and counters */
    188         pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    189         do { async_usleep(10); }
    190         while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
    191 
    192         /* Set framelist pointer */
    193         const uint32_t pa = addr_to_phys(instance->frame_list);
    194         pio_write_32(&registers->flbaseadd, pa);
    195 
    196         /* Enable all interrupts, but resume interrupt */
    197 //      pio_write_16(&instance->registers->usbintr,
    198 //          UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    199 
    200         uint16_t status = pio_read_16(&registers->usbcmd);
    201         if (status != 0)
    202                 usb_log_warning("Previous command value: %x.\n", status);
    203 
    204         /* Start the hc with large(64B) packet FSBR */
    205         pio_write_16(&registers->usbcmd,
    206             UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
    207 }
    208 /*----------------------------------------------------------------------------*/
    209 /** Initializes UHCI hcd memory structures.
    210  *
    211  * @param[in] instance UHCI structure to use.
    212  * @return Error code
    213  * @note Should be called only once on any structure.
    214  */
    215 int uhci_init_mem_structures(uhci_t *instance)
    216 {
    217         assert(instance);
    218 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
    219         if (ret != EOK) { \
    220                 usb_log_error(message); \
    221                 if (instance->interrupt_code.cmds != NULL) \
    222                         free(instance->interrupt_code.cmds); \
    223                 return ret; \
    224         } else (void) 0
    225 
    226         /* Init interrupt code */
    227         instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
    228         int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
    229         CHECK_RET_DEST_CMDS_RETURN(ret,
    230             "Failed to allocate interrupt cmds space.\n");
    231 
    232         {
    233                 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
    234                 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    235                 interrupt_commands[0].addr =
    236                     (void*)&instance->registers->usbsts;
    237                 interrupt_commands[1].addr =
    238                     (void*)&instance->registers->usbsts;
    239                 instance->interrupt_code.cmdcount =
    240                     sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    241         }
    242 
    243         /* Init transfer lists */
    244         ret = uhci_init_transfer_lists(instance);
    245         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
    246         usb_log_debug("Initialized transfer lists.\n");
    247 
    248         /* Init USB frame list page*/
    249         instance->frame_list = get_page();
    250         ret = instance ? EOK : ENOMEM;
    251         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
    252         usb_log_debug("Initialized frame list.\n");
    253 
    254         /* Set all frames to point to the first queue head */
    255         const uint32_t queue =
    256           instance->transfers_interrupt.queue_head_pa
    257           | LINK_POINTER_QUEUE_HEAD_FLAG;
    258 
    259         unsigned i = 0;
    260         for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
    261                 instance->frame_list[i] = queue;
    262         }
    263 
    264         /* Init device keeper*/
    265         device_keeper_init(&instance->device_manager);
    266         usb_log_debug("Initialized device manager.\n");
    267 
    268         return EOK;
    269 #undef CHECK_RET_DEST_CMDS_RETURN
    270 }
    271 /*----------------------------------------------------------------------------*/
    272 /** Initializes UHCI hcd transfer lists.
    273  *
    274  * @param[in] instance UHCI structure to use.
    275  * @return Error code
    276  * @note Should be called only once on any structure.
    277  */
    278 int uhci_init_transfer_lists(uhci_t *instance)
    279 {
    280         assert(instance);
    281 #define CHECK_RET_CLEAR_RETURN(ret, message...) \
    282         if (ret != EOK) { \
    283                 usb_log_error(message); \
    284                 transfer_list_fini(&instance->transfers_bulk_full); \
    285                 transfer_list_fini(&instance->transfers_control_full); \
    286                 transfer_list_fini(&instance->transfers_control_slow); \
    287                 transfer_list_fini(&instance->transfers_interrupt); \
    288                 return ret; \
    289         } else (void) 0
    290 
    291         /* initialize TODO: check errors */
    292         int ret;
    293         ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    294         CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
    295 
    296         ret = transfer_list_init(
    297             &instance->transfers_control_full, "CONTROL_FULL");
    298         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
    299 
    300         ret = transfer_list_init(
    301             &instance->transfers_control_slow, "CONTROL_SLOW");
    302         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
    303 
    304         ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    305         CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
    306 
    307         transfer_list_set_next(&instance->transfers_control_full,
    308                 &instance->transfers_bulk_full);
    309         transfer_list_set_next(&instance->transfers_control_slow,
    310                 &instance->transfers_control_full);
    311         transfer_list_set_next(&instance->transfers_interrupt,
    312                 &instance->transfers_control_slow);
    313 
    314         /*FSBR*/
    315 #ifdef FSBR
    316         transfer_list_set_next(&instance->transfers_bulk_full,
    317                 &instance->transfers_control_full);
    318 #endif
    319 
    320         /* Assign pointers to be used during scheduling */
    321         instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
    322           &instance->transfers_interrupt;
    323         instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
    324           &instance->transfers_interrupt;
    325         instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
    326           &instance->transfers_control_full;
    327         instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
    328           &instance->transfers_control_slow;
    329         instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
    330           &instance->transfers_bulk_full;
    331 
    332         return EOK;
    333 #undef CHECK_RET_CLEAR_RETURN
    334 }
    335 /*----------------------------------------------------------------------------*/
    336 /** Schedules batch for execution.
    337  *
    338  * @param[in] instance UHCI structure to use.
    339  * @param[in] batch Transfer batch to schedule.
    340  * @return Error code
    341  */
    342 int uhci_schedule(uhci_t *instance, batch_t *batch)
    343 {
    344         assert(instance);
    345         assert(batch);
    346         const int low_speed = (batch->speed == USB_SPEED_LOW);
    347         if (!allowed_usb_packet(
    348             low_speed, batch->transfer_type, batch->max_packet_size)) {
    349                 usb_log_warning(
    350                     "Invalid USB packet specified %s SPEED %d %zu.\n",
    351                     low_speed ? "LOW" : "FULL" , batch->transfer_type,
    352                     batch->max_packet_size);
    353                 return ENOTSUP;
    354         }
    355         /* TODO: check available bandwith here */
    356 
    357         transfer_list_t *list =
    358             instance->transfers[low_speed][batch->transfer_type];
    359         assert(list);
    360         transfer_list_add_batch(list, batch);
    361 
    362         return EOK;
    363 }
    364 /*----------------------------------------------------------------------------*/
    365 /** Takes action based on the interrupt cause.
    366  *
    367  * @param[in] instance UHCI structure to use.
    368  * @param[in] status Value of the stsatus regiser at the time of interrupt.
    369  */
    370 void uhci_interrupt(uhci_t *instance, uint16_t status)
    371 {
    372         assert(instance);
    373         /* TODO: Check interrupt cause here */
    374         transfer_list_remove_finished(&instance->transfers_interrupt);
    375         transfer_list_remove_finished(&instance->transfers_control_slow);
    376         transfer_list_remove_finished(&instance->transfers_control_full);
    377         transfer_list_remove_finished(&instance->transfers_bulk_full);
    378 }
    379 /*----------------------------------------------------------------------------*/
    380 /** Polling function, emulates interrupts.
    381  *
    382  * @param[in] arg UHCI structure to use.
    383  * @return EOK
    384  */
    385 int uhci_interrupt_emulator(void* arg)
    386 {
    387         usb_log_debug("Started interrupt emulator.\n");
    388         uhci_t *instance = (uhci_t*)arg;
    389         assert(instance);
    390 
    391         while (1) {
    392                 uint16_t status = pio_read_16(&instance->registers->usbsts);
    393                 if (status != 0)
    394                         usb_log_debug2("UHCI status: %x.\n", status);
    395                 status |= 1;
    396                 uhci_interrupt(instance, status);
    397                 pio_write_16(&instance->registers->usbsts, 0x1f);
    398                 async_usleep(UHCI_CLEANER_TIMEOUT);
    399         }
    400         return EOK;
    401 }
    402 /*---------------------------------------------------------------------------*/
    403 /** Debug function, checks consistency of memory structures.
    404  *
    405  * @param[in] arg UHCI structure to use.
    406  * @return EOK
    407  */
    408 int uhci_debug_checker(void *arg)
    409 {
    410         uhci_t *instance = (uhci_t*)arg;
    411         assert(instance);
    412 
    413 #define QH(queue) \
    414         instance->transfers_##queue.queue_head
    415 
    416         while (1) {
    417                 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    418                 const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    419                 const uint16_t intr =
    420                     pio_read_16(&instance->registers->usbintr);
    421 
    422                 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
    423                         usb_log_debug2("Command: %X Status: %X Intr: %x\n",
    424                             cmd, sts, intr);
    425                 }
    426 
    427                 uintptr_t frame_list =
    428                     pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
    429                 if (frame_list != addr_to_phys(instance->frame_list)) {
    430                         usb_log_debug("Framelist address: %p vs. %p.\n",
    431                             frame_list, addr_to_phys(instance->frame_list));
    432                 }
    433 
    434                 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
    435                 usb_log_debug2("Framelist item: %d \n", frnum );
    436 
    437                 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
    438                 uintptr_t real_pa = addr_to_phys(QH(interrupt));
    439                 if (expected_pa != real_pa) {
    440                         usb_log_debug("Interrupt QH: %p vs. %p.\n",
    441                             expected_pa, real_pa);
    442                 }
    443 
    444                 expected_pa = QH(interrupt)->next_queue & (~0xf);
    445                 real_pa = addr_to_phys(QH(control_slow));
    446                 if (expected_pa != real_pa) {
    447                         usb_log_debug("Control Slow QH: %p vs. %p.\n",
    448                             expected_pa, real_pa);
    449                 }
    450 
    451                 expected_pa = QH(control_slow)->next_queue & (~0xf);
    452                 real_pa = addr_to_phys(QH(control_full));
    453                 if (expected_pa != real_pa) {
    454                         usb_log_debug("Control Full QH: %p vs. %p.\n",
    455                             expected_pa, real_pa);
    456                 }
    457 
    458                 expected_pa = QH(control_full)->next_queue & (~0xf);
    459                 real_pa = addr_to_phys(QH(bulk_full));
    460                 if (expected_pa != real_pa ) {
    461                         usb_log_debug("Bulk QH: %p vs. %p.\n",
    462                             expected_pa, real_pa);
    463                 }
    464                 async_usleep(UHCI_DEBUGER_TIMEOUT);
    465         }
    466         return EOK;
    467 #undef QH
    468 }
    469 /*----------------------------------------------------------------------------*/
    470 /** Checks transfer packets, for USB validity
    471  *
    472  * @param[in] low_speed Transfer speed.
    473  * @param[in] transfer Transer type
    474  * @param[in] size Maximum size of used packets
    475  * @return EOK
    476  */
    477 bool allowed_usb_packet(
    478     bool low_speed, usb_transfer_type_t transfer, size_t size)
    479 {
    480         /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    481         switch(transfer)
    482         {
    483         case USB_TRANSFER_ISOCHRONOUS:
    484                 return (!low_speed && size < 1024);
    485         case USB_TRANSFER_INTERRUPT:
    486                 return size <= (low_speed ? 8 : 64);
    487         case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    488                 return (size <= (low_speed ? 8 : 64));
    489         case USB_TRANSFER_BULK: /* device specifies its own max size */
    490                 return (!low_speed && size <= 64);
    491         }
    492         return false;
     237#undef CHECK_RET_FINI_RETURN
    493238}
    494239/**
  • uspace/drv/uhci-hcd/uhci.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief UHCI driver
     33 * @brief UHCI driver main structure for both host controller and root-hub.
    3434 */
    3535#ifndef DRV_UHCI_UHCI_H
    3636#define DRV_UHCI_UHCI_H
     37#include <ddi.h>
     38#include <ddf/driver.h>
    3739
    38 #include <fibril.h>
    39 #include <fibril_synch.h>
    40 #include <adt/list.h>
    41 #include <ddi.h>
    42 
    43 #include <usbhc_iface.h>
    44 
    45 #include "batch.h"
    46 #include "transfer_list.h"
    47 #include "utils/device_keeper.h"
    48 
    49 typedef struct uhci_regs {
    50         uint16_t usbcmd;
    51 #define UHCI_CMD_MAX_PACKET (1 << 7)
    52 #define UHCI_CMD_CONFIGURE  (1 << 6)
    53 #define UHCI_CMD_DEBUG  (1 << 5)
    54 #define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
    55 #define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
    56 #define UHCI_CMD_GLOBAL_RESET  (1 << 2)
    57 #define UHCI_CMD_HCRESET  (1 << 1)
    58 #define UHCI_CMD_RUN_STOP  (1 << 0)
    59 
    60         uint16_t usbsts;
    61 #define UHCI_STATUS_HALTED (1 << 5)
    62 #define UHCI_STATUS_PROCESS_ERROR (1 << 4)
    63 #define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
    64 #define UHCI_STATUS_RESUME (1 << 2)
    65 #define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
    66 #define UHCI_STATUS_INTERRUPT (1 << 0)
    67 
    68         uint16_t usbintr;
    69 #define UHCI_INTR_SHORT_PACKET (1 << 3)
    70 #define UHCI_INTR_COMPLETE (1 << 2)
    71 #define UHCI_INTR_RESUME (1 << 1)
    72 #define UHCI_INTR_CRC (1 << 0)
    73 
    74         uint16_t frnum;
    75         uint32_t flbaseadd;
    76         uint8_t sofmod;
    77 } regs_t;
    78 
    79 #define UHCI_FRAME_LIST_COUNT 1024
    80 #define UHCI_CLEANER_TIMEOUT 10000
    81 #define UHCI_DEBUGER_TIMEOUT 5000000
     40#include "uhci_hc.h"
     41#include "uhci_rh.h"
    8242
    8343typedef struct uhci {
    84         device_keeper_t device_manager;
     44        ddf_fun_t *hc_fun;
     45        ddf_fun_t *rh_fun;
    8546
    86         regs_t *registers;
    87 
    88         link_pointer_t *frame_list;
    89 
    90         transfer_list_t transfers_bulk_full;
    91         transfer_list_t transfers_control_full;
    92         transfer_list_t transfers_control_slow;
    93         transfer_list_t transfers_interrupt;
    94 
    95         transfer_list_t *transfers[2][4];
    96 
    97         irq_code_t interrupt_code;
    98 
    99         fid_t cleaner;
    100         fid_t debug_checker;
    101 
    102         ddf_fun_t *ddf_instance;
     47        uhci_hc_t hc;
     48        uhci_rh_t rh;
    10349} uhci_t;
    10450
    105 /* init uhci specifics in device.driver_data */
    106 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size);
    107 
    108 static inline void uhci_fini(uhci_t *instance) {};
    109 
    110 int uhci_schedule(uhci_t *instance, batch_t *batch);
    111 
    112 void uhci_interrupt(uhci_t *instance, uint16_t status);
    113 
    114 static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
    115         { return (uhci_t*)dev->driver_data; }
    116 
    117 static inline uhci_t * fun_to_uhci(ddf_fun_t *fun)
    118         { return (uhci_t*)fun->driver_data; }
    119 
     51int uhci_init(uhci_t *instance, ddf_dev_t *device);
    12052
    12153#endif
  • uspace/drv/uhci-hcd/uhci_rh.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28
     29/** @addtogroup drvusbuhci
    2930 * @{
    3031 */
     
    3233 * @brief UHCI driver
    3334 */
    34 #ifndef DRV_UHCI_TD_PORT_STATUS_H
    35 #define DRV_UHCI_TD_PORT_STATUS_H
     35#ifndef DRV_UHCI_UHCI_RH_H
     36#define DRV_UHCI_UHCI_RH_H
    3637
    37 #include <libarch/ddi.h> /* pio_read and pio_write */
     38#include <ddf/driver.h>
     39#include <ops/hw_res.h>
    3840
    39 #include <stdint.h>
     41typedef struct uhci_rh {
     42        hw_resource_list_t resource_list;
     43        hw_resource_t io_regs;
     44} uhci_rh_t;
    4045
    41 typedef uint16_t port_status_t;
     46int uhci_rh_init(
     47    uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
    4248
    43 #define STATUS_CONNECTED         (1 << 0)
    44 #define STATUS_CONNECTED_CHANGED (1 << 1)
    45 #define STATUS_ENABLED           (1 << 2)
    46 #define STATUS_ENABLED_CHANGED   (1 << 3)
    47 #define STATUS_LINE_D_PLUS       (1 << 4)
    48 #define STATUS_LINE_D_MINUS      (1 << 5)
    49 #define STATUS_RESUME            (1 << 6)
    50 #define STATUS_ALWAYS_ONE        (1 << 7)
    51 
    52 #define STATUS_LOW_SPEED (1 <<  8)
    53 #define STATUS_IN_RESET  (1 <<  9)
    54 #define STATUS_SUSPEND   (1 << 12)
    55 
    56 static inline port_status_t port_status_read(port_status_t * address)
    57         { return pio_read_16(address); }
    58 
    59 static inline void port_status_write(
    60   port_status_t *address, port_status_t value)
    61         { pio_write_16(address, value); }
    62 
    63 void print_port_status(const port_status_t status);
    6449#endif
    6550/**
  • uspace/drv/uhci-hcd/uhci_struct/link_pointer.h

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
     
    4646#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
    4747
     48#define LINK_POINTER_QH(address) \
     49        ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
     50
    4851#endif
    4952/**
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    rc32688d r361e61b  
    1 
    21/*
    32 * Copyright (c) 2010 Jan Vesely
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
    29 /** @addtogroup usb
     28/** @addtogroup drv usbuhcihc
    3029 * @{
    3130 */
     
    4342
    4443typedef struct queue_head {
    45         volatile link_pointer_t next_queue;
     44        volatile link_pointer_t next;
    4645        volatile link_pointer_t element;
    47 } __attribute__((packed)) queue_head_t;
    48 
    49 static inline void queue_head_init(queue_head_t *instance)
     46} __attribute__((packed)) qh_t;
     47/*----------------------------------------------------------------------------*/
     48/** Initialize queue head structure
     49 *
     50 * @param[in] instance qh_t structure to initialize.
     51 *
     52 * Sets both pointer to terminal NULL.
     53 */
     54static inline void qh_init(qh_t *instance)
    5055{
    5156        assert(instance);
    5257
    5358        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    54         instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
     59        instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    5560}
    56 
    57 static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
     61/*----------------------------------------------------------------------------*/
     62/** Set queue head next pointer
     63 *
     64 * @param[in] instance qh_t structure to use.
     65 * @param[in] pa Physical address of the next queue head.
     66 *
     67 * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
     68 * NULL.
     69 */
     70static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
    5871{
    59         if (pa) {
    60                 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     72        /* Address is valid and not terminal */
     73        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     74                instance->next = (pa & LINK_POINTER_ADDRESS_MASK)
    6175                    | LINK_POINTER_QUEUE_HEAD_FLAG;
     76        } else {
     77                instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    6278        }
    6379}
    64 
    65 static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
     80/*----------------------------------------------------------------------------*/
     81/** Set queue head element pointer
     82 *
     83 * @param[in] instance qh_t structure to initialize.
     84 * @param[in] pa Physical address of the next queue head.
     85 *
     86 * Adds proper flag. If the pointer is NULL or terminal, sets element
     87 * to terminal NULL.
     88 */
     89static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
    6690{
    67         if (pa) {
    68                 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     91        /* Address is valid and not terminal */
     92        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     93                instance->element = (pa & LINK_POINTER_ADDRESS_MASK)
    6994                    | LINK_POINTER_QUEUE_HEAD_FLAG;
     95        } else {
     96                instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    7097        }
    7198}
    72 
    73 static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
     99/*----------------------------------------------------------------------------*/
     100/** Set queue head element pointer
     101 *
     102 * @param[in] instance qh_t structure to initialize.
     103 * @param[in] pa Physical address of the TD structure.
     104 *
     105 * Adds proper flag. If the pointer is NULL or terminal, sets element
     106 * to terminal NULL.
     107 */
     108static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
    74109{
    75         if (pa) {
     110        if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    76111                instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
     112        } else {
     113                instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    77114        }
    78115}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
     
    3838#include "utils/malloc32.h"
    3939
    40 /** Initializes Transfer Descriptor
     40/** Initialize Transfer Descriptor
    4141 *
    4242 * @param[in] instance Memory place to initialize.
     
    4444 * @param[in] size Size of data source.
    4545 * @param[in] toggle Value of toggle bit.
    46  * @param[in] iso True if TD is for Isochronous transfer.
     46 * @param[in] iso True if TD represents Isochronous transfer.
    4747 * @param[in] low_speed Target device's speed.
    4848 * @param[in] target Address and endpoint receiving the transfer.
     
    5151 * @param[in] next Net TD in transaction.
    5252 * @return Error code.
     53 *
     54 * Uses a mix of supplied and default values.
     55 * Implicit values:
     56 *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
     57 *  - in the error field only active it is set
     58 *  - if the packet uses PID_IN and is not isochronous SPD is set
     59 *
     60 * Dumps 8 bytes of buffer if PID_SETUP is used.
    5361 */
    5462void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
     
    8896        }
    8997
    90         usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
    91             instance->next, instance->status, instance->device,
     98        usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
     99            instance, instance->next, instance->status, instance->device,
    92100            instance->buffer_ptr, buffer);
     101        td_print_status(instance);
    93102        if (pid == USB_PID_SETUP) {
    94103                usb_log_debug("SETUP BUFFER: %s\n",
    95                         usb_debug_str_buffer(buffer, 8, 8));
     104                    usb_debug_str_buffer(buffer, 8, 8));
    96105        }
    97106}
    98107/*----------------------------------------------------------------------------*/
    99 /** Converts TD status into standard error code
     108/** Convert TD status into standard error code
    100109 *
    101110 * @param[in] instance TD structure to use.
     
    126135        return EOK;
    127136}
     137/*----------------------------------------------------------------------------*/
     138/** Print values in status field (dw1) in a human readable way.
     139 *
     140 * @param[in] instance TD structure to use.
     141 */
     142void td_print_status(td_t *instance)
     143{
     144        assert(instance);
     145        const uint32_t s = instance->status;
     146        usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n",
     147            instance, instance->status,
     148            (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
     149            (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
     150            (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
     151            (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
     152            (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
     153            (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
     154            (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
     155            (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
     156            (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
     157            (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
     158            (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
     159            (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
     160            (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
     161            td_act_size(instance)
     162        );
     163}
    128164/**
    129165 * @}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
     
    4545
    4646        volatile uint32_t status;
    47 
    4847#define TD_STATUS_RESERVED_MASK 0xc000f800
    4948#define TD_STATUS_SPD_FLAG ( 1 << 29 )
    5049#define TD_STATUS_ERROR_COUNT_POS ( 27 )
    5150#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
    52 #define TD_STATUS_ERROR_COUNT_DEFAULT 3
    5351#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    5452#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    55 #define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
     53#define TD_STATUS_IOC_FLAG ( 1 << 24 )
    5654
    5755#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
     
    7068
    7169        volatile uint32_t device;
    72 
    7370#define TD_DEVICE_MAXLEN_POS 21
    7471#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
     
    8582
    8683        /* there is 16 bytes of data available here, according to UHCI
    87          * Design guide, according to linux kernel the hardware does not care
    88          * we don't use it anyway
     84         * Design guide, according to linux kernel the hardware does not care,
     85         * it just needs to be aligned, we don't use it anyway
    8986         */
    9087} __attribute__((packed)) td_t;
    9188
    9289
    93 void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,
    94     bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
    95     td_t *next);
     90void td_init(td_t *instance, int error_count, size_t size, bool toggle,
     91    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
     92    void *buffer, td_t *next);
    9693
    9794int td_status(td_t *instance);
    9895
     96void td_print_status(td_t *instance);
     97/*----------------------------------------------------------------------------*/
     98/** Helper function for parsing actual size out of TD.
     99 *
     100 * @param[in] instance TD structure to use.
     101 * @return Parsed actual size.
     102 */
    99103static inline size_t td_act_size(td_t *instance)
    100104{
    101105        assert(instance);
    102         return
    103             ((instance->status >> TD_STATUS_ACTLEN_POS) + 1)
    104             & TD_STATUS_ACTLEN_MASK;
     106        const uint32_t s = instance->status;
     107        return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
    105108}
    106 
     109/*----------------------------------------------------------------------------*/
     110/** Check whether less than max data were recieved and packet is marked as SPD.
     111 *
     112 * @param[in] instance TD structure to use.
     113 * @return True if packet is short (less than max bytes and SPD set), false
     114 *     otherwise.
     115 */
    107116static inline bool td_is_short(td_t *instance)
    108117{
     
    114123            (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
    115124}
    116 
     125/*----------------------------------------------------------------------------*/
     126/** Helper function for parsing value of toggle bit.
     127 *
     128 * @param[in] instance TD structure to use.
     129 * @return Toggle bit value.
     130 */
    117131static inline int td_toggle(td_t *instance)
    118132{
    119133        assert(instance);
    120         return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0)
    121             ? 1 : 0;
     134        return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
    122135}
    123 
     136/*----------------------------------------------------------------------------*/
     137/** Helper function for parsing value of active bit
     138 *
     139 * @param[in] instance TD structure to use.
     140 * @return Active bit value.
     141 */
    124142static inline bool td_is_active(td_t *instance)
    125143{
     
    127145        return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
    128146}
     147/*----------------------------------------------------------------------------*/
     148/** Helper function for setting IOC bit.
     149 *
     150 * @param[in] instance TD structure to use.
     151 */
     152static inline void td_set_ioc(td_t *instance)
     153{
     154        assert(instance);
     155        instance->status |= TD_STATUS_IOC_FLAG;
     156}
     157/*----------------------------------------------------------------------------*/
    129158#endif
    130159/**
  • uspace/drv/uhci-hcd/utils/malloc32.h

    rc32688d r361e61b  
    4343#define UHCI_REQUIRED_PAGE_SIZE 4096
    4444
     45/** Get physical address translation
     46 *
     47 * @param[in] addr Virtual address to translate
     48 * @return Physical address if exists, NULL otherwise.
     49 */
    4550static inline uintptr_t addr_to_phys(void *addr)
    4651{
     
    4853        int ret = as_get_physical_mapping(addr, &result);
    4954
    50         assert(ret == 0);
     55        if (ret != EOK)
     56                return 0;
    5157        return (result | ((uintptr_t)addr & 0xfff));
    5258}
    53 
     59/*----------------------------------------------------------------------------*/
     60/** Physical mallocator simulator
     61 *
     62 * @param[in] size Size of the required memory space
     63 * @return Address of the alligned and big enough memory place, NULL on failure.
     64 */
    5465static inline void * malloc32(size_t size)
    5566        { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
    56 
    57 static inline void * get_page()
     67/*----------------------------------------------------------------------------*/
     68/** Physical mallocator simulator
     69 *
     70 * @param[in] addr Address of the place allocated by malloc32
     71 */
     72static inline void free32(void *addr)
     73        { if (addr) free(addr); }
     74/*----------------------------------------------------------------------------*/
     75/** Create 4KB page mapping
     76 *
     77 * @return Address of the mapped page, NULL on failure.
     78 */
     79static inline void * get_page(void)
    5880{
    5981        void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
    6082        assert(free_address);
    6183        if (free_address == 0)
    62                 return 0;
     84                return NULL;
    6385        void* ret =
    6486          as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    6587                  AS_AREA_READ | AS_AREA_WRITE);
    6688        if (ret != free_address)
    67                 return 0;
     89                return NULL;
    6890        return ret;
    6991}
    70 
    71 static inline void free32(void *addr)
    72         { if (addr) free(addr); }
    7392
    7493#endif
  • uspace/drv/uhci-rhd/Makefile

    rc32688d r361e61b  
    3535        main.c \
    3636        port.c \
    37         port_status.c \
    3837        root_hub.c
    3938
  • uspace/drv/uhci-rhd/main.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI root hub initialization routines
    3333 */
    3434#include <ddf/driver.h>
     
    4040#include <usb/debug.h>
    4141
    42 
    43 
    4442#include "root_hub.h"
    4543
     
    4745static int hc_get_my_registers(ddf_dev_t *dev,
    4846    uintptr_t *io_reg_address, size_t *io_reg_size);
     47#if 0
    4948/*----------------------------------------------------------------------------*/
    5049static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
     
    6766        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6867};
     68#endif
    6969/*----------------------------------------------------------------------------*/
    70 /** Initializes a new ddf driver instance of UHCI root hub.
     70/** Initialize a new ddf driver instance of UHCI root hub.
    7171 *
    7272 * @param[in] device DDF instance of the device to initialize.
     
    8181
    8282        //device->ops = &uhci_rh_ops;
    83         (void) uhci_rh_ops;
    84 
    85         uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
    86         if (!rh) {
    87                 usb_log_error("Failed to allocate memory for driver instance.\n");
    88                 return ENOMEM;
    89         }
    90 
    9183        uintptr_t io_regs = 0;
    9284        size_t io_size = 0;
    9385
    9486        int ret = hc_get_my_registers(device, &io_regs, &io_size);
    95         assert(ret == EOK);
     87        if (ret != EOK) {
     88                usb_log_error("Failed(%d) to get registers from parent hc.",
     89                    ret);
     90        }
     91        usb_log_info("I/O regs at %#X (size %zu).\n", io_regs, io_size);
    9692
    97         /* TODO: verify values from hc */
    98         usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size);
     93        uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
     94        if (!rh) {
     95                usb_log_error("Failed to allocate driver instance.\n");
     96                return ENOMEM;
     97        }
     98
    9999        ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
    100100        if (ret != EOK) {
     
    119119};
    120120/*----------------------------------------------------------------------------*/
    121 /** Initializes global driver structures (NONE).
     121/** Initialize global driver structures (NONE).
    122122 *
    123123 * @param[in] argc Nmber of arguments in argv vector (ignored).
  • uspace/drv/uhci-rhd/port.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
    33  */
     32 * @brief UHCI root hub port routines
     33 */
     34#include <libarch/ddi.h> /* pio_read and pio_write */
    3435#include <errno.h>
    3536#include <str_error.h>
     
    3738
    3839#include <usb/usb.h>    /* usb_address_t */
    39 #include <usb/usbdevice.h>
    4040#include <usb/hub.h>
    41 #include <usb/request.h>
    4241#include <usb/debug.h>
    43 #include <usb/recognise.h>
    4442
    4543#include "port.h"
    46 #include "port_status.h"
    4744
    4845static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
     
    5148static int uhci_port_check(void *port);
    5249static int uhci_port_reset_enable(int portno, void *arg);
    53 /*----------------------------------------------------------------------------*/
    54 /** Initializes UHCI root hub port instance.
     50static void uhci_port_print_status(
     51    uhci_port_t *port, const port_status_t value);
     52
     53/** Register reading helper function.
     54 *
     55 * @param[in] port Structure to use.
     56 * @return Error code. (Always EOK)
     57 */
     58static inline port_status_t uhci_port_read_status(uhci_port_t *port)
     59{
     60        assert(port);
     61        return pio_read_16(port->address);
     62}
     63/*----------------------------------------------------------------------------*/
     64/** Register writing helper function.
     65 *
     66 * @param[in] port Structure to use.
     67 * @param[in] value New register value.
     68 * @return Error code. (Always EOK)
     69 */
     70static inline void uhci_port_write_status(
     71    uhci_port_t *port, port_status_t value)
     72{
     73        assert(port);
     74        pio_write_16(port->address, value);
     75}
     76
     77/*----------------------------------------------------------------------------*/
     78/** Initialize UHCI root hub port instance.
    5579 *
    5680 * @param[in] port Memory structure to use.
     
    6185 * @return Error code.
    6286 *
    63  * Starts the polling fibril.
     87 * Creates and starts the polling fibril.
    6488 */
    6589int uhci_port_init(uhci_port_t *port,
     
    6791{
    6892        assert(port);
     93        asprintf(&port->id_string, "Port (%p - %d)", port, number);
     94        if (port->id_string == NULL) {
     95                return ENOMEM;
     96        }
    6997
    7098        port->address = address;
     
    83111        port->checker = fibril_create(uhci_port_check, port);
    84112        if (port->checker == 0) {
    85                 usb_log_error("Port(%p - %d): failed to launch root hub fibril.",
    86                     port->address, port->number);
     113                usb_log_error("%s: failed to create polling fibril.",
     114                    port->id_string);
    87115                return ENOMEM;
    88116        }
    89117
    90118        fibril_add_ready(port->checker);
    91         usb_log_debug("Port(%p - %d): Added fibril. %x\n",
    92             port->address, port->number, port->checker);
    93         return EOK;
    94 }
    95 /*----------------------------------------------------------------------------*/
    96 /** Finishes UHCI root hub port instance.
     119        usb_log_debug("%s: Started polling fibril(%x).\n",
     120            port->id_string, port->checker);
     121        return EOK;
     122}
     123/*----------------------------------------------------------------------------*/
     124/** Cleanup UHCI root hub port instance.
    97125 *
    98126 * @param[in] port Memory structure to use.
     
    102130void uhci_port_fini(uhci_port_t *port)
    103131{
     132        assert(port);
     133        free(port->id_string);
    104134        /* TODO: Kill fibril here */
    105135        return;
     
    108138/** Periodically checks port status and reports new devices.
    109139 *
    110  * @param[in] port Memory structure to use.
     140 * @param[in] port Port structure to use.
    111141 * @return Error code.
    112142 */
     
    116146        assert(instance);
    117147
    118         /* Iteration count, for debug purposes only */
    119         unsigned count = 0;
    120 
    121148        while (1) {
    122149                async_usleep(instance->wait_period_usec);
    123150
    124                 /* read register value */
    125                 port_status_t port_status = port_status_read(instance->address);
    126 
    127                 /* debug print mutex */
    128                 static fibril_mutex_t dbg_mtx =
    129                     FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
    130                 fibril_mutex_lock(&dbg_mtx);
    131                 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
    132                   instance->address, instance->number, port_status, count++);
    133 //              print_port_status(port_status);
    134                 fibril_mutex_unlock(&dbg_mtx);
     151                /* Read register value */
     152                port_status_t port_status = uhci_port_read_status(instance);
     153
     154                /* Print the value if it's interesting */
     155                if (port_status & ~STATUS_ALWAYS_ONE)
     156                        uhci_port_print_status(instance, port_status);
    135157
    136158                if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
    137159                        continue;
    138160
    139                 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
    140                     instance->address, instance->number, port_status);
     161                usb_log_debug("%s: Connected change detected: %x.\n",
     162                    instance->id_string, port_status);
    141163
    142164                int rc =
    143165                    usb_hc_connection_open(&instance->hc_connection);
    144166                if (rc != EOK) {
    145                         usb_log_error("Port(%p - %d): Failed to connect to HC.",
    146                             instance->address, instance->number);
     167                        usb_log_error("%s: Failed to connect to HC.",
     168                            instance->id_string);
    147169                        continue;
    148170                }
     
    150172                /* Remove any old device */
    151173                if (instance->attached_device) {
    152                         usb_log_debug2("Port(%p - %d): Removing device.\n",
    153                             instance->address, instance->number);
     174                        usb_log_debug2("%s: Removing device.\n",
     175                            instance->id_string);
    154176                        uhci_port_remove_device(instance);
    155177                }
     
    163185                } else {
    164186                        /* Write one to WC bits, to ack changes */
    165                         port_status_write(instance->address, port_status);
    166                         usb_log_debug("Port(%p - %d): Change status ACK.\n",
    167                             instance->address, instance->number);
     187                        uhci_port_write_status(instance, port_status);
     188                        usb_log_debug("%s: status change ACK.\n",
     189                            instance->id_string);
    168190                }
    169191
    170192                rc = usb_hc_connection_close(&instance->hc_connection);
    171193                if (rc != EOK) {
    172                         usb_log_error("Port(%p - %d): Failed to disconnect.",
    173                             instance->address, instance->number);
     194                        usb_log_error("%s: Failed to disconnect.",
     195                            instance->id_string);
    174196                }
    175197        }
     
    182204 * @param arg Pointer to uhci_port_t of port with the new device.
    183205 * @return Error code.
     206 *
     207 * Resets and enables the ub port.
    184208 */
    185209int uhci_port_reset_enable(int portno, void *arg)
     
    187211        uhci_port_t *port = (uhci_port_t *) arg;
    188212
    189         usb_log_debug2("Port(%p - %d): new_device_enable_port.\n",
    190             port->address, port->number);
     213        usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
    191214
    192215        /*
     
    196219        async_usleep(100000);
    197220
    198 
    199         /* The hub maintains the reset signal to that port for 10 ms
    200          * (See Section 11.5.1.5)
     221        /*
     222         * Resets from root ports should be nominally 50ms
    201223         */
    202224        {
    203                 usb_log_debug("Port(%p - %d): Reset Signal start.\n",
    204                     port->address, port->number);
    205                 port_status_t port_status =
    206                         port_status_read(port->address);
     225                usb_log_debug("%s: Reset Signal start.\n", port->id_string);
     226                port_status_t port_status = uhci_port_read_status(port);
    207227                port_status |= STATUS_IN_RESET;
    208                 port_status_write(port->address, port_status);
    209                 async_usleep(10000);
    210                 port_status = port_status_read(port->address);
     228                uhci_port_write_status(port, port_status);
     229                async_usleep(50000);
     230                port_status = uhci_port_read_status(port);
    211231                port_status &= ~STATUS_IN_RESET;
    212                 port_status_write(port->address, port_status);
    213                 usb_log_debug("Port(%p - %d): Reset Signal stop.\n",
    214                     port->address, port->number);
    215         }
     232                uhci_port_write_status(port, port_status);
     233                usb_log_debug("%s: Reset Signal stop.\n", port->id_string);
     234        }
     235
     236        /* the reset recovery time 10ms */
     237        async_usleep(10000);
    216238
    217239        /* Enable the port. */
    218240        uhci_port_set_enabled(port, true);
    219         return EOK;
    220 }
    221 /*----------------------------------------------------------------------------*/
    222 /** Initializes and reports connected device.
    223  *
    224  * @param[in] port Memory structure to use.
     241
     242        return EOK;
     243}
     244/*----------------------------------------------------------------------------*/
     245/** Initialize and report connected device.
     246 *
     247 * @param[in] port Port structure to use.
    225248 * @param[in] speed Detected speed.
    226249 * @return Error code.
     
    233256        assert(usb_hc_connection_is_opened(&port->hc_connection));
    234257
    235         usb_log_info("Port(%p-%d): Detected new device.\n",
    236             port->address, port->number);
     258        usb_log_info("%s: Detected new device.\n", port->id_string);
    237259
    238260        usb_address_t dev_addr;
     
    242264
    243265        if (rc != EOK) {
    244                 usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
    245                     port->address, port->number, rc, str_error(rc));
     266                usb_log_error("%s: Failed(%d) to add device: %s.\n",
     267                    port->id_string, rc, str_error(rc));
    246268                uhci_port_set_enabled(port, false);
    247269                return rc;
    248270        }
    249271
    250         usb_log_info("Port(%p-%d): New device has address %d (handle %zu).\n",
    251             port->address, port->number, dev_addr, port->attached_device);
    252 
    253         return EOK;
    254 }
    255 /*----------------------------------------------------------------------------*/
    256 /** Removes device.
     272        usb_log_info("%s: New device has address %d (handle %zu).\n",
     273            port->id_string, dev_addr, port->attached_device);
     274
     275        return EOK;
     276}
     277/*----------------------------------------------------------------------------*/
     278/** Remove device.
    257279 *
    258280 * @param[in] port Memory structure to use.
    259281 * @return Error code.
    260282 *
    261  * Does not work DDF does not support device removal.
     283 * Does not work, DDF does not support device removal.
     284 * Does not even free used USB address (it would be dangerous if tis driver
     285 * is still running).
    262286 */
    263287int uhci_port_remove_device(uhci_port_t *port)
    264288{
    265         usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
    266             port->address, port->number, (unsigned int)port->attached_device);
    267         return EOK;
    268 }
    269 /*----------------------------------------------------------------------------*/
    270 /** Enables and disables port.
    271  *
    272  * @param[in] port Memory structure to use.
     289        usb_log_error("%s: Don't know how to remove device %d.\n",
     290            port->id_string, (unsigned int)port->attached_device);
     291        return EOK;
     292}
     293/*----------------------------------------------------------------------------*/
     294/** Enable or disable root hub port.
     295 *
     296 * @param[in] port Port structure to use.
     297 * @param[in] enabled Port status to set.
    273298 * @return Error code. (Always EOK)
    274299 */
     
    278303
    279304        /* Read register value */
    280         port_status_t port_status = port_status_read(port->address);
     305        port_status_t port_status = uhci_port_read_status(port);
    281306
    282307        /* Set enabled bit */
     
    288313
    289314        /* Write new value. */
    290         port_status_write(port->address, port_status);
    291 
    292         usb_log_info("Port(%p-%d): %sabled port.\n",
    293                 port->address, port->number, enabled ? "En" : "Dis");
    294         return EOK;
    295 }
    296 /*----------------------------------------------------------------------------*/
     315        uhci_port_write_status(port, port_status);
     316
     317        usb_log_info("%s: %sabled port.\n",
     318                port->id_string, enabled ? "En" : "Dis");
     319        return EOK;
     320}
     321/*----------------------------------------------------------------------------*/
     322/** Print the port status value in a human friendly way
     323 *
     324 * @param[in] port Port structure to use.
     325 * @param[in] value Port register value to print.
     326 * @return Error code. (Always EOK)
     327 */
     328void uhci_port_print_status(uhci_port_t *port, const port_status_t value)
     329{
     330        assert(port);
     331        usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n",
     332            port->id_string, value,
     333            (value & STATUS_SUSPEND) ? " SUSPENDED," : "",
     334            (value & STATUS_RESUME) ? " IN RESUME," : "",
     335            (value & STATUS_IN_RESET) ? " IN RESET," : "",
     336            (value & STATUS_LINE_D_MINUS) ? " VD-," : "",
     337            (value & STATUS_LINE_D_PLUS) ? " VD+," : "",
     338            (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "",
     339            (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "",
     340            (value & STATUS_ENABLED) ? " ENABLED," : "",
     341            (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "",
     342            (value & STATUS_CONNECTED) ? " CONNECTED," : "",
     343            (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERROR: NO ALWAYS ONE"
     344        );
     345}
    297346/**
    298347 * @}
  • uspace/drv/uhci-rhd/port.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI port driver
     32 * @brief UHCI root hub port routines
    3333 */
    3434#ifndef DRV_UHCI_PORT_H
    3535#define DRV_UHCI_PORT_H
    3636
    37 #include <assert.h>
     37#include <stdint.h>
     38#include <fibril.h>
    3839#include <ddf/driver.h>
    39 #include <stdint.h>
    40 #include <usb/usbdevice.h>
     40#include <usb/usbdevice.h> /* usb_hc_connection_t */
    4141
    42 #include "port_status.h"
     42typedef uint16_t port_status_t;
     43#define STATUS_CONNECTED         (1 << 0)
     44#define STATUS_CONNECTED_CHANGED (1 << 1)
     45#define STATUS_ENABLED           (1 << 2)
     46#define STATUS_ENABLED_CHANGED   (1 << 3)
     47#define STATUS_LINE_D_PLUS       (1 << 4)
     48#define STATUS_LINE_D_MINUS      (1 << 5)
     49#define STATUS_RESUME            (1 << 6)
     50#define STATUS_ALWAYS_ONE        (1 << 7)
     51
     52#define STATUS_LOW_SPEED (1 <<  8)
     53#define STATUS_IN_RESET  (1 <<  9)
     54#define STATUS_SUSPEND   (1 << 12)
    4355
    4456typedef struct uhci_port
    4557{
     58        char *id_string;
    4659        port_status_t *address;
    4760        unsigned number;
     
    5871
    5972void uhci_port_fini(uhci_port_t *port);
     73
    6074#endif
    6175/**
  • uspace/drv/uhci-rhd/root_hub.c

    rc32688d r361e61b  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI root hub driver
    3333 */
    3434#include <errno.h>
    35 #include <stdint.h>
    3635#include <ddi.h>
    37 #include <devman.h>
    3836#include <usb/debug.h>
    3937
    4038#include "root_hub.h"
    4139
    42 /** Initializes UHCI root hub instance.
     40/** Initialize UHCI root hub instance.
    4341 *
    4442 * @param[in] instance Driver memory structure to use.
    4543 * @param[in] addr Address of I/O registers.
    4644 * @param[in] size Size of available I/O space.
    47  * @param[in] rh Pointer to ddf instance fo the root hub driver.
     45 * @param[in] rh Pointer to ddf instance of the root hub driver.
    4846 * @return Error code.
    4947 */
     
    6159        if (ret < 0) {
    6260                usb_log_error(
    63                     "Failed to gain access to port registers at %p\n", regs);
     61                    "Failed(%d) to gain access to port registers at %p\n",
     62                    ret, regs);
    6463                return ret;
    6564        }
    6665
    67         /* add fibrils for periodic port checks */
     66        /* Initialize root hub ports */
    6867        unsigned i = 0;
    6968        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
     
    8281}
    8382/*----------------------------------------------------------------------------*/
    84 /** Finishes UHCI root hub instance.
     83/** Cleanup UHCI root hub instance.
    8584 *
    86  * @param[in] instance Driver memory structure to use.
     85 * @param[in] instance Root hub structure to use.
    8786 * @return Error code.
    8887 */
  • uspace/drv/uhci-rhd/root_hub.h

    rc32688d r361e61b  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcirh
    2929 * @{
    3030 */
     
    3535#define DRV_UHCI_ROOT_HUB_H
    3636
    37 #include <fibril.h>
    3837#include <ddf/driver.h>
    3938
  • uspace/drv/usbhid/hiddev.c

    rc32688d r361e61b  
    411411                return rc;
    412412        }
    413        
     413        rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe);
     414        if (rc != EOK) {
     415                usb_log_error("Probing default control pipe failed: %s.\n",
     416                    str_error(rc));
     417                return rc;
     418        }
     419
    414420        /*
    415421         * Initialize the report parser.
     
    434440        if (rc != EOK) {
    435441                /* TODO: end session?? */
     442                usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    436443                usb_log_error("Failed to process descriptors: %s.\n",
    437444                    str_error(rc));
  • uspace/drv/usbhid/hiddev.h

    rc32688d r361e61b  
    3232/** @file
    3333 * Generic USB HID device structure and API.
     34 *
     35 * @todo Add function for parsing report - this is generic HID function, not
     36 *       keyboard-specific, as the report parser is also generic.
     37 * @todo Add function for polling as that is also a generic HID process.
     38 * @todo Add interrupt in pipe to the structure.
    3439 */
    3540
  • uspace/drv/usbhid/kbddev.c

    rc32688d r361e61b  
    5151#include <usb/classes/hidparser.h>
    5252#include <usb/classes/classes.h>
     53#include <usb/classes/hidut.h>
    5354
    5455#include "kbddev.h"
     
    9394        .flags = 0
    9495};
     96
     97typedef enum usbhid_kbd_flags {
     98        USBHID_KBD_STATUS_UNINITIALIZED = 0,
     99        USBHID_KBD_STATUS_INITIALIZED = 1,
     100        USBHID_KBD_STATUS_TO_DESTROY = -1
     101} usbhid_kbd_flags;
    95102
    96103/*----------------------------------------------------------------------------*/
     
    124131};
    125132
     133typedef enum usbhid_lock_code {
     134        USBHID_LOCK_NUM = 0x53,
     135        USBHID_LOCK_CAPS = 0x39,
     136        USBHID_LOCK_SCROLL = 0x47,
     137        USBHID_LOCK_COUNT = 3
     138} usbhid_lock_code;
     139
     140static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = {
     141        USBHID_LOCK_NUM,
     142        USBHID_LOCK_CAPS,
     143        USBHID_LOCK_SCROLL
     144};
     145
    126146/*----------------------------------------------------------------------------*/
    127147/* IPC method handler                                                         */
     
    218238       
    219239        assert(kbd_dev->hid_dev != NULL);
    220         assert(kbd_dev->hid_dev->initialized);
     240        assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
    221241        usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT,
    222242            buffer, BOOTP_BUFFER_OUT_SIZE);
     
    346366 * @sa usbhid_kbd_push_ev()
    347367 */
    348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    349     uint8_t modifiers)
    350 {
    351         /*
    352          * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
    353          *       both as modifiers and as keys with their own scancodes???
    354          *
    355          * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
    356          * so maybe it would be better if I received it from report parser in
    357          * that way
    358          */
    359        
    360         int i;
    361         for (i = 0; i < USB_HID_MOD_COUNT; ++i) {
    362                 if ((modifiers & usb_hid_modifiers_consts[i]) &&
    363                     !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
    364                         // modifier pressed
    365                         if (usbhid_modifiers_keycodes[i] != 0) {
    366                                 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS,
    367                                     usbhid_modifiers_keycodes[i]);
    368                         }
    369                 } else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
    370                     (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
    371                         // modifier released
    372                         if (usbhid_modifiers_keycodes[i] != 0) {
    373                                 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE,
    374                                     usbhid_modifiers_keycodes[i]);
    375                         }
    376                 }       // no change
    377         }
    378        
    379         kbd_dev->modifiers = modifiers;
     368//static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
     369//    const uint8_t *key_codes, size_t count)
     370//{
     371//      /*
     372//       * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
     373//       *       both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes???
     374//       *
     375//       * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
     376//       * so maybe it would be better if I received it from report parser in
     377//       * that way
     378//       */
     379       
     380//      int i;
     381//      for (i = 0; i < count; ++i) {
     382//              if ((modifiers & usb_hid_modifiers_consts[i]) &&
     383//                  !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
     384//                      // modifier pressed
     385//                      if (usbhid_modifiers_keycodes[i] != 0) {
     386//                              usbhid_kbd_push_ev(kbd_dev, KEY_PRESS,
     387//                                  usbhid_modifiers_keycodes[i]);
     388//                      }
     389//              } else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
     390//                  (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
     391//                      // modifier released
     392//                      if (usbhid_modifiers_keycodes[i] != 0) {
     393//                              usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE,
     394//                                  usbhid_modifiers_keycodes[i]);
     395//                      }
     396//              }       // no change
     397//      }
     398       
     399//      kbd_dev->modifiers = modifiers;
     400//}
     401
     402/*----------------------------------------------------------------------------*/
     403
     404static inline int usbhid_kbd_is_lock(unsigned int key_code)
     405{
     406        return (key_code == KC_NUM_LOCK
     407            || key_code == KC_SCROLL_LOCK
     408            || key_code == KC_CAPS_LOCK);
    380409}
    381410
     
    404433        /*
    405434         * First of all, check if the kbd have reported phantom state.
     435         *
     436         * TODO: this must be changed as we don't know which keys are modifiers
     437         *       and which are regular keys.
    406438         */
    407439        i = 0;
     
    434466                        // not found, i.e. the key was released
    435467                        key = usbhid_parse_scancode(kbd_dev->keys[j]);
    436                         usbhid_kbd_repeat_stop(kbd_dev, key);
     468                        if (!usbhid_kbd_is_lock(key)) {
     469                                usbhid_kbd_repeat_stop(kbd_dev, key);
     470                        }
    437471                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    438472                        usb_log_debug2("Key released: %d\n", key);
     
    458492                            key_codes[i]);
    459493                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    460                         usbhid_kbd_repeat_start(kbd_dev, key);
     494                        if (!usbhid_kbd_is_lock(key)) {
     495                                usbhid_kbd_repeat_start(kbd_dev, key);
     496                        }
    461497                } else {
    462498                        // found, nothing happens
     
    510546        }
    511547       
    512         usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
     548        ///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count);
    513549        usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
    514550}
     
    535571                                    uint8_t *buffer, size_t actual_size)
    536572{
    537         assert(kbd_dev->initialized);
     573        assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
    538574        assert(kbd_dev->hid_dev->parser != NULL);
    539575       
     
    589625       
    590626        kbd_dev->console_phone = -1;
    591         kbd_dev->initialized = 0;
     627        kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;
    592628       
    593629        return kbd_dev;
     
    595631
    596632/*----------------------------------------------------------------------------*/
    597 /**
    598  * Properly destroys the USB/HID keyboard structure.
    599  *
    600  * @param kbd_dev Pointer to the structure to be destroyed.
    601  */
    602 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    603 {
    604         if (kbd_dev == NULL || *kbd_dev == NULL) {
    605                 return;
    606         }
    607        
    608         // hangup phone to the console
    609         async_hangup((*kbd_dev)->console_phone);
    610        
    611         if ((*kbd_dev)->hid_dev != NULL) {
    612                 usbhid_dev_free(&(*kbd_dev)->hid_dev);
    613                 assert((*kbd_dev)->hid_dev == NULL);
    614         }
    615        
    616         if ((*kbd_dev)->repeat_mtx != NULL) {
    617                 /* TODO: replace by some check and wait */
    618                 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    619                 free((*kbd_dev)->repeat_mtx);
    620         }
    621 
    622         free(*kbd_dev);
    623         *kbd_dev = NULL;
     633
     634static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
     635{
     636        kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
    624637}
    625638
     
    663676        }
    664677       
    665         if (kbd_dev->initialized) {
     678        if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) {
    666679                usb_log_warning("Keyboard structure already initialized.\n");
    667680                return EINVAL;
     
    676689        }
    677690       
    678         assert(kbd_dev->hid_dev->initialized);
     691        assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
    679692       
    680693        // save the size of the report (boot protocol report by default)
    681         kbd_dev->key_count = BOOTP_REPORT_SIZE;
     694//      kbd_dev->key_count = BOOTP_REPORT_SIZE;
     695       
     696        usb_hid_report_path_t path;
     697        path.usage_page = USB_HIDUT_PAGE_KEYBOARD;
     698        kbd_dev->key_count = usb_hid_report_input_length(
     699            kbd_dev->hid_dev->parser, &path);
     700       
     701        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
     702       
    682703        kbd_dev->keys = (uint8_t *)calloc(
    683704            kbd_dev->key_count, sizeof(uint8_t));
     
    720741        usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
    721742       
    722         kbd_dev->initialized = 1;
     743        kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;
    723744        usb_log_info("HID/KBD device structure initialized.\n");
    724745       
     
    834855        usbhid_kbd_poll(kbd_dev);
    835856       
     857        // as there is another fibril using this device, so we must leave the
     858        // structure to it, but mark it for destroying.
     859        usbhid_kbd_mark_unusable(kbd_dev);
    836860        // at the end, properly destroy the KBD structure
    837         usbhid_kbd_free(&kbd_dev);
    838         assert(kbd_dev == NULL);
     861//      usbhid_kbd_free(&kbd_dev);
     862//      assert(kbd_dev == NULL);
    839863
    840864        return EOK;
     
    958982}
    959983
     984/*----------------------------------------------------------------------------*/
     985
     986int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev)
     987{
     988        return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
     989}
     990
     991/*----------------------------------------------------------------------------*/
     992/**
     993 * Properly destroys the USB/HID keyboard structure.
     994 *
     995 * @param kbd_dev Pointer to the structure to be destroyed.
     996 */
     997void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
     998{
     999        if (kbd_dev == NULL || *kbd_dev == NULL) {
     1000                return;
     1001        }
     1002       
     1003        // hangup phone to the console
     1004        async_hangup((*kbd_dev)->console_phone);
     1005       
     1006        if ((*kbd_dev)->hid_dev != NULL) {
     1007                usbhid_dev_free(&(*kbd_dev)->hid_dev);
     1008                assert((*kbd_dev)->hid_dev == NULL);
     1009        }
     1010       
     1011        if ((*kbd_dev)->repeat_mtx != NULL) {
     1012                /* TODO: replace by some check and wait */
     1013                assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     1014                free((*kbd_dev)->repeat_mtx);
     1015        }
     1016
     1017        free(*kbd_dev);
     1018        *kbd_dev = NULL;
     1019}
     1020
    9601021/**
    9611022 * @}
  • uspace/drv/usbhid/kbddev.h

    rc32688d r361e61b  
    101101        fibril_mutex_t *repeat_mtx;
    102102       
    103         /** State of the structure (for checking before use). */
     103        /** State of the structure (for checking before use).
     104         *
     105         * 0 - not initialized
     106         * 1 - initialized
     107         * -1 - ready for destroying
     108         */
    104109        int initialized;
    105110} usbhid_kbd_t;
     
    108113
    109114int usbhid_kbd_try_add_device(ddf_dev_t *dev);
     115
     116int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev);
     117
     118void usbhid_kbd_free(usbhid_kbd_t **kbd_dev);
    110119
    111120void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
  • uspace/drv/usbhid/kbdrepeat.c

    rc32688d r361e61b  
    7777
    7878        while (true) {
     79                // check if the kbd structure is usable
     80                if (!usbhid_kbd_is_usable(kbd)) {
     81                        usbhid_kbd_free(&kbd);
     82                        assert(kbd == NULL);
     83                        return;
     84                }
     85               
    7986                fibril_mutex_lock(kbd->repeat_mtx);
    8087
  • uspace/drv/usbhub/main.c

    rc32688d r361e61b  
    3636#include <stdio.h>
    3737
     38#include <usb/devdrv.h>
     39#include <usb/classes/classes.h>
     40
    3841#include "usbhub.h"
    3942#include "usbhub_private.h"
    4043
    4144
    42 usb_general_list_t usb_hub_list;
    43 fibril_mutex_t usb_hub_list_lock;
    44 
    45 static driver_ops_t hub_driver_ops = {
    46         .add_device = usb_add_hub_device,
     45usb_endpoint_description_t hub_status_change_endpoint_description = {
     46        .transfer_type = USB_TRANSFER_INTERRUPT,
     47        .direction = USB_DIRECTION_IN,
     48        .interface_class = USB_CLASS_HUB,
     49        .interface_subclass = 0,
     50        .interface_protocol = 0,
     51        .flags = 0
    4752};
    4853
    49 static driver_t hub_driver = {
     54
     55static usb_driver_ops_t usb_hub_driver_ops = {
     56        .add_device = usb_hub_add_device
     57};
     58
     59static usb_driver_t usb_hub_driver = {
    5060        .name = "usbhub",
    51         .driver_ops = &hub_driver_ops
     61        .ops = &usb_hub_driver_ops
    5262};
     63
    5364
    5465int main(int argc, char *argv[])
    5566{
    5667        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    57         dprintf(USB_LOG_LEVEL_INFO, "starting hub driver");
     68        usb_log_info("starting hub driver\n");
    5869
    59         //this is probably not needed anymore
    60         fibril_mutex_initialize(&usb_hub_list_lock);
    61         fibril_mutex_lock(&usb_hub_list_lock);
    62         usb_lst_init(&usb_hub_list);
    63         fibril_mutex_unlock(&usb_hub_list_lock);
    6470       
    65         return ddf_driver_main(&hub_driver);
     71        usb_hub_driver.endpoints = (usb_endpoint_description_t**)
     72                        malloc(2 * sizeof(usb_endpoint_description_t*));
     73        usb_hub_driver.endpoints[0] = &hub_status_change_endpoint_description;
     74        usb_hub_driver.endpoints[1] = NULL;
     75
     76        return usb_driver_main(&usb_hub_driver);
    6677}
    6778
  • uspace/drv/usbhub/port_status.h

    rc32688d r361e61b  
    270270}
    271271
     272//low speed device attached
     273static inline bool usb_port_high_speed(usb_port_status_t * status){
     274        return usb_port_get_bit(status,10);
     275}
     276
     277static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){
     278        usb_port_set_bit(status,10,high_speed);
     279}
     280
     281static inline usb_speed_t usb_port_speed(usb_port_status_t * status){
     282        if(usb_port_low_speed(status))
     283                return USB_SPEED_LOW;
     284        if(usb_port_high_speed(status))
     285                return USB_SPEED_HIGH;
     286        return USB_SPEED_FULL;
     287}
     288
    272289
    273290//connect change
  • uspace/drv/usbhub/usbhub.c

    rc32688d r361e61b  
    5353#include "usb/classes/classes.h"
    5454
    55 static ddf_dev_ops_t hub_device_ops = {
    56         .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
    57 };
    58 
    59 /** Hub status-change endpoint description
    60  *
    61  * For more see usb hub specification in 11.15.1 of
    62  */
    63 static usb_endpoint_description_t status_change_endpoint_description = {
    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 };
    71 
    7255int usb_hub_control_loop(void * hub_info_param){
    7356        usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
    74         while(true){
    75                 usb_hub_check_hub_changes(hub_info);
     57        int errorCode = EOK;
     58
     59        while(errorCode == EOK){
     60                errorCode = usb_hub_check_hub_changes(hub_info);
    7661                async_usleep(1000 * 1000 );/// \TODO proper number once
    7762        }
     63        usb_log_error("something in ctrl loop went wrong, errno %d\n",errorCode);
     64
    7865        return 0;
    7966}
     
    8774
    8875/**
    89  * Initialize connnections to host controller, device, and device
    90  * control endpoint
    91  * @param hub
    92  * @param device
     76 * create usb_hub_info_t structure
     77 *
     78 * Does only basic copying of known information into new structure.
     79 * @param usb_dev usb device structure
     80 * @return basic usb_hub_info_t structure
     81 */
     82static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
     83        usb_hub_info_t * result = usb_new(usb_hub_info_t);
     84        if(!result) return NULL;
     85        result->usb_device = usb_dev;
     86        result->status_change_pipe = usb_dev->pipes[0].pipe;
     87        result->control_pipe = &usb_dev->ctrl_pipe;
     88        result->is_default_address_used = false;
     89        return result;
     90}
     91
     92/**
     93 * Load hub-specific information into hub_info structure.
     94 *
     95 * Particularly read port count and initialize structure holding port
     96 * information.
     97 * This function is hub-specific and should be run only after the hub is
     98 * configured using usb_hub_set_configuration function.
     99 * @param hub_info pointer to structure with usb hub data
     100 * @return error code
     101 */
     102static int usb_hub_get_hub_specific_info(usb_hub_info_t * hub_info){
     103        // get hub descriptor
     104        usb_log_debug("creating serialized descriptor\n");
     105        void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
     106        usb_hub_descriptor_t * descriptor;
     107
     108        /* this was one fix of some bug, should not be needed anymore
     109        int opResult = usb_request_set_configuration(&result->endpoints.control, 1);
     110        if(opResult!=EOK){
     111                usb_log_error("could not set default configuration, errno %d",opResult);
     112                return opResult;
     113        }
     114         */
     115        size_t received_size;
     116        int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,
     117                        USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     118                        USB_DESCTYPE_HUB,
     119                        0, 0, serialized_descriptor,
     120                        USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
     121
     122        if (opResult != EOK) {
     123                usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
     124                                opResult);
     125                free(serialized_descriptor);
     126                return opResult;
     127        }
     128        usb_log_debug2("deserializing descriptor\n");
     129        descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
     130        if(descriptor==NULL){
     131                usb_log_warning("could not deserialize descriptor \n");
     132                return opResult;
     133        }
     134        usb_log_info("setting port count to %d\n",descriptor->ports_count);
     135        hub_info->port_count = descriptor->ports_count;
     136        hub_info->attached_devs = (usb_hc_attached_device_t*)
     137            malloc((hub_info->port_count+1) * sizeof(usb_hc_attached_device_t));
     138        int i;
     139        for(i=0;i<hub_info->port_count+1;++i){
     140                hub_info->attached_devs[i].handle=0;
     141                hub_info->attached_devs[i].address=0;
     142        }
     143        usb_log_debug2("freeing data\n");
     144        free(serialized_descriptor);
     145        free(descriptor->devices_removable);
     146        free(descriptor);
     147        return EOK;
     148}
     149/**
     150 * Set configuration of hub
     151 *
     152 * Check whether there is at least one configuration and sets the first one.
     153 * This function should be run prior to running any hub-specific action.
     154 * @param hub_info
    93155 * @return
    94156 */
    95 static int usb_hub_init_communication(usb_hub_info_t * hub){
    96         usb_log_debug("Initializing hub USB communication (hub->device->handle=%zu).\n", hub->device->handle);
    97         int opResult;
    98         opResult = usb_device_connection_initialize_from_device(
    99                         &hub->device_connection,
    100                         hub->device);
    101         if(opResult != EOK){
    102                 dprintf(USB_LOG_LEVEL_ERROR,
    103                                 "could not initialize connection to hc, errno %d",opResult);
    104                 return opResult;
    105         }
    106         usb_log_debug("Initializing USB wire abstraction.\n");
    107         opResult = usb_hc_connection_initialize_from_device(&hub->connection,
    108                         hub->device);
    109         if(opResult != EOK){
    110                 dprintf(USB_LOG_LEVEL_ERROR,
    111                                 "could not initialize connection to device, errno %d",opResult);
    112                 return opResult;
    113         }
    114         usb_log_debug("Initializing default control pipe.\n");
    115         opResult = usb_endpoint_pipe_initialize_default_control(&hub->endpoints.control,
    116             &hub->device_connection);
    117         if(opResult != EOK){
    118                 dprintf(USB_LOG_LEVEL_ERROR,
    119                                 "could not initialize connection to device endpoint, errno %d",opResult);
    120         }
    121         return opResult;
    122 }
    123 
    124 /**
    125  * When entering this function, hub->endpoints.control should be active.
    126  * @param hub
    127  * @return
    128  */
    129 static int usb_hub_process_configuration_descriptors(
    130         usb_hub_info_t * hub){
    131         if(hub==NULL) {
    132                 return EINVAL;
    133         }
    134         int opResult;
    135        
     157static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
    136158        //device descriptor
    137159        usb_standard_device_descriptor_t std_descriptor;
    138         opResult = usb_request_get_device_descriptor(&hub->endpoints.control,
     160        int opResult = usb_request_get_device_descriptor(
     161                &hub_info->usb_device->ctrl_pipe,
    139162            &std_descriptor);
    140163        if(opResult!=EOK){
    141                 dprintf(USB_LOG_LEVEL_ERROR, "could not get device descriptor, %d",opResult);
    142                 return opResult;
    143         }
    144         dprintf(USB_LOG_LEVEL_INFO, "hub has %d configurations",
     164                usb_log_error("could not get device descriptor, %d\n",opResult);
     165                return opResult;
     166        }
     167        usb_log_info("hub has %d configurations\n",
    145168                        std_descriptor.configuration_count);
    146169        if(std_descriptor.configuration_count<1){
    147                 dprintf(USB_LOG_LEVEL_ERROR, "THERE ARE NO CONFIGURATIONS AVAILABLE");
     170                usb_log_error("THERE ARE NO CONFIGURATIONS AVAILABLE\n");
    148171                //shouldn`t I return?
    149172        }
     
    153176        size_t descriptors_size = 0;
    154177        opResult = usb_request_get_full_configuration_descriptor_alloc(
    155             &hub->endpoints.control, 0,
     178            &hub_info->usb_device->ctrl_pipe, 0,
    156179            (void **) &descriptors, &descriptors_size);
    157180        if (opResult != EOK) {
     
    164187
    165188        /* Set configuration. */
    166         opResult = usb_request_set_configuration(&hub->endpoints.control,
     189        opResult = usb_request_set_configuration(&hub_info->usb_device->ctrl_pipe,
    167190            config_descriptor->configuration_number);
    168191
     
    172195                return opResult;
    173196        }
    174         dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",
     197        usb_log_debug("\tused configuration %d\n",
    175198                        config_descriptor->configuration_number);
    176 
    177         usb_endpoint_mapping_t endpoint_mapping[1] = {
    178                 {
    179                         .pipe = &hub->endpoints.status_change,
    180                         .description = &status_change_endpoint_description,
    181                         .interface_no =
    182                             usb_device_get_assigned_interface(hub->device)
    183                 }
    184         };
    185         opResult = usb_endpoint_pipe_initialize_from_configuration(
    186             endpoint_mapping, 1,
    187             descriptors, descriptors_size,
    188             &hub->device_connection);
    189         if (opResult != EOK) {
    190                 dprintf(USB_LOG_LEVEL_ERROR,
    191                                 "Failed to initialize status change pipe: %s",
    192                     str_error(opResult));
    193                 return opResult;
    194         }
    195         if (!endpoint_mapping[0].present) {
    196                 dprintf(USB_LOG_LEVEL_ERROR,"Not accepting device, " \
    197                     "cannot understand what is happenning");
    198                 return EREFUSED;
    199         }
    200 
    201199        free(descriptors);
    202200        return EOK;
     201}
     202
     203/**
     204 * Initialize hub device driver fibril
     205 *
     206 * Creates hub representation and fibril that periodically checks hub`s status.
     207 * Hub representation is passed to the fibril.
     208 * @param usb_dev generic usb device information
     209 * @return error code
     210 */
     211int usb_hub_add_device(usb_device_t * usb_dev){
     212        if(!usb_dev) return EINVAL;
     213        usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
     214        //create hc connection
     215        usb_log_debug("Initializing USB wire abstraction.\n");
     216        int opResult = usb_hc_connection_initialize_from_device(
     217                        &hub_info->connection,
     218                        hub_info->usb_device->ddf_dev);
     219        if(opResult != EOK){
     220                usb_log_error("could not initialize connection to device, errno %d\n",
     221                                opResult);
     222                free(hub_info);
     223                return opResult;
     224        }
    203225       
    204 }
    205 
    206 
    207 /**
    208  * Create hub representation from device information.
    209  * @param device
    210  * @return pointer to created structure or NULL in case of error
    211  */
    212 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device) {
    213         usb_hub_info_t* result = usb_new(usb_hub_info_t);
    214         result->device = device;
    215         int opResult;
    216         opResult = usb_hub_init_communication(result);
    217         if(opResult != EOK){
    218                 free(result);
    219                 return NULL;
    220         }
    221 
    222         //result->device = device;
    223         result->port_count = -1;
    224         result->device = device;
    225 
    226         //result->usb_device = usb_new(usb_hcd_attached_device_info_t);
    227         size_t received_size;
    228 
    229         // get hub descriptor
    230         dprintf(USB_LOG_LEVEL_DEBUG, "creating serialized descripton");
    231         void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
    232         usb_hub_descriptor_t * descriptor;
    233         dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
    234         usb_endpoint_pipe_start_session(&result->endpoints.control);
    235         opResult = usb_request_set_configuration(&result->endpoints.control, 1);
    236         assert(opResult == EOK);
    237 
    238         opResult = usb_request_get_descriptor(&result->endpoints.control,
    239                         USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
    240                         USB_DESCTYPE_HUB,
    241                         0, 0, serialized_descriptor,
    242                         USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    243         usb_endpoint_pipe_end_session(&result->endpoints.control);
    244 
    245         if (opResult != EOK) {
    246                 dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult);
    247                 free(serialized_descriptor);
    248                 free(result);
    249                 return NULL;
    250         }
    251         dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor");
    252         descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
    253         if(descriptor==NULL){
    254                 dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor ");
    255                 free(result);
    256                 return NULL;
    257         }
    258 
    259         dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
    260         result->port_count = descriptor->ports_count;
    261         result->attached_devs = (usb_hc_attached_device_t*)
    262             malloc((result->port_count+1) * sizeof(usb_hc_attached_device_t));
    263         int i;
    264         for(i=0;i<result->port_count+1;++i){
    265                 result->attached_devs[i].handle=0;
    266                 result->attached_devs[i].address=0;
    267         }
    268         dprintf(USB_LOG_LEVEL_DEBUG2, "freeing data");
    269         free(serialized_descriptor);
    270         free(descriptor->devices_removable);
    271         free(descriptor);
    272 
    273         //finish
    274 
    275         dprintf(USB_LOG_LEVEL_INFO, "hub info created");
    276 
    277         return result;
    278 }
    279 
    280 /**
    281  * Create hub representation and add it into hub list
    282  * @param dev
    283  * @return
    284  */
    285 int usb_add_hub_device(ddf_dev_t *dev) {
    286         dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle);
    287 
    288         //dev->ops = &hub_device_ops;
    289         (void) hub_device_ops;
    290 
    291         usb_hub_info_t * hub_info = usb_create_hub_info(dev);
    292         if(!hub_info){
    293                 return EINTR;
    294         }
    295 
    296         int opResult;
    297 
    298         //perform final configurations
    299         usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
    300         // process descriptors
    301         opResult = usb_hub_process_configuration_descriptors(hub_info);
    302         if(opResult != EOK){
    303                 dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d",
    304                                 opResult);
    305                 return opResult;
    306         }
    307         //power ports
    308         usb_device_request_setup_packet_t request;
    309         int port;
    310         for (port = 1; port < hub_info->port_count+1; ++port) {
    311                 usb_hub_set_power_port_request(&request, port);
    312                 opResult = usb_endpoint_pipe_control_write(&hub_info->endpoints.control,
    313                                 &request,sizeof(usb_device_request_setup_packet_t), NULL, 0);
    314                 dprintf(USB_LOG_LEVEL_INFO, "powering port %d",port);
    315                 if (opResult != EOK) {
    316                         dprintf(USB_LOG_LEVEL_WARNING, "something went wrong when setting hub`s %dth port", port);
    317                 }
    318         }
    319         //ports powered, hub seems to be enabled
    320         usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
    321 
    322         //add the hub to list
    323         //is this needed now?
    324         fibril_mutex_lock(&usb_hub_list_lock);
    325         usb_lst_append(&usb_hub_list, hub_info);
    326         fibril_mutex_unlock(&usb_hub_list_lock);
    327         dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list");
    328 
    329         dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf");
    330         ddf_fun_t *hub_fun = ddf_fun_create(dev, fun_exposed, "hub");
     226        usb_endpoint_pipe_start_session(hub_info->control_pipe);
     227        //set hub configuration
     228        opResult = usb_hub_set_configuration(hub_info);
     229        if(opResult!=EOK){
     230                usb_log_error("could not set hub configuration, errno %d\n",opResult);
     231                free(hub_info);
     232                return opResult;
     233        }
     234        //get port count and create attached_devs
     235        opResult = usb_hub_get_hub_specific_info(hub_info);
     236        if(opResult!=EOK){
     237                usb_log_error("could not set hub configuration, errno %d\n",opResult);
     238                free(hub_info);
     239                return opResult;
     240        }
     241        usb_endpoint_pipe_end_session(hub_info->control_pipe);
     242
     243
     244        /// \TODO what is this?
     245        usb_log_debug("adding to ddf");
     246        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
     247                        fun_exposed, "hub");
    331248        assert(hub_fun != NULL);
    332249        hub_fun->ops = NULL;
     
    337254        assert(rc == EOK);
    338255
     256        //create fibril for the hub control loop
    339257        fid_t fid = fibril_create(usb_hub_control_loop, hub_info);
    340258        if (fid == 0) {
    341                 dprintf(USB_LOG_LEVEL_ERROR,
    342                                 ": failed to start monitoring fibril for new hub");
     259                usb_log_error("failed to start monitoring fibril for new hub");
    343260                return ENOMEM;
    344261        }
    345262        fibril_add_ready(fid);
    346 
    347         dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created");
    348         //(void)hub_info;
    349         //usb_hub_check_hub_changes();
    350        
    351         dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
    352         //address is lost...
    353         dprintf(USB_LOG_LEVEL_DEBUG, "\taddress %d, has %d ports ",
    354                         //hub_info->endpoints.control.,
    355                         hub_info->port_count);
    356 
     263        usb_log_debug("hub fibril created");
     264        usb_log_debug("has %d ports ",hub_info->port_count);
    357265        return EOK;
    358         //return ENOTSUP;
    359266}
    360267
     
    367274
    368275/**
     276 * release default address used by given hub
     277 *
     278 * Also unsets hub->is_default_address_used. Convenience wrapper function.
     279 * @note hub->connection MUST be open for communication
     280 * @param hub hub representation
     281 * @return error code
     282 */
     283static int usb_hub_release_default_address(usb_hub_info_t * hub){
     284        int opResult = usb_hc_release_default_address(&hub->connection);
     285        if(opResult!=EOK){
     286                usb_log_error("could not release default address, errno %d\n",opResult);
     287                return opResult;
     288        }
     289        hub->is_default_address_used = false;
     290        return EOK;
     291}
     292
     293/**
    369294 * Reset the port with new device and reserve the default address.
    370295 * @param hc
     
    372297 * @param target
    373298 */
    374 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) {
     299static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,
     300                usb_speed_t speed) {
     301        //if this hub already uses default address, it cannot request it once more
     302        if(hub->is_default_address_used) return;
     303        usb_log_info("some connection changed\n");
     304        assert(hub->control_pipe->hc_phone);
     305        int opResult = usb_hub_clear_port_feature(hub->control_pipe,
     306                                port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     307        if(opResult != EOK){
     308                usb_log_warning("could not clear port-change-connection flag\n");
     309        }
    375310        usb_device_request_setup_packet_t request;
    376         int opResult;
    377         dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
    378         assert(hub->endpoints.control.hc_phone);
     311       
    379312        //get default address
    380         //opResult = usb_drv_reserve_default_address(hc);
    381         opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
     313        opResult = usb_hc_reserve_default_address(&hub->connection, speed);
    382314       
    383315        if (opResult != EOK) {
    384                 dprintf(USB_LOG_LEVEL_WARNING,
    385                                 "cannot assign default address, it is probably used %d",opResult);
    386                 return;
    387         }
     316                usb_log_warning("cannot assign default address, it is probably used %d\n",
     317                                opResult);
     318                return;
     319        }
     320        hub->is_default_address_used = true;
    388321        //reset port
    389322        usb_hub_set_reset_port_request(&request, port);
    390323        opResult = usb_endpoint_pipe_control_write(
    391                         &hub->endpoints.control,
     324                        hub->control_pipe,
    392325                        &request,sizeof(usb_device_request_setup_packet_t),
    393326                        NULL, 0
    394327                        );
    395328        if (opResult != EOK) {
    396                 dprintf(USB_LOG_LEVEL_ERROR,
    397                                 "something went wrong when reseting a port %d",opResult);
     329                usb_log_error("something went wrong when reseting a port %d\n",opResult);
    398330                //usb_hub_release_default_address(hc);
    399                 usb_hc_release_default_address(&hub->connection);
    400         }
     331                usb_hub_release_default_address(hub);
     332        }
     333        return;
    401334}
    402335
     
    408341 */
    409342static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
    410                 uint16_t port, bool isLowSpeed) {
     343                uint16_t port, usb_speed_t speed) {
    411344
    412345        int opResult;
    413         dprintf(USB_LOG_LEVEL_INFO, "finalizing add device");
    414         opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
     346        usb_log_info("finalizing add device\n");
     347        opResult = usb_hub_clear_port_feature(hub->control_pipe,
    415348            port, USB_HUB_FEATURE_C_PORT_RESET);
    416349
    417350        if (opResult != EOK) {
    418                 dprintf(USB_LOG_LEVEL_ERROR, "failed to clear port reset feature");
    419                 usb_hc_release_default_address(&hub->connection);
     351                usb_log_error("failed to clear port reset feature\n");
     352                usb_hub_release_default_address(hub);
    420353                return;
    421354        }
     
    430363                        &new_device_pipe,
    431364                        &new_device_connection);
    432         /// \TODO get highspeed info
    433         usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
    434 
     365        usb_endpoint_pipe_probe_default_control(&new_device_pipe);
    435366
    436367        /* Request address from host controller. */
    437368        usb_address_t new_device_address = usb_hc_request_address(
    438369                        &hub->connection,
    439                         speed/// \TODO fullspeed??
     370                        speed
    440371                        );
    441372        if (new_device_address < 0) {
    442                 dprintf(USB_LOG_LEVEL_ERROR, "failed to get free USB address");
     373                usb_log_error("failed to get free USB address\n");
    443374                opResult = new_device_address;
    444                 usb_hc_release_default_address(&hub->connection);
    445                 return;
    446         }
    447         dprintf(USB_LOG_LEVEL_INFO, "setting new address %d",new_device_address);
     375                usb_hub_release_default_address(hub);
     376                return;
     377        }
     378        usb_log_info("setting new address %d\n",new_device_address);
    448379        //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
    449380        //    new_device_address);
     
    452383        usb_endpoint_pipe_end_session(&new_device_pipe);
    453384        if (opResult != EOK) {
    454                 dprintf(USB_LOG_LEVEL_ERROR,
    455                                 "could not set address for new device %d",opResult);
    456                 usb_hc_release_default_address(&hub->connection);
     385                usb_log_error("could not set address for new device %d\n",opResult);
     386                usb_hub_release_default_address(hub);
    457387                return;
    458388        }
     
    460390
    461391        //opResult = usb_hub_release_default_address(hc);
    462         opResult = usb_hc_release_default_address(&hub->connection);
     392        opResult = usb_hub_release_default_address(hub);
    463393        if(opResult!=EOK){
    464394                return;
     
    468398        //??
    469399    opResult = usb_device_register_child_in_devman(new_device_address,
    470             hub->connection.hc_handle, hub->device, &child_handle,
     400            hub->connection.hc_handle, hub->usb_device->ddf_dev, &child_handle,
    471401            NULL, NULL, NULL);
    472402
    473403        if (opResult != EOK) {
    474                 dprintf(USB_LOG_LEVEL_ERROR,
    475                                 "could not start driver for new device %d",opResult);
     404                usb_log_error("could not start driver for new device %d\n",opResult);
    476405                return;
    477406        }
     
    484413                        &hub->attached_devs[port]);
    485414        if (opResult != EOK) {
    486                 dprintf(USB_LOG_LEVEL_ERROR,
    487                                 "could not assign address of device in hcd %d",opResult);
    488                 return;
    489         }
    490         dprintf(USB_LOG_LEVEL_INFO, "new device address %d, handle %zu",
     415                usb_log_error("could not assign address of device in hcd %d\n",opResult);
     416                return;
     417        }
     418        usb_log_info("new device address %d, handle %zu\n",
    491419            new_device_address, child_handle);
    492420
     
    501429static void usb_hub_removed_device(
    502430    usb_hub_info_t * hub,uint16_t port) {
    503         //usb_device_request_setup_packet_t request;
    504         int opResult;
    505        
     431
     432        int opResult = usb_hub_clear_port_feature(hub->control_pipe,
     433                                port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     434        if(opResult != EOK){
     435                usb_log_warning("could not clear port-change-connection flag\n");
     436        }
    506437        /** \TODO remove device from device manager - not yet implemented in
    507438         * devide manager
     
    510441        //close address
    511442        if(hub->attached_devs[port].address!=0){
    512                 //opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);
     443                /*uncomment this code to use it when DDF allows device removal
    513444                opResult = usb_hc_unregister_device(
    514445                                &hub->connection, hub->attached_devs[port].address);
     
    519450                hub->attached_devs[port].address = 0;
    520451                hub->attached_devs[port].handle = 0;
     452                 */
    521453        }else{
    522                 dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address");
     454                usb_log_warning("this is strange, disconnected device had no address\n");
    523455                //device was disconnected before it`s port was reset - return default address
    524                 //usb_drv_release_default_address(hc);
    525                 usb_hc_release_default_address(&hub->connection);
    526         }
    527 }
    528 
    529 
    530 /**
    531  *Process over current condition on port.
     456                usb_hub_release_default_address(hub);
     457        }
     458}
     459
     460
     461/**
     462 * Process over current condition on port.
    532463 *
    533464 * Turn off the power on the port.
     
    539470                uint16_t port){
    540471        int opResult;
    541         opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
     472        opResult = usb_hub_clear_port_feature(hub->control_pipe,
    542473            port, USB_HUB_FEATURE_PORT_POWER);
    543474        if(opResult!=EOK){
    544                 dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d;  %d",
     475                usb_log_error("cannot power off port %d;  %d\n",
    545476                                port, opResult);
    546477        }
     
    555486static void usb_hub_process_interrupt(usb_hub_info_t * hub,
    556487        uint16_t port) {
    557         dprintf(USB_LOG_LEVEL_DEBUG, "interrupt at port %d", port);
     488        usb_log_debug("interrupt at port %d\n", port);
    558489        //determine type of change
    559         usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
     490        usb_endpoint_pipe_t *pipe = hub->control_pipe;
    560491       
    561492        int opResult;
     
    574505                        );
    575506        if (opResult != EOK) {
    576                 dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
     507                usb_log_error("could not get port status\n");
    577508                return;
    578509        }
    579510        if (rcvd_size != sizeof (usb_port_status_t)) {
    580                 dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
     511                usb_log_error("received status has incorrect size\n");
    581512                return;
    582513        }
    583514        //something connected/disconnected
    584515        if (usb_port_connect_change(&status)) {
    585                 opResult = usb_hub_clear_port_feature(pipe,
    586                     port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    587                 // TODO: check opResult
    588516                if (usb_port_dev_connected(&status)) {
    589                         dprintf(USB_LOG_LEVEL_INFO, "some connection changed");
    590                         usb_hub_init_add_device(hub, port);
     517                        usb_log_info("some connection changed\n");
     518                        usb_hub_init_add_device(hub, port, usb_port_speed(&status));
    591519                } else {
    592520                        usb_hub_removed_device(hub, port);
     
    599527                        usb_hub_over_current(hub,port);
    600528                }else{
    601                         dprintf(USB_LOG_LEVEL_INFO,
    602                                 "over current condition was auto-resolved on port %d",port);
     529                        usb_log_info("over current condition was auto-resolved on port %d\n",
     530                                        port);
    603531                }
    604532        }
    605533        //port reset
    606534        if (usb_port_reset_completed(&status)) {
    607                 dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
     535                usb_log_info("port reset complete");
    608536                if (usb_port_enabled(&status)) {
    609                         usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
     537                        usb_hub_finalize_add_device(hub, port, usb_port_speed(&status));
    610538                } else {
    611                         dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");
     539                        usb_log_warning("port reset, but port still not enabled\n");
    612540                }
    613541        }
     
    618546        usb_port_set_dev_connected(&status, false);
    619547        if (status>>16) {
    620                 dprintf(USB_LOG_LEVEL_INFO, "there was some unsupported change on port %d: %X",port,status);
    621 
    622         }
    623         /// \TODO handle other changes
     548                usb_log_info("there was some unsupported change on port %d: %X\n",
     549                                port,status);
     550
     551        }
    624552}
    625553
    626554/**
    627555 * Check changes on particular hub
    628  * @param hub_info_param
    629  */
    630 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
     556 * @param hub_info_param pointer to usb_hub_info_t structure
     557 * @return error code if there is problem when initializing communication with
     558 * hub, EOK otherwise
     559 */
     560int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
    631561        int opResult;
    632         opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
     562        opResult = usb_endpoint_pipe_start_session(
     563                        hub_info->status_change_pipe);
    633564        if(opResult != EOK){
    634                 dprintf(USB_LOG_LEVEL_ERROR,
    635                                 "could not initialize communication for hub; %d", opResult);
    636                 return;
     565                usb_log_error("could not initialize communication for hub; %d\n",
     566                                opResult);
     567                return opResult;
    637568        }
    638569
     
    648579         */
    649580        opResult = usb_endpoint_pipe_read(
    650                         &hub_info->endpoints.status_change,
     581                        hub_info->status_change_pipe,
    651582                        change_bitmap, byte_length, &actual_size
    652583                        );
     
    654585        if (opResult != EOK) {
    655586                free(change_bitmap);
    656                 dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
    657                 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    658                 return;
     587                usb_log_warning("something went wrong while getting status of hub\n");
     588                usb_endpoint_pipe_end_session(hub_info->status_change_pipe);
     589                return opResult;
    659590        }
    660591        unsigned int port;
    661         opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
    662         if(opResult!=EOK){
    663                 dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d",
     592        opResult = usb_endpoint_pipe_start_session(hub_info->control_pipe);
     593        if(opResult!=EOK){
     594                usb_log_error("could not start control pipe session %d\n", opResult);
     595                usb_endpoint_pipe_end_session(hub_info->status_change_pipe);
     596                return opResult;
     597        }
     598        opResult = usb_hc_connection_open(&hub_info->connection);
     599        if(opResult!=EOK){
     600                usb_log_error("could not start host controller session %d\n",
    664601                                opResult);
    665                 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    666                 return;
    667         }
    668         opResult = usb_hc_connection_open(&hub_info->connection);
    669         if(opResult!=EOK){
    670                 dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d",
    671                                 opResult);
    672                 usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
    673                 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
    674                 return;
     602                usb_endpoint_pipe_end_session(hub_info->control_pipe);
     603                usb_endpoint_pipe_end_session(hub_info->status_change_pipe);
     604                return opResult;
    675605        }
    676606
     
    685615        }
    686616        usb_hc_connection_close(&hub_info->connection);
    687         usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
    688         usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
     617        usb_endpoint_pipe_end_session(hub_info->control_pipe);
     618        usb_endpoint_pipe_end_session(hub_info->status_change_pipe);
    689619        free(change_bitmap);
     620        return EOK;
    690621}
    691622
  • uspace/drv/usbhub/usbhub.h

    rc32688d r361e61b  
    4545
    4646#include <usb/pipes.h>
     47#include <usb/devdrv.h>
     48
     49
     50/** Hub status-change endpoint description
     51 *
     52 * For more see usb hub specification in 11.15.1 of
     53 */
     54extern usb_endpoint_description_t hub_status_change_endpoint_description;
     55
     56
    4757
    4858/* Hub endpoints. */
    49 typedef struct {
     59/*typedef struct {
    5060        usb_endpoint_pipe_t control;
    5161        usb_endpoint_pipe_t status_change;
    5262} usb_hub_endpoints_t;
    53 
     63*/
    5464
    5565
     
    5868        /** Number of ports. */
    5969        int port_count;
     70
    6071        /** attached device handles, for each port one */
    6172        usb_hc_attached_device_t * attached_devs;
    62         /** General usb device info. */
    63         //usb_hcd_attached_device_info_t * usb_device;
    64         /** General device info*/
    65         ddf_dev_t * device;
     73       
    6674        /** connection to hcd */
    67         //usb_device_connection_t connection;
    6875        usb_hc_connection_t connection;
    69         /** */
    70         usb_device_connection_t device_connection;
    71         /** hub endpoints */
    72         usb_hub_endpoints_t endpoints;
     76
     77        /** default address is used indicator
     78         *
     79         * If default address is requested by this device, it cannot
     80         * be requested by the same hub again, otherwise a deadlock will occur.
     81         */
     82        bool is_default_address_used;
     83
     84        /** convenience pointer to status change pipe
     85         *
     86         * Status change pipe is initialized in usb_device structure. This is
     87         * pointer into this structure, so that it does not have to be
     88         * searched again and again for the 'right pipe'.
     89         */
     90        usb_endpoint_pipe_t * status_change_pipe;
     91
     92        /** convenience pointer to control pipe
     93         *
     94         * Control pipe is initialized in usb_device structure. This is
     95         * pointer into this structure, so that it does not have to be
     96         * searched again and again for the 'right pipe'.
     97         */
     98        usb_endpoint_pipe_t * control_pipe;
     99
     100        /** generic usb device data*/
     101        usb_device_t * usb_device;
    73102} usb_hub_info_t;
    74103
     
    79108int usb_hub_control_loop(void * hub_info_param);
    80109
    81 /** Callback when new hub device is detected.
    82  *
    83  * @param dev New device.
    84  * @return Error code.
     110/**
     111 * Check changes on specified hub
     112 * @param hub_info_param pointer to usb_hub_info_t structure
     113 * @return error code if there is problem when initializing communication with
     114 * hub, EOK otherwise
    85115 */
    86 int usb_add_hub_device(ddf_dev_t *dev);
    87 
    88 /**
    89  * check changes on specified hub
    90  * @param hub_info_param pointer to usb_hub_info_t structure
    91  */
    92 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
     116int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    93117
    94118
    95 
    96 
     119int usb_hub_add_device(usb_device_t * usb_dev);
    97120
    98121#endif
  • uspace/drv/usbhub/usbhub_private.h

    rc32688d r361e61b  
    5858
    5959
    60 //************
    61 //
    62 // convenience debug printf for usb hub
    63 //
    64 //************
    65 #define dprintf(level, format, ...) \
    66         usb_log_printf((level), format "\n", ##__VA_ARGS__)
    67 
    68 
    6960/**
    7061 * Create hub structure instance
     
    7768 */
    7869usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
    79 
    80 /** List of hubs maanged by this driver */
    81 extern usb_general_list_t usb_hub_list;
    82 
    83 /** Lock for hub list*/
    84 extern fibril_mutex_t usb_hub_list_lock;
    85 
    86 
    87 /**
    88  * Perform complete control read transaction
    89  *
    90  * Manages all three steps of transaction: setup, read and finalize
    91  * @param phone
    92  * @param target
    93  * @param request Request packet
    94  * @param rcvd_buffer Received data
    95  * @param rcvd_size
    96  * @param actual_size Actual size of received data
    97  * @return error code
    98  */
    99 /*
    100 int usb_drv_sync_control_read(
    101     usb_endpoint_pipe_t *pipe,
    102     usb_device_request_setup_packet_t * request,
    103     void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
    104 );*/
    105 
    106 /**
    107  * Perform complete control write transaction
    108  *
    109  * Manages all three steps of transaction: setup, write and finalize
    110  * @param phone
    111  * @param target
    112  * @param request Request packet to send data
    113  * @param sent_buffer
    114  * @param sent_size
    115  * @return error code
    116  */
    117 /*int usb_drv_sync_control_write(
    118     usb_endpoint_pipe_t *pipe,
    119     usb_device_request_setup_packet_t * request,
    120     void * sent_buffer, size_t sent_size
    121 );*/
    12270
    12371/**
     
    163111
    164112/**
    165  * @brief create uint8_t array with serialized descriptor
     113 * create uint8_t array with serialized descriptor
    166114 *
    167115 * @param descriptor
     
    171119
    172120/**
    173  * @brief create deserialized desriptor structure out of serialized descriptor
     121 * create deserialized desriptor structure out of serialized descriptor
    174122 *
    175123 * The serialized descriptor must be proper usb hub descriptor,
  • uspace/drv/usbhub/utils.c

    rc32688d r361e61b  
    8888
    8989        if (sdescriptor[1] != USB_DESCTYPE_HUB) {
    90                 dprintf(1,"[usb_hub] wrong descriptor %x\n",sdescriptor[1]);
     90                usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]);
    9191                return NULL;
    9292        }
     
    103103                        ? 1 : 0);
    104104        result->devices_removable = (uint8_t*) malloc(var_size);
    105         //printf("[usb_hub] getting removable devices data \n");
     105
    106106        size_t i;
    107107        for (i = 0; i < var_size; ++i) {
     
    111111}
    112112
    113 //control transactions
    114 /*
    115 int usb_drv_sync_control_read(
    116     int phone, usb_target_t target,
    117     usb_device_request_setup_packet_t * request,
    118     void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
    119 ) {
    120         usb_handle_t handle;
    121         int opResult;
    122         //setup
    123         opResult = usb_drv_async_control_read_setup(phone, target,
    124             request, sizeof (usb_device_request_setup_packet_t),
    125             &handle);
    126         if (opResult != EOK) {
    127                 return opResult;
    128         }
    129         opResult = usb_drv_async_wait_for(handle);
    130         if (opResult != EOK) {
    131                 return opResult;
    132         }
    133         //read
    134         opResult = usb_drv_async_control_read_data(phone, target,
    135                         rcvd_buffer, rcvd_size, actual_size,
    136                         &handle);
    137         if (opResult != EOK) {
    138                 return opResult;
    139         }
    140         opResult = usb_drv_async_wait_for(handle);
    141         if (opResult != EOK) {
    142                 return opResult;
    143         }
    144         //finalize
    145         opResult = usb_drv_async_control_read_status(phone, target,
    146                         &handle);
    147         if (opResult != EOK) {
    148                 return opResult;
    149         }
    150         opResult = usb_drv_async_wait_for(handle);
    151         if (opResult != EOK) {
    152                 return opResult;
    153         }
    154         return EOK;
    155 }
    156 
    157 int usb_drv_sync_control_write(
    158     int phone, usb_target_t target,
    159     usb_device_request_setup_packet_t * request,
    160     void * sent_buffer, size_t sent_size
    161 ) {
    162         usb_handle_t handle;
    163         int opResult;
    164         //setup
    165         opResult = usb_drv_async_control_write_setup(phone, target,
    166             request, sizeof (usb_device_request_setup_packet_t),
    167             &handle);
    168         if (opResult != EOK) {
    169                 return opResult;
    170         }
    171         opResult = usb_drv_async_wait_for(handle);
    172         if (opResult != EOK) {
    173                 return opResult;
    174         }
    175         //write
    176         opResult = usb_drv_async_control_write_data(phone, target,
    177                         sent_buffer, sent_size,
    178                         &handle);
    179         if (opResult != EOK) {
    180                 return opResult;
    181         }
    182         opResult = usb_drv_async_wait_for(handle);
    183         if (opResult != EOK) {
    184                 return opResult;
    185         }
    186         //finalize
    187         opResult = usb_drv_async_control_write_status(phone, target,
    188             &handle);
    189         if (opResult != EOK) {
    190                 return opResult;
    191         }
    192         opResult = usb_drv_async_wait_for(handle);
    193         if (opResult != EOK) {
    194                 return opResult;
    195         }
    196         return EOK;
    197 }
    198 
    199 */
    200 
    201113
    202114
  • uspace/drv/usbmid/usbmid.c

    rc32688d r361e61b  
    116116                return NULL;
    117117        }
     118        rc = usb_endpoint_pipe_probe_default_control(&mid->ctrl_pipe);
     119        if (rc != EOK) {
     120                usb_log_error("Probing default control pipe failed: %s.\n",
     121                    str_error(rc));
     122                free(mid);
     123                return NULL;
     124        }
    118125
    119126        mid->dev = dev;
  • uspace/drv/usbmouse/init.c

    rc32688d r361e61b  
    4242
    4343/** Mouse polling endpoint description for boot protocol subclass. */
    44 static usb_endpoint_description_t poll_endpoint_description = {
     44usb_endpoint_description_t poll_endpoint_description = {
    4545        .transfer_type = USB_TRANSFER_INTERRUPT,
    4646        .direction = USB_DIRECTION_IN,
     
    5050        .flags = 0
    5151};
    52 
    53 /** Initialize poll pipe.
    54  *
    55  * Expects that session is already started on control pipe zero.
    56  *
    57  * @param mouse Mouse device.
    58  * @param my_interface Interface number.
    59  * @return Error code.
    60  */
    61 static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)
    62 {
    63         assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));
    64 
    65         int rc;
    66 
    67         void *config_descriptor;
    68         size_t config_descriptor_size;
    69 
    70         rc = usb_request_get_full_configuration_descriptor_alloc(
    71             &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);
    72         if (rc != EOK) {
    73                 return rc;
    74         }
    75 
    76         usb_endpoint_mapping_t endpoint_mapping[1] = {
    77                 {
    78                         .pipe = &mouse->poll_pipe,
    79                         .description = &poll_endpoint_description,
    80                         .interface_no = my_interface
    81                 }
    82         };
    83 
    84         rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,
    85             1, config_descriptor, config_descriptor_size, &mouse->wire);
    86         if (rc != EOK) {
    87                 return rc;
    88         }
    89 
    90         if (!endpoint_mapping[0].present) {
    91                 return ENOENT;
    92         }
    93 
    94         mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;
    95 
    96         usb_log_debug("prepared polling endpoint %d (interval %zu).\n",
    97             mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);
    98 
    99         return EOK;
    100 }
    10152
    10253static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
     
    14394 * @return Error code.
    14495 */
    145 int usb_mouse_create(ddf_dev_t *dev)
     96int usb_mouse_create(usb_device_t *dev)
    14697{
    14798        usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
     
    149100                return ENOMEM;
    150101        }
    151         mouse->device = dev;
     102        mouse->dev = dev;
    152103        mouse->console_phone = -1;
    153104
    154105        int rc;
    155106
    156         /* Initialize the backing connection. */
    157         rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);
    158         if (rc != EOK) {
    159                 goto leave;
    160         }
    161 
    162         /* Initialize the default control pipe. */
    163         rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,
    164             &mouse->wire);
    165         if (rc != EOK) {
    166                 goto leave;
    167         }
    168 
    169         rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);
    170         if (rc != EOK) {
    171                 goto leave;
    172         }
    173 
    174         rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));
    175 
    176         /* We can ignore error here. */
    177         usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);
    178 
    179         if (rc != EOK) {
    180                 goto leave;
    181         }
    182 
    183107        /* Create DDF function. */
    184         mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
     108        mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
    185109        if (mouse->mouse_fun == NULL) {
    186110                rc = ENOMEM;
     
    200124                goto leave;
    201125        }
     126       
     127        /* Open the control pipe. */
     128        rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe);
     129        if (rc != EOK) {
     130                goto leave;
     131        }
     132       
     133        /* Set the boot protocol. */
     134        rc = usb_control_request_set(&dev->ctrl_pipe,
     135            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     136            USB_HIDREQ_SET_PROTOCOL, USB_HID_PROTOCOL_BOOT, dev->interface_no,
     137            NULL, 0);
     138        if (rc != EOK) {
     139                goto leave;
     140        }
     141       
     142        /* Close the control pipe (ignore errors). */
     143        usb_endpoint_pipe_end_session(&dev->ctrl_pipe);
     144
    202145
    203146        /* Everything allright. */
  • uspace/drv/usbmouse/main.c

    rc32688d r361e61b  
    4444 * @return Error code.
    4545 */
    46 static int usbmouse_add_device(ddf_dev_t *dev)
     46static int usbmouse_add_device(usb_device_t *dev)
    4747{
    4848        int rc = usb_mouse_create(dev);
     
    5353        }
    5454
    55         fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
    56         if (poll_fibril == 0) {
    57                 usb_log_error("Failed to initialize polling fibril.\n");
    58                 /* FIXME: free allocated resources. */
    59                 return ENOMEM;
     55        usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no);
     56
     57        rc = usb_device_auto_poll(dev, 0,
     58            usb_mouse_polling_callback, dev->pipes[0].pipe->max_packet_size,
     59            usb_mouse_polling_ended_callback, dev->driver_data);
     60
     61        if (rc != EOK) {
     62                usb_log_error("Failed to start polling fibril: %s.\n",
     63                    str_error(rc));
     64                return rc;
    6065        }
    6166
    62         fibril_add_ready(poll_fibril);
    63 
    6467        usb_log_info("controlling new mouse (handle %llu).\n",
    65             dev->handle);
     68            dev->ddf_dev->handle);
    6669
    6770        return EOK;
     
    6972
    7073/** USB mouse driver ops. */
    71 static driver_ops_t mouse_driver_ops = {
     74static usb_driver_ops_t mouse_driver_ops = {
    7275        .add_device = usbmouse_add_device,
    7376};
    7477
     78static usb_endpoint_description_t *endpoints[] = {
     79        &poll_endpoint_description,
     80        NULL
     81};
     82
    7583/** USB mouse driver. */
    76 static driver_t mouse_driver = {
     84static usb_driver_t mouse_driver = {
    7785        .name = NAME,
    78         .driver_ops = &mouse_driver_ops
     86        .ops = &mouse_driver_ops,
     87        .endpoints = endpoints
    7988};
    8089
     
    8392        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    8493
    85         return ddf_driver_main(&mouse_driver);
     94        return usb_driver_main(&mouse_driver);
    8695}
    8796
  • uspace/drv/usbmouse/mouse.c

    rc32688d r361e61b  
    4040#include <ipc/mouse.h>
    4141
    42 /** Fibril function for polling the mouse device.
     42/** Mouse polling callback.
    4343 *
    44  * This function shall not terminate unless the device breaks and fails
    45  * to send data (e.g. stalls on data request).
    46  *
    47  * @param arg ddf_dev_t type representing the mouse device.
    48  * @return EOK Always.
     44 * @param dev Device that is being polled.
     45 * @param buffer Data buffer.
     46 * @param buffer_size Buffer size in bytes.
     47 * @param arg Custom argument - points to usb_mouse_t.
     48 * @return Always true.
    4949 */
    50 int usb_mouse_polling_fibril(void *arg)
     50bool usb_mouse_polling_callback(usb_device_t *dev,
     51    uint8_t *buffer, size_t buffer_size, void *arg)
    5152{
    52         assert(arg != NULL);
    53         ddf_dev_t *dev = (ddf_dev_t *) arg;
    54         usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
     53        usb_mouse_t *mouse = (usb_mouse_t *) arg;
    5554
    56         assert(mouse);
     55        usb_log_debug2("got buffer: %s.\n",
     56            usb_debug_str_buffer(buffer, buffer_size, 0));
    5757
    58         size_t buffer_size = mouse->poll_pipe.max_packet_size;
     58        uint8_t butt = buffer[0];
     59        char str_buttons[4] = {
     60                butt & 1 ? '#' : '.',
     61                butt & 2 ? '#' : '.',
     62                butt & 4 ? '#' : '.',
     63                0
     64        };
    5965
    60         if (buffer_size < 4) {
    61                 usb_log_error("Weird mouse, results will be skewed.\n");
    62                 buffer_size = 4;
     66        int shift_x = ((int) buffer[1]) - 127;
     67        int shift_y = ((int) buffer[2]) - 127;
     68        int wheel = ((int) buffer[3]) - 127;
     69
     70        if (buffer[1] == 0) {
     71                shift_x = 0;
     72        }
     73        if (buffer[2] == 0) {
     74                shift_y = 0;
     75        }
     76        if (buffer[3] == 0) {
     77                wheel = 0;
    6378        }
    6479
    65         uint8_t *buffer = malloc(buffer_size);
    66         if (buffer == NULL) {
    67                 usb_log_error("Out of memory, poll fibril aborted.\n");
    68                 return ENOMEM;
     80        if (mouse->console_phone >= 0) {
     81                if ((shift_x != 0) || (shift_y != 0)) {
     82                        /* FIXME: guessed for QEMU */
     83                        async_req_2_0(mouse->console_phone,
     84                            MEVENT_MOVE,
     85                            - shift_x / 10,  - shift_y / 10);
     86                }
     87                if (butt) {
     88                        /* FIXME: proper button clicking. */
     89                        async_req_2_0(mouse->console_phone,
     90                            MEVENT_BUTTON, 1, 1);
     91                        async_req_2_0(mouse->console_phone,
     92                            MEVENT_BUTTON, 1, 0);
     93                }
    6994        }
    7095
    71         while (true) {
    72                 async_usleep(mouse->poll_interval_us);
     96        usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     97            str_buttons, shift_x, shift_y, wheel);
    7398
    74                 size_t actual_size;
    75                 int rc;
     99        /* Guess. */
     100        async_usleep(1000);
    76101
    77                 /*
    78                  * Error checking note:
    79                  * - failure when starting a session is considered
    80                  *   temporary (e.g. out of phones, next try might succeed)
    81                  * - failure of transfer considered fatal (probably the
    82                  *   device was unplugged)
    83                  * - session closing not checked (shall not fail anyway)
    84                  */
     102        return true;
     103}
    85104
    86                 rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe);
    87                 if (rc != EOK) {
    88                         usb_log_warning("Failed to start session, will try again: %s.\n",
    89                             str_error(rc));
    90                         continue;
    91                 }
     105/** Callback when polling is terminated.
     106 *
     107 * @param dev Device where the polling terminated.
     108 * @param recurring_errors Whether the polling was terminated due to
     109 *      recurring errors.
     110 * @param arg Custom argument - points to usb_mouse_t.
     111 */
     112void usb_mouse_polling_ended_callback(usb_device_t *dev,
     113    bool recurring_errors, void *arg)
     114{
     115        usb_mouse_t *mouse = (usb_mouse_t *) arg;
    92116
    93                 rc = usb_endpoint_pipe_read(&mouse->poll_pipe,
    94                     buffer, buffer_size, &actual_size);
    95 
    96                 usb_endpoint_pipe_end_session(&mouse->poll_pipe);
    97 
    98                 if (rc != EOK) {
    99                         usb_log_error("Failed reading mouse input: %s.\n",
    100                             str_error(rc));
    101                         break;
    102                 }
    103 
    104                 usb_log_debug2("got buffer: %s.\n",
    105                     usb_debug_str_buffer(buffer, buffer_size, 0));
    106 
    107                 uint8_t butt = buffer[0];
    108                 char str_buttons[4] = {
    109                         butt & 1 ? '#' : '.',
    110                         butt & 2 ? '#' : '.',
    111                         butt & 4 ? '#' : '.',
    112                         0
    113                 };
    114 
    115                 int shift_x = ((int) buffer[1]) - 127;
    116                 int shift_y = ((int) buffer[2]) - 127;
    117                 int wheel = ((int) buffer[3]) - 127;
    118 
    119                 if (buffer[1] == 0) {
    120                         shift_x = 0;
    121                 }
    122                 if (buffer[2] == 0) {
    123                         shift_y = 0;
    124                 }
    125                 if (buffer[3] == 0) {
    126                         wheel = 0;
    127                 }
    128 
    129                 if (mouse->console_phone >= 0) {
    130                         if ((shift_x != 0) || (shift_y != 0)) {
    131                                 /* FIXME: guessed for QEMU */
    132                                 async_req_2_0(mouse->console_phone,
    133                                     MEVENT_MOVE,
    134                                     - shift_x / 10,  - shift_y / 10);
    135                         }
    136                         if (butt) {
    137                                 /* FIXME: proper button clicking. */
    138                                 async_req_2_0(mouse->console_phone,
    139                                     MEVENT_BUTTON, 1, 1);
    140                                 async_req_2_0(mouse->console_phone,
    141                                     MEVENT_BUTTON, 1, 0);
    142                         }
    143                 }
    144 
    145                 usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
    146                    str_buttons, shift_x, shift_y, wheel);
    147         }
    148 
    149         /*
    150          * Device was probably unplugged.
    151          * Hang-up the phone to the console.
    152          * FIXME: release allocated memory.
    153          */
    154117        async_hangup(mouse->console_phone);
    155118        mouse->console_phone = -1;
    156 
    157         usb_log_error("Mouse polling fibril terminated.\n");
    158 
    159         return EOK;
    160119}
    161 
    162120
    163121/**
  • uspace/drv/usbmouse/mouse.h

    rc32688d r361e61b  
    3737#define USBMOUSE_MOUSE_H_
    3838
    39 #include <ddf/driver.h>
     39#include <usb/devdrv.h>
    4040#include <usb/pipes.h>
    4141#include <time.h>
     
    4646typedef struct {
    4747        /** Generic device container. */
    48         ddf_dev_t *device;
     48        usb_device_t *dev;
    4949        /** Function representing the device. */
    5050        ddf_fun_t *mouse_fun;
    51         /** Representation of connection to the device. */
    52         usb_device_connection_t wire;
    53         /** Default (zero) control pipe. */
    54         usb_endpoint_pipe_t ctrl_pipe;
    55         /** Polling (in) pipe. */
    56         usb_endpoint_pipe_t poll_pipe;
    5751        /** Polling interval in microseconds. */
    5852        suseconds_t poll_interval_us;
     
    6155} usb_mouse_t;
    6256
    63 int usb_mouse_create(ddf_dev_t *);
     57#define POLL_PIPE(dev) ((dev)->pipes[0].pipe)
    6458
    65 int usb_mouse_polling_fibril(void *);
     59extern usb_endpoint_description_t poll_endpoint_description;
     60
     61int usb_mouse_create(usb_device_t *);
     62
     63bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *);
     64void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
    6665
    6766#endif
Note: See TracChangeset for help on using the changeset viewer.