Changes in / [72af8da:3e7b7cd] in mainline


Ignore:
Files:
7 added
14 deleted
78 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r72af8da r3e7b7cd  
    8484./uspace/drv/test1/test1
    8585./uspace/drv/test2/test2
    86 ./uspace/drv/ehci-hcd/ehci-hcd
    8786./uspace/drv/uhci-hcd/uhci-hcd
    8887./uspace/drv/uhci-rhd/uhci-rhd
  • boot/arch/amd64/Makefile.inc

    r72af8da r3e7b7cd  
    4343        isa \
    4444        ns8250 \
    45         ehci-hcd \
    4645        uhci-hcd \
    4746        uhci-rhd \
  • boot/arch/mips32/src/asm.S

    r72af8da r3e7b7cd  
    4141
    4242start:
    43         /*
    44          * Setup the CP0 configuration
    45          *  - Disable 64-bit kernel addressing mode
    46          *  - DIsable 64-bit supervisor adressing mode
    47          *  - Disable 64-bit user addressing mode
    48          */
    49         mfc0 $a0, $status
    50         la $a1, 0xffffff1f
    51         and $a0, $a1, $a0
    52         mtc0 $a0, $status
    53        
    54         /*
    55          * Setup CPU map (on msim this code
    56          * is executed in parallel on all CPUs,
    57          * but it not an issue).
    58          */
     43        /* Setup CPU map (on msim this code
     44           is executed in parallel on all CPUs,
     45           but it not an issue) */
    5946        la $a0, PA2KA(CPUMAP_OFFSET)
    6047       
     
    10794        lw $k1, ($k0)
    10895       
    109         /*
    110          * If we are not running on BSP
    111          * then end in an infinite loop.
    112          */
     96        /* If we are not running on BSP
     97           then end in an infinite loop  */
    11398        beq $k1, $zero, bsp
    11499        nop
     
    142127
    143128jump_to_kernel:
    144         /*
    145          * TODO:
    146          *
    147          * Make sure that the I-cache, D-cache and memory are mutually
    148          * coherent before passing control to the copied code.
    149          */
     129        #
     130        # TODO:
     131        # Make sure that the I-cache, D-cache and memory are mutually coherent
     132        # before passing control to the copied code.
     133        #
    150134        j $a0
    151135        nop
  • dist/Makefile

    r72af8da r3e7b7cd  
    4343
    4444SUFFIX = $(suffix $(IMGFILE))
    45 
    46 ifdef PROFILE
    47         DISTFILE = Helenos-$(shell echo $(PROFILE) | tr '/' '-')$(SUFFIX)
    48 else
    49         DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
    50 endif
     45DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
    5146
    5247.PHONY: all clean dist distfile
     
    5853        cp $< $@
    5954
    60 $(IMGFILE):
    61         $(MAKE) -C ..
    62 
    6355dist:
    6456        for profile in $(PROFILES); do \
  • uspace/Makefile

    r72af8da r3e7b7cd  
    117117                srv/hw/irc/apic \
    118118                srv/hw/irc/i8259 \
    119                 drv/ehci-hcd \
    120119                drv/uhci-hcd \
    121120                drv/uhci-rhd \
     
    135134                srv/hw/irc/apic \
    136135                srv/hw/irc/i8259 \
    137                 drv/ehci-hcd \
    138136                drv/uhci-hcd \
    139137                drv/uhci-rhd \
  • uspace/app/bdsh/cmds/modules/mkfile/mkfile.c

    r72af8da r3e7b7cd  
    125125
    126126        for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
    127                 c = getopt_long(argc, argv, "s:h", long_options, &opt_ind);
     127                c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
    128128                switch (c) {
    129129                case 'h':
  • uspace/app/usbinfo/info.c

    r72af8da r3e7b7cd  
    6565                goto leave;
    6666        }
    67         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    68         if (rc != EOK) {
    69                 fprintf(stderr,
    70                     NAME ": probing default control pipe failed: %s.\n",
    71                     str_error(rc));
    72                 goto leave;
    73         }
    7467        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
    7568        if (rc != EOK) {
  • uspace/app/usbinfo/main.c

    r72af8da r3e7b7cd  
    8282
    8383        if (str_cmp(path, "uhci") == 0) {
    84                 path = "/hw/pci0/00:01.2/uhci-hc";
     84                path = "/hw/pci0/00:01.2/uhci";
    8585        }
    8686
  • uspace/doc/doxygroups.h

    r72af8da r3e7b7cd  
    253253         * @defgroup drvusbuhci UHCI driver
    254254         * @ingroup usb
    255          * @brief Drivers for USB UHCI host controller and root hub.
    256          */
    257 
    258                 /**
    259                  * @defgroup drvusbuhcirh UHCI root hub driver
    260                  * @ingroup drvusbuhci
    261                  * @brief Driver for UHCI complaint root hub.
    262                  */
    263 
    264                 /**
    265                  * @defgroup drvusbuhcihc UHCI host controller driver
    266                  * @ingroup drvusbuhci
    267                  * @brief Driver for UHCI complaint USB host controller.
    268                  */
    269 
    270         /**
    271          * @defgroup drvusbehci EHCI driver
    272          * @ingroup usb
    273          * @brief Driver for EHCI host controller.
    274          */
    275 
    276 
     255         * @brief Driver for USB host controller UHCI.
     256         */
     257
  • uspace/drv/pciintel/pci.c

    r72af8da r3e7b7cd  
    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 = -1;
    99 
    100         if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
    101                 irc_service = SERVICE_APIC;
     98        int irc_service = 0;
     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 == -1) {
     103    irc_service = SERVICE_I8259;
     104        }
     105
     106  if (irc_service == 0)
    107107                return false;
    108         }
    109108
    110109        irc_phone = service_connect_blocking(irc_service, 0, 0);
    111         if (irc_phone < 0) {
     110        if (irc_phone < 0)
    112111                return false;
    113         }
    114112
    115113        size_t i;
    116         for (i = 0; i < dev_data->hw_resources.count; i++) {
     114  for (i = 0; i < dev_data->hw_resources.count; i++) {
    117115                if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
    118116                        int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
     
    129127}
    130128
    131 static int pci_config_space_write_32(
    132     ddf_fun_t *fun, uint32_t address, uint32_t data)
    133 {
    134         if (address > 252)
    135                 return EINVAL;
    136         pci_conf_write_32(PCI_FUN(fun), address, data);
    137         return EOK;
    138 }
    139 
    140 static int pci_config_space_write_16(
    141     ddf_fun_t *fun, uint32_t address, uint16_t data)
     129static int pci_config_space_write_16(ddf_fun_t *fun, uint32_t address, uint16_t data)
    142130{
    143131        if (address > 254)
     
    147135}
    148136
    149 static int pci_config_space_write_8(
    150     ddf_fun_t *fun, uint32_t address, uint8_t data)
    151 {
    152         if (address > 255)
    153                 return EINVAL;
    154         pci_conf_write_8(PCI_FUN(fun), address, data);
    155         return EOK;
    156 }
    157 
    158 static int pci_config_space_read_32(
    159     ddf_fun_t *fun, uint32_t address, uint32_t *data)
    160 {
    161         if (address > 252)
    162                 return EINVAL;
    163         *data = pci_conf_read_32(PCI_FUN(fun), address);
    164         return EOK;
    165 }
    166 
    167 static int pci_config_space_read_16(
    168     ddf_fun_t *fun, uint32_t address, uint16_t *data)
    169 {
    170         if (address > 254)
    171                 return EINVAL;
    172         *data = pci_conf_read_16(PCI_FUN(fun), address);
    173         return EOK;
    174 }
    175 
    176 static int pci_config_space_read_8(
    177     ddf_fun_t *fun, uint32_t address, uint8_t *data)
    178 {
    179         if (address > 255)
    180                 return EINVAL;
    181         *data = pci_conf_read_8(PCI_FUN(fun), address);
    182         return EOK;
    183 }
    184137
    185138static hw_res_ops_t pciintel_hw_res_ops = {
     
    189142
    190143static pci_dev_iface_t pci_dev_ops = {
    191         .config_space_read_8 = &pci_config_space_read_8,
    192         .config_space_read_16 = &pci_config_space_read_16,
    193         .config_space_read_32 = &pci_config_space_read_32,
    194         .config_space_write_8 = &pci_config_space_write_8,
     144        .config_space_read_8 = NULL,
     145        .config_space_read_16 = NULL,
     146        .config_space_read_32 = NULL,
     147        .config_space_write_8 = NULL,
    195148        .config_space_write_16 = &pci_config_space_write_16,
    196         .config_space_write_32 = &pci_config_space_write_32
     149        .config_space_write_32 = NULL
    197150};
    198151
  • uspace/drv/uhci-hcd/Makefile

    r72af8da r3e7b7cd  
    3535        iface.c \
    3636        main.c \
     37        root_hub.c \
    3738        transfer_list.c \
    3839        uhci.c \
    39         uhci_hc.c \
    40         uhci_rh.c \
    4140        uhci_struct/transfer_descriptor.c \
    4241        utils/device_keeper.c \
  • uspace/drv/uhci-hcd/batch.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "uhci_hc.h"
     42#include "uhci.h"
    4343#include "utils/malloc32.h"
    4444
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 static void batch_control(batch_t *instance,
    48     usb_packet_id data_stage, usb_packet_id status_stage);
    49 static void batch_data(batch_t *instance, usb_packet_id pid);
     47static int batch_schedule(batch_t *instance);
     48
     49static void batch_control(
     50    batch_t *instance, int data_stage, int status_stage);
    5051static void batch_call_in(batch_t *instance);
    5152static void batch_call_out(batch_t *instance);
     
    5455
    5556
    56 /** Allocate memory and initialize internal data structure.
    57  *
    58  * @param[in] fun DDF function to pass to callback.
    59  * @param[in] target Device and endpoint target of the transaction.
    60  * @param[in] transfer_type Interrupt, Control or Bulk.
    61  * @param[in] max_packet_size maximum allowed size of data packets.
    62  * @param[in] speed Speed of the transaction.
    63  * @param[in] buffer Data source/destination.
    64  * @param[in] size Size of the buffer.
    65  * @param[in] setup_buffer Setup data source (if not NULL)
    66  * @param[in] setup_size Size of setup_buffer (should be always 8)
    67  * @param[in] func_in function to call on inbound transaction completion
    68  * @param[in] func_out function to call on outbound transaction completion
    69  * @param[in] arg additional parameter to func_in or func_out
    70  * @param[in] manager Pointer to toggle management structure.
    71  * @return Valid pointer if all substructures were successfully created,
    72  * NULL otherwise.
    73  *
    74  * Determines the number of needed packets (TDs). Prepares a transport buffer
    75  * (that is accessible by the hardware). Initializes parameters needed for the
    76  * transaction and callback.
    77  */
    7857batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7958    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    8160    char* setup_buffer, size_t setup_size,
    8261    usbhc_iface_transfer_in_callback_t func_in,
    83     usbhc_iface_transfer_out_callback_t func_out, void *arg,
    84     device_keeper_t *manager
    85     )
     62    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    8663{
    8764        assert(func_in == NULL || func_out == NULL);
    8865        assert(func_in != NULL || func_out != NULL);
    8966
    90 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    91         if (ptr == NULL) { \
    92                 usb_log_error(message); \
    93                 if (instance) { \
    94                         batch_dispose(instance); \
    95                 } \
    96                 return NULL; \
    97         } else (void)0
    98 
    9967        batch_t *instance = malloc(sizeof(batch_t));
    100         CHECK_NULL_DISPOSE_RETURN(instance,
    101             "Failed to allocate batch instance.\n");
    102         bzero(instance, sizeof(batch_t));
    103 
    104         instance->qh = malloc32(sizeof(qh_t));
    105         CHECK_NULL_DISPOSE_RETURN(instance->qh,
    106             "Failed to allocate batch queue head.\n");
    107         qh_init(instance->qh);
     68        if (instance == NULL) {
     69                usb_log_error("Failed to allocate batch instance.\n");
     70                return NULL;
     71        }
     72
     73        instance->qh = queue_head_get();
     74        if (instance->qh == NULL) {
     75                usb_log_error("Failed to allocate queue head.\n");
     76                free(instance);
     77                return NULL;
     78        }
    10879
    10980        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    11283        }
    11384
    114         instance->tds = malloc32(sizeof(td_t) * instance->packets);
    115         CHECK_NULL_DISPOSE_RETURN(
    116             instance->tds, "Failed to allocate transfer descriptors.\n");
    117         bzero(instance->tds, sizeof(td_t) * instance->packets);
    118 
    119         if (size > 0) {
    120                 instance->transport_buffer = malloc32(size);
    121                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    122                     "Failed to allocate device accessible buffer.\n");
    123         }
    124 
    125         if (setup_size > 0) {
    126                 instance->setup_buffer = malloc32(setup_size);
    127                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    128                     "Failed to allocate device accessible setup buffer.\n");
     85        instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
     86        if (instance->tds == NULL) {
     87                usb_log_error("Failed to allocate transfer descriptors.\n");
     88                queue_head_dispose(instance->qh);
     89                free(instance);
     90                return NULL;
     91        }
     92        bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
     93
     94        const size_t transport_size = max_packet_size * instance->packets;
     95
     96        instance->transport_buffer =
     97           (size > 0) ? malloc32(transport_size) : NULL;
     98
     99        if ((size > 0) && (instance->transport_buffer == NULL)) {
     100                usb_log_error("Failed to allocate device accessible buffer.\n");
     101                queue_head_dispose(instance->qh);
     102                free32(instance->tds);
     103                free(instance);
     104                return NULL;
     105        }
     106
     107        instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
     108        if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
     109                usb_log_error("Failed to allocate device accessible setup buffer.\n");
     110                queue_head_dispose(instance->qh);
     111                free32(instance->tds);
     112                free32(instance->transport_buffer);
     113                free(instance);
     114                return NULL;
     115        }
     116        if (instance->setup_buffer) {
    129117                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    130118        }
    131119
     120        instance->max_packet_size = max_packet_size;
    132121
    133122        link_initialize(&instance->link);
    134123
    135         instance->max_packet_size = max_packet_size;
    136124        instance->target = target;
    137125        instance->transfer_type = transfer_type;
     126
     127        if (func_out)
     128                instance->callback_out = func_out;
     129        if (func_in)
     130                instance->callback_in = func_in;
     131
    138132        instance->buffer = buffer;
    139133        instance->buffer_size = size;
     
    142136        instance->arg = arg;
    143137        instance->speed = speed;
    144         instance->manager = manager;
    145         instance->callback_out = func_out;
    146         instance->callback_in = func_in;
    147 
    148         qh_set_element_td(instance->qh, addr_to_phys(instance->tds));
    149 
     138
     139        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
    150140        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    151141            instance, target.address, target.endpoint);
     
    153143}
    154144/*----------------------------------------------------------------------------*/
    155 /** Check batch TDs for activity.
    156  *
    157  * @param[in] instance Batch structure to use.
    158  * @return False, if there is an active TD, true otherwise.
    159  *
    160  * Walk all TDs. Stop with false if there is an active one (it is to be
    161  * processed). Stop with true if an error is found. Return true if the last TS
    162  * is reached.
    163  */
    164145bool batch_is_complete(batch_t *instance)
    165146{
     
    170151        size_t i = 0;
    171152        for (;i < instance->packets; ++i) {
    172                 if (td_is_active(&instance->tds[i])) {
     153                if (transfer_descriptor_is_active(&instance->tds[i])) {
    173154                        return false;
    174155                }
    175 
    176                 instance->error = td_status(&instance->tds[i]);
     156                instance->error = transfer_descriptor_status(&instance->tds[i]);
    177157                if (instance->error != EOK) {
     158                        if (i > 0)
     159                                instance->transfered_size -= instance->setup_size;
    178160                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    179                             instance, i, instance->tds[i].status);
    180                         td_print_status(&instance->tds[i]);
    181 
    182                         device_keeper_set_toggle(instance->manager,
    183                             instance->target, td_toggle(&instance->tds[i]));
    184                         if (i > 0)
    185                                 goto substract_ret;
     161                          instance, i, instance->tds[i].status);
    186162                        return true;
    187163                }
    188 
    189                 instance->transfered_size += td_act_size(&instance->tds[i]);
    190                 if (td_is_short(&instance->tds[i]))
    191                         goto substract_ret;
    192         }
    193 substract_ret:
     164                instance->transfered_size +=
     165                    transfer_descriptor_actual_size(&instance->tds[i]);
     166        }
    194167        instance->transfered_size -= instance->setup_size;
    195168        return true;
    196169}
    197170/*----------------------------------------------------------------------------*/
    198 /** Prepares control write transaction.
    199  *
    200  * @param[in] instance Batch structure to use.
    201  *
    202  * Uses genercir control function with pids OUT and IN.
    203  */
    204171void batch_control_write(batch_t *instance)
    205172{
    206173        assert(instance);
    207         /* We are data out, we are supposed to provide data */
    208         memcpy(instance->transport_buffer, instance->buffer,
    209             instance->buffer_size);
     174        /* we are data out, we are supposed to provide data */
     175        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    210176        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    211177        instance->next_step = batch_call_out_and_dispose;
    212178        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    213 }
    214 /*----------------------------------------------------------------------------*/
    215 /** Prepares control read transaction.
    216  *
    217  * @param[in] instance Batch structure to use.
    218  *
    219  * Uses generic control with pids IN and OUT.
    220  */
     179        batch_schedule(instance);
     180}
     181/*----------------------------------------------------------------------------*/
    221182void batch_control_read(batch_t *instance)
    222183{
     
    225186        instance->next_step = batch_call_in_and_dispose;
    226187        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    227 }
    228 /*----------------------------------------------------------------------------*/
    229 /** Prepare interrupt in transaction.
    230  *
    231  * @param[in] instance Batch structure to use.
    232  *
    233  * Data transaction with PID_IN.
    234  */
     188        batch_schedule(instance);
     189}
     190/*----------------------------------------------------------------------------*/
    235191void batch_interrupt_in(batch_t *instance)
    236192{
    237193        assert(instance);
    238         batch_data(instance, USB_PID_IN);
     194
     195        const bool low_speed = instance->speed == USB_SPEED_LOW;
     196        int toggle = 1;
     197        size_t i = 0;
     198        for (;i < instance->packets; ++i) {
     199                char *data =
     200                    instance->transport_buffer + (i  * instance->max_packet_size);
     201                transfer_descriptor_t *next = (i + 1) < instance->packets ?
     202                    &instance->tds[i + 1] : NULL;
     203                toggle = 1 - toggle;
     204
     205                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     206                    instance->max_packet_size, toggle, false, low_speed,
     207                    instance->target, USB_PID_IN, data, next);
     208        }
     209
     210        instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     211
    239212        instance->next_step = batch_call_in_and_dispose;
    240213        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    241 }
    242 /*----------------------------------------------------------------------------*/
    243 /** Prepare interrupt out transaction.
    244  *
    245  * @param[in] instance Batch structure to use.
    246  *
    247  * Data transaction with PID_OUT.
    248  */
     214        batch_schedule(instance);
     215}
     216/*----------------------------------------------------------------------------*/
    249217void batch_interrupt_out(batch_t *instance)
    250218{
    251219        assert(instance);
    252         /* We are data out, we are supposed to provide data */
    253220        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    254         batch_data(instance, USB_PID_OUT);
     221
     222        const bool low_speed = instance->speed == USB_SPEED_LOW;
     223        int toggle = 1;
     224        size_t i = 0;
     225        for (;i < instance->packets; ++i) {
     226                char *data =
     227                    instance->transport_buffer + (i  * instance->max_packet_size);
     228                transfer_descriptor_t *next = (i + 1) < instance->packets ?
     229                    &instance->tds[i + 1] : NULL;
     230                toggle = 1 - toggle;
     231
     232                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     233                    instance->max_packet_size, toggle++, false, low_speed,
     234                    instance->target, USB_PID_OUT, data, next);
     235        }
     236
     237        instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     238
    255239        instance->next_step = batch_call_out_and_dispose;
    256240        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    257 }
    258 /*----------------------------------------------------------------------------*/
    259 /** Prepare bulk in transaction.
    260  *
    261  * @param[in] instance Batch structure to use.
    262  *
    263  * Data transaction with PID_IN.
    264  */
    265 void batch_bulk_in(batch_t *instance)
    266 {
    267         assert(instance);
    268         batch_data(instance, USB_PID_IN);
    269         instance->next_step = batch_call_in_and_dispose;
    270         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    271 }
    272 /*----------------------------------------------------------------------------*/
    273 /** Prepare bulk out transaction.
    274  *
    275  * @param[in] instance Batch structure to use.
    276  *
    277  * Data transaction with PID_OUT.
    278  */
    279 void batch_bulk_out(batch_t *instance)
    280 {
    281         assert(instance);
    282         /* We are data out, we are supposed to provide data */
    283         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    284         batch_data(instance, USB_PID_OUT);
    285         instance->next_step = batch_call_out_and_dispose;
    286         usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    287 }
    288 /*----------------------------------------------------------------------------*/
    289 /** Prepare generic data transaction
    290  *
    291  * @param[in] instance Batch structure to use.
    292  * @param[in] pid to use for data packets.
    293  *
    294  * Packets with alternating toggle bit and supplied pid value.
    295  * The last packet is marked with IOC flag.
    296  */
    297 void batch_data(batch_t *instance, usb_packet_id pid)
    298 {
    299         assert(instance);
    300         const bool low_speed = instance->speed == USB_SPEED_LOW;
    301         int toggle =
    302             device_keeper_get_toggle(instance->manager, instance->target);
    303         assert(toggle == 0 || toggle == 1);
    304 
    305         size_t packet = 0;
    306         size_t remain_size = instance->buffer_size;
    307         while (remain_size > 0) {
    308                 char *data =
    309                     instance->transport_buffer + instance->buffer_size
    310                     - remain_size;
    311 
    312                 const size_t packet_size =
    313                     (instance->max_packet_size > remain_size) ?
    314                     remain_size : instance->max_packet_size;
    315 
    316                 td_t *next_packet = (packet + 1 < instance->packets)
    317                     ? &instance->tds[packet + 1] : NULL;
    318 
    319                 assert(packet < instance->packets);
    320                 assert(packet_size <= remain_size);
    321 
    322                 td_init(
    323                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    324                     toggle, false, low_speed, instance->target, pid, data,
    325                     next_packet);
    326 
    327 
    328                 toggle = 1 - toggle;
    329                 remain_size -= packet_size;
    330                 ++packet;
    331         }
    332         td_set_ioc(&instance->tds[packet - 1]);
    333         device_keeper_set_toggle(instance->manager, instance->target, toggle);
    334 }
    335 /*----------------------------------------------------------------------------*/
    336 /** Prepare generic control transaction
    337  *
    338  * @param[in] instance Batch structure to use.
    339  * @param[in] data_stage to use for data packets.
    340  * @param[in] status_stage to use for data packets.
    341  *
    342  * Setup stage with toggle 0 and USB_PID_SETUP.
    343  * Data stage with alternating toggle and pid supplied by parameter.
    344  * Status stage with toggle 1 and pid supplied by parameter.
    345  * The last packet is marked with IOC.
    346  */
    347 void batch_control(batch_t *instance,
    348    usb_packet_id data_stage, usb_packet_id status_stage)
     241        batch_schedule(instance);
     242}
     243/*----------------------------------------------------------------------------*/
     244static void batch_control(
     245    batch_t *instance, int data_stage, int status_stage)
    349246{
    350247        assert(instance);
     
    353250        int toggle = 0;
    354251        /* setup stage */
    355         td_init(instance->tds, DEFAULT_ERROR_COUNT,
     252        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    356253            instance->setup_size, toggle, false, low_speed, instance->target,
    357254            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     
    371268                    remain_size : instance->max_packet_size;
    372269
    373                 td_init(
    374                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    375                     toggle, false, low_speed, instance->target, data_stage,
    376                     data, &instance->tds[packet + 1]);
     270                transfer_descriptor_init(&instance->tds[packet],
     271                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     272                    instance->target, data_stage, data,
     273                    &instance->tds[packet + 1]);
    377274
    378275                ++packet;
     
    384281        /* status stage */
    385282        assert(packet == instance->packets - 1);
    386         td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
     283        transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
    387284            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    388285
    389         td_set_ioc(&instance->tds[packet]);
     286
     287        instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    390288        usb_log_debug2("Control last TD status: %x.\n",
    391289            instance->tds[packet].status);
    392290}
    393291/*----------------------------------------------------------------------------*/
    394 /** Prepare data, get error status and call callback in.
    395  *
    396  * @param[in] instance Batch structure to use.
    397  * Copies data from transport buffer, and calls callback with appropriate
    398  * parameters.
    399  */
    400292void batch_call_in(batch_t *instance)
    401293{
     
    403295        assert(instance->callback_in);
    404296
    405         /* We are data in, we need data */
    406         memcpy(instance->buffer, instance->transport_buffer,
    407             instance->buffer_size);
     297        memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
    408298
    409299        int err = instance->error;
     
    412302            instance->transfered_size);
    413303
    414         instance->callback_in(
    415             instance->fun, err, instance->transfered_size, instance->arg);
    416 }
    417 /*----------------------------------------------------------------------------*/
    418 /** Get error status and call callback out.
    419  *
    420  * @param[in] instance Batch structure to use.
    421  */
     304        instance->callback_in(instance->fun,
     305            err, instance->transfered_size,
     306            instance->arg);
     307}
     308/*----------------------------------------------------------------------------*/
    422309void batch_call_out(batch_t *instance)
    423310{
     
    432319}
    433320/*----------------------------------------------------------------------------*/
    434 /** Helper function calls callback and correctly disposes of batch structure.
    435  *
    436  * @param[in] instance Batch structure to use.
    437  */
    438321void batch_call_in_and_dispose(batch_t *instance)
    439322{
    440323        assert(instance);
    441324        batch_call_in(instance);
    442         batch_dispose(instance);
    443 }
    444 /*----------------------------------------------------------------------------*/
    445 /** Helper function calls callback and correctly disposes of batch structure.
    446  *
    447  * @param[in] instance Batch structure to use.
    448  */
    449 void batch_call_out_and_dispose(batch_t *instance)
    450 {
    451         assert(instance);
    452         batch_call_out(instance);
    453         batch_dispose(instance);
    454 }
    455 /*----------------------------------------------------------------------------*/
    456 /** Correctly dispose all used data structures.
    457  *
    458  * @param[in] instance Batch structure to use.
    459  */
    460 void batch_dispose(batch_t *instance)
    461 {
    462         assert(instance);
    463325        usb_log_debug("Batch(%p) disposing.\n", instance);
    464         /* free32 is NULL safe */
    465326        free32(instance->tds);
    466327        free32(instance->qh);
     
    469330        free(instance);
    470331}
     332/*----------------------------------------------------------------------------*/
     333void batch_call_out_and_dispose(batch_t *instance)
     334{
     335        assert(instance);
     336        batch_call_out(instance);
     337        usb_log_debug("Batch(%p) disposing.\n", instance);
     338        free32(instance->tds);
     339        free32(instance->qh);
     340        free32(instance->setup_buffer);
     341        free32(instance->transport_buffer);
     342        free(instance);
     343}
     344/*----------------------------------------------------------------------------*/
     345int batch_schedule(batch_t *instance)
     346{
     347        assert(instance);
     348        uhci_t *hc = fun_to_uhci(instance->fun);
     349        assert(hc);
     350        return uhci_schedule(hc, instance);
     351}
    471352/**
    472353 * @}
  • uspace/drv/uhci-hcd/batch.h

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
     
    4242#include "uhci_struct/transfer_descriptor.h"
    4343#include "uhci_struct/queue_head.h"
    44 #include "utils/device_keeper.h"
    4544
    4645typedef struct batch
     
    5049        usb_target_t target;
    5150        usb_transfer_type_t transfer_type;
    52         usbhc_iface_transfer_in_callback_t callback_in;
    53         usbhc_iface_transfer_out_callback_t callback_out;
     51        union {
     52                usbhc_iface_transfer_in_callback_t callback_in;
     53                usbhc_iface_transfer_out_callback_t callback_out;
     54        };
    5455        void *arg;
    5556        char *transport_buffer;
     
    6364        int error;
    6465        ddf_fun_t *fun;
    65         qh_t *qh;
    66         td_t *tds;
     66        queue_head_t *qh;
     67        transfer_descriptor_t *tds;
    6768        void (*next_step)(struct batch*);
    68         device_keeper_t *manager;
    6969} batch_t;
    7070
     
    7474                char *setup_buffer, size_t setup_size,
    7575    usbhc_iface_transfer_in_callback_t func_in,
    76     usbhc_iface_transfer_out_callback_t func_out, void *arg,
    77                 device_keeper_t *manager
    78                 );
    79 
    80 void batch_dispose(batch_t *instance);
     76    usbhc_iface_transfer_out_callback_t func_out, void *arg);
    8177
    8278bool batch_is_complete(batch_t *instance);
     
    9086void batch_interrupt_out(batch_t *instance);
    9187
    92 void batch_bulk_in(batch_t *instance);
     88/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
     89void batch_control_setup_old(batch_t *instance);
    9390
    94 void batch_bulk_out(batch_t *instance);
     91void batch_control_write_data_old(batch_t *instance);
     92
     93void batch_control_read_data_old(batch_t *instance);
     94
     95void batch_control_write_status_old(batch_t *instance);
     96
     97void batch_control_read_status_old(batch_t *instance);
    9598#endif
    9699/**
  • uspace/drv/uhci-hcd/iface.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver hc interface implementation
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
     
    4040
    4141#include "iface.h"
    42 #include "uhci_hc.h"
     42#include "uhci.h"
    4343#include "utils/device_keeper.h"
    4444
    45 /** Reserve default address interface function
    46  *
    47  * @param[in] fun DDF function that was called.
    48  * @param[in] speed Speed to associate with the new default address.
    49  * @return Error code.
    50  */
    5145/*----------------------------------------------------------------------------*/
    5246static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    5347{
    5448        assert(fun);
    55         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     49        uhci_t *hc = fun_to_uhci(fun);
    5650        assert(hc);
    5751        usb_log_debug("Default address request with speed %d.\n", speed);
     
    6054}
    6155/*----------------------------------------------------------------------------*/
    62 /** Release default address interface function
    63  *
    64  * @param[in] fun DDF function that was called.
    65  * @return Error code.
    66  */
    6756static int release_default_address(ddf_fun_t *fun)
    6857{
    6958        assert(fun);
    70         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     59        uhci_t *hc = fun_to_uhci(fun);
    7160        assert(hc);
    7261        usb_log_debug("Default address release.\n");
     
    7564}
    7665/*----------------------------------------------------------------------------*/
    77 /** Request address interface function
    78  *
    79  * @param[in] fun DDF function that was called.
    80  * @param[in] speed Speed to associate with the new default address.
    81  * @param[out] address Place to write a new address.
    82  * @return Error code.
    83  */
    8466static int request_address(ddf_fun_t *fun, usb_speed_t speed,
    8567    usb_address_t *address)
    8668{
    8769        assert(fun);
    88         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     70        uhci_t *hc = fun_to_uhci(fun);
    8971        assert(hc);
    9072        assert(address);
     
    9880}
    9981/*----------------------------------------------------------------------------*/
    100 /** Bind address interface function
    101  *
    102  * @param[in] fun DDF function that was called.
    103  * @param[in] address Address of the device
    104  * @param[in] handle Devman handle of the device driver.
    105  * @return Error code.
    106  */
    10782static int bind_address(
    10883  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    10984{
    11085        assert(fun);
    111         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     86        uhci_t *hc = fun_to_uhci(fun);
    11287        assert(hc);
    11388        usb_log_debug("Address bind %d-%d.\n", address, handle);
     
    11691}
    11792/*----------------------------------------------------------------------------*/
    118 /** Release address interface function
    119  *
    120  * @param[in] fun DDF function that was called.
    121  * @param[in] address USB address to be released.
    122  * @return Error code.
    123  */
    12493static int release_address(ddf_fun_t *fun, usb_address_t address)
    12594{
    12695        assert(fun);
    127         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     96        uhci_t *hc = fun_to_uhci(fun);
    12897        assert(hc);
    12998        usb_log_debug("Address release %d.\n", address);
     
    132101}
    133102/*----------------------------------------------------------------------------*/
    134 /** Interrupt out transaction interface function
    135  *
    136  * @param[in] fun DDF function that was called.
    137  * @param[in] target USB device to write to.
    138  * @param[in] max_packet_size maximum size of data packet the device accepts
    139  * @param[in] data Source of data.
    140  * @param[in] size Size of data source.
    141  * @param[in] callback Function to call on transaction completion
    142  * @param[in] arg Additional for callback function.
    143  * @return Error code.
    144  */
    145103static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    146104    size_t max_packet_size, void *data, size_t size,
     
    148106{
    149107        assert(fun);
    150         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     108        uhci_t *hc = fun_to_uhci(fun);
    151109        assert(hc);
    152110        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    156114
    157115        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    158             max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
    159             &hc->device_manager);
     116            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
    160117        if (!batch)
    161118                return ENOMEM;
    162119        batch_interrupt_out(batch);
    163         const int ret = uhci_hc_schedule(hc, batch);
    164         if (ret != EOK) {
    165                 batch_dispose(batch);
    166                 return ret;
    167         }
    168         return EOK;
    169 }
    170 /*----------------------------------------------------------------------------*/
    171 /** Interrupt in transaction interface function
    172  *
    173  * @param[in] fun DDF function that was called.
    174  * @param[in] target USB device to write to.
    175  * @param[in] max_packet_size maximum size of data packet the device accepts
    176  * @param[out] data Data destination.
    177  * @param[in] size Size of data source.
    178  * @param[in] callback Function to call on transaction completion
    179  * @param[in] arg Additional for callback function.
    180  * @return Error code.
    181  */
     120        return EOK;
     121}
     122/*----------------------------------------------------------------------------*/
    182123static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    183124    size_t max_packet_size, void *data, size_t size,
     
    185126{
    186127        assert(fun);
    187         uhci_hc_t *hc = fun_to_uhci_hc(fun);
     128        uhci_t *hc = fun_to_uhci(fun);
    188129        assert(hc);
    189130        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     
    192133
    193134        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
    194             max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
    195                         &hc->device_manager);
     135            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
    196136        if (!batch)
    197137                return ENOMEM;
    198138        batch_interrupt_in(batch);
    199         const int ret = uhci_hc_schedule(hc, batch);
    200         if (ret != EOK) {
    201                 batch_dispose(batch);
    202                 return ret;
    203         }
    204         return EOK;
    205 }
    206 /*----------------------------------------------------------------------------*/
    207 /** Bulk out transaction interface function
    208  *
    209  * @param[in] fun DDF function that was called.
    210  * @param[in] target USB device to write to.
    211  * @param[in] max_packet_size maximum size of data packet the device accepts
    212  * @param[in] data Source of data.
    213  * @param[in] size Size of data source.
    214  * @param[in] callback Function to call on transaction completion
    215  * @param[in] arg Additional for callback function.
    216  * @return Error code.
    217  */
    218 static int bulk_out(ddf_fun_t *fun, usb_target_t target,
    219     size_t max_packet_size, void *data, size_t size,
    220     usbhc_iface_transfer_out_callback_t callback, void *arg)
    221 {
    222         assert(fun);
    223         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    224         assert(hc);
    225         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    226 
    227         usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
    228             target.address, target.endpoint, size, max_packet_size);
    229 
    230         batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
    231             max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
    232             &hc->device_manager);
    233         if (!batch)
    234                 return ENOMEM;
    235         batch_bulk_out(batch);
    236         const int ret = uhci_hc_schedule(hc, batch);
    237         if (ret != EOK) {
    238                 batch_dispose(batch);
    239                 return ret;
    240         }
    241         return EOK;
    242 }
    243 /*----------------------------------------------------------------------------*/
    244 /** Bulk in transaction interface function
    245  *
    246  * @param[in] fun DDF function that was called.
    247  * @param[in] target USB device to write to.
    248  * @param[in] max_packet_size maximum size of data packet the device accepts
    249  * @param[out] data Data destination.
    250  * @param[in] size Size of data source.
    251  * @param[in] callback Function to call on transaction completion
    252  * @param[in] arg Additional for callback function.
    253  * @return Error code.
    254  */
    255 static int bulk_in(ddf_fun_t *fun, usb_target_t target,
    256     size_t max_packet_size, void *data, size_t size,
    257     usbhc_iface_transfer_in_callback_t callback, void *arg)
    258 {
    259         assert(fun);
    260         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    261         assert(hc);
    262         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    263         usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
    264             target.address, target.endpoint, size, max_packet_size);
    265 
    266         batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
    267             max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
    268             &hc->device_manager);
    269         if (!batch)
    270                 return ENOMEM;
    271         batch_bulk_in(batch);
    272         const int ret = uhci_hc_schedule(hc, batch);
    273         if (ret != EOK) {
    274                 batch_dispose(batch);
    275                 return ret;
    276         }
    277         return EOK;
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 /** Control write transaction interface function
    281  *
    282  * @param[in] fun DDF function that was called.
    283  * @param[in] target USB device to write to.
    284  * @param[in] max_packet_size maximum size of data packet the device accepts.
    285  * @param[in] setup_data Data to send with SETUP packet.
    286  * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
    287  * @param[in] data Source of data.
    288  * @param[in] size Size of data source.
    289  * @param[in] callback Function to call on transaction completion.
    290  * @param[in] arg Additional for callback function.
    291  * @return Error code.
    292  */
     139        return EOK;
     140}
     141/*----------------------------------------------------------------------------*/
    293142static int control_write(ddf_fun_t *fun, usb_target_t target,
    294143    size_t max_packet_size,
     
    297146{
    298147        assert(fun);
    299         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    300         assert(hc);
    301         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    302         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    303             speed, target.address, target.endpoint, size, max_packet_size);
    304 
    305         if (setup_size != 8)
    306                 return EINVAL;
     148        uhci_t *hc = fun_to_uhci(fun);
     149        assert(hc);
     150        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     151        usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",
     152            target.address, target.endpoint, size, max_packet_size);
    307153
    308154        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    309155            max_packet_size, speed, data, size, setup_data, setup_size,
    310             NULL, callback, arg, &hc->device_manager);
    311         if (!batch)
    312                 return ENOMEM;
    313         device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
     156            NULL, callback, arg);
     157        if (!batch)
     158                return ENOMEM;
    314159        batch_control_write(batch);
    315         const int ret = uhci_hc_schedule(hc, batch);
    316         if (ret != EOK) {
    317                 batch_dispose(batch);
    318                 return ret;
    319         }
    320         return EOK;
    321 }
    322 /*----------------------------------------------------------------------------*/
    323 /** Control read transaction interface function
    324  *
    325  * @param[in] fun DDF function that was called.
    326  * @param[in] target USB device to write to.
    327  * @param[in] max_packet_size maximum size of data packet the device accepts.
    328  * @param[in] setup_data Data to send with SETUP packet.
    329  * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
    330  * @param[out] data Source of data.
    331  * @param[in] size Size of data source.
    332  * @param[in] callback Function to call on transaction completion.
    333  * @param[in] arg Additional for callback function.
    334  * @return Error code.
    335  */
     160        return EOK;
     161}
     162/*----------------------------------------------------------------------------*/
    336163static int control_read(ddf_fun_t *fun, usb_target_t target,
    337164    size_t max_packet_size,
     
    340167{
    341168        assert(fun);
    342         uhci_hc_t *hc = fun_to_uhci_hc(fun);
    343         assert(hc);
    344         usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
    345 
    346         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    347             speed, target.address, target.endpoint, size, max_packet_size);
     169        uhci_t *hc = fun_to_uhci(fun);
     170        assert(hc);
     171        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     172
     173        usb_log_debug("Control READ %d:%d %zu(%zu).\n",
     174            target.address, target.endpoint, size, max_packet_size);
    348175        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    349176            max_packet_size, speed, data, size, setup_data, setup_size, callback,
    350             NULL, arg, &hc->device_manager);
     177            NULL, arg);
    351178        if (!batch)
    352179                return ENOMEM;
    353180        batch_control_read(batch);
    354         const int ret = uhci_hc_schedule(hc, batch);
    355         if (ret != EOK) {
    356                 batch_dispose(batch);
    357                 return ret;
    358         }
    359         return EOK;
    360 }
    361 /*----------------------------------------------------------------------------*/
    362 usbhc_iface_t uhci_hc_iface = {
     181        return EOK;
     182}
     183
     184
     185/*----------------------------------------------------------------------------*/
     186usbhc_iface_t uhci_iface = {
    363187        .reserve_default_address = reserve_default_address,
    364188        .release_default_address = release_default_address,
     
    370194        .interrupt_in = interrupt_in,
    371195
    372         .bulk_in = bulk_in,
    373         .bulk_out = bulk_out,
    374 
    375196        .control_read = control_read,
    376197        .control_write = control_write,
  • uspace/drv/uhci-hcd/iface.h

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

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver initialization
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
     35#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
    3537#include <errno.h>
    3638#include <str_error.h>
    3739
     40#include <usb_iface.h>
    3841#include <usb/ddfiface.h>
    3942#include <usb/debug.h>
    4043
    4144#include "iface.h"
     45#include "pci.h"
     46#include "root_hub.h"
    4247#include "uhci.h"
    4348
     
    5560};
    5661/*----------------------------------------------------------------------------*/
    57 /** Initialize a new ddf driver instance for uhci hc and hub.
    58  *
    59  * @param[in] device DDF instance of the device to initialize.
    60  * @return Error code.
    61  */
    62 int uhci_add_device(ddf_dev_t *device)
     62static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    6363{
    64         usb_log_info("uhci_add_device() called\n");
    65         assert(device);
    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         }
    71 
    72         int ret = uhci_init(uhci, device);
    73         if (ret != EOK) {
    74                 usb_log_error("Failed to initialzie UHCI driver.\n");
    75                 return ret;
    76         }
    77         device->driver_data = uhci;
    78         return EOK;
     64        assert(dev);
     65        uhci_t *hc = dev_to_uhci(dev);
     66        uint16_t status = IPC_GET_ARG1(*call);
     67        assert(hc);
     68        uhci_interrupt(hc, status);
    7969}
    8070/*----------------------------------------------------------------------------*/
    81 /** Initialize global driver structures (NONE).
    82  *
    83  * @param[in] argc Nmber of arguments in argv vector (ignored).
    84  * @param[in] argv Cmdline argument vector (ignored).
    85  * @return Error code.
    86  *
    87  * Driver debug level is set here.
    88  */
     71static int uhci_add_device(ddf_dev_t *device)
     72{
     73        assert(device);
     74        uhci_t *hcd = NULL;
     75#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
     76if (ret != EOK) { \
     77        usb_log_error(message); \
     78        if (hcd != NULL) \
     79                free(hcd); \
     80        return ret; \
     81}
     82
     83        usb_log_info("uhci_add_device() called\n");
     84
     85        uintptr_t io_reg_base = 0;
     86        size_t io_reg_size = 0;
     87        int irq = 0;
     88
     89        int ret =
     90            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     91        CHECK_RET_FREE_HC_RETURN(ret,
     92            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
     93        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
     94            io_reg_base, io_reg_size, irq);
     95
     96        ret = pci_disable_legacy(device);
     97        CHECK_RET_FREE_HC_RETURN(ret,
     98            "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
     99
     100#if 0
     101        ret = pci_enable_interrupts(device);
     102        if (ret != EOK) {
     103                usb_log_warning(
     104                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     105                    ret);
     106        }
     107#endif
     108
     109        hcd = malloc(sizeof(uhci_t));
     110        ret = (hcd != NULL) ? EOK : ENOMEM;
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
     113
     114        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     115        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n",
     116            ret);
     117#undef CHECK_RET_FREE_HC_RETURN
     118
     119        /*
     120         * We might free hcd, but that does not matter since no one
     121         * else would access driver_data anyway.
     122         */
     123        device->driver_data = hcd;
     124
     125        ddf_fun_t *rh = NULL;
     126#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     127if (ret != EOK) { \
     128        usb_log_error(message); \
     129        if (hcd != NULL) {\
     130                uhci_fini(hcd); \
     131                free(hcd); \
     132        } \
     133        if (rh != NULL) \
     134                free(rh); \
     135        return ret; \
     136}
     137
     138        /* It does no harm if we register this on polling */
     139        ret = register_interrupt_handler(device, irq, irq_handler,
     140            &hcd->interrupt_code);
     141        CHECK_RET_FINI_FREE_RETURN(ret,
     142            "Failed(%d) to register interrupt handler.\n", ret);
     143
     144        ret = setup_root_hub(&rh, device);
     145        CHECK_RET_FINI_FREE_RETURN(ret,
     146            "Failed(%d) to setup UHCI root hub.\n", ret);
     147        rh->driver_data = hcd->ddf_instance;
     148
     149        ret = ddf_fun_bind(rh);
     150        CHECK_RET_FINI_FREE_RETURN(ret,
     151            "Failed(%d) to register UHCI root hub.\n", ret);
     152
     153        return EOK;
     154#undef CHECK_RET_FINI_FREE_RETURN
     155}
     156/*----------------------------------------------------------------------------*/
    89157int main(int argc, char *argv[])
    90158{
    91         sleep(3); /* TODO: remove in final version */
     159        sleep(3);
    92160        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    93161
  • uspace/drv/uhci-hcd/pci.c

    r72af8da r3e7b7cd  
    2727 */
    2828/**
    29  * @addtogroup drvusbuhcihc
     29 * @addtogroup drvusbuhci
    3030 * @{
    3131 */
     
    6565
    6666        int rc;
     67
    6768        hw_resource_list_t hw_resources;
    6869        rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     
    8182        for (i = 0; i < hw_resources.count; i++) {
    8283                hw_resource_t *res = &hw_resources.resources[i];
    83                 switch (res->type)
    84                 {
    85                 case INTERRUPT:
    86                         irq = res->res.interrupt.irq;
    87                         irq_found = true;
    88                         usb_log_debug2("Found interrupt: %d.\n", irq);
    89                         break;
    90 
    91                 case IO_RANGE:
    92                         io_address = res->res.io_range.address;
    93                         io_size = res->res.io_range.size;
    94                         usb_log_debug2("Found io: %llx %zu.\n",
    95                             res->res.io_range.address, res->res.io_range.size);
    96                         io_found = true;
    97 
    98                 default:
    99                         break;
     84                switch (res->type) {
     85                        case INTERRUPT:
     86                                irq = res->res.interrupt.irq;
     87                                irq_found = true;
     88                                usb_log_debug2("Found interrupt: %d.\n", irq);
     89                                break;
     90                        case IO_RANGE:
     91                                io_address = res->res.io_range.address;
     92                                io_size = res->res.io_range.size;
     93                                usb_log_debug2("Found io: %llx %zu.\n",
     94                                    res->res.io_range.address, res->res.io_range.size);
     95                                io_found = true;
     96                                break;
     97                        default:
     98                                break;
    10099                }
    101100        }
    102101
    103         if (!io_found || !irq_found) {
     102        if (!io_found) {
     103                rc = ENOENT;
     104                goto leave;
     105        }
     106
     107        if (!irq_found) {
    104108                rc = ENOENT;
    105109                goto leave;
     
    117121}
    118122/*----------------------------------------------------------------------------*/
    119 /** Call the PCI driver with a request to enable interrupts
    120  *
    121  * @param[in] device Device asking for interrupts
    122  * @return Error code.
    123  */
    124123int pci_enable_interrupts(ddf_dev_t *device)
    125124{
     
    131130}
    132131/*----------------------------------------------------------------------------*/
    133 /** Call the PCI driver with a request to clear legacy support register
    134  *
    135  * @param[in] device Device asking to disable interrupts
    136  * @return Error code.
    137  */
    138132int pci_disable_legacy(ddf_dev_t *device)
    139133{
    140134        assert(device);
    141         int parent_phone =
    142             devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
     135        int parent_phone = devman_parent_device_connect(device->handle,
     136                IPC_FLAG_BLOCKING);
    143137        if (parent_phone < 0) {
    144138                return parent_phone;
     
    150144        sysarg_t value = 0x8f00;
    151145
    152         int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     146  int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    153147            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
    154148        async_hangup(parent_phone);
    155149
    156         return rc;
     150  return rc;
    157151}
    158152/*----------------------------------------------------------------------------*/
  • uspace/drv/uhci-hcd/pci.h

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

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver transfer list implementation
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     35
    3536#include <usb/debug.h>
    3637
    3738#include "transfer_list.h"
    3839
    39 static void transfer_list_remove_batch(
    40     transfer_list_t *instance, batch_t *batch);
    41 /*----------------------------------------------------------------------------*/
    42 /** Initialize transfer list structures.
    43  *
    44  * @param[in] instance Memory place to use.
    45  * @param[in] name Name of the new list.
    46  * @return Error code
    47  *
    48  * Allocates memory for internal qh_t structure.
    49  */
    5040int transfer_list_init(transfer_list_t *instance, const char *name)
    5141{
    5242        assert(instance);
     43        instance->next = NULL;
    5344        instance->name = name;
    54         instance->queue_head = malloc32(sizeof(qh_t));
     45        instance->queue_head = queue_head_get();
    5546        if (!instance->queue_head) {
    5647                usb_log_error("Failed to allocate queue head.\n");
    5748                return ENOMEM;
    5849        }
    59         instance->queue_head_pa = addr_to_phys(instance->queue_head);
     50        instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
    6051
    61         qh_init(instance->queue_head);
     52        queue_head_init(instance->queue_head);
    6253        list_initialize(&instance->batch_list);
    6354        fibril_mutex_initialize(&instance->guard);
     
    6556}
    6657/*----------------------------------------------------------------------------*/
    67 /** Set the next list in transfer list chain.
    68  *
    69  * @param[in] instance List to lead.
    70  * @param[in] next List to append.
    71  * @return Error code
    72  *
    73  * Does not check whether this replaces an existing list .
    74  */
    7558void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
    7659{
     
    7962        if (!instance->queue_head)
    8063                return;
    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);
     64        queue_head_append_qh(instance->queue_head, next->queue_head_pa);
     65        instance->queue_head->element = instance->queue_head->next_queue;
    8466}
    8567/*----------------------------------------------------------------------------*/
    86 /** Submit transfer batch to the list and queue.
    87  *
    88  * @param[in] instance List to use.
    89  * @param[in] batch Transfer batch to submit.
    90  * @return Error code
    91  *
    92  * The batch is added to the end of the list and queue.
    93  */
    9468void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
    9569{
    9670        assert(instance);
    9771        assert(batch);
    98         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     72        usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
    9973
    100         const uint32_t pa = addr_to_phys(batch->qh);
     74        uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
    10175        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
     76        pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    10277
    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, instance->queue_head->next);
     78        batch->qh->next_queue = instance->queue_head->next_queue;
    10679
    10780        fibril_mutex_lock(&instance->guard);
    10881
    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(last->qh, pa);
     82        if (instance->queue_head->element == instance->queue_head->next_queue) {
     83                /* there is nothing scheduled */
     84                list_append(&batch->link, &instance->batch_list);
     85                instance->queue_head->element = pa;
     86                usb_log_debug("Batch(%p) added to queue %s first.\n",
     87                        batch, instance->name);
     88                fibril_mutex_unlock(&instance->guard);
     89                return;
    12090        }
    121         /* Add to the driver list */
     91        /* now we can be sure that there is someting scheduled */
     92        assert(!list_empty(&instance->batch_list));
     93        batch_t *first = list_get_instance(
     94                  instance->batch_list.next, batch_t, link);
     95        batch_t *last = list_get_instance(
     96            instance->batch_list.prev, batch_t, link);
     97        queue_head_append_qh(last->qh, pa);
    12298        list_append(&batch->link, &instance->batch_list);
    123 
    124         batch_t *first = list_get_instance(
    125             instance->batch_list.next, batch_t, link);
    126         usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
    127                 batch, instance->name, first);
     99        usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
     100                batch, instance->name, first );
    128101        fibril_mutex_unlock(&instance->guard);
    129102}
    130103/*----------------------------------------------------------------------------*/
    131 /** Remove a transfer batch from the list and queue.
    132  *
    133  * @param[in] instance List to use.
    134  * @param[in] batch Transfer batch to remove.
    135  * @return Error code
    136  *
    137  * Does not lock the transfer list, caller is responsible for that.
    138  */
    139 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
     104static void transfer_list_remove_batch(
     105    transfer_list_t *instance, batch_t *batch)
    140106{
    141107        assert(instance);
     
    143109        assert(instance->queue_head);
    144110        assert(batch->qh);
    145         usb_log_debug2(
    146             "Queue %s: removing batch(%p).\n", instance->name, batch);
     111        usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
    147112
    148         const char * pos = NULL;
    149         /* Remove from the hardware queue */
     113        /* I'm the first one here */
    150114        if (batch->link.prev == &instance->batch_list) {
    151                 /* I'm the first one here */
    152                 qh_set_element_qh(instance->queue_head, batch->qh->next);
    153                 pos = "FIRST";
     115                usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
     116                        batch, instance->name, batch->qh->next_queue);
     117                instance->queue_head->element = batch->qh->next_queue;
    154118        } else {
    155                 batch_t *prev =
    156                     list_get_instance(batch->link.prev, batch_t, link);
    157                 qh_set_next_qh(prev->qh, batch->qh->next);
    158                 pos = "NOT FIRST";
     119                usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
     120                        batch, instance->name, batch->qh->next_queue);
     121                batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
     122                prev->qh->next_queue = batch->qh->next_queue;
    159123        }
    160         /* Remove from the driver list */
    161124        list_remove(&batch->link);
    162         usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
    163             batch, pos, instance->name, batch->qh->next);
    164125}
    165126/*----------------------------------------------------------------------------*/
    166 /** Check list for finished batches.
    167  *
    168  * @param[in] instance List to use.
    169  * @return Error code
    170  *
    171  * Creates a local list of finished batches and calls next_step on each and
    172  * every one. This is safer because next_step may theoretically access
    173  * this transfer list leading to the deadlock if its done inline.
    174  */
    175127void transfer_list_remove_finished(transfer_list_t *instance)
    176128{
     
    186138
    187139                if (batch_is_complete(batch)) {
    188                         /* Save for post-processing */
    189140                        transfer_list_remove_batch(instance, batch);
    190141                        list_append(current, &done);
  • uspace/drv/uhci-hcd/transfer_list.h

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver transfer list structure
     32 * @brief UHCI driver
    3333 */
    3434#ifndef DRV_UHCI_TRANSFER_LIST_H
     
    4444{
    4545        fibril_mutex_t guard;
    46         qh_t *queue_head;
     46        queue_head_t *queue_head;
    4747        uint32_t queue_head_pa;
     48        struct transfer_list *next;
    4849        const char *name;
    4950        link_t batch_list;
    5051} 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  */
    58 static inline void transfer_list_fini(transfer_list_t *instance)
    59 {
    60         assert(instance);
    61         free32(instance->queue_head);
    62 }
    6352
    6453int transfer_list_init(transfer_list_t *instance, const char *name);
     
    6655void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    6756
     57static inline void transfer_list_fini(transfer_list_t *instance)
     58{
     59        assert(instance);
     60        queue_head_dispose(instance->queue_head);
     61}
    6862void transfer_list_remove_finished(transfer_list_t *instance);
    6963
  • uspace/drv/uhci-hcd/uhci.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    29 /** @addtogroup drvusbuhci
     28/** @addtogroup usb
    3029 * @{
    3130 */
     
    3534#include <errno.h>
    3635#include <str_error.h>
    37 #include <ddf/interrupt.h>
     36#include <adt/list.h>
     37#include <libarch/ddi.h>
     38
     39#include <usb/debug.h>
     40#include <usb/usb.h>
     41#include <usb/ddfiface.h>
    3842#include <usb_iface.h>
    39 #include <usb/ddfiface.h>
    40 #include <usb/debug.h>
    4143
    4244#include "uhci.h"
    4345#include "iface.h"
    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  */
    53 static 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);
     46
     47static 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
     63static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
     64    usb_address_t *address)
     65{
     66        assert(fun);
     67        uhci_t *hc = fun_to_uhci(fun);
    5868        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.
    67  */
    68 static int usb_iface_get_address(
    69     ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    70 {
    71         assert(fun);
    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);
     69
     70        usb_address_t addr = device_keeper_find(&hc->device_manager,
     71            handle);
    7572        if (addr < 0) {
    7673                return addr;
     
    8481}
    8582/*----------------------------------------------------------------------------*/
    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  */
    92 static 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. */
    104 static usb_iface_t usb_iface = {
    105         .get_hc_handle = usb_iface_get_hc_handle,
     83static usb_iface_t hc_usb_iface = {
     84        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
    10685        .get_address = usb_iface_get_address
    10786};
    10887/*----------------------------------------------------------------------------*/
    109 static 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 */
     88static ddf_dev_ops_t uhci_ops = {
     89        .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
     90        .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    11291};
    11392/*----------------------------------------------------------------------------*/
    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  */
    119 static 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 /*----------------------------------------------------------------------------*/
    125 static hw_res_ops_t hw_res_iface = {
    126         .get_resource_list = get_resource_list,
    127         .enable_interrupt = NULL
    128 };
    129 /*----------------------------------------------------------------------------*/
    130 static 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  */
    146 int uhci_init(uhci_t *instance, ddf_dev_t *device)
    147 {
    148         assert(instance);
    149         instance->hc_fun = NULL;
    150         instance->rh_fun = NULL;
     93static int uhci_init_transfer_lists(uhci_t *instance);
     94static int uhci_init_mem_structures(uhci_t *instance);
     95static void uhci_init_hw(uhci_t *instance);
     96
     97static int uhci_interrupt_emulator(void *arg);
     98static int uhci_debug_checker(void *arg);
     99
     100static bool allowed_usb_packet(
     101        bool low_speed, usb_transfer_type_t, size_t size);
     102
     103
     104int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
     105{
     106        assert(reg_size >= sizeof(regs_t));
     107        int ret;
     108
    151109#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
    152 if (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);
     110        if (ret != EOK) { \
     111                usb_log_error(message); \
     112                if (instance->ddf_instance) \
     113                        ddf_fun_destroy(instance->ddf_instance); \
     114                return ret; \
     115        } else (void) 0
     116
     117        /* Create UHCI function. */
     118        instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
     119        ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    167120        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);
     121            "Failed to create UHCI device function.\n");
     122
     123        instance->ddf_instance->ops = &uhci_ops;
     124        instance->ddf_instance->driver_data = instance;
     125
     126        ret = ddf_fun_bind(instance->ddf_instance);
    198127        CHECK_RET_DEST_FUN_RETURN(ret,
    199128            "Failed(%d) to bind UHCI device function: %s.\n",
    200129            ret, str_error(ret));
    201 #undef CHECK_RET_HC_RETURN
    202 
    203 #define CHECK_RET_FINI_RETURN(ret, message...) \
    204 if (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 
    236         return EOK;
    237 #undef CHECK_RET_FINI_RETURN
     130
     131        /* allow access to hc control registers */
     132        regs_t *io;
     133        ret = pio_enable(regs, reg_size, (void**)&io);
     134        CHECK_RET_DEST_FUN_RETURN(ret,
     135            "Failed(%d) to gain access to registers at %p: %s.\n",
     136            ret, str_error(ret), io);
     137        instance->registers = io;
     138        usb_log_debug("Device registers at %p(%u) accessible.\n",
     139            io, reg_size);
     140
     141        ret = uhci_init_mem_structures(instance);
     142        CHECK_RET_DEST_FUN_RETURN(ret,
     143            "Failed to initialize UHCI memory structures.\n");
     144
     145        uhci_init_hw(instance);
     146        instance->cleaner =
     147            fibril_create(uhci_interrupt_emulator, instance);
     148        fibril_add_ready(instance->cleaner);
     149
     150        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
     151        fibril_add_ready(instance->debug_checker);
     152
     153        usb_log_info("Started UHCI driver.\n");
     154        return EOK;
     155#undef CHECK_RET_DEST_FUN_RETURN
     156}
     157/*----------------------------------------------------------------------------*/
     158void uhci_init_hw(uhci_t *instance)
     159{
     160        assert(instance);
     161
     162        /* reset everything, who knows what touched it before us */
     163        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     164        async_usleep(10000); /* 10ms according to USB spec */
     165        pio_write_16(&instance->registers->usbcmd, 0);
     166
     167        /* reset hc, all states and counters */
     168        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
     169        while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
     170                { async_usleep(10); }
     171
     172        /* set framelist pointer */
     173        const uint32_t pa = addr_to_phys(instance->frame_list);
     174        pio_write_32(&instance->registers->flbaseadd, pa);
     175
     176        /* enable all interrupts, but resume interrupt */
     177        pio_write_16(&instance->registers->usbintr,
     178            UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     179
     180        /* Start the hc with large(64B) packet FSBR */
     181        pio_write_16(&instance->registers->usbcmd,
     182            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
     183}
     184/*----------------------------------------------------------------------------*/
     185int uhci_init_mem_structures(uhci_t *instance)
     186{
     187        assert(instance);
     188#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
     189        if (ret != EOK) { \
     190                usb_log_error(message); \
     191                if (instance->interrupt_code.cmds != NULL) \
     192                        free(instance->interrupt_code.cmds); \
     193                return ret; \
     194        } else (void) 0
     195
     196        /* init interrupt code */
     197        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
     198        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
     199        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
     200
     201        {
     202                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
     203                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     204                interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
     205                interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     206                instance->interrupt_code.cmdcount =
     207                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     208        }
     209
     210        /* init transfer lists */
     211        ret = uhci_init_transfer_lists(instance);
     212        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
     213        usb_log_debug("Initialized transfer lists.\n");
     214
     215        /* frame list initialization */
     216        instance->frame_list = get_page();
     217        ret = instance ? EOK : ENOMEM;
     218        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
     219        usb_log_debug("Initialized frame list.\n");
     220
     221        /* initialize all frames to point to the first queue head */
     222        const uint32_t queue =
     223          instance->transfers_interrupt.queue_head_pa
     224          | LINK_POINTER_QUEUE_HEAD_FLAG;
     225
     226        unsigned i = 0;
     227        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     228                instance->frame_list[i] = queue;
     229        }
     230
     231        /* init address keeper(libusb) */
     232        device_keeper_init(&instance->device_manager);
     233        usb_log_debug("Initialized device manager.\n");
     234
     235        return EOK;
     236#undef CHECK_RET_DEST_CMDS_RETURN
     237}
     238/*----------------------------------------------------------------------------*/
     239int uhci_init_transfer_lists(uhci_t *instance)
     240{
     241        assert(instance);
     242#define CHECK_RET_CLEAR_RETURN(ret, message...) \
     243        if (ret != EOK) { \
     244                usb_log_error(message); \
     245                transfer_list_fini(&instance->transfers_bulk_full); \
     246                transfer_list_fini(&instance->transfers_control_full); \
     247                transfer_list_fini(&instance->transfers_control_slow); \
     248                transfer_list_fini(&instance->transfers_interrupt); \
     249                return ret; \
     250        } else (void) 0
     251
     252        /* initialize TODO: check errors */
     253        int ret;
     254        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     255        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
     256
     257        ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
     258        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
     259
     260        ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
     261        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     262
     263        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
     264        CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
     265
     266        transfer_list_set_next(&instance->transfers_control_full,
     267                &instance->transfers_bulk_full);
     268        transfer_list_set_next(&instance->transfers_control_slow,
     269                &instance->transfers_control_full);
     270        transfer_list_set_next(&instance->transfers_interrupt,
     271                &instance->transfers_control_slow);
     272
     273        /*FSBR*/
     274#ifdef FSBR
     275        transfer_list_set_next(&instance->transfers_bulk_full,
     276                &instance->transfers_control_full);
     277#endif
     278
     279        instance->transfers[0][USB_TRANSFER_INTERRUPT] =
     280          &instance->transfers_interrupt;
     281        instance->transfers[1][USB_TRANSFER_INTERRUPT] =
     282          &instance->transfers_interrupt;
     283        instance->transfers[0][USB_TRANSFER_CONTROL] =
     284          &instance->transfers_control_full;
     285        instance->transfers[1][USB_TRANSFER_CONTROL] =
     286          &instance->transfers_control_slow;
     287        instance->transfers[0][USB_TRANSFER_BULK] =
     288          &instance->transfers_bulk_full;
     289
     290        return EOK;
     291#undef CHECK_RET_CLEAR_RETURN
     292}
     293/*----------------------------------------------------------------------------*/
     294int uhci_schedule(uhci_t *instance, batch_t *batch)
     295{
     296        assert(instance);
     297        assert(batch);
     298        const int low_speed = (batch->speed == USB_SPEED_LOW);
     299        if (!allowed_usb_packet(
     300            low_speed, batch->transfer_type, batch->max_packet_size)) {
     301                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
     302                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
     303                    batch->max_packet_size);
     304                return ENOTSUP;
     305        }
     306        /* TODO: check available bandwith here */
     307
     308        transfer_list_t *list =
     309            instance->transfers[low_speed][batch->transfer_type];
     310        assert(list);
     311        transfer_list_add_batch(list, batch);
     312
     313        return EOK;
     314}
     315/*----------------------------------------------------------------------------*/
     316void uhci_interrupt(uhci_t *instance, uint16_t status)
     317{
     318        assert(instance);
     319        transfer_list_remove_finished(&instance->transfers_interrupt);
     320        transfer_list_remove_finished(&instance->transfers_control_slow);
     321        transfer_list_remove_finished(&instance->transfers_control_full);
     322        transfer_list_remove_finished(&instance->transfers_bulk_full);
     323}
     324/*----------------------------------------------------------------------------*/
     325int uhci_interrupt_emulator(void* arg)
     326{
     327        usb_log_debug("Started interrupt emulator.\n");
     328        uhci_t *instance = (uhci_t*)arg;
     329        assert(instance);
     330
     331        while (1) {
     332                uint16_t status = pio_read_16(&instance->registers->usbsts);
     333                if (status != 0)
     334                        usb_log_debug2("UHCI status: %x.\n", status);
     335                status |= 1;
     336                uhci_interrupt(instance, status);
     337                pio_write_16(&instance->registers->usbsts, 0x1f);
     338                async_usleep(UHCI_CLEANER_TIMEOUT * 5);
     339        }
     340        return EOK;
     341}
     342/*---------------------------------------------------------------------------*/
     343int uhci_debug_checker(void *arg)
     344{
     345        uhci_t *instance = (uhci_t*)arg;
     346        assert(instance);
     347
     348#define QH(queue) \
     349        instance->transfers_##queue.queue_head
     350
     351        while (1) {
     352                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
     353                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
     354                const uint16_t intr =
     355                    pio_read_16(&instance->registers->usbintr);
     356
     357                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
     358                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
     359                            cmd, sts, intr);
     360                }
     361
     362                uintptr_t frame_list =
     363                    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
     364                if (frame_list != addr_to_phys(instance->frame_list)) {
     365                        usb_log_debug("Framelist address: %p vs. %p.\n",
     366                            frame_list, addr_to_phys(instance->frame_list));
     367                }
     368
     369                int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
     370                usb_log_debug2("Framelist item: %d \n", frnum );
     371
     372                uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
     373                uintptr_t real_pa = addr_to_phys(QH(interrupt));
     374                if (expected_pa != real_pa) {
     375                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
     376                            expected_pa, real_pa);
     377                }
     378
     379                expected_pa = QH(interrupt)->next_queue & (~0xf);
     380                real_pa = addr_to_phys(QH(control_slow));
     381                if (expected_pa != real_pa) {
     382                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
     383                            expected_pa, real_pa);
     384                }
     385
     386                expected_pa = QH(control_slow)->next_queue & (~0xf);
     387                real_pa = addr_to_phys(QH(control_full));
     388                if (expected_pa != real_pa) {
     389                        usb_log_debug("Control Full QH: %p vs. %p.\n",
     390                            expected_pa, real_pa);
     391                }
     392
     393                expected_pa = QH(control_full)->next_queue & (~0xf);
     394                real_pa = addr_to_phys(QH(bulk_full));
     395                if (expected_pa != real_pa ) {
     396                        usb_log_debug("Bulk QH: %p vs. %p.\n",
     397                            expected_pa, real_pa);
     398                }
     399                async_usleep(UHCI_DEBUGER_TIMEOUT);
     400        }
     401        return 0;
     402#undef QH
     403}
     404/*----------------------------------------------------------------------------*/
     405bool allowed_usb_packet(
     406    bool low_speed, usb_transfer_type_t transfer, size_t size)
     407{
     408        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
     409        switch(transfer)
     410        {
     411        case USB_TRANSFER_ISOCHRONOUS:
     412                return (!low_speed && size < 1024);
     413        case USB_TRANSFER_INTERRUPT:
     414                return size <= (low_speed ? 8 : 64);
     415        case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     416                return (size <= (low_speed ? 8 : 64));
     417        case USB_TRANSFER_BULK: /* device specifies its own max size */
     418                return (!low_speed && size <= 64);
     419        }
     420        return false;
    238421}
    239422/**
  • uspace/drv/uhci-hcd/uhci.h

    r72af8da r3e7b7cd  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  * @brief UHCI driver main structure for both host controller and root-hub.
     33 * @brief UHCI driver
    3434 */
    3535#ifndef DRV_UHCI_UHCI_H
    3636#define DRV_UHCI_UHCI_H
     37
     38#include <fibril.h>
     39#include <fibril_synch.h>
     40#include <adt/list.h>
    3741#include <ddi.h>
    38 #include <ddf/driver.h>
    3942
    40 #include "uhci_hc.h"
    41 #include "uhci_rh.h"
     43#include <usbhc_iface.h>
     44
     45#include "batch.h"
     46#include "transfer_list.h"
     47#include "utils/device_keeper.h"
     48
     49typedef 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
    4282
    4383typedef struct uhci {
    44         ddf_fun_t *hc_fun;
    45         ddf_fun_t *rh_fun;
     84        device_keeper_t device_manager;
    4685
    47         uhci_hc_t hc;
    48         uhci_rh_t rh;
     86        volatile 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;
    49103} uhci_t;
    50104
    51 int uhci_init(uhci_t *instance, ddf_dev_t *device);
     105/* init uhci specifics in device.driver_data */
     106int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size);
     107
     108static inline void uhci_fini(uhci_t *instance) {};
     109
     110int uhci_schedule(uhci_t *instance, batch_t *batch);
     111
     112void uhci_interrupt(uhci_t *instance, uint16_t status);
     113
     114static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
     115        { return (uhci_t*)dev->driver_data; }
     116
     117static inline uhci_t * fun_to_uhci(ddf_fun_t *fun)
     118        { return (uhci_t*)fun->driver_data; }
     119
    52120
    53121#endif
  • uspace/drv/uhci-hcd/uhci_struct/link_pointer.h

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    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 
    5148#endif
    5249/**
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    r72af8da r3e7b7cd  
     1
    12/*
    23 * Copyright (c) 2010 Jan Vesely
     
    2627 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2728 */
    28 /** @addtogroup drv usbuhcihc
     29/** @addtogroup usb
    2930 * @{
    3031 */
     
    4243
    4344typedef struct queue_head {
    44         volatile link_pointer_t next;
     45        volatile link_pointer_t next_queue;
    4546        volatile link_pointer_t element;
    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  */
    54 static inline void qh_init(qh_t *instance)
     47} __attribute__((packed)) queue_head_t;
     48
     49static inline void queue_head_init(queue_head_t *instance)
    5550{
    5651        assert(instance);
    5752
    5853        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    59         instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
     54        instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
    6055}
    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  */
    70 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
     56
     57static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
    7158{
    72         /* Address is valid and not terminal */
    73         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    74                 instance->next = (pa & LINK_POINTER_ADDRESS_MASK)
     59        if (pa) {
     60                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
    7561                    | LINK_POINTER_QUEUE_HEAD_FLAG;
    76         } else {
    77                 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    7862        }
    7963}
    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  */
    89 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
     64
     65static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
    9066{
    91         /* Address is valid and not terminal */
    92         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    93                 instance->element = (pa & LINK_POINTER_ADDRESS_MASK)
     67        if (pa) {
     68                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
    9469                    | LINK_POINTER_QUEUE_HEAD_FLAG;
    95         } else {
    96                 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    9770        }
    9871}
    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  */
    108 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
     72
     73static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
    10974{
    110         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     75        if (pa) {
    11176                instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
    112         } else {
    113                 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
    11477        }
    11578}
     79
     80static inline queue_head_t * queue_head_get() {
     81        queue_head_t *ret = malloc32(sizeof(queue_head_t));
     82        if (ret)
     83                queue_head_init(ret);
     84        return ret;
     85}
     86
     87static inline void queue_head_dispose(queue_head_t *head)
     88        { free32(head); }
     89
    11690
    11791#endif
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    3838#include "utils/malloc32.h"
    3939
    40 /** Initialize Transfer Descriptor
    41  *
    42  * @param[in] instance Memory place to initialize.
    43  * @param[in] err_count Number of retries hc should attempt.
    44  * @param[in] size Size of data source.
    45  * @param[in] toggle Value of toggle bit.
    46  * @param[in] iso True if TD represents Isochronous transfer.
    47  * @param[in] low_speed Target device's speed.
    48  * @param[in] target Address and endpoint receiving the transfer.
    49  * @param[in] pid Packet identification (SETUP, IN or OUT).
    50  * @param[in] buffer Source of data.
    51  * @param[in] next Net TD in transaction.
    52  * @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.
    61  */
    62 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
    63     bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
    64     td_t *next)
     40void transfer_descriptor_init(transfer_descriptor_t *instance,
     41    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
     42    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
    6543{
    6644        assert(instance);
    67         assert(size < 1024);
    68         assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
    69             || (pid == USB_PID_OUT));
    7045
    7146        instance->next = 0
     
    7449
    7550        instance->status = 0
    76             | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
    77             | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    78             | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
    79             | TD_STATUS_ERROR_ACTIVE;
     51          | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     52                | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
     53          | TD_STATUS_ERROR_ACTIVE;
    8054
    81         if (pid == USB_PID_IN && !iso) {
    82                 instance->status |= TD_STATUS_SPD_FLAG;
    83         }
    84 
     55        assert(size < 1024);
    8556        instance->device = 0
    86             | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
    87             | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    88             | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    89             | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
    90             | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
     57                | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
     58                | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
     59                | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
     60                | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     61                | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    9162
    9263        instance->buffer_ptr = 0;
     
    9667        }
    9768
    98         usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
    99             instance, instance->next, instance->status, instance->device,
    100             instance->buffer_ptr, buffer);
    101         td_print_status(instance);
    102         if (pid == USB_PID_SETUP) {
    103                 usb_log_debug("SETUP BUFFER: %s\n",
    104                     usb_debug_str_buffer(buffer, 8, 8));
    105         }
     69        usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
     70                instance->next, instance->status, instance->device,
     71          instance->buffer_ptr, buffer);
    10672}
    10773/*----------------------------------------------------------------------------*/
    108 /** Convert TD status into standard error code
    109  *
    110  * @param[in] instance TD structure to use.
    111  * @return Error code.
    112  */
    113 int td_status(td_t *instance)
     74int transfer_descriptor_status(transfer_descriptor_t *instance)
    11475{
    11576        assert(instance);
     
    13596        return EOK;
    13697}
    137 /*----------------------------------------------------------------------------*/
    138 /** Print values in status field (dw1) in a human readable way.
    139  *
    140  * @param[in] instance TD structure to use.
    141  */
    142 void 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             (s >> TD_STATUS_ACTLEN_POS) & TD_STATUS_ACTLEN_MASK
    162         );
    163 }
    16498/**
    16599 * @}
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    r72af8da r3e7b7cd  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup usb
    2929 * @{
    3030 */
     
    4545
    4646        volatile uint32_t status;
     47
    4748#define TD_STATUS_RESERVED_MASK 0xc000f800
    4849#define TD_STATUS_SPD_FLAG ( 1 << 29 )
    4950#define TD_STATUS_ERROR_COUNT_POS ( 27 )
    5051#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
     52#define TD_STATUS_ERROR_COUNT_DEFAULT 3
    5153#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    5254#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    53 #define TD_STATUS_IOC_FLAG ( 1 << 24 )
     55#define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
    5456
    5557#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
     
    6870
    6971        volatile uint32_t device;
     72
    7073#define TD_DEVICE_MAXLEN_POS 21
    7174#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
     
    8285
    8386        /* there is 16 bytes of data available here, according to UHCI
    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
     87         * Design guide, according to linux kernel the hardware does not care
     88         * we don't use it anyway
    8689         */
    87 } __attribute__((packed)) td_t;
     90} __attribute__((packed)) transfer_descriptor_t;
    8891
    8992
    90 void 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);
     93void transfer_descriptor_init(transfer_descriptor_t *instance,
     94    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
     95    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
    9396
    94 int td_status(td_t *instance);
     97int transfer_descriptor_status(transfer_descriptor_t *instance);
    9598
    96 void 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  */
    103 static inline size_t td_act_size(td_t *instance)
     99static inline size_t transfer_descriptor_actual_size(
     100    transfer_descriptor_t *instance)
    104101{
    105102        assert(instance);
    106         const uint32_t s = instance->status;
    107         return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
     103        return
     104            ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
    108105}
    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  */
    116 static inline bool td_is_short(td_t *instance)
    117 {
    118         const size_t act_size = td_act_size(instance);
    119         const size_t max_size =
    120             ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
    121             & TD_DEVICE_MAXLEN_MASK;
    122         return
    123             (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
    124 }
    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  */
    131 static inline int td_toggle(td_t *instance)
    132 {
    133         assert(instance);
    134         return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
    135 }
    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  */
    142 static inline bool td_is_active(td_t *instance)
     106
     107static inline bool transfer_descriptor_is_active(
     108    transfer_descriptor_t *instance)
    143109{
    144110        assert(instance);
    145111        return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
    146112}
    147 /*----------------------------------------------------------------------------*/
    148 /** Helper function for setting IOC bit.
    149  *
    150  * @param[in] instance TD structure to use.
    151  */
    152 static inline void td_set_ioc(td_t *instance)
    153 {
    154         assert(instance);
    155         instance->status |= TD_STATUS_IOC_FLAG;
    156 }
    157 /*----------------------------------------------------------------------------*/
    158113#endif
    159114/**
  • uspace/drv/uhci-hcd/utils/device_keeper.c

    r72af8da r3e7b7cd  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup drvusbuhci
    3030 * @{
    3131 */
     
    3535#include <assert.h>
    3636#include <errno.h>
    37 #include <usb/debug.h>
    3837
    3938#include "device_keeper.h"
    4039
    4140/*----------------------------------------------------------------------------*/
    42 /** Initialize device keeper structure.
    43  *
    44  * @param[in] instance Memory place to initialize.
    45  *
    46  * Set all values to false/0.
    47  */
    4841void device_keeper_init(device_keeper_t *instance)
    4942{
     
    5649                instance->devices[i].occupied = false;
    5750                instance->devices[i].handle = 0;
    58                 instance->devices[i].toggle_status = 0;
    5951        }
    6052}
    6153/*----------------------------------------------------------------------------*/
    62 /** Attempt to obtain address 0, blocks.
    63  *
    64  * @param[in] instance Device keeper structure to use.
    65  * @param[in] speed Speed of the device requesting default address.
    66  */
    67 void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
     54void device_keeper_reserve_default(
     55    device_keeper_t *instance, usb_speed_t speed)
    6856{
    6957        assert(instance);
     
    7866}
    7967/*----------------------------------------------------------------------------*/
    80 /** Attempt to obtain address 0, blocks.
    81  *
    82  * @param[in] instance Device keeper structure to use.
    83  * @param[in] speed Speed of the device requesting default address.
    84  */
    8568void device_keeper_release_default(device_keeper_t *instance)
    8669{
     
    9275}
    9376/*----------------------------------------------------------------------------*/
    94 /** Check setup packet data for signs of toggle reset.
    95  *
    96  * @param[in] instance Device keeper structure to use.
    97  * @param[in] target Device to receive setup packet.
    98  * @param[in] data Setup packet data.
    99  *
    100  * Really ugly one.
    101  */
    102 void device_keeper_reset_if_need(
    103     device_keeper_t *instance, usb_target_t target, const unsigned char *data)
    104 {
    105         assert(instance);
    106         fibril_mutex_lock(&instance->guard);
    107         if (target.endpoint > 15 || target.endpoint < 0
    108             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    109             || !instance->devices[target.address].occupied) {
    110                 fibril_mutex_unlock(&instance->guard);
    111                 usb_log_error("Invalid data when checking for toggle reset.\n");
    112                 return;
    113         }
    114 
    115         switch (data[1])
    116         {
    117         case 0x01: /*clear feature*/
    118                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    119                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    120                         /* endpoint number is < 16, thus first byte is enough */
    121                         instance->devices[target.address].toggle_status &=
    122                             ~(1 << data[4]);
    123                 }
    124         break;
    125 
    126         case 0x9: /* set configuration */
    127         case 0x11: /* set interface */
    128                 /* target must be device */
    129                 if ((data[0] & 0xf) == 0) {
    130                         instance->devices[target.address].toggle_status = 0;
    131                 }
    132         break;
    133         }
    134         fibril_mutex_unlock(&instance->guard);
    135 }
    136 /*----------------------------------------------------------------------------*/
    137 /** Get current value of endpoint toggle.
    138  *
    139  * @param[in] instance Device keeper structure to use.
    140  * @param[in] target Device and endpoint used.
    141  * @return Error code
    142  */
    143 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
    144 {
    145         assert(instance);
    146         int ret;
    147         fibril_mutex_lock(&instance->guard);
    148         if (target.endpoint > 15 || target.endpoint < 0
    149             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    150             || !instance->devices[target.address].occupied) {
    151                 usb_log_error("Invalid data when asking for toggle value.\n");
    152                 ret = EINVAL;
    153         } else {
    154                 ret = (instance->devices[target.address].toggle_status
    155                         >> target.endpoint) & 1;
    156         }
    157         fibril_mutex_unlock(&instance->guard);
    158         return ret;
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Set current value of endpoint toggle.
    162  *
    163  * @param[in] instance Device keeper structure to use.
    164  * @param[in] target Device and endpoint used.
    165  * @param[in] toggle Toggle value.
    166  * @return Error code.
    167  */
    168 int device_keeper_set_toggle(
    169     device_keeper_t *instance, usb_target_t target, bool toggle)
    170 {
    171         assert(instance);
    172         int ret;
    173         fibril_mutex_lock(&instance->guard);
    174         if (target.endpoint > 15 || target.endpoint < 0
    175             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    176             || !instance->devices[target.address].occupied) {
    177                 usb_log_error("Invalid data when setting toggle value.\n");
    178                 ret = EINVAL;
    179         } else {
    180                 if (toggle) {
    181                         instance->devices[target.address].toggle_status |= (1 << target.endpoint);
    182                 } else {
    183                         instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
    184                 }
    185                 ret = EOK;
    186         }
    187         fibril_mutex_unlock(&instance->guard);
    188         return ret;
    189 }
    190 /*----------------------------------------------------------------------------*/
    191 /** Get a free USB address
    192  *
    193  * @param[in] instance Device keeper structure to use.
    194  * @param[in] speed Speed of the device requiring address.
    195  * @return Free address, or error code.
    196  */
    19777usb_address_t device_keeper_request(
    19878    device_keeper_t *instance, usb_speed_t speed)
     
    21696        instance->devices[new_address].occupied = true;
    21797        instance->devices[new_address].speed = speed;
    218         instance->devices[new_address].toggle_status = 0;
    21998        instance->last_address = new_address;
    22099        fibril_mutex_unlock(&instance->guard);
     
    222101}
    223102/*----------------------------------------------------------------------------*/
    224 /** Bind USB address to devman handle.
    225  *
    226  * @param[in] instance Device keeper structure to use.
    227  * @param[in] address Device address
    228  * @param[in] handle Devman handle of the device.
    229  */
    230103void device_keeper_bind(
    231104    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
     
    240113}
    241114/*----------------------------------------------------------------------------*/
    242 /** Release used USB address.
    243  *
    244  * @param[in] instance Device keeper structure to use.
    245  * @param[in] address Device address
    246  */
    247115void device_keeper_release(device_keeper_t *instance, usb_address_t address)
    248116{
     
    257125}
    258126/*----------------------------------------------------------------------------*/
    259 /** Find USB address associated with the device
    260  *
    261  * @param[in] instance Device keeper structure to use.
    262  * @param[in] handle Devman handle of the device seeking its address.
    263  * @return USB Address, or error code.
    264  */
    265127usb_address_t device_keeper_find(
    266128    device_keeper_t *instance, devman_handle_t handle)
     
    280142}
    281143/*----------------------------------------------------------------------------*/
    282 /** Get speed associated with the address
    283  *
    284  * @param[in] instance Device keeper structure to use.
    285  * @param[in] address Address of the device.
    286  * @return USB speed.
    287  */
    288144usb_speed_t device_keeper_speed(
    289145    device_keeper_t *instance, usb_address_t address)
  • uspace/drv/uhci-hcd/utils/device_keeper.h

    r72af8da r3e7b7cd  
    2727 */
    2828
    29 /** @addtogroup drvusbuhcihc
     29/** @addtogroup drvusbuhci
    3030 * @{
    3131 */
     
    4444        usb_speed_t speed;
    4545        bool occupied;
    46         uint16_t toggle_status;
    4746        devman_handle_t handle;
    4847};
     
    5655
    5756void device_keeper_init(device_keeper_t *instance);
    58 
    5957void device_keeper_reserve_default(
    6058    device_keeper_t *instance, usb_speed_t speed);
    61 
    6259void device_keeper_release_default(device_keeper_t *instance);
    63 
    64 void device_keeper_reset_if_need(
    65     device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
    66 
    67 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
    68 
    69 int device_keeper_set_toggle(
    70     device_keeper_t *instance, usb_target_t target, bool toggle);
    7160
    7261usb_address_t device_keeper_request(
    7362    device_keeper_t *instance, usb_speed_t speed);
    74 
    7563void device_keeper_bind(
    7664    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
    77 
    7865void device_keeper_release(device_keeper_t *instance, usb_address_t address);
    79 
    8066usb_address_t device_keeper_find(
    8167    device_keeper_t *instance, devman_handle_t handle);
  • uspace/drv/uhci-hcd/utils/malloc32.h

    r72af8da r3e7b7cd  
    3535#define DRV_UHCI_TRANSLATOR_H
    3636
     37#include <usb/usbmem.h>
     38
    3739#include <assert.h>
    3840#include <malloc.h>
     
    4345#define UHCI_REQUIRED_PAGE_SIZE 4096
    4446
    45 /** Get physical address translation
    46  *
    47  * @param[in] addr Virtual address to translate
    48  * @return Physical address if exists, NULL otherwise.
    49  */
    5047static inline uintptr_t addr_to_phys(void *addr)
    5148{
     
    5350        int ret = as_get_physical_mapping(addr, &result);
    5451
    55         if (ret != EOK)
    56                 return 0;
     52        assert(ret == 0);
    5753        return (result | ((uintptr_t)addr & 0xfff));
    5854}
    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  */
     55
    6556static inline void * malloc32(size_t size)
    6657        { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
    67 /*----------------------------------------------------------------------------*/
    68 /** Physical mallocator simulator
    69  *
    70  * @param[in] addr Address of the place allocated by malloc32
    71  */
    72 static 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  */
    79 static inline void * get_page(void)
     58
     59static inline void * get_page()
    8060{
    8161        void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
    8262        assert(free_address);
    8363        if (free_address == 0)
    84                 return NULL;
     64                return 0;
    8565        void* ret =
    8666          as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
    8767                  AS_AREA_READ | AS_AREA_WRITE);
    8868        if (ret != free_address)
    89                 return NULL;
     69                return 0;
    9070        return ret;
    9171}
     72
     73static inline void free32(void *addr)
     74        { if (addr) free(addr); }
    9275
    9376#endif
  • uspace/drv/uhci-rhd/Makefile

    r72af8da r3e7b7cd  
    3535        main.c \
    3636        port.c \
     37        port_status.c \
    3738        root_hub.c
    3839
  • uspace/drv/uhci-rhd/main.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub initialization routines
     32 * @brief UHCI driver
    3333 */
    3434#include <ddf/driver.h>
    3535#include <devman.h>
    3636#include <device/hw_res.h>
    37 #include <errno.h>
    3837#include <usb_iface.h>
    3938#include <usb/ddfiface.h>
     39
     40#include <errno.h>
     41
    4042#include <usb/debug.h>
    4143
     
    4547static int hc_get_my_registers(ddf_dev_t *dev,
    4648    uintptr_t *io_reg_address, size_t *io_reg_size);
    47 #if 0
    48 /*----------------------------------------------------------------------------*/
     49
    4950static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
    5051{
     
    5758        return EOK;
    5859}
    59 /*----------------------------------------------------------------------------*/
     60
    6061static usb_iface_t uhci_rh_usb_iface = {
    6162        .get_hc_handle = usb_iface_get_hc_handle,
    6263        .get_address = usb_iface_get_address_hub_impl
    6364};
    64 /*----------------------------------------------------------------------------*/
     65
    6566static ddf_dev_ops_t uhci_rh_ops = {
    6667        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6768};
    68 #endif
    69 /*----------------------------------------------------------------------------*/
    70 /** Initialize a new ddf driver instance of UHCI root hub.
    71  *
    72  * @param[in] device DDF instance of the device to initialize.
    73  * @return Error code.
    74  */
     69
    7570static int uhci_rh_add_device(ddf_dev_t *device)
    7671{
     
    8176
    8277        //device->ops = &uhci_rh_ops;
     78        (void) uhci_rh_ops;
     79
     80        uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
     81        if (!rh) {
     82                usb_log_error("Failed to allocate memory for driver instance.\n");
     83                return ENOMEM;
     84        }
     85
    8386        uintptr_t io_regs = 0;
    8487        size_t io_size = 0;
    8588
    8689        int ret = hc_get_my_registers(device, &io_regs, &io_size);
    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);
     90        assert(ret == EOK);
    9291
    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 
     92        /* TODO: verify values from hc */
     93        usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size);
    9994        ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
    10095        if (ret != EOK) {
     
    109104        return EOK;
    110105}
    111 /*----------------------------------------------------------------------------*/
     106
    112107static driver_ops_t uhci_rh_driver_ops = {
    113108        .add_device = uhci_rh_add_device,
    114109};
    115 /*----------------------------------------------------------------------------*/
     110
    116111static driver_t uhci_rh_driver = {
    117112        .name = NAME,
     
    119114};
    120115/*----------------------------------------------------------------------------*/
    121 /** Initialize global driver structures (NONE).
    122  *
    123  * @param[in] argc Nmber of arguments in argv vector (ignored).
    124  * @param[in] argv Cmdline argument vector (ignored).
    125  * @return Error code.
    126  *
    127  * Driver debug level is set here.
    128  */
    129116int main(int argc, char *argv[])
    130117{
     
    133120}
    134121/*----------------------------------------------------------------------------*/
    135 /** Get address of I/O registers.
    136  *
    137  * @param[in] dev Device asking for the addresses.
    138  * @param[out] io_reg_address Base address of the memory range.
    139  * @param[out] io_reg_size Size of the memory range.
    140  * @return Error code.
    141  */
    142 int hc_get_my_registers(
    143     ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
     122int hc_get_my_registers(ddf_dev_t *dev,
     123    uintptr_t *io_reg_address, size_t *io_reg_size)
    144124{
    145125        assert(dev != NULL);
     
    166146        for (i = 0; i < hw_resources.count; i++) {
    167147                hw_resource_t *res = &hw_resources.resources[i];
    168                 switch (res->type)
    169                 {
    170                 case IO_RANGE:
    171                         io_address = (uintptr_t) res->res.io_range.address;
    172                         io_size = res->res.io_range.size;
    173                         io_found = true;
    174 
    175                 default:
    176                         break;
     148                switch (res->type) {
     149                        case IO_RANGE:
     150                                io_address = (uintptr_t)
     151                                    res->res.io_range.address;
     152                                io_size = res->res.io_range.size;
     153                                io_found = true;
     154                                break;
     155                        default:
     156                                break;
    177157                }
    178158        }
     
    190170        }
    191171        rc = EOK;
    192 
    193172leave:
    194173        async_hangup(parent_phone);
     174
    195175        return rc;
    196176}
  • uspace/drv/uhci-rhd/port.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub port routines
    33  */
    34 #include <libarch/ddi.h> /* pio_read and pio_write */
     32 * @brief UHCI driver
     33 */
    3534#include <errno.h>
    3635#include <str_error.h>
     
    3837
    3938#include <usb/usb.h>    /* usb_address_t */
     39#include <usb/usbdevice.h>
    4040#include <usb/hub.h>
     41#include <usb/request.h>
    4142#include <usb/debug.h>
     43#include <usb/recognise.h>
    4244
    4345#include "port.h"
    44 
    45 static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
     46#include "port_status.h"
     47
     48static int uhci_port_new_device(uhci_port_t *port, uint16_t status);
    4649static int uhci_port_remove_device(uhci_port_t *port);
    4750static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
    4851static int uhci_port_check(void *port);
    49 static int uhci_port_reset_enable(int portno, void *arg);
    50 static 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  */
    58 static inline port_status_t uhci_port_read_status(uhci_port_t *port)
     52static int new_device_enable_port(int portno, void *arg);
     53
     54int uhci_port_init(
     55  uhci_port_t *port, port_status_t *address, unsigned number,
     56  unsigned usec, ddf_dev_t *rh)
    5957{
    6058        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  */
    70 static 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.
    79  *
    80  * @param[in] port Memory structure to use.
    81  * @param[in] addr Address of I/O register.
    82  * @param[in] number Port number.
    83  * @param[in] usec Polling interval.
    84  * @param[in] rh Pointer to ddf instance fo the root hub driver.
    85  * @return Error code.
    86  *
    87  * Creates and starts the polling fibril.
    88  */
    89 int uhci_port_init(uhci_port_t *port,
    90     port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
    91 {
    92         assert(port);
    93         asprintf(&port->id_string, "Port (%p - %d)", port, number);
    94         if (port->id_string == NULL) {
    95                 return ENOMEM;
    96         }
    97 
    9859        port->address = address;
    9960        port->number = number;
     
    10162        port->attached_device = 0;
    10263        port->rh = rh;
    103 
    10464        int rc = usb_hc_connection_initialize_from_device(
    10565            &port->hc_connection, rh);
     
    11171        port->checker = fibril_create(uhci_port_check, port);
    11272        if (port->checker == 0) {
    113                 usb_log_error("%s: failed to create polling fibril.",
    114                     port->id_string);
     73                usb_log_error("Port(%p - %d): failed to launch root hub fibril.",
     74                    port->address, port->number);
    11575                return ENOMEM;
    11676        }
    117 
    11877        fibril_add_ready(port->checker);
    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.
    125  *
    126  * @param[in] port Memory structure to use.
    127  *
    128  * Stops the polling fibril.
    129  */
     78        usb_log_debug("Port(%p - %d): Added fibril. %x\n",
     79            port->address, port->number, port->checker);
     80        return EOK;
     81}
     82/*----------------------------------------------------------------------------*/
    13083void uhci_port_fini(uhci_port_t *port)
    13184{
    132         assert(port);
    133         free(port->id_string);
    134         /* TODO: Kill fibril here */
     85// TODO: destroy fibril
     86// TODO: hangup phone
     87//      fibril_teardown(port->checker);
    13588        return;
    13689}
    13790/*----------------------------------------------------------------------------*/
    138 /** Periodically checks port status and reports new devices.
    139  *
    140  * @param[in] port Port structure to use.
    141  * @return Error code.
    142  */
    14391int uhci_port_check(void *port)
    14492{
    145         uhci_port_t *instance = port;
    146         assert(instance);
     93        uhci_port_t *port_instance = port;
     94        assert(port_instance);
     95//      port_status_write(port_instance->address, 0);
     96
     97        unsigned count = 0;
    14798
    14899        while (1) {
    149                 async_usleep(instance->wait_period_usec);
    150 
    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);
    157 
    158                 if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
    159                         continue;
    160 
    161                 usb_log_debug("%s: Connected change detected: %x.\n",
    162                     instance->id_string, port_status);
    163 
    164                 int rc =
    165                     usb_hc_connection_open(&instance->hc_connection);
    166                 if (rc != EOK) {
    167                         usb_log_error("%s: Failed to connect to HC.",
    168                             instance->id_string);
    169                         continue;
     100                async_usleep(port_instance->wait_period_usec);
     101
     102                /* read register value */
     103                port_status_t port_status =
     104                        port_status_read(port_instance->address);
     105
     106                /* debug print */
     107                static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
     108                fibril_mutex_lock(&dbg_mtx);
     109                usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
     110                  port_instance->address, port_instance->number, port_status, count++);
     111//              print_port_status(port_status);
     112                fibril_mutex_unlock(&dbg_mtx);
     113
     114                if ((port_status & STATUS_CONNECTED_CHANGED) != 0) {
     115                        usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
     116                            port_instance->address, port_instance->number, port_status);
     117
     118
     119                        int rc = usb_hc_connection_open(
     120                            &port_instance->hc_connection);
     121                        if (rc != EOK) {
     122                                usb_log_error("Port(%p - %d): Failed to connect to HC.",
     123                                    port_instance->address, port_instance->number);
     124                                continue;
     125                        }
     126
     127                        /* remove any old device */
     128                        if (port_instance->attached_device) {
     129                                usb_log_debug("Port(%p - %d): Removing device.\n",
     130                                    port_instance->address, port_instance->number);
     131                                uhci_port_remove_device(port_instance);
     132                        }
     133
     134                        if ((port_status & STATUS_CONNECTED) != 0) {
     135                                /* new device */
     136                                uhci_port_new_device(port_instance, port_status);
     137                        } else {
     138                                /* ack changes by writing one to WC bits */
     139                                port_status_write(port_instance->address, port_status);
     140                                usb_log_debug("Port(%p - %d): Change status ACK.\n",
     141                                                port_instance->address, port_instance->number);
     142                        }
     143
     144                        rc = usb_hc_connection_close(
     145                            &port_instance->hc_connection);
     146                        if (rc != EOK) {
     147                                usb_log_error("Port(%p - %d): Failed to disconnect from HC.",
     148                                    port_instance->address, port_instance->number);
     149                        }
    170150                }
    171 
    172                 /* Remove any old device */
    173                 if (instance->attached_device) {
    174                         usb_log_debug2("%s: Removing device.\n",
    175                             instance->id_string);
    176                         uhci_port_remove_device(instance);
    177                 }
    178 
    179                 if ((port_status & STATUS_CONNECTED) != 0) {
    180                         /* New device */
    181                         const usb_speed_t speed =
    182                             ((port_status & STATUS_LOW_SPEED) != 0) ?
    183                             USB_SPEED_LOW : USB_SPEED_FULL;
    184                         uhci_port_new_device(instance, speed);
    185                 } else {
    186                         /* Write one to WC bits, to ack changes */
    187                         uhci_port_write_status(instance, port_status);
    188                         usb_log_debug("%s: status change ACK.\n",
    189                             instance->id_string);
    190                 }
    191 
    192                 rc = usb_hc_connection_close(&instance->hc_connection);
    193                 if (rc != EOK) {
    194                         usb_log_error("%s: Failed to disconnect.",
    195                             instance->id_string);
    196                 }
    197         }
    198         return EOK;
    199 }
    200 /*----------------------------------------------------------------------------*/
     151        }
     152        return EOK;
     153}
     154
    201155/** Callback for enabling port during adding a new device.
    202156 *
     
    204158 * @param arg Pointer to uhci_port_t of port with the new device.
    205159 * @return Error code.
    206  *
    207  * Resets and enables the ub port.
    208  */
    209 int uhci_port_reset_enable(int portno, void *arg)
     160 */
     161static int new_device_enable_port(int portno, void *arg)
    210162{
    211163        uhci_port_t *port = (uhci_port_t *) arg;
    212164
    213         usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
     165        usb_log_debug2("Port(%p - %d): new_device_enable_port.\n",
     166            port->address, port->number);
    214167
    215168        /*
     
    219172        async_usleep(100000);
    220173
    221         /*
    222          * Resets from root ports should be nominally 50ms
     174
     175        /* The hub maintains the reset signal to that port for 10 ms
     176         * (See Section 11.5.1.5)
    223177         */
    224178        {
    225                 usb_log_debug("%s: Reset Signal start.\n", port->id_string);
    226                 port_status_t port_status = uhci_port_read_status(port);
     179                usb_log_debug("Port(%p - %d): Reset Signal start.\n",
     180                    port->address, port->number);
     181                port_status_t port_status =
     182                        port_status_read(port->address);
    227183                port_status |= STATUS_IN_RESET;
    228                 uhci_port_write_status(port, port_status);
    229                 async_usleep(50000);
    230                 port_status = uhci_port_read_status(port);
     184                port_status_write(port->address, port_status);
     185                async_usleep(10000);
     186                port_status =
     187                        port_status_read(port->address);
    231188                port_status &= ~STATUS_IN_RESET;
    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);
     189                port_status_write(port->address, port_status);
     190                usb_log_debug("Port(%p - %d): Reset Signal stop.\n",
     191                    port->address, port->number);
     192        }
    238193
    239194        /* Enable the port. */
     
    242197        return EOK;
    243198}
    244 /*----------------------------------------------------------------------------*/
    245 /** Initialize and report connected device.
    246  *
    247  * @param[in] port Port structure to use.
    248  * @param[in] speed Detected speed.
    249  * @return Error code.
    250  *
    251  * Uses libUSB function to do the actual work.
    252  */
    253 int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
     199
     200/*----------------------------------------------------------------------------*/
     201static int uhci_port_new_device(uhci_port_t *port, uint16_t status)
    254202{
    255203        assert(port);
    256204        assert(usb_hc_connection_is_opened(&port->hc_connection));
    257205
    258         usb_log_info("%s: Detected new device.\n", port->id_string);
     206        usb_log_info("Port(%p-%d): Detected new device.\n",
     207            port->address, port->number);
    259208
    260209        usb_address_t dev_addr;
    261210        int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    262             speed, uhci_port_reset_enable, port->number, port,
     211            ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL,
     212            new_device_enable_port, port->number, port,
    263213            &dev_addr, &port->attached_device, NULL, NULL, NULL);
    264214
    265215        if (rc != EOK) {
    266                 usb_log_error("%s: Failed(%d) to add device: %s.\n",
    267                     port->id_string, rc, str_error(rc));
     216                usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n",
     217                    port->address, port->number, rc, str_error(rc));
    268218                uhci_port_set_enabled(port, false);
    269219                return rc;
    270220        }
    271221
    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.
    279  *
    280  * @param[in] port Memory structure to use.
    281  * @return Error code.
    282  *
    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).
    286  */
    287 int uhci_port_remove_device(uhci_port_t *port)
    288 {
    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.
    298  * @return Error code. (Always EOK)
    299  */
    300 int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
     222        usb_log_info("Port(%p-%d): New device has address %d (handle %zu).\n",
     223            port->address, port->number, dev_addr, port->attached_device);
     224
     225        return EOK;
     226}
     227
     228/*----------------------------------------------------------------------------*/
     229static int uhci_port_remove_device(uhci_port_t *port)
     230{
     231        usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
     232                port->address, port->number, (unsigned int)port->attached_device);
     233//      uhci_port_set_enabled(port, false);
     234        return EOK;
     235}
     236/*----------------------------------------------------------------------------*/
     237static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
    301238{
    302239        assert(port);
    303240
    304         /* Read register value */
    305         port_status_t port_status = uhci_port_read_status(port);
    306 
    307         /* Set enabled bit */
     241        /* read register value */
     242        port_status_t port_status
     243                = port_status_read(port->address);
     244
     245        /* enable port: register write */
    308246        if (enabled) {
    309247                port_status |= STATUS_ENABLED;
     
    311249                port_status &= ~STATUS_ENABLED;
    312250        }
    313 
    314         /* Write new value. */
    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  */
    328 void 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 }
     251        port_status_write(port->address, port_status);
     252
     253        usb_log_info("Port(%p-%d): %sabled port.\n",
     254                port->address, port->number, enabled ? "En" : "Dis");
     255        return EOK;
     256}
     257/*----------------------------------------------------------------------------*/
    346258/**
    347259 * @}
  • uspace/drv/uhci-rhd/port.h

    r72af8da r3e7b7cd  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2010 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub port routines
     32 * @brief UHCI port driver
    3333 */
    3434#ifndef DRV_UHCI_PORT_H
    3535#define DRV_UHCI_PORT_H
    3636
     37#include <assert.h>
     38#include <ddf/driver.h>
    3739#include <stdint.h>
    38 #include <fibril.h>
    39 #include <ddf/driver.h>
    40 #include <usb/usbdevice.h> /* usb_hc_connection_t */
     40#include <usb/usbdevice.h>
    4141
    42 typedef 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)
     42#include "port_status.h"
    5543
    5644typedef struct uhci_port
    5745{
    58         char *id_string;
    5946        port_status_t *address;
    6047        unsigned number;
     
    7158
    7259void uhci_port_fini(uhci_port_t *port);
    73 
    7460#endif
    7561/**
  • uspace/drv/uhci-rhd/root_hub.c

    r72af8da r3e7b7cd  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcirh
     28/** @addtogroup usb
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI root hub driver
     32 * @brief UHCI driver
    3333 */
    3434#include <errno.h>
     35#include <stdint.h>
    3536#include <ddi.h>
     37#include <devman.h>
    3638#include <usb/debug.h>
    3739
    3840#include "root_hub.h"
    3941
    40 /** Initialize UHCI root hub instance.
    41  *
    42  * @param[in] instance Driver memory structure to use.
    43  * @param[in] addr Address of I/O registers.
    44  * @param[in] size Size of available I/O space.
    45  * @param[in] rh Pointer to ddf instance of the root hub driver.
    46  * @return Error code.
    47  */
    4842int uhci_root_hub_init(
    4943  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
     
    5347        int ret;
    5448
    55         /* Allow access to root hub port registers */
    56         assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
     49        /* allow access to root hub registers */
     50        assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
    5751        port_status_t *regs;
    5852        ret = pio_enable(addr, size, (void**)&regs);
     53
    5954        if (ret < 0) {
    60                 usb_log_error(
    61                     "Failed(%d) to gain access to port registers at %p\n",
    62                     ret, regs);
     55                usb_log_error("Failed to gain access to port registers at %p\n", regs);
    6356                return ret;
    6457        }
    6558
    66         /* Initialize root hub ports */
     59        /* add fibrils for periodic port checks */
    6760        unsigned i = 0;
    6861        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
    69                 /* NOTE: mind pointer arithmetics here */
     62                /* mind pointer arithmetics */
    7063                ret = uhci_port_init(
    71                     &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
     64                  &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
    7265                if (ret != EOK) {
    7366                        unsigned j = 0;
     
    8174}
    8275/*----------------------------------------------------------------------------*/
    83 /** Cleanup UHCI root hub instance.
    84  *
    85  * @param[in] instance Root hub structure to use.
    86  * @return Error code.
    87  */
    88 int uhci_root_hub_fini(uhci_root_hub_t* instance)
     76int uhci_root_hub_fini( uhci_root_hub_t* instance )
    8977{
    90         assert(instance);
    91         unsigned i = 0;
    92         for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
    93                 uhci_port_fini(&instance->ports[i]);
    94         }
     78        assert( instance );
     79        // TODO:
     80        //destroy fibril here
     81        //disable access to registers
    9582        return EOK;
    9683}
  • uspace/drv/uhci-rhd/root_hub.h

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

    r72af8da r3e7b7cd  
    4242        hidreq.c \
    4343        kbddev.c \
    44         kbdrepeat.c \
    4544        hiddev.c \
    4645        $(STOLEN_LAYOUT_SOURCES)
  • uspace/drv/usbhid/conv.c

    r72af8da r3e7b7cd  
    4040#include "conv.h"
    4141
    42 /**
    43  * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
    44  * HelenOS key codes.
    45  */
    4642static int scanmap_simple[255] = {
    4743
     
    167163};
    168164
    169 /**
    170  * Translate USB HID key codes (from HID Usage Tables) to generic key codes
    171  * recognized by HelenOS.
    172  *
    173  * @param scancode USB HID key code (from HID Usage Tables).
    174  *
    175  * @retval HelenOS key code corresponding to the given USB HID key code.
    176  */
    177165unsigned int usbhid_parse_scancode(int scancode)
    178166{
  • uspace/drv/usbhid/descdump.c

    r72af8da r3e7b7cd  
    4444#define BYTES_PER_LINE 12
    4545
    46 /**
    47  * Dumps the given buffer in hexadecimal format to standard output.
    48  *
    49  * @param msg Message to print before the buffer.
    50  * @param buffer Buffer to print.
    51  * @param length Size of the buffer in bytes.
    52  */
    5346static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
    5447{
     
    6962#define INDENT "  "
    7063
    71 /**
    72  * Print standard configuration descriptor to standard output.
    73  *
    74  * @param index Index of the descriptor.
    75  * @param d Standard configuration descriptor to print.
    76  */
    7764void dump_standard_configuration_descriptor(
    7865    int index, const usb_standard_configuration_descriptor_t *d)
     
    9784}
    9885
    99 /**
    100  * Print standard interface descriptor to standard output.
    101  *
    102  * @param d Standard interface descriptor to print.
    103  */
    10486void dump_standard_interface_descriptor(
    10587    const usb_standard_interface_descriptor_t *d)
     
    11799}
    118100
    119 /**
    120  * Print standard endpoint descriptor to standard output.
    121  *
    122  * @param d Standard endpoint descriptor to print.
    123  */
    124101void dump_standard_endpoint_descriptor(
    125102    const usb_standard_endpoint_descriptor_t *d)
     
    149126}
    150127
    151 /**
    152  * Print standard HID descriptor to standard output.
    153  *
    154  * @param d Standard HID descriptor to print.
    155  */
    156128void dump_standard_hid_descriptor_header(
    157129    const usb_standard_hid_descriptor_t *d)
     
    167139}
    168140
    169 /**
    170  * Print HID class-specific descriptor header (type and length) to standard
    171  * output.
    172  *
    173  * @param d HID class-specific descriptor header to print.
    174  */
    175141void dump_standard_hid_class_descriptor_info(
    176142    const usb_standard_hid_class_descriptor_info_t *d)
     
    180146}
    181147
    182 /**
    183  * Print HID class-specific descriptor (without the header) to standard output.
    184  *
    185  * @param index Index of the descriptor.
    186  * @param type Type of the HID class-specific descriptor (Report or Physical).
    187  * @param d HID class descriptor to print.
    188  * @param size Size of the descriptor in bytes.
    189  */
    190148void dump_hid_class_descriptor(int index, uint8_t type,
    191149    const uint8_t *d, size_t size )
  • uspace/drv/usbhid/hiddev.c

    r72af8da r3e7b7cd  
    5353/* Non-API functions                                                          */
    5454/*----------------------------------------------------------------------------*/
    55 /**
    56  * Retreives HID Report descriptor from the device.
    57  *
    58  * This function first parses the HID descriptor from the Interface descriptor
    59  * to get the size of the Report descriptor and then requests the Report
    60  * descriptor from the device.
    61  *
    62  * @param hid_dev HID device structure.
    63  * @param config_desc Full configuration descriptor (including all nested
    64  *                    descriptors).
    65  * @param config_desc_size Size of the full configuration descriptor (in bytes).
    66  * @param iface_desc Pointer to the interface descriptor inside the full
    67  *                   configuration descriptor (@a config_desc) for the interface
    68  *                   assigned with this device (@a hid_dev).
    69  *
    70  * @retval EOK if successful.
    71  * @retval ENOENT if no HID descriptor could be found.
    72  * @retval EINVAL if the HID descriptor  or HID report descriptor have different
    73  *                size than expected.
    74  * @retval ENOMEM if some allocation failed.
    75  * @return Other value inherited from function usb_request_get_descriptor().
    76  *
    77  * @sa usb_request_get_descriptor()
    78  */
     55
    7956static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev,
    8057    uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc)
     
    164141
    165142/*----------------------------------------------------------------------------*/
    166 /**
    167  * Retreives descriptors from the device, initializes pipes and stores
    168  * important information from descriptors.
    169  *
    170  * Initializes the polling pipe described by the given endpoint description
    171  * (@a poll_ep_desc).
    172  *
    173  * Information retreived from descriptors and stored in the HID device structure:
    174  *    - Assigned interface number (the interface controlled by this instance of
    175  *                                 the driver)
    176  *    - Polling interval (from the interface descriptor)
    177  *    - Report descriptor
    178  *
    179  * @param hid_dev HID device structure to be initialized.
    180  * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
    181  *                     that has to be present in the device in order to
    182  *                     successfuly initialize the structure.
    183  *
    184  * @sa usb_endpoint_pipe_initialize_from_configuration(),
    185  *     usbhid_dev_get_report_descriptor()
    186  */
     143
    187144static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev,
    188145    usb_endpoint_description_t *poll_ep_desc)
     
    273230/* API functions                                                              */
    274231/*----------------------------------------------------------------------------*/
    275 /**
    276  * Creates new uninitialized HID device structure.
    277  *
    278  * @return Pointer to the new HID device structure, or NULL if an error occured.
    279  */
     232
    280233usbhid_dev_t *usbhid_dev_new(void)
    281234{
     
    296249
    297250/*----------------------------------------------------------------------------*/
    298 /**
    299  * Properly destroys the HID device structure.
    300  *
    301  * @note Currently does not clean-up the used pipes, as there are no functions
    302  *       offering such functionality.
    303  *
    304  * @param hid_dev Pointer to the structure to be destroyed.
    305  */
     251
    306252void usbhid_dev_free(usbhid_dev_t **hid_dev)
    307253{
     
    326272
    327273/*----------------------------------------------------------------------------*/
    328 /**
    329  * Initializes HID device structure.
    330  *
    331  * @param hid_dev HID device structure to be initialized.
    332  * @param dev DDF device representing the HID device.
    333  * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
    334  *                     that has to be present in the device in order to
    335  *                     successfuly initialize the structure.
    336  *
    337  * @retval EOK if successful.
    338  * @retval EINVAL if some argument is missing.
    339  * @return Other value inherited from one of functions
    340  *         usb_device_connection_initialize_from_device(),
    341  *         usb_endpoint_pipe_initialize_default_control(),
    342  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    343  *         usbhid_dev_process_descriptors().
    344  *
    345  * @sa usbhid_dev_process_descriptors()
    346  */
     274
    347275int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev,
    348276    usb_endpoint_description_t *poll_ep_desc)
     
    391319                return rc;
    392320        }
    393         rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe);
    394         if (rc != EOK) {
    395                 usb_log_error("Probing default control pipe failed: %s.\n",
    396                     str_error(rc));
    397                 return rc;
    398         }
    399321
    400322        /*
    401323         * Get descriptors, parse descriptors and save endpoints.
    402324         */
    403         rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    404         if (rc != EOK) {
    405                 usb_log_error("Failed to start session on the control pipe: %s"
    406                     ".\n", str_error(rc));
    407                 return rc;
    408         }
     325        usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    409326       
    410327        rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc);
    411         if (rc != EOK) {
    412                 /* TODO: end session?? */
     328       
     329        usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     330        if (rc != EOK) {
    413331                usb_log_error("Failed to process descriptors: %s.\n",
    414332                    str_error(rc));
    415                 return rc;
    416         }
    417        
    418         rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    419         if (rc != EOK) {
    420                 usb_log_warning("Failed to start session on the control pipe: "
    421                     "%s.\n", str_error(rc));
    422333                return rc;
    423334        }
  • uspace/drv/usbhid/hiddev.h

    r72af8da r3e7b7cd  
    4848
    4949/**
    50  * USB/HID device type.
    51  *
    52  * Holds a reference to DDF device structure, and HID-specific data, such
    53  * as information about used pipes (one Control pipe and one Interrupt In pipe),
    54  * polling interval, assigned interface number, Report descriptor and a
    55  * reference to the Report parser used to parse incoming reports and composing
    56  * outgoing reports.
     50 * @brief USB/HID device type.
    5751 */
    5852typedef struct {
    59         /** DDF device representing the controlled HID device. */
    6053        ddf_dev_t *device;
    6154
    62         /** Physical connection to the device. */
    6355        usb_device_connection_t wire;
    64         /** USB pipe corresponding to the default Control endpoint. */
    6556        usb_endpoint_pipe_t ctrl_pipe;
    66         /** USB pipe corresponding to the Interrupt In (polling) pipe. */
    6757        usb_endpoint_pipe_t poll_pipe;
    6858       
    69         /** Polling interval retreived from the Interface descriptor. */
    7059        short poll_interval;
    7160       
    72         /** Interface number assigned to this device. */
    7361        uint16_t iface;
    7462       
    75         /** Report descriptor. */
    7663        uint8_t *report_desc;
    77         /** HID Report parser. */
    7864        usb_hid_report_parser_t *parser;
    7965       
    80         /** State of the structure (for checking before use). */
    8166        int initialized;
    8267} usbhid_dev_t;
  • uspace/drv/usbhid/hidreq.c

    r72af8da r3e7b7cd  
    4646
    4747/*----------------------------------------------------------------------------*/
    48 /**
    49  * Send Set Report request to the HID device.
    50  *
    51  * @param hid_dev HID device to send the request to.
    52  * @param type Type of the report.
    53  * @param buffer Report data.
    54  * @param buf_size Report data size (in bytes).
    55  *
    56  * @retval EOK if successful.
    57  * @retval EINVAL if no HID device is given.
    58  * @return Other value inherited from one of functions
    59  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    60  *         usb_control_request_set().
    61  */
     48
    6249int usbhid_req_set_report(usbhid_dev_t *hid_dev,
    6350    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
     
    8269                return sess_rc;
    8370        }
    84        
    85         uint16_t value = 0;
    86         value |= (type << 8);
    8771
    8872        usb_log_debug("Sending Set_Report request to the device.\n");
     
    9074        rc = usb_control_request_set(&hid_dev->ctrl_pipe,
    9175            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    92             USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
     76            USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size);
    9377
    9478        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     
    11094
    11195/*----------------------------------------------------------------------------*/
    112 /**
    113  * Send Set Protocol request to the HID device.
    114  *
    115  * @param hid_dev HID device to send the request to.
    116  * @param protocol Protocol to set.
    117  *
    118  * @retval EOK if successful.
    119  * @retval EINVAL if no HID device is given.
    120  * @return Other value inherited from one of functions
    121  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    122  *         usb_control_request_set().
    123  */
     96
    12497int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
    12598{
     
    169142
    170143/*----------------------------------------------------------------------------*/
    171 /**
    172  * Send Set Idle request to the HID device.
    173  *
    174  * @param hid_dev HID device to send the request to.
    175  * @param duration Duration value (is multiplicated by 4 by the device to
    176  *                 get real duration in miliseconds).
    177  *
    178  * @retval EOK if successful.
    179  * @retval EINVAL if no HID device is given.
    180  * @return Other value inherited from one of functions
    181  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    182  *         usb_control_request_set().
    183  */
    184 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
    185 {
    186         if (hid_dev == NULL) {
    187                 usb_log_error("usbhid_req_set_idle(): no HID device "
    188                     "structure given.\n");
    189                 return EINVAL;
    190         }
    191        
    192         /*
    193          * No need for checking other parameters, as they are checked in
    194          * the called function (usb_control_request_set()).
    195          */
    196        
    197         int rc, sess_rc;
    198        
    199         sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    200         if (sess_rc != EOK) {
    201                 usb_log_warning("Failed to start a session: %s.\n",
    202                     str_error(sess_rc));
    203                 return sess_rc;
    204         }
    205 
    206         usb_log_debug("Sending Set_Idle request to the device ("
    207             "duration: %u, iface: %d).\n", duration, hid_dev->iface);
    208        
    209         uint16_t value = duration << 8;
    210        
    211         rc = usb_control_request_set(&hid_dev->ctrl_pipe,
    212             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    213             USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
    214 
    215         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    216 
    217         if (rc != EOK) {
    218                 usb_log_warning("Error sending output report to the keyboard: "
    219                     "%s.\n", str_error(rc));
    220                 return rc;
    221         }
    222 
    223         if (sess_rc != EOK) {
    224                 usb_log_warning("Error closing session: %s.\n",
    225                     str_error(sess_rc));
    226                 return sess_rc;
    227         }
    228        
    229         return EOK;
    230 }
    231 
    232 /*----------------------------------------------------------------------------*/
    233 /**
    234  * Send Get Report request to the HID device.
    235  *
    236  * @param[in] hid_dev HID device to send the request to.
    237  * @param[in] type Type of the report.
    238  * @param[in][out] buffer Buffer for the report data.
    239  * @param[in] buf_size Size of the buffer (in bytes).
    240  * @param[out] actual_size Actual size of report received from the device
    241  *                         (in bytes).
    242  *
    243  * @retval EOK if successful.
    244  * @retval EINVAL if no HID device is given.
    245  * @return Other value inherited from one of functions
    246  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    247  *         usb_control_request_set().
    248  */
    249 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
    250     uint8_t *buffer, size_t buf_size, size_t *actual_size)
    251 {
    252         if (hid_dev == NULL) {
    253                 usb_log_error("usbhid_req_set_report(): no HID device structure"
    254                     " given.\n");
    255                 return EINVAL;
    256         }
    257        
    258         /*
    259          * No need for checking other parameters, as they are checked in
    260          * the called function (usb_control_request_set()).
    261          */
    262        
    263         int rc, sess_rc;
    264        
    265         sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    266         if (sess_rc != EOK) {
    267                 usb_log_warning("Failed to start a session: %s.\n",
    268                     str_error(sess_rc));
    269                 return sess_rc;
    270         }
    271 
    272         uint16_t value = 0;
    273         value |= (type << 8);
    274        
    275         usb_log_debug("Sending Get_Report request to the device.\n");
    276        
    277         rc = usb_control_request_get(&hid_dev->ctrl_pipe,
    278             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    279             USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
    280             actual_size);
    281 
    282         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    283 
    284         if (rc != EOK) {
    285                 usb_log_warning("Error sending output report to the keyboard: "
    286                     "%s.\n", str_error(rc));
    287                 return rc;
    288         }
    289 
    290         if (sess_rc != EOK) {
    291                 usb_log_warning("Error closing session: %s.\n",
    292                     str_error(sess_rc));
    293                 return sess_rc;
    294         }
    295        
    296         return EOK;
    297 }
    298 
    299 /*----------------------------------------------------------------------------*/
    300 /**
    301  * Send Get Protocol request to the HID device.
    302  *
    303  * @param[in] hid_dev HID device to send the request to.
    304  * @param[out] protocol Current protocol of the device.
    305  *
    306  * @retval EOK if successful.
    307  * @retval EINVAL if no HID device is given.
    308  * @return Other value inherited from one of functions
    309  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    310  *         usb_control_request_set().
    311  */
    312 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
    313 {
    314         if (hid_dev == NULL) {
    315                 usb_log_error("usbhid_req_set_protocol(): no HID device "
    316                     "structure given.\n");
    317                 return EINVAL;
    318         }
    319        
    320         /*
    321          * No need for checking other parameters, as they are checked in
    322          * the called function (usb_control_request_set()).
    323          */
    324        
    325         int rc, sess_rc;
    326        
    327         sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    328         if (sess_rc != EOK) {
    329                 usb_log_warning("Failed to start a session: %s.\n",
    330                     str_error(sess_rc));
    331                 return sess_rc;
    332         }
    333 
    334         usb_log_debug("Sending Get_Protocol request to the device ("
    335             "iface: %d).\n", hid_dev->iface);
    336        
    337         uint8_t buffer[1];
    338         size_t actual_size = 0;
    339        
    340         rc = usb_control_request_get(&hid_dev->ctrl_pipe,
    341             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    342             USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
    343 
    344         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    345 
    346         if (rc != EOK) {
    347                 usb_log_warning("Error sending output report to the keyboard: "
    348                     "%s.\n", str_error(rc));
    349                 return rc;
    350         }
    351 
    352         if (sess_rc != EOK) {
    353                 usb_log_warning("Error closing session: %s.\n",
    354                     str_error(sess_rc));
    355                 return sess_rc;
    356         }
    357        
    358         if (actual_size != 1) {
    359                 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
    360                         actual_size);
    361                 return ELIMIT;
    362         }
    363        
    364         *protocol = buffer[0];
    365        
    366         return EOK;
    367 }
    368 
    369 /*----------------------------------------------------------------------------*/
    370 /**
    371  * Send Get Idle request to the HID device.
    372  *
    373  * @param[in] hid_dev HID device to send the request to.
    374  * @param[out] duration Duration value (multiplicate by 4 to get real duration
    375  *                      in miliseconds).
    376  *
    377  * @retval EOK if successful.
    378  * @retval EINVAL if no HID device is given.
    379  * @return Other value inherited from one of functions
    380  *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
    381  *         usb_control_request_set().
    382  */
    383 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
    384 {
    385         if (hid_dev == NULL) {
    386                 usb_log_error("usbhid_req_set_idle(): no HID device "
    387                     "structure given.\n");
    388                 return EINVAL;
    389         }
    390        
    391         /*
    392          * No need for checking other parameters, as they are checked in
    393          * the called function (usb_control_request_set()).
    394          */
    395        
    396         int rc, sess_rc;
    397        
    398         sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
    399         if (sess_rc != EOK) {
    400                 usb_log_warning("Failed to start a session: %s.\n",
    401                     str_error(sess_rc));
    402                 return sess_rc;
    403         }
    404 
    405         usb_log_debug("Sending Get_Idle request to the device ("
    406             "iface: %d).\n", hid_dev->iface);
    407        
    408         uint16_t value = 0;
    409         uint8_t buffer[1];
    410         size_t actual_size = 0;
    411        
    412         rc = usb_control_request_get(&hid_dev->ctrl_pipe,
    413             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    414             USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1,
    415             &actual_size);
    416 
    417         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    418 
    419         if (rc != EOK) {
    420                 usb_log_warning("Error sending output report to the keyboard: "
    421                     "%s.\n", str_error(rc));
    422                 return rc;
    423         }
    424 
    425         if (sess_rc != EOK) {
    426                 usb_log_warning("Error closing session: %s.\n",
    427                     str_error(sess_rc));
    428                 return sess_rc;
    429         }
    430        
    431         if (actual_size != 1) {
    432                 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
    433                         actual_size);
    434                 return ELIMIT;
    435         }
    436        
    437         *duration = buffer[0];
    438        
    439         return EOK;
    440 }
    441 
    442 /*----------------------------------------------------------------------------*/
    443144
    444145/**
  • uspace/drv/usbhid/hidreq.h

    r72af8da r3e7b7cd  
    5050int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
    5151
    52 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
    53 
    54 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
    55     uint8_t *buffer, size_t buf_size, size_t *actual_size);
    56 
    57 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
    58 
    59 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
    60 
    6152/*----------------------------------------------------------------------------*/
    6253
  • uspace/drv/usbhid/kbddev.c

    r72af8da r3e7b7cd  
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <stdio.h>
     39#include <fibril.h>
    4040
    4141#include <io/keycode.h>
    4242#include <ipc/kbd.h>
    4343#include <async.h>
    44 #include <fibril.h>
    45 #include <fibril_synch.h>
    4644
    4745#include <usb/usb.h>
     
    5755#include "layout.h"
    5856#include "conv.h"
    59 #include "kbdrepeat.h"
    60 
    61 /*----------------------------------------------------------------------------*/
    62 /** Default modifiers when the keyboard is initialized. */
     57
     58/*----------------------------------------------------------------------------*/
     59
    6360static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
    64 
    65 /** Boot protocol report size (key part). */
    6661static const size_t BOOTP_REPORT_SIZE = 6;
    67 
    68 /** Boot protocol total report size. */
    6962static const size_t BOOTP_BUFFER_SIZE = 8;
    70 
    71 /** Boot protocol output report size. */
    7263static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
    73 
    74 /** Boot protocol error key code. */
    75 static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
    76 
    77 /** Default idle rate for keyboards. */
    78 static const uint8_t IDLE_RATE = 0;
    79 
    80 /** Delay before a pressed key starts auto-repeating. */
    81 static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
    82 
    83 /** Delay between two repeats of a pressed key when auto-repeating. */
    84 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
    8564
    8665/** Keyboard polling endpoint description for boot protocol class. */
     
    10079#define NUM_LAYOUTS 3
    10180
    102 /** Keyboard layout map. */
    10381static layout_op_t *layout[NUM_LAYOUTS] = {
    10482        &us_qwerty_op,
     
    11290/* Modifier constants                                                         */
    11391/*----------------------------------------------------------------------------*/
    114 /** Mapping of USB modifier key codes to generic modifier key codes. */
     92
    11593static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    11694        KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     
    133111};
    134112
    135 /**
    136  * Default handler for IPC methods not handled by DDF.
     113/** Default handler for IPC methods not handled by DDF.
    137114 *
    138  * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
    139  * assumes the caller is the console and thus it stores IPC phone to it for
    140  * later use by the driver to notify about key events.
    141  *
    142  * @param fun Device function handling the call.
     115 * @param dev Device handling the call.
    143116 * @param icallid Call id.
    144117 * @param icall Call data.
     
    171144/* Key processing functions                                                   */
    172145/*----------------------------------------------------------------------------*/
    173 /**
    174  * Handles turning of LED lights on and off.
    175  *
    176  * In case of USB keyboards, the LEDs are handled in the driver, not in the
    177  * device. When there should be a change (lock key was pressed), the driver
    178  * uses a Set_Report request sent to the device to set the state of the LEDs.
    179  *
    180  * This functions sets the LED lights according to current settings of modifiers
    181  * kept in the keyboard device structure.
    182  *
    183  * @param kbd_dev Keyboard device structure.
    184  */
     146
    185147static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev)
    186148{
    187149        uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
    188150        int rc= 0;
     151        unsigned i;
    189152       
    190153        memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
     
    214177        }
    215178       
    216         usb_log_debug("Output report buffer: %s\n",
    217             usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
    218        
     179        // TODO: REFACTOR!!!
     180       
     181        usb_log_debug("Output report buffer: ");
     182        for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
     183                usb_log_debug("0x%x ", buffer[i]);
     184        }
     185        usb_log_debug("\n");
     186       
     187        uint16_t value = 0;
     188        value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
     189
    219190        assert(kbd_dev->hid_dev != NULL);
    220191        assert(kbd_dev->hid_dev->initialized);
    221         usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT,
    222             buffer, BOOTP_BUFFER_OUT_SIZE);
    223 }
    224 
    225 /*----------------------------------------------------------------------------*/
    226 /**
    227  * Processes key events.
    228  *
    229  * @note This function was copied from AT keyboard driver and modified to suit
    230  *       USB keyboard.
    231  *
    232  * @note Lock keys are not sent to the console, as they are completely handled
    233  *       in the driver. It may, however, be required later that the driver
    234  *       sends also these keys to application (otherwise it cannot use those
    235  *       keys at all).
    236  *
    237  * @param kbd_dev Keyboard device structure.
    238  * @param type Type of the event (press / release). Recognized values:
    239  *             KEY_PRESS, KEY_RELEASE
    240  * @param key Key code of the key according to HID Usage Tables.
    241  */
    242 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
     192        usbhid_req_set_report(kbd_dev->hid_dev, value, buffer,
     193            BOOTP_BUFFER_OUT_SIZE);
     194}
     195
     196/*----------------------------------------------------------------------------*/
     197
     198static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
     199    unsigned int key)
    243200{
    244201        console_event_t ev;
    245202        unsigned mod_mask;
    246203
    247         /*
    248          * These parts are copy-pasted from the AT keyboard driver.
    249          *
    250          * They definitely require some refactoring, but will keep it for later
    251          * when the console and keyboard system is changed in HelenOS.
    252          */
     204        // TODO: replace by our own parsing?? or are the key codes identical??
    253205        switch (key) {
    254206        case KC_LCTRL: mod_mask = KM_LCTRL; break;
     
    276228
    277229        if (mod_mask != 0) {
     230                usb_log_debug2("\n\nChanging mods and lock keys\n");
     231                usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
     232                usb_log_debug2("\nLock keys before:0x%x\n\n",
     233                    kbd_dev->lock_keys);
     234               
    278235                if (type == KEY_PRESS) {
     236                        usb_log_debug2("\nKey pressed.\n");
    279237                        /*
    280238                         * Only change lock state on transition from released
     
    282240                         * up the lock state.
    283241                         */
    284                         unsigned int locks_old = kbd_dev->lock_keys;
    285                        
    286242                        kbd_dev->mods =
    287243                            kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
     
    289245
    290246                        /* Update keyboard lock indicator lights. */
    291                         if (kbd_dev->lock_keys != locks_old) {
    292                                 usbhid_kbd_set_led(kbd_dev);
    293                         }
     247                        usbhid_kbd_set_led(kbd_dev);
    294248                } else {
     249                        usb_log_debug2("\nKey released.\n");
    295250                        kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
    296251                }
    297252        }
    298253
     254        usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
     255        usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
     256       
    299257        if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
    300258                // do not send anything to the console, this is our business
     
    323281        ev.key = key;
    324282        ev.mods = kbd_dev->mods;
     283       
     284        if (ev.mods & KM_NUM_LOCK) {
     285                usb_log_debug("\n\nNum Lock turned on.\n\n");
     286        }
    325287
    326288        ev.c = layout[active_layout]->parse_ev(&ev);
     
    338300
    339301/*----------------------------------------------------------------------------*/
    340 /**
    341  * Checks if modifiers were pressed or released and generates key events.
    342  *
    343  * @param kbd_dev Keyboard device structure.
    344  * @param modifiers Bitmap of modifiers.
    345  *
    346  * @sa usbhid_kbd_push_ev()
    347  */
     302
    348303static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    349304    uint8_t modifiers)
     
    381336
    382337/*----------------------------------------------------------------------------*/
    383 /**
    384  * Checks if some keys were pressed or released and generates key events.
    385  *
    386  * An event is created only when key is pressed or released. Besides handling
    387  * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about
    388  * key presses and releases (see usbhid_kbd_repeat_start() and
    389  * usbhid_kbd_repeat_stop()).
    390  *
    391  * @param kbd_dev Keyboard device structure.
    392  * @param key_codes Parsed keyboard report - codes of currently pressed keys
    393  *                  according to HID Usage Tables.
    394  * @param count Number of key codes in report (size of the report).
    395  *
    396  * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop()
    397  */
     338
    398339static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,
    399     const uint8_t *key_codes, size_t count)
    400 {
     340    const uint8_t *key_codes)
     341{
     342        // TODO: phantom state!!
     343       
    401344        unsigned int key;
    402345        unsigned int i, j;
    403346       
    404         /*
    405          * First of all, check if the kbd have reported phantom state.
    406          */
    407         i = 0;
    408         // all fields should report Error Rollover
    409         while (i < count &&
    410             key_codes[i] == BOOTP_ERROR_ROLLOVER) {
    411                 ++i;
    412         }
    413         if (i == count) {
    414                 usb_log_debug("Phantom state occured.\n");
    415                 // phantom state, do nothing
    416                 return;
    417         }
    418        
    419         /* TODO: quite dummy right now, think of better implementation */
    420         assert(count == kbd_dev->key_count);
     347        // TODO: quite dummy right now, think of better implementation
    421348       
    422349        /*
    423350         * 1) Key releases
    424351         */
    425         for (j = 0; j < count; ++j) {
     352        for (j = 0; j < kbd_dev->keycode_count; ++j) {
    426353                // try to find the old key in the new key list
    427354                i = 0;
    428                 while (i < kbd_dev->key_count
    429                     && key_codes[i] != kbd_dev->keys[j]) {
     355                while (i < kbd_dev->keycode_count
     356                    && key_codes[i] != kbd_dev->keycodes[j]) {
    430357                        ++i;
    431358                }
    432359               
    433                 if (i == count) {
     360                if (i == kbd_dev->keycode_count) {
    434361                        // not found, i.e. the key was released
    435                         key = usbhid_parse_scancode(kbd_dev->keys[j]);
    436                         usbhid_kbd_repeat_stop(kbd_dev, key);
     362                        key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
    437363                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    438                         usb_log_debug2("Key released: %d\n", key);
     364                        usb_log_debug2("\nKey released: %d\n", key);
    439365                } else {
    440366                        // found, nothing happens
     
    445371         * 1) Key presses
    446372         */
    447         for (i = 0; i < kbd_dev->key_count; ++i) {
     373        for (i = 0; i < kbd_dev->keycode_count; ++i) {
    448374                // try to find the new key in the old key list
    449375                j = 0;
    450                 while (j < count && kbd_dev->keys[j] != key_codes[i]) {
     376                while (j < kbd_dev->keycode_count
     377                    && kbd_dev->keycodes[j] != key_codes[i]) {
    451378                        ++j;
    452379                }
    453380               
    454                 if (j == count) {
     381                if (j == kbd_dev->keycode_count) {
    455382                        // not found, i.e. new key pressed
    456383                        key = usbhid_parse_scancode(key_codes[i]);
    457                         usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
     384                        usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
    458385                            key_codes[i]);
    459386                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
    460                         usbhid_kbd_repeat_start(kbd_dev, key);
    461387                } else {
    462388                        // found, nothing happens
     
    464390        }
    465391       
    466         memcpy(kbd_dev->keys, key_codes, count);
    467 
    468         usb_log_debug("New stored keycodes: %s\n",
    469             usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
     392        memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
     393       
     394        usb_log_debug2("\nNew stored keycodes: ");
     395        for (i = 0; i < kbd_dev->keycode_count; ++i) {
     396                usb_log_debug2("%d ", kbd_dev->keycodes[i]);
     397        }
    470398}
    471399
     
    473401/* Callbacks for parser                                                       */
    474402/*----------------------------------------------------------------------------*/
    475 /**
    476  * Callback function for the HID report parser.
    477  *
    478  * This function is called by the HID report parser with the parsed report.
    479  * The parsed report is used to check if any events occured (key was pressed or
    480  * released, modifier was pressed or released).
    481  *
    482  * @param key_codes Parsed keyboard report - codes of currently pressed keys
    483  *                  according to HID Usage Tables.
    484  * @param count Number of key codes in report (size of the report).
    485  * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
    486  * @param arg User-specified argument. Expects pointer to the keyboard device
    487  *            structure representing the keyboard.
    488  *
    489  * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes()
    490  */
     403
    491404static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    492405    uint8_t modifiers, void *arg)
     
    497410                return;
    498411        }
     412
     413        usb_log_debug2("Got keys from parser: ");
     414        unsigned i;
     415        for (i = 0; i < count; ++i) {
     416                usb_log_debug2("%d ", key_codes[i]);
     417        }
     418        usb_log_debug2("\n");
    499419       
    500420        usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
    501421        assert(kbd_dev != NULL);
    502 
    503         usb_log_debug("Got keys from parser: %s\n",
    504             usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0));
    505        
    506         if (count != kbd_dev->key_count) {
     422       
     423        if (count != kbd_dev->keycode_count) {
    507424                usb_log_warning("Number of received keycodes (%d) differs from"
    508                     " expected number (%d).\n", count, kbd_dev->key_count);
     425                    " expected number (%d).\n", count, kbd_dev->keycode_count);
    509426                return;
    510427        }
    511428       
    512429        usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
    513         usbhid_kbd_check_key_changes(kbd_dev, key_codes, count);
     430        usbhid_kbd_check_key_changes(kbd_dev, key_codes);
    514431}
    515432
     
    517434/* General kbd functions                                                      */
    518435/*----------------------------------------------------------------------------*/
    519 /**
    520  * Processes data received from the device in form of report.
    521  *
    522  * This function uses the HID report parser to translate the data received from
    523  * the device into generic USB HID key codes and into generic modifiers bitmap.
    524  * The parser then calls the given callback (usbhid_kbd_process_keycodes()).
    525  *
    526  * @note Currently, only the boot protocol is supported.
    527  *
    528  * @param kbd_dev Keyboard device structure (must be initialized).
    529  * @param buffer Data from the keyboard (i.e. the report).
    530  * @param actual_size Size of the data from keyboard (report size) in bytes.
    531  *
    532  * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
    533  */
     436
    534437static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
    535438                                    uint8_t *buffer, size_t actual_size)
     
    541444        callbacks->keyboard = usbhid_kbd_process_keycodes;
    542445
    543         usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with "
    544             "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
     446        //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
     447        //    NULL);
     448        /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
     449            " %zu\n", actual_size);*/
     450        //dump_buffer("bufffer: ", buffer, actual_size);
    545451       
    546452        int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
     
    556462/* HID/KBD structure manipulation                                             */
    557463/*----------------------------------------------------------------------------*/
    558 /**
    559  * Creates a new USB/HID keyboard structure.
    560  *
    561  * The structure returned by this function is not initialized. Use
    562  * usbhid_kbd_init() to initialize it prior to polling.
    563  *
    564  * @return New uninitialized structure for representing a USB/HID keyboard or
    565  *         NULL if not successful (memory error).
    566  */
     464
    567465static usbhid_kbd_t *usbhid_kbd_new(void)
    568466{
     
    590488
    591489/*----------------------------------------------------------------------------*/
    592 /**
    593  * Properly destroys the USB/HID keyboard structure.
    594  *
    595  * @param kbd_dev Pointer to the structure to be destroyed.
    596  */
     490
    597491static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    598492{
     
    609503        }
    610504       
    611         if ((*kbd_dev)->repeat_mtx != NULL) {
    612                 /* TODO: replace by some check and wait */
    613                 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    614                 free((*kbd_dev)->repeat_mtx);
    615         }
    616        
    617505        free(*kbd_dev);
    618506        *kbd_dev = NULL;
     
    620508
    621509/*----------------------------------------------------------------------------*/
    622 /**
    623  * Initialization of the USB/HID keyboard structure.
    624  *
    625  * This functions initializes required structures from the device's descriptors.
    626  *
    627  * During initialization, the keyboard is switched into boot protocol, the idle
    628  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    629  * when a key is pressed or released. Finally, the LED lights are turned on
    630  * according to the default setup of lock keys.
    631  *
    632  * @note By default, the keyboards is initialized with Num Lock turned on and
    633  *       other locks turned off.
    634  *
    635  * @param kbd_dev Keyboard device structure to be initialized.
    636  * @param dev DDF device structure of the keyboard.
    637  *
    638  * @retval EOK if successful.
    639  * @retval EINVAL if some parameter is not given.
    640  * @return Other value inherited from function usbhid_dev_init().
    641  */
     510
    642511static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
    643512{
     
    674543       
    675544        // save the size of the report (boot protocol report by default)
    676         kbd_dev->key_count = BOOTP_REPORT_SIZE;
    677         kbd_dev->keys = (uint8_t *)calloc(
    678             kbd_dev->key_count, sizeof(uint8_t));
    679        
    680         if (kbd_dev->keys == NULL) {
     545        kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
     546        kbd_dev->keycodes = (uint8_t *)calloc(
     547            kbd_dev->keycode_count, sizeof(uint8_t));
     548       
     549        if (kbd_dev->keycodes == NULL) {
    681550                usb_log_fatal("No memory!\n");
    682                 return ENOMEM;
     551                return rc;
    683552        }
    684553       
     
    687556        kbd_dev->lock_keys = 0;
    688557       
    689         kbd_dev->repeat.key_new = 0;
    690         kbd_dev->repeat.key_repeated = 0;
    691         kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    692         kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    693        
    694         kbd_dev->repeat_mtx = (fibril_mutex_t *)(
    695             malloc(sizeof(fibril_mutex_t)));
    696         if (kbd_dev->repeat_mtx == NULL) {
    697                 usb_log_fatal("No memory!\n");
    698                 free(kbd_dev->keys);
    699                 return ENOMEM;
    700         }
    701        
    702         fibril_mutex_initialize(kbd_dev->repeat_mtx);
    703        
    704558        /*
    705559         * Set boot protocol.
    706560         * Set LEDs according to initial setup.
    707          * Set Idle rate
    708561         */
    709562        assert(kbd_dev->hid_dev != NULL);
     
    713566        usbhid_kbd_set_led(kbd_dev);
    714567       
    715         usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
    716        
    717568        kbd_dev->initialized = 1;
    718569        usb_log_info("HID/KBD device structure initialized.\n");
     
    724575/* HID/KBD polling                                                            */
    725576/*----------------------------------------------------------------------------*/
    726 /**
    727  * Main keyboard polling function.
    728  *
    729  * This function uses the Interrupt In pipe of the keyboard to poll for events.
    730  * The keyboard is initialized in a way that it reports only when a key is
    731  * pressed or released, so there is no actual need for any sleeping between
    732  * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
    733  *
    734  * @param kbd_dev Initialized keyboard structure representing the device to
    735  *                poll.
    736  *
    737  * @sa usbhid_kbd_process_data()
    738  */
     577
    739578static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
    740579{
     
    759598                        usb_log_warning("Failed to start a session: %s.\n",
    760599                            str_error(sess_rc));
    761                         break;
     600                        continue;
    762601                }
    763602
     
    771610                        usb_log_warning("Error polling the keyboard: %s.\n",
    772611                            str_error(rc));
    773                         break;
     612                        continue;
    774613                }
    775614
     
    777616                        usb_log_warning("Error closing session: %s.\n",
    778617                            str_error(sess_rc));
    779                         break;
     618                        continue;
    780619                }
    781620
     
    795634                usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
    796635               
    797                 // disabled for now, no reason to sleep
    798                 //async_usleep(kbd_dev->hid_dev->poll_interval);
    799         }
    800 }
    801 
    802 /*----------------------------------------------------------------------------*/
    803 /**
    804  * Function executed by the main driver fibril.
    805  *
    806  * Just starts polling the keyboard for events.
    807  *
    808  * @param arg Initialized keyboard device structure (of type usbhid_kbd_t)
    809  *            representing the device.
    810  *
    811  * @retval EOK if the fibril finished polling the device.
    812  * @retval EINVAL if no device was given in the argument.
    813  *
    814  * @sa usbhid_kbd_poll()
    815  *
    816  * @todo Change return value - only case when the fibril finishes is in case
    817  *       of some error, so the error should probably be propagated from function
    818  *       usbhid_kbd_poll() to here and up.
    819  */
     636                async_usleep(kbd_dev->hid_dev->poll_interval);
     637        }
     638
     639        // not reached
     640        assert(0);
     641}
     642
     643/*----------------------------------------------------------------------------*/
     644
    820645static int usbhid_kbd_fibril(void *arg)
    821646{
     
    839664/* API functions                                                              */
    840665/*----------------------------------------------------------------------------*/
    841 /**
    842  * Function for adding a new device of type USB/HID/keyboard.
    843  *
    844  * This functions initializes required structures from the device's descriptors
    845  * and starts new fibril for polling the keyboard for events and another one for
    846  * handling auto-repeat of keys.
    847  *
    848  * During initialization, the keyboard is switched into boot protocol, the idle
    849  * rate is set to 0 (infinity), resulting in the keyboard only reporting event
    850  * when a key is pressed or released. Finally, the LED lights are turned on
    851  * according to the default setup of lock keys.
    852  *
    853  * @note By default, the keyboards is initialized with Num Lock turned on and
    854  *       other locks turned off.
    855  * @note Currently supports only boot-protocol keyboards.
    856  *
    857  * @param dev Device to add.
    858  *
    859  * @retval EOK if successful.
    860  * @retval ENOMEM if there
    861  * @return Other error code inherited from one of functions usbhid_kbd_init(),
    862  *         ddf_fun_bind() and ddf_fun_add_to_class().
    863  *
    864  * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
    865  */
     666
    866667int usbhid_kbd_try_add_device(ddf_dev_t *dev)
    867668{
     
    885686                    "structure.\n");
    886687                ddf_fun_destroy(kbd_fun);
    887                 return ENOMEM;  // TODO: some other code??
     688                return EINVAL;  // TODO: some other code??
    888689        }
    889690       
     
    934735        }
    935736        fibril_add_ready(fid);
    936        
    937         /*
    938          * Create new fibril for auto-repeat
    939          */
    940         fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
    941         if (fid == 0) {
    942                 usb_log_error("Failed to start fibril for KBD auto-repeat");
    943                 return ENOMEM;
    944         }
    945         fibril_add_ready(fid);
    946737
    947738        (void)keyboard_ops;
  • uspace/drv/usbhid/kbddev.h

    r72af8da r3e7b7cd  
    3939#include <stdint.h>
    4040
    41 #include <fibril_synch.h>
    42 
    4341#include <usb/classes/hid.h>
    4442#include <ddf/driver.h>
     
    4846
    4947/*----------------------------------------------------------------------------*/
     48
    5049/**
    51  * Structure for keeping information needed for auto-repeat of keys.
     50 * @brief USB/HID keyboard device type.
    5251 */
    5352typedef struct {
    54         /** Last pressed key. */
    55         unsigned int key_new;
    56         /** Key to be repeated. */
    57         unsigned int key_repeated;
    58         /** Delay before first repeat in microseconds. */
    59         unsigned int delay_before;
    60         /** Delay between repeats in microseconds. */
    61         unsigned int delay_between;
    62 } usbhid_kbd_repeat_t;
    63 
    64 /**
    65  * USB/HID keyboard device type.
    66  *
    67  * Holds a reference to generic USB/HID device structure and keyboard-specific
    68  * data, such as currently pressed keys, modifiers and lock keys.
    69  *
    70  * Also holds a IPC phone to the console (since there is now no other way to
    71  * communicate with it).
    72  *
    73  * @note Storing active lock keys in this structure results in their setting
    74  *       being device-specific.
    75  */
    76 typedef struct {
    77         /** Structure holding generic USB/HID device information. */
    7853        usbhid_dev_t *hid_dev;
    7954       
    80         /** Currently pressed keys (not translated to key codes). */
    81         uint8_t *keys;
    82         /** Count of stored keys (i.e. number of keys in the report). */
    83         size_t key_count;
    84         /** Currently pressed modifiers (bitmap). */
     55        uint8_t *keycodes;
     56        size_t keycode_count;
    8557        uint8_t modifiers;
    8658       
    87         /** Currently active modifiers including locks. Sent to the console. */
    8859        unsigned mods;
    89        
    90         /** Currently active lock keys. */
    9160        unsigned lock_keys;
    9261       
    93         /** IPC phone to the console device (for sending key events). */
    9462        int console_phone;
    9563       
    96         /** Information for auto-repeat of keys. */
    97         usbhid_kbd_repeat_t repeat;
    98        
    99         /** Mutex for accessing the information about auto-repeat. */
    100         fibril_mutex_t *repeat_mtx;
    101        
    102         /** State of the structure (for checking before use). */
    10364        int initialized;
    10465} usbhid_kbd_t;
     
    10869int usbhid_kbd_try_add_device(ddf_dev_t *dev);
    10970
    110 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
    111 
    11271#endif /* USBHID_KBDDEV_H_ */
    11372
  • uspace/drv/usbhid/main.c

    r72af8da r3e7b7cd  
    4747
    4848/*----------------------------------------------------------------------------*/
    49 /**
    50  * Callback for passing a new device to the driver.
    51  *
    52  * @note Currently, only boot-protocol keyboards are supported by this driver.
    53  *
    54  * @param dev Structure representing the new device.
    55  *
    56  * @retval EOK if successful.
    57  * @retval EREFUSED if the device is not supported.
    58  */
     49
    5950static int usbhid_add_device(ddf_dev_t *dev)
    6051{
     
    8980int main(int argc, char *argv[])
    9081{
    91         usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
     82        usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
    9283        return ddf_driver_main(&kbd_driver);
    9384}
  • uspace/drv/usbhub/usbhub.c

    r72af8da r3e7b7cd  
    118118                dprintf(USB_LOG_LEVEL_ERROR,
    119119                                "could not initialize connection to device endpoint, errno %d",opResult);
    120                 return opResult;
    121         }
    122 
    123         opResult = usb_endpoint_pipe_probe_default_control(&hub->endpoints.control);
    124         if (opResult != EOK) {
    125                 dprintf(USB_LOG_LEVEL_ERROR, "failed probing endpoint 0, %d", opResult);
    126                 return opResult;
    127         }
    128 
    129         return EOK;
     120        }
     121        return opResult;
    130122}
    131123
     
    241233        dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
    242234        usb_endpoint_pipe_start_session(&result->endpoints.control);
    243         opResult = usb_request_set_configuration(&result->endpoints.control, 1);
    244         assert(opResult == EOK);
    245 
    246235        opResult = usb_request_get_descriptor(&result->endpoints.control,
    247236                        USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     
    438427                        &new_device_pipe,
    439428                        &new_device_connection);
    440         usb_endpoint_pipe_probe_default_control(&new_device_pipe);
    441429        /// \TODO get highspeed info
    442430        usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
  • uspace/drv/usbmid/main.c

    r72af8da r3e7b7cd  
    4444#include "usbmid.h"
    4545
    46 /** Callback when new MID device is attached to the host.
    47  *
    48  * @param gen_dev Generic DDF device representing the new device.
    49  * @return Error code.
    50  */
    5146static int usbmid_add_device(ddf_dev_t *gen_dev)
    5247{
     
    9186}
    9287
    93 /** USB MID driver ops. */
    9488static driver_ops_t mid_driver_ops = {
    9589        .add_device = usbmid_add_device,
    9690};
    9791
    98 /** USB MID driver. */
    9992static driver_t mid_driver = {
    10093        .name = NAME,
  • uspace/drv/usbmid/usbmid.c

    r72af8da r3e7b7cd  
    6767}
    6868
    69 /** DDF interface of the child - interface function. */
    7069static usb_iface_t child_usb_iface = {
    7170        .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
     
    7473};
    7574
    76 /** Operations for children - interface functions. */
     75
    7776static ddf_dev_ops_t child_device_ops = {
    7877        .interfaces[USB_DEV_IFACE] = &child_usb_iface
    7978};
    8079
    81 /** Operations of the device itself. */
    8280static ddf_dev_ops_t mid_device_ops = {
    8381        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
     
    116114                return NULL;
    117115        }
    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         }
    125116
    126117        mid->dev = dev;
     
    132123/** Create new interface for USB MID device.
    133124 *
    134  * @param fun Backing generic DDF device function (representing interface).
     125 * @param dev Backing generic DDF child device (representing interface).
    135126 * @param iface_no Interface number.
    136127 * @return New interface.
  • uspace/drv/usbmid/usbmid.h

    r72af8da r3e7b7cd  
    4444#define NAME "usbmid"
    4545
    46 /** USB MID device container. */
    4746typedef struct {
    4847        /** Device container. */
     
    5554} usbmid_device_t;
    5655
    57 
    58 /** Container for single interface in a MID device. */
    5956typedef struct {
    6057        /** Function container. */
  • uspace/drv/usbmouse/init.c

    r72af8da r3e7b7cd  
    4242
    4343/** Mouse polling endpoint description for boot protocol subclass. */
    44 usb_endpoint_description_t poll_endpoint_description = {
     44static usb_endpoint_description_t poll_endpoint_description = {
    4545        .transfer_type = USB_TRANSFER_INTERRUPT,
    4646        .direction = USB_DIRECTION_IN,
     
    5151};
    5252
     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 */
     61static 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}
     101
    53102static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    54 /** Device ops for USB mouse. */
    55103static ddf_dev_ops_t mouse_ops = {
    56104        .default_handler = default_connection_handler
     
    59107/** Default handler for IPC methods not handled by DDF.
    60108 *
    61  * @param fun Device function handling the call.
     109 * @param dev Device handling the call.
    62110 * @param icallid Call id.
    63111 * @param icall Call data.
     
    87135}
    88136
    89 /** Create USB mouse device.
    90  *
    91  * The mouse device is stored into <code>dev-&gt;driver_data</code>.
    92  *
    93  * @param dev Generic device.
    94  * @return Error code.
    95  */
    96 int usb_mouse_create(usb_device_t *dev)
     137
     138int usb_mouse_create(ddf_dev_t *dev)
    97139{
    98140        usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
     
    100142                return ENOMEM;
    101143        }
    102         mouse->dev = dev;
     144        mouse->device = dev;
    103145        mouse->console_phone = -1;
    104146
    105147        int rc;
    106148
     149        /* Initialize the backing connection. */
     150        rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);
     151        if (rc != EOK) {
     152                goto leave;
     153        }
     154
     155        /* Initialize the default control pipe. */
     156        rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,
     157            &mouse->wire);
     158        if (rc != EOK) {
     159                goto leave;
     160        }
     161
     162        rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);
     163        if (rc != EOK) {
     164                goto leave;
     165        }
     166
     167        rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));
     168
     169        /* We can ignore error here. */
     170        usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);
     171
     172        if (rc != EOK) {
     173                goto leave;
     174        }
     175
    107176        /* Create DDF function. */
    108         mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
     177        mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
    109178        if (mouse->mouse_fun == NULL) {
    110179                rc = ENOMEM;
  • uspace/drv/usbmouse/main.c

    r72af8da r3e7b7cd  
    3939#include <str_error.h>
    4040
    41 /** Callback when new mouse device is attached and recognised by DDF.
    42  *
    43  * @param dev Representation of a generic DDF device.
    44  * @return Error code.
    45  */
    46 static int usbmouse_add_device(usb_device_t *dev)
     41static int usbmouse_add_device(ddf_dev_t *dev)
    4742{
    4843        int rc = usb_mouse_create(dev);
     
    5348        }
    5449
    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;
     50        fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
     51        if (poll_fibril == 0) {
     52                usb_log_error("Failed to initialize polling fibril.\n");
     53                /* FIXME: free allocated resources. */
     54                return ENOMEM;
    6555        }
    6656
     57        fibril_add_ready(poll_fibril);
     58
    6759        usb_log_info("controlling new mouse (handle %llu).\n",
    68             dev->ddf_dev->handle);
     60            dev->handle);
    6961
    7062        return EOK;
    7163}
    7264
    73 /** USB mouse driver ops. */
    74 static usb_driver_ops_t mouse_driver_ops = {
     65static driver_ops_t mouse_driver_ops = {
    7566        .add_device = usbmouse_add_device,
    7667};
    7768
    78 static usb_endpoint_description_t *endpoints[] = {
    79         &poll_endpoint_description,
    80         NULL
    81 };
    82 
    83 /** USB mouse driver. */
    84 static usb_driver_t mouse_driver = {
     69static driver_t mouse_driver = {
    8570        .name = NAME,
    86         .ops = &mouse_driver_ops,
    87         .endpoints = endpoints
     71        .driver_ops = &mouse_driver_ops
    8872};
    8973
     
    9276        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    9377
    94         return usb_driver_main(&mouse_driver);
     78        return ddf_driver_main(&mouse_driver);
    9579}
    9680
  • uspace/drv/usbmouse/mouse.c

    r72af8da r3e7b7cd  
    3737#include <usb/debug.h>
    3838#include <errno.h>
    39 #include <str_error.h>
    4039#include <ipc/mouse.h>
    4140
    42 /** Mouse polling callback.
    43  *
    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.
    49  */
    50 bool usb_mouse_polling_callback(usb_device_t *dev,
    51     uint8_t *buffer, size_t buffer_size, void *arg)
     41int usb_mouse_polling_fibril(void *arg)
    5242{
    53         usb_mouse_t *mouse = (usb_mouse_t *) arg;
     43        assert(arg != NULL);
     44        ddf_dev_t *dev = (ddf_dev_t *) arg;
     45        usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
    5446
    55         usb_log_debug2("got buffer: %s.\n",
    56             usb_debug_str_buffer(buffer, buffer_size, 0));
     47        assert(mouse);
    5748
    58         uint8_t butt = buffer[0];
    59         char str_buttons[4] = {
    60                 butt & 1 ? '#' : '.',
    61                 butt & 2 ? '#' : '.',
    62                 butt & 4 ? '#' : '.',
    63                 0
    64         };
     49        size_t buffer_size = mouse->poll_pipe.max_packet_size;
    6550
    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;
     51        if (buffer_size < 4) {
     52                usb_log_error("Weird mouse, results will be skewed.\n");
     53                buffer_size = 4;
    7854        }
    7955
    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                 }
     56        uint8_t *buffer = malloc(buffer_size);
     57        if (buffer == NULL) {
     58                usb_log_error("Out of memory, poll fibril aborted.\n");
     59                return ENOMEM;
    9460        }
    9561
    96         usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
    97             str_buttons, shift_x, shift_y, wheel);
     62        while (true) {
     63                async_usleep(mouse->poll_interval_us);
    9864
    99         /* Guess. */
    100         async_usleep(1000);
     65                size_t actual_size;
    10166
    102         return true;
     67                /* FIXME: check for errors. */
     68                usb_endpoint_pipe_start_session(&mouse->poll_pipe);
     69
     70                usb_endpoint_pipe_read(&mouse->poll_pipe,
     71                    buffer, buffer_size, &actual_size);
     72
     73                usb_endpoint_pipe_end_session(&mouse->poll_pipe);
     74
     75                uint8_t butt = buffer[0];
     76                char str_buttons[4] = {
     77                        butt & 1 ? '#' : '.',
     78                        butt & 2 ? '#' : '.',
     79                        butt & 4 ? '#' : '.',
     80                        0
     81                };
     82
     83                int shift_x = ((int) buffer[1]) - 127;
     84                int shift_y = ((int) buffer[2]) - 127;
     85                int wheel = ((int) buffer[3]) - 127;
     86
     87                if (buffer[1] == 0) {
     88                        shift_x = 0;
     89                }
     90                if (buffer[2] == 0) {
     91                        shift_y = 0;
     92                }
     93                if (buffer[3] == 0) {
     94                        wheel = 0;
     95                }
     96
     97                if (mouse->console_phone >= 0) {
     98                        if ((shift_x != 0) || (shift_y != 0)) {
     99                                /* FIXME: guessed for QEMU */
     100                                async_req_2_0(mouse->console_phone,
     101                                    MEVENT_MOVE,
     102                                    - shift_x / 10,  - shift_y / 10);
     103                        }
     104                        if (butt) {
     105                                /* FIXME: proper button clicking. */
     106                                async_req_2_0(mouse->console_phone,
     107                                    MEVENT_BUTTON, 1, 1);
     108                                async_req_2_0(mouse->console_phone,
     109                                    MEVENT_BUTTON, 1, 0);
     110                        }
     111                }
     112
     113                usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     114                   str_buttons, shift_x, shift_y, wheel);
     115        }
     116
     117        return EOK;
    103118}
    104119
    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  */
    112 void 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;
    116 
    117         async_hangup(mouse->console_phone);
    118         mouse->console_phone = -1;
    119 }
    120120
    121121/**
  • uspace/drv/usbmouse/mouse.h

    r72af8da r3e7b7cd  
    3737#define USBMOUSE_MOUSE_H_
    3838
    39 #include <usb/devdrv.h>
     39#include <ddf/driver.h>
    4040#include <usb/pipes.h>
    4141#include <time.h>
     
    4343#define NAME "usbmouse"
    4444
    45 /** Container for USB mouse device. */
    4645typedef struct {
    47         /** Generic device container. */
    48         usb_device_t *dev;
    49         /** Function representing the device. */
     46        ddf_dev_t *device;
    5047        ddf_fun_t *mouse_fun;
    51         /** Polling interval in microseconds. */
     48        usb_device_connection_t wire;
     49        usb_endpoint_pipe_t ctrl_pipe;
     50        usb_endpoint_pipe_t poll_pipe;
    5251        suseconds_t poll_interval_us;
    53         /** IPC phone to console (consumer). */
    5452        int console_phone;
    5553} usb_mouse_t;
    5654
    57 #define POLL_PIPE(dev) ((dev)->pipes[0].pipe)
     55int usb_mouse_create(ddf_dev_t *);
    5856
    59 extern usb_endpoint_description_t poll_endpoint_description;
    60 
    61 int usb_mouse_create(usb_device_t *);
    62 
    63 bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *);
    64 void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
     57int usb_mouse_polling_fibril(void *);
    6558
    6659#endif
  • uspace/drv/vhc/conndev.c

    r72af8da r3e7b7cd  
    110110/** Callback for DDF when client disconnects.
    111111 *
    112  * @param fun Device function the client was connected to.
     112 * @param d Device the client was connected to.
    113113 */
    114114void on_client_close(ddf_fun_t *fun)
  • uspace/lib/block/libblock.c

    r72af8da r3e7b7cd  
    411411        l = hash_table_find(&cache->block_hash, &key);
    412412        if (l) {
    413 found:
    414413                /*
    415414                 * We found the block in the cache.
     
    494493                                        fibril_mutex_unlock(&b->lock);
    495494                                        goto retry;
    496                                 }
    497                                 l = hash_table_find(&cache->block_hash, &key);
    498                                 if (l) {
    499                                         /*
    500                                          * Someone else must have already
    501                                          * instantiated the block while we were
    502                                          * not holding the cache lock.
    503                                          * Leave the recycled block on the
    504                                          * freelist and continue as if we
    505                                          * found the block of interest during
    506                                          * the first try.
    507                                          */
    508                                         fibril_mutex_unlock(&b->lock);
    509                                         goto found;
    510495                                }
    511496
  • uspace/lib/drv/generic/remote_usbhc.c

    r72af8da r3e7b7cd  
    5555static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5656static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    57 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    58 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5957//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    6058
     
    7573
    7674        remote_usbhc_control_write,
    77         remote_usbhc_control_read,
    78 
    79         remote_usbhc_register_endpoint,
    80         remote_usbhc_unregister_endpoint
     75        remote_usbhc_control_read
    8176};
    8277
     
    527522
    528523
    529 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    530     ipc_callid_t callid, ipc_call_t *call)
    531 {
    532         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    533 
    534         if (!usb_iface->register_endpoint) {
    535                 async_answer_0(callid, ENOTSUP);
    536                 return;
    537         }
    538 
    539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \
    540         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
    541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \
    542         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
    543 
    544         INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
    545         INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
    546         INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
    547         INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
    548 
    549 #undef INIT_FROM_HIGH_DATA
    550 #undef INIT_FROM_LOW_DATA
    551 
    552         size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
    553         unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
    554 
    555         int rc = usb_iface->register_endpoint(fun, address, endpoint,
    556             transfer_type, direction, max_packet_size, interval);
    557 
    558         async_answer_0(callid, rc);
    559 }
    560 
    561 
    562 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
    563     ipc_callid_t callid, ipc_call_t *call)
    564 {
    565         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    566 
    567         if (!usb_iface->unregister_endpoint) {
    568                 async_answer_0(callid, ENOTSUP);
    569                 return;
    570         }
    571 
    572         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    573         usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
    574         usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
    575 
    576         int rc = usb_iface->unregister_endpoint(fun,
    577             address, endpoint, direction);
    578 
    579         async_answer_0(callid, rc);
    580 }
    581 
    582524
    583525/**
  • uspace/lib/drv/include/usbhc_iface.h

    r72af8da r3e7b7cd  
    167167        IPC_M_USBHC_CONTROL_READ,
    168168
    169         /** Register endpoint attributes at host controller.
    170          * This is used to reserve portion of USB bandwidth.
    171          * Parameters:
    172          * - USB address + endpoint number (ADDR * 256 + EP)
    173          * - transfer type + direction (TYPE * 256 + DIR)
    174          * - maximum packet size
    175          * - interval (in milliseconds)
    176          * Answer:
    177          * - EOK - reservation successful
    178          * - ELIMIT - not enough bandwidth to satisfy the request
    179          */
    180         IPC_M_USBHC_REGISTER_ENDPOINT,
    181 
    182         /** Revert endpoint registration.
    183          * Parameters:
    184          * - USB address
    185          * - endpoint number
    186          * - data direction
    187          * Answer:
    188          * - EOK - endpoint unregistered
    189          * - ENOENT - unknown endpoint
    190          */
    191         IPC_M_USBHC_UNREGISTER_ENDPOINT
     169        /* IPC_M_USB_ */
    192170} usbhc_iface_funcs_t;
    193171
     
    222200        int (*release_address)(ddf_fun_t *, usb_address_t);
    223201
    224         int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
    225             usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    226         int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
    227             usb_direction_t);
    228 
    229202        usbhc_iface_transfer_out_t interrupt_out;
    230203        usbhc_iface_transfer_in_t interrupt_in;
  • uspace/lib/usb/Makefile

    r72af8da r3e7b7cd  
    3737        src/ddfiface.c \
    3838        src/debug.c \
    39         src/devdrv.c \
    40         src/devpoll.c \
    4139        src/dp.c \
    4240        src/dump.c \
     
    4947        src/request.c \
    5048        src/usb.c \
    51         src/usbdevice.c
     49        src/usbdevice.c \
     50        src/usbmem.c
    5251
    5352include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usb/include/usb/classes/classes.h

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * USB device classes (generic constants and functions).
     33 * @brief USB device classes and subclasses.
    3434 */
    3535#ifndef LIBUSB_CLASSES_H_
  • uspace/lib/usb/include/usb/debug.h

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Debugging related functions.
     33 * @brief Debugging related functions.
    3434 */
    3535#ifndef LIBUSB_DEBUG_H_
     
    3939#include <assert.h>
    4040
     41void usb_dprintf(const char *tag, int level, const char *format, ...);
     42void usb_dprintf_enable(const char *tag, int level);
     43
    4144void usb_dump_standard_descriptor(FILE *, const char *, const char *,
    4245    const uint8_t *, size_t);
     
    4447/** Logging level. */
    4548typedef enum {
    46         /** Fatal, unrecoverable, error.
    47          * Such error prevents the driver from working at all.
    48          */
    4949        USB_LOG_LEVEL_FATAL,
    50 
    51         /** Serious but recoverable error
    52          * Shall be used for errors fatal for single device but not for
    53          * driver itself.
    54          */
    5550        USB_LOG_LEVEL_ERROR,
    56 
    57         /** Warning.
    58          * Problems from which the driver is able to recover gracefully.
    59          */
    6051        USB_LOG_LEVEL_WARNING,
    61 
    62         /** Information message.
    63          * This should be the last level that is printed by default to
    64          * the screen.
    65          * Typical usage is to inform that new device was found and what
    66          * are its capabilities.
    67          * Do not use for repetitive actions (such as device polling).
    68          */
    6952        USB_LOG_LEVEL_INFO,
    70 
    71         /** Debugging message. */
    7253        USB_LOG_LEVEL_DEBUG,
    73 
    74         /** More detailed debugging message. */
    7554        USB_LOG_LEVEL_DEBUG2,
    76 
    77         /** Terminating constant for logging levels. */
    7855        USB_LOG_LEVEL_MAX
    7956} usb_log_level_t;
     
    8461void usb_log_printf(usb_log_level_t, const char *, ...);
    8562
    86 /** Log fatal error. */
    8763#define usb_log_fatal(format, ...) \
    8864        usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__)
    8965
    90 /** Log normal (recoverable) error. */
    9166#define usb_log_error(format, ...) \
    9267        usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
    9368
    94 /** Log warning. */
    9569#define usb_log_warning(format, ...) \
    9670        usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
    9771
    98 /** Log informational message. */
    9972#define usb_log_info(format, ...) \
    10073        usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__)
    10174
    102 /** Log debugging message. */
    10375#define usb_log_debug(format, ...) \
    10476        usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
    10577
    106 /** Log verbose debugging message. */
    10778#define usb_log_debug2(format, ...) \
    10879        usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
    10980
    110 const char *usb_debug_str_buffer(const uint8_t *, size_t, size_t);
    11181
    11282
  • uspace/lib/usb/include/usb/descriptor.h

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Standard USB descriptors.
     33 * @brief Standard USB descriptors.
    3434 */
    3535#ifndef LIBUSB_DESCRIPTOR_H_
     
    8383        /** Product descriptor index. */
    8484        uint8_t str_product;
    85         /** Device serial number descriptor index. */
     85        /** Device serial number desriptor index. */
    8686        uint8_t str_serial_number;
    8787        /** Number of possible configurations. */
     
    167167} __attribute__ ((packed)) usb_standard_endpoint_descriptor_t;
    168168
     169
     170/* TODO: string descriptors. */
     171
    169172#endif
    170173/**
  • uspace/lib/usb/include/usb/dp.h

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * USB descriptor parser.
     33 * @brief USB descriptor parser.
    3434 */
    3535#ifndef LIBUSB_DP_H_
     
    4040#include <usb/descriptor.h>
    4141
    42 /** USB descriptors nesting.
    43  * The nesting describes the logical tree USB descriptors form
    44  * (e.g. that endpoint descriptor belongs to interface or that
    45  * interface belongs to configuration).
    46  *
    47  * See usb_descriptor_type_t for descriptor constants.
    48  */
    4942typedef struct {
    50         /** Child descriptor id. */
    5143        int child;
    52         /** Parent descriptor id. */
    5344        int parent;
    5445} usb_dp_descriptor_nesting_t;
     
    5647extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
    5748
    58 /** Descriptor parser structure. */
    5949typedef struct {
    60         /** Used descriptor nesting. */
    6150        usb_dp_descriptor_nesting_t *nesting;
    6251} usb_dp_parser_t;
    6352
    64 /** Descriptor parser data. */
    6553typedef struct {
    66         /** Data to be parsed. */
    6754        uint8_t *data;
    68         /** Size of input data in bytes. */
    6955        size_t size;
    70         /** Custom argument. */
    7156        void *arg;
    7257} usb_dp_parser_data_t;
  • uspace/lib/usb/include/usb/hub.h

    r72af8da r3e7b7cd  
    3232/** @file
    3333 * Functions needed by hub drivers.
    34  *
    35  * For class specific requests, see usb/classes/hub.h.
    3634 */
    3735#ifndef LIBUSB_HUB_H_
  • uspace/lib/usb/include/usb/pipes.h

    r72af8da r3e7b7cd  
    4343#include <ddf/driver.h>
    4444
    45 /** Abstraction of a physical connection to the device.
     45/**
     46 * Abstraction of a physical connection to the device.
    4647 * This type is an abstraction of the USB wire that connects the host and
    4748 * the function (device).
     
    5455} usb_device_connection_t;
    5556
    56 /** Abstraction of a logical connection to USB device endpoint.
     57/**
     58 * Abstraction of a logical connection to USB device endpoint.
    5759 * It encapsulates endpoint attributes (transfer type etc.) as well
    5860 * as information about currently running sessions.
     
    106108        const usb_endpoint_description_t *description;
    107109        /** Interface number the endpoint must belong to (-1 for any). */
    108         int interface_no;
     110        const int interface_no;
    109111        /** Found descriptor fitting the description. */
    110112        usb_standard_endpoint_descriptor_t *descriptor;
    111         /** Interface descriptor the endpoint belongs to. */
     113        /** Interface the endpoint belongs to. */
    112114        usb_standard_interface_descriptor_t *interface;
    113115        /** Whether the endpoint was actually found. */
     
    129131int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
    130132    usb_device_connection_t *);
    131 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *);
    132133int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    133134    size_t, uint8_t *, size_t, usb_device_connection_t *);
    134 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int,
    135     usb_hc_connection_t *);
    136 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *);
     135
    137136
    138137int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
  • uspace/lib/usb/include/usb/request.h

    r72af8da r3e7b7cd  
    7272        union {
    7373                uint16_t value;
    74                 /* FIXME: add #ifdefs according to host endianness */
     74                /* FIXME: add #ifdefs according to host endianess */
    7575                struct {
    7676                        uint8_t value_low;
  • uspace/lib/usb/include/usb/usb.h

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Common USB types and functions.
     33 * @brief Base USB types.
    3434 */
    3535#ifndef LIBUSB_USB_H_
     
    121121} usb_target_t;
    122122
    123 /** Compare USB targets (addresses and endpoints).
    124  *
    125  * @param a First target.
    126  * @param b Second target.
    127  * @return Whether @p a and @p b points to the same pipe on the same device.
    128  */
    129123static inline int usb_target_same(usb_target_t a, usb_target_t b)
    130124{
  • uspace/lib/usb/src/ddfiface.c

    r72af8da r3e7b7cd  
    5656/** Get host controller handle, interface implementation for hub driver.
    5757 *
    58  * @param[in] fun Device function the operation is running on.
     58 * @param[in] device Device the operation is running on.
    5959 * @param[out] handle Storage for the host controller handle.
    6060 * @return Error code.
     
    6969 * a hub driver.
    7070 *
    71  * @param[in] fun Device function the operation is running on.
     71 * @param[in] device Device the operation is running on.
    7272 * @param[out] handle Storage for the host controller handle.
    7373 * @return Error code.
     
    8888            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
    8989
    90         async_hangup(parent_phone);
    91 
    9290        if (rc != EOK) {
    9391                return rc;
     
    10199/** Get host controller handle, interface implementation for HC driver.
    102100 *
    103  * @param[in] fun Device function the operation is running on.
     101 * @param[in] device Device the operation is running on.
    104102 * @param[out] handle Storage for the host controller handle.
    105103 * @return Always EOK.
     
    118116/** Get USB device address, interface implementation for hub driver.
    119117 *
    120  * @param[in] fun Device function the operation is running on.
     118 * @param[in] device Device the operation is running on.
    121119 * @param[in] handle Devman handle of USB device we want address of.
    122120 * @param[out] address Storage for USB address of device with handle @p handle.
     
    153151 * a hub driver.
    154152 *
    155  * @param[in] fun Device function the operation is running on.
     153 * @param[in] device Device the operation is running on.
    156154 * @param[in] handle Devman handle of USB device we want address of.
    157155 * @param[out] address Storage for USB address of device with handle @p handle.
  • uspace/lib/usb/src/debug.c

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Debugging and logging support.
     33 * @brief Debugging support.
    3434 */
    3535#include <adt/list.h>
     
    4040#include <usb/debug.h>
    4141
     42/** Debugging tag. */
     43typedef struct {
     44        /** Linked list member. */
     45        link_t link;
     46        /** Tag name.
     47         * We always have a private copy of the name.
     48         */
     49        char *tag;
     50        /** Enabled level of debugging. */
     51        int level;
     52} usb_debug_tag_t;
     53
     54/** Get instance of usb_debug_tag_t from link_t. */
     55#define USB_DEBUG_TAG_INSTANCE(iterator) \
     56        list_get_instance(iterator, usb_debug_tag_t, link)
     57
     58/** List of all known tags. */
     59static LIST_INITIALIZE(tag_list);
     60/** Mutex guard for the list of all tags. */
     61static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
     62
    4263/** Level of logging messages. */
    4364static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
    44 
    4565/** Prefix for logging messages. */
    4666static const char *log_prefix = "usb";
    47 
    4867/** Serialization mutex for logging functions. */
    4968static FIBRIL_MUTEX_INITIALIZE(log_serializer);
    50 
    51 /** File where to store the log. */
    5269static FILE *log_stream = NULL;
    5370
     71/** Find or create new tag with given name.
     72 *
     73 * @param tagname Tag name.
     74 * @return Debug tag structure.
     75 * @retval NULL Out of memory.
     76 */
     77static usb_debug_tag_t *get_tag(const char *tagname)
     78{
     79        link_t *link;
     80        for (link = tag_list.next; \
     81            link != &tag_list; \
     82            link = link->next) {
     83                usb_debug_tag_t *tag = USB_DEBUG_TAG_INSTANCE(link);
     84                if (str_cmp(tag->tag, tagname) == 0) {
     85                        return tag;
     86                }
     87        }
     88
     89        /*
     90         * Tag not found, we will create a new one.
     91         */
     92        usb_debug_tag_t *new_tag = malloc(sizeof(usb_debug_tag_t));
     93        int rc = asprintf(&new_tag->tag, "%s", tagname);
     94        if (rc < 0) {
     95                free(new_tag);
     96                return NULL;
     97        }
     98        list_initialize(&new_tag->link);
     99        new_tag->level = 1;
     100
     101        /*
     102         * Append it to the end of known tags.
     103         */
     104        list_append(&new_tag->link, &tag_list);
     105
     106        return new_tag;
     107}
     108
     109/** Print debugging information.
     110 * If the tag is used for the first time, its structures are automatically
     111 * created and initial verbosity level is set to 1.
     112 *
     113 * @param tagname Tag name.
     114 * @param level Level (verbosity) of the message.
     115 * @param format Formatting string for printf().
     116 */
     117void usb_dprintf(const char *tagname, int level, const char *format, ...)
     118{
     119        fibril_mutex_lock(&tag_list_guard);
     120        usb_debug_tag_t *tag = get_tag(tagname);
     121        if (tag == NULL) {
     122                printf("USB debug: FATAL ERROR - failed to create tag.\n");
     123                goto leave;
     124        }
     125
     126        if (tag->level < level) {
     127                goto leave;
     128        }
     129
     130        va_list args;
     131        va_start(args, format);
     132
     133        printf("[%s:%d]: ", tagname, level);
     134        vprintf(format, args);
     135
     136        va_end(args);
     137
     138leave:
     139        fibril_mutex_unlock(&tag_list_guard);
     140}
     141
     142/** Enable debugging prints for given tag.
     143 *
     144 * Setting level to <i>n</i> will cause that only printing messages
     145 * with level lower or equal to <i>n</i> will be printed.
     146 *
     147 * @param tagname Tag name.
     148 * @param level Enabled level.
     149 */
     150void usb_dprintf_enable(const char *tagname, int level)
     151{
     152        fibril_mutex_lock(&tag_list_guard);
     153        usb_debug_tag_t *tag = get_tag(tagname);
     154        if (tag == NULL) {
     155                printf("USB debug: FATAL ERROR - failed to create tag.\n");
     156                goto leave;
     157        }
     158
     159        tag->level = level;
     160
     161leave:
     162        fibril_mutex_unlock(&tag_list_guard);
     163}
    54164
    55165/** Enable logging.
     
    72182}
    73183
    74 /** Get log level name prefix.
    75  *
    76  * @param level Log level.
    77  * @return String prefix for the message.
    78  */
     184
    79185static const char *log_level_name(usb_log_level_t level)
    80186{
     
    146252}
    147253
    148 
    149 #define REMAINDER_STR_FMT " (%zu)..."
    150 /* string + terminator + number width (enough for 4GB)*/
    151 #define REMAINDER_STR_LEN (5 + 1 + 10)
    152 
    153 /** How many bytes to group together. */
    154 #define BUFFER_DUMP_GROUP_SIZE 4
    155 
    156 /** Size of the string for buffer dumps. */
    157 #define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
    158 
    159 /** Fibril local storage for the dumped buffer. */
    160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
    161 
    162 /** Dump buffer into string.
    163  *
    164  * The function dumps given buffer into hexadecimal format and stores it
    165  * in a static fibril local string.
    166  * That means that you do not have to deallocate the string (actually, you
    167  * can not do that) and you do not have to guard it against concurrent
    168  * calls to it.
    169  * The only limitation is that each call rewrites the buffer again.
    170  * Thus, it is necessary to copy the buffer elsewhere (that includes printing
    171  * to screen or writing to file).
    172  * Since this function is expected to be used for debugging prints only,
    173  * that is not a big limitation.
    174  *
    175  * @warning You cannot use this function twice in the same printf
    176  * (see detailed explanation).
    177  *
    178  * @param buffer Buffer to be printed (can be NULL).
    179  * @param size Size of the buffer in bytes (can be zero).
    180  * @param dumped_size How many bytes to actually dump (zero means all).
    181  * @return Dumped buffer as a static (but fibril local) string.
    182  */
    183 const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,
    184     size_t dumped_size)
    185 {
    186         /*
    187          * Remove previous string (that might also reveal double usage of
    188          * this function).
    189          */
    190         bzero(buffer_dump, BUFFER_DUMP_LEN);
    191 
    192         if (buffer == NULL) {
    193                 return "(null)";
    194         }
    195         if (size == 0) {
    196                 return "(empty)";
    197         }
    198         if ((dumped_size == 0) || (dumped_size > size)) {
    199                 dumped_size = size;
    200         }
    201 
    202         /* How many bytes are available in the output buffer. */
    203         size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
    204         char *it = buffer_dump;
    205 
    206         size_t index = 0;
    207 
    208         while (index < size) {
    209                 /* Determine space before the number. */
    210                 const char *space_before;
    211                 if (index == 0) {
    212                         space_before = "";
    213                 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
    214                         space_before = "  ";
    215                 } else {
    216                         space_before = " ";
    217                 }
    218 
    219                 /*
    220                  * Add the byte as a hexadecimal number plus the space.
    221                  * We do it into temporary buffer to ensure that always
    222                  * the whole byte is printed.
    223                  */
    224                 int val = buffer[index];
    225                 char current_byte[16];
    226                 int printed = snprintf(current_byte, 16,
    227                     "%s%02x", space_before, val);
    228                 if (printed < 0) {
    229                         break;
    230                 }
    231 
    232                 if ((size_t) printed > buffer_remaining_size) {
    233                         break;
    234                 }
    235 
    236                 /* We can safely add 1, because space for end 0 is reserved. */
    237                 str_append(it, buffer_remaining_size + 1, current_byte);
    238 
    239                 buffer_remaining_size -= printed;
    240                 /* Point at the terminator 0. */
    241                 it += printed;
    242                 index++;
    243 
    244                 if (index >= dumped_size) {
    245                         break;
    246                 }
    247         }
    248 
    249         /* Add how many bytes were not printed. */
    250         if (index < size) {
    251                 snprintf(it, REMAINDER_STR_LEN,
    252                     REMAINDER_STR_FMT, size - index);
    253         }
    254 
    255         return buffer_dump;
    256 }
    257 
    258 
    259254/**
    260255 * @}
  • uspace/lib/usb/src/dp.c

    r72af8da r3e7b7cd  
    3232/**
    3333 * @file
    34  * USB descriptor parser (implementation).
    35  *
    36  * The descriptor parser is a generic parser for structure, where individual
    37  * items are stored in single buffer and each item begins with length followed
    38  * by type. These types are organized into tree hierarchy.
    39  *
    40  * The parser is able of only two actions: find first child and find next
    41  * sibling.
     34 * @brief USB descriptor parser (implementation).
    4235 */
    4336#include <stdio.h>
  • uspace/lib/usb/src/dump.c

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Descriptor dumping.
     33 * @brief Descriptor dumping.
    3434 */
    3535#include <adt/list.h>
     
    4343#include <usb/classes/hid.h>
    4444
    45 /** Mapping between descriptor id and dumping function. */
    4645typedef struct {
    47         /** Descriptor id. */
    4846        int id;
    49         /** Dumping function. */
    5047        void (*dump)(FILE *, const char *, const char *,
    5148            const uint8_t *, size_t);
     
    6966    const uint8_t *, size_t);
    7067
    71 /** Descriptor dumpers mapping. */
    7268static descriptor_dump_t descriptor_dumpers[] = {
    7369        { USB_DESCTYPE_DEVICE, usb_dump_descriptor_device },
     
    277273    const uint8_t *descriptor, size_t descriptor_length)
    278274{
    279         /* TODO */
    280275}
    281276
     
    284279    const uint8_t *descriptor, size_t descriptor_length)
    285280{
    286         /* TODO */
    287281}
    288282
  • uspace/lib/usb/src/hub.c

    r72af8da r3e7b7cd  
    5757 *
    5858 * @param connection Opened connection to host controller.
    59  * @param speed Speed of the device that will respond on the default address.
    6059 * @return Error code.
    6160 */
     
    8786 *
    8887 * @param connection Opened connection to host controller.
    89  * @param speed Speed of the new device (device that will be assigned
    90  *    the returned address).
    9188 * @return Assigned USB address or negative error code.
    9289 */
     
    147144/** Wrapper for registering attached device to the hub.
    148145 *
    149  * The @p enable_port function is expected to enable signaling on given
     146 * The @p enable_port function is expected to enable singalling on given
    150147 * port.
    151148 * The two arguments to it can have arbitrary meaning
     
    155152 *
    156153 * If the @p enable_port fails (i.e. does not return EOK), the device
    157  * addition is canceled.
     154 * addition is cancelled.
    158155 * The return value is then returned (it is good idea to use different
    159156 * error codes than those listed as return codes by this function itself).
    160157 *
    161  * @param[in] parent Parent device (i.e. the hub device).
    162  * @param[in] connection Opened connection to host controller.
    163  * @param[in] dev_speed New device speed.
    164  * @param[in] enable_port Function for enabling signaling through the port the
     158 * @param parent Parent device (i.e. the hub device).
     159 * @param connection Opened connection to host controller.
     160 * @param dev_speed New device speed.
     161 * @param enable_port Function for enabling signalling through the port the
    165162 *      device is attached to.
    166  * @param[in] port_no Port number (passed through to @p enable_port).
    167  * @param[in] arg Any data argument to @p enable_port.
     163 * @param port_no Port number (passed through to @p enable_port).
     164 * @param arg Any data argument to @p enable_port.
    168165 * @param[out] assigned_address USB address of the device.
    169166 * @param[out] assigned_handle Devman handle of the new device.
    170  * @param[in] dev_ops Child device ops.
    171  * @param[in] new_dev_data Arbitrary pointer to be stored in the child
    172  *      as @c driver_data.
    173  * @param[out] new_fun Storage where pointer to allocated child function
    174  *      will be written.
    175167 * @return Error code.
    176168 * @retval ENOENT Connection to HC not opened.
     
    209201
    210202        /*
    211          * Enable the port (i.e. allow signaling through this port).
     203         * Enable the port (i.e. allow signalling through this port).
    212204         */
    213205        rc = enable_port(port_no, arg);
     
    231223        rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
    232224            &dev_conn);
    233         if (rc != EOK) {
    234                 rc = ENOTCONN;
    235                 goto leave_release_default_address;
    236         }
    237         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    238225        if (rc != EOK) {
    239226                rc = ENOTCONN;
  • uspace/lib/usb/src/pipes.c

    r72af8da r3e7b7cd  
    9999 *
    100100 * @param connection Connection structure to be initialized.
    101  * @param dev Generic device backing the USB device.
     101 * @param device Generic device backing the USB device.
    102102 * @return Error code.
    103103 */
  • uspace/lib/usb/src/pipesinit.c

    r72af8da r3e7b7cd  
    3737#include <usb/pipes.h>
    3838#include <usb/dp.h>
    39 #include <usb/request.h>
    40 #include <usbhc_iface.h>
    4139#include <errno.h>
    4240#include <assert.h>
    43 
    44 #define CTRL_PIPE_MIN_PACKET_SIZE 8
    45 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
    4641
    4742
     
    374369
    375370        int rc = usb_endpoint_pipe_initialize(pipe, connection,
    376             0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    377             USB_DIRECTION_BOTH);
     371            0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
    378372
    379373        return rc;
    380 }
    381 
    382 /** Probe default control pipe for max packet size.
    383  *
    384  * The function tries to get the correct value of max packet size several
    385  * time before giving up.
    386  *
    387  * The session on the pipe shall not be started.
    388  *
    389  * @param pipe Default control pipe.
    390  * @return Error code.
    391  */
    392 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe)
    393 {
    394         assert(pipe);
    395         assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
    396 
    397         if ((pipe->direction != USB_DIRECTION_BOTH) ||
    398             (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
    399             (pipe->endpoint_no != 0)) {
    400                 return EINVAL;
    401         }
    402 
    403 #define TRY_LOOP(attempt_var) \
    404         for (attempt_var = 0; attempt_var < 3; attempt_var++)
    405 
    406         size_t failed_attempts;
    407         int rc;
    408 
    409         TRY_LOOP(failed_attempts) {
    410                 rc = usb_endpoint_pipe_start_session(pipe);
    411                 if (rc == EOK) {
    412                         break;
    413                 }
    414         }
    415         if (rc != EOK) {
    416                 return rc;
    417         }
    418 
    419 
    420         uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    421         size_t transferred_size;
    422         TRY_LOOP(failed_attempts) {
    423                 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    424                     USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
    425                     0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
    426                     &transferred_size);
    427                 if (rc == EOK) {
    428                         if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
    429                                 rc = ELIMIT;
    430                                 continue;
    431                         }
    432                         break;
    433                 }
    434         }
    435         usb_endpoint_pipe_end_session(pipe);
    436         if (rc != EOK) {
    437                 return rc;
    438         }
    439 
    440         pipe->max_packet_size
    441             = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
    442 
    443         return EOK;
    444 }
    445 
    446 /** Register endpoint with the host controller.
    447  *
    448  * @param pipe Pipe to be registered.
    449  * @param interval Polling interval.
    450  * @param hc_connection Connection to the host controller (must be opened).
    451  * @return Error code.
    452  */
    453 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,
    454     unsigned int interval,
    455     usb_hc_connection_t *hc_connection)
    456 {
    457         assert(pipe);
    458         assert(hc_connection);
    459 
    460         if (!usb_hc_connection_is_opened(hc_connection)) {
    461                 return EBADF;
    462         }
    463 
    464 #define _PACK(high, low) ((high) * 256 + (low))
    465 
    466         return async_req_5_0(hc_connection->hc_phone,
    467             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    468             _PACK(pipe->wire->address, pipe->endpoint_no),
    469             _PACK(pipe->transfer_type, pipe->direction),
    470             pipe->max_packet_size, interval);
    471 
    472 #undef _PACK
    473 }
    474 
    475 /** Revert endpoint registration with the host controller.
    476  *
    477  * @param pipe Pipe to be unregistered.
    478  * @param hc_connection Connection to the host controller (must be opened).
    479  * @return Error code.
    480  */
    481 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,
    482     usb_hc_connection_t *hc_connection)
    483 {
    484         assert(pipe);
    485         assert(hc_connection);
    486 
    487         if (!usb_hc_connection_is_opened(hc_connection)) {
    488                 return EBADF;
    489         }
    490 
    491         return async_req_4_0(hc_connection->hc_phone,
    492             DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
    493             pipe->wire->address, pipe->endpoint_no, pipe->direction);
    494374}
    495375
  • uspace/lib/usb/src/pipesio.c

    r72af8da r3e7b7cd  
    115115
    116116        if (data_request_rc != EOK) {
    117                 /* Prefer the return code of the opening request. */
    118                 if (opening_request_rc != EOK) {
    119                         return (int) opening_request_rc;
    120                 } else {
    121                         return (int) data_request_rc;
    122                 }
     117                return (int) data_request_rc;
    123118        }
    124119        if (opening_request_rc != EOK) {
     
    336331
    337332        if (data_request_rc != EOK) {
    338                 /* Prefer the return code of the opening request. */
    339                 if (opening_request_rc != EOK) {
    340                         return (int) opening_request_rc;
    341                 } else {
    342                         return (int) data_request_rc;
    343                 }
     333                return (int) data_request_rc;
    344334        }
    345335        if (opening_request_rc != EOK) {
  • uspace/lib/usb/src/recognise.c

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Functions for recognition of attached devices.
     33 * @brief Functions for recognising kind of attached devices.
    3434 */
    3535#include <sys/types.h>
     
    4444#include <assert.h>
    4545
    46 /** Index to append after device name for uniqueness. */
    4746static size_t device_name_index = 0;
    48 /** Mutex guard for device_name_index. */
    4947static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
    5048
    51 /** DDF operations of child devices. */
    5249ddf_dev_ops_t child_ops = {
    5350        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5451};
    5552
    56 /** Get integer part from BCD coded number. */
    5753#define BCD_INT(a) (((unsigned int)(a)) / 256)
    58 /** Get fraction part from BCD coded number (as an integer, no less). */
    5954#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
    6055
    61 /** Format for BCD coded number to be used in printf. */
    6256#define BCD_FMT "%x.%x"
    63 /** Arguments to printf for BCD coded number. */
    6457#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6558
     
    120113}
    121114
    122 /** Add match id to list or return with error code.
    123  *
    124  * @param match_ids List of match ids.
    125  * @param score Match id score.
    126  * @param format Format of the matching string
    127  * @param ... Arguments for the format.
    128  */
    129115#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    130116        do { \
     
    138124/** Create device match ids based on its interface.
    139125 *
    140  * @param[in] desc_device Device descriptor.
    141  * @param[in] desc_interface Interface descriptor.
     126 * @param[in] descriptor Interface descriptor.
    142127 * @param[out] matches Initialized list of match ids.
    143128 * @return Error code (the two mentioned are not the only ones).
    144129 * @retval EINVAL Invalid input parameters (expects non NULL pointers).
    145  * @retval ENOENT Device class is not "use interface".
     130 * @retval ENOENT Interface does not specify class.
    146131 */
    147132int usb_device_create_match_ids_from_interface(
     
    334319 * @param[in] parent Parent device.
    335320 * @param[out] child_handle Handle of the child device.
    336  * @param[in] dev_ops Child device ops.
    337  * @param[in] dev_data Arbitrary pointer to be stored in the child
    338  *      as @c driver_data.
    339  * @param[out] child_fun Storage where pointer to allocated child function
    340  *      will be written.
    341321 * @return Error code.
    342322 */
     
    369349                goto failure;
    370350        }
    371         rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
    372         if (rc != EOK) {
    373                 goto failure;
    374         }
    375351
    376352        /*
     
    378354         * naming etc., something more descriptive could be created.
    379355         */
    380         rc = asprintf(&child_name, "usb%02zu_a%d",
    381             this_device_name_index, address);
     356        rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
    382357        if (rc < 0) {
    383358                goto failure;
  • uspace/lib/usb/src/request.c

    r72af8da r3e7b7cd  
    110110  *     (must be in USB endianness).
    111111  * @param data Buffer where to store data accepted during the DATA stage.
    112   *     (they will come in USB endianness).
     112  *     (they will come in USB endianess).
    113113  * @param data_size Size of the @p data buffer
    114114  *     (in native endianness).
     
    161161 * the new address.
    162162 *
     163 * @see usb_drv_reserve_default_address
     164 * @see usb_drv_release_default_address
     165 * @see usb_drv_request_address
     166 * @see usb_drv_release_address
     167 * @see usb_drv_bind_address
     168 *
    163169 * @param pipe Control endpoint pipe (session must be already started).
    164170 * @param new_address New USB address to be set (in native endianness).
     
    195201 * @param[in] pipe Control endpoint pipe (session must be already started).
    196202 * @param[in] request_type Request type (standard/class/vendor).
    197  * @param[in] recipient Request recipient (device/interface/endpoint).
    198203 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
    199204 * @param[in] descriptor_index Descriptor index.
     
    230235 * @param[in] pipe Control endpoint pipe (session must be already started).
    231236 * @param[in] request_type Request type (standard/class/vendor).
    232  * @param[in] recipient Request recipient (device/interface/endpoint).
    233237 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
    234238 * @param[in] descriptor_index Descriptor index.
     
    524528                return EEMPTY;
    525529        }
    526         /* Subtract first 2 bytes (length and descriptor type). */
     530        /* Substract first 2 bytes (length and descriptor type). */
    527531        string_descriptor_size -= 2;
    528532
     
    544548        size_t i;
    545549        for (i = 0; i < langs_count; i++) {
    546                 /* Language code from the descriptor is in USB endianness. */
     550                /* Language code from the descriptor is in USB endianess. */
    547551                /* FIXME: is this really correct? */
    548552                uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
     
    565569 *
    566570 * @param[in] pipe Control endpoint pipe (session must be already started).
    567  * @param[in] index String index (in native endianness),
     571 * @param[in] index String index (in native endianess),
    568572 *      first index has number 1 (index from descriptors can be used directly).
    569  * @param[in] lang String language (in native endianness).
     573 * @param[in] lang String language (in native endianess).
    570574 * @param[out] string_ptr Where to store allocated string in native encoding.
    571575 * @return Error code.
     
    609613                goto leave;
    610614        }
    611         /* Subtract first 2 bytes (length and descriptor type). */
     615        /* Substract first 2 bytes (length and descriptor type). */
    612616        string_size -= 2;
    613617
  • uspace/lib/usb/src/usb.c

    r72af8da r3e7b7cd  
    3131 */
    3232/** @file
    33  * Common USB functions.
     33 * @brief Base USB types.
    3434 */
    3535#include <usb/usb.h>
     
    3737
    3838
    39 /** String representation for USB transfer type.
    40  *
    41  * @param t Transfer type.
    42  * @return Transfer type as a string (in English).
    43  */
     39/** String representation for USB transfer type. */
    4440const char * usb_str_transfer_type(usb_transfer_type_t t)
    4541{
  • uspace/srv/hw/irc/apic/apic.c

    r72af8da r3e7b7cd  
    5454#define NAME  "apic"
    5555
    56 static bool apic_found = false;
    57 
    5856static int apic_enable_irq(sysarg_t irq)
    5957{
     
    8179                callid = async_get_call(&call);
    8280               
    83                 sysarg_t method = IPC_GET_IMETHOD(call);
    84                 if (method == IPC_M_PHONE_HUNGUP) {
    85                         return;
    86                 }
    87 
    88                 if (!apic_found) {
    89                         async_answer_0(callid, ENOTSUP);
    90                         break;
    91                 }
    92 
    93                 switch (method) {
     81                switch (IPC_GET_IMETHOD(call)) {
    9482                case IRC_ENABLE_INTERRUPT:
    9583                        async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
     
    10997 *
    11098 */
    111 static void apic_init(void)
     99static bool apic_init(void)
    112100{
    113101        sysarg_t apic;
    114102       
    115         apic_found = sysinfo_get_value("apic", &apic) && apic;
    116         if (!apic_found) {
    117                 printf(NAME ": Warning: no APIC found\n");
     103        if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
     104                printf(NAME ": No APIC found\n");
     105                return false;
    118106        }
    119107       
    120108        async_set_client_connection(apic_connection);
    121109        service_register(SERVICE_APIC);
     110       
     111        return true;
    122112}
    123113
     
    126116        printf(NAME ": HelenOS APIC driver\n");
    127117       
    128         apic_init();
    129 
     118        if (!apic_init())
     119                return -1;
     120       
    130121        printf(NAME ": Accepting connections\n");
    131122        async_manager();
Note: See TracChangeset for help on using the changeset viewer.