Changeset 4069f5c in mainline


Ignore:
Timestamp:
2011-07-17T09:52:42Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
64639256, ca1f1ec
Parents:
27eddb52 (diff), 4118f5f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Files:
3 added
47 edited
4 moved

Legend:

Unmodified
Added
Removed
  • HelenOS.config

    r27eddb52 r4069f5c  
    573573! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
    574574
    575 % Polling UHCI & OHCI (no interrupts)
    576 ! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (n/y)
    577 
     575% OHCI root hub port power switching
     576@ "no" All root hub ports are always powered.
     577@ "ganged" Root hub ports are all powered or all off.
     578@ "per_port" Powered status of every root hub port is independent.
     579![PLATFORM=ia32|PLATFORM=amd64] OHCI_POWER_SWITCH (choice)
  • defaults/amd64/Makefile.config

    r27eddb52 r4069f5c  
    6565CONFIG_MOUNT_DATA = n
    6666
     67# OHCI root hub power switch, ganged is enough
     68OHCI_POWER_SWITCH = ganged
  • defaults/ia32/Makefile.config

    r27eddb52 r4069f5c  
    7171CONFIG_MOUNT_DATA = n
    7272
     73# OHCI root hub power switch, ganged is enough
     74OHCI_POWER_SWITCH = ganged
  • uspace/app/bdsh/Makefile

    r27eddb52 r4069f5c  
    5454        cmds/mod_cmds.c \
    5555        cmds/builtin_cmds.c \
     56        compl.c \
    5657        errors.c \
    5758        input.c \
  • uspace/app/bdsh/config.h

    r27eddb52 r4069f5c  
    4040#endif
    4141
    42 /* Work around for getenv() */
    43 #define PATH "/srv:/app"
    44 #define PATH_DELIM ":"
    45 
    4642/* Used in many places */
    4743#define SMALL_BUFLEN 256
  • uspace/app/bdsh/exec.c

    r27eddb52 r4069f5c  
    5252static int try_access(const char *);
    5353
     54const char *search_dir[] = { "app", "srv", NULL };
     55
    5456/* work-around for access() */
    5557static int try_access(const char *f)
     
    6971static char *find_command(char *cmd)
    7072{
    71         char *path_tok;
    72         char *path[PATH_MAX];
    73         int n = 0, i = 0;
    74         size_t x = str_size(cmd) + 2;
     73        size_t i;
    7574
    7675        found = (char *)malloc(PATH_MAX);
     
    8180        }
    8281
    83         path_tok = str_dup(PATH);
    84 
    85         /* Extract the PATH env to a path[] array */
    86         path[n] = strtok(path_tok, PATH_DELIM);
    87         while (NULL != path[n]) {
    88                 if ((str_size(path[n]) + x ) > PATH_MAX) {
    89                         cli_error(CL_ENOTSUP,
    90                                 "Segment %d of path is too large, search ends at segment %d",
    91                                 n, n-1);
    92                         break;
    93                 }
    94                 path[++n] = strtok(NULL, PATH_DELIM);
    95         }
    96 
    9782        /* We now have n places to look for the command */
    98         for (i=0; path[i]; i++) {
     83        for (i = 0; search_dir[i] != NULL; i++) {
    9984                memset(found, 0, sizeof(found));
    100                 snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
     85                snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);
    10186                if (-1 != try_access(found)) {
    102                         free(path_tok);
    10387                        return (char *) found;
    10488                }
     
    10690
    10791        /* We didn't find it, just give it back as-is. */
    108         free(path_tok);
    10992        return (char *) cmd;
    11093}
  • uspace/app/bdsh/exec.h

    r27eddb52 r4069f5c  
    3333#include "scli.h"
    3434
     35extern const char *search_dir[];
     36
    3537extern unsigned int try_exec(char *, char **, iostate_t *);
    3638
  • uspace/app/bdsh/input.c

    r27eddb52 r4069f5c  
    11/*
    22 * Copyright (c) 2008 Tim Post
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4344
    4445#include "config.h"
     46#include "compl.h"
    4547#include "util.h"
    4648#include "scli.h"
     
    226228        int rc;
    227229       
    228         console_flush(tinput->console);
    229         console_set_style(tinput->console, STYLE_EMPHASIS);
    230         printf("%s", usr->prompt);
    231         console_flush(tinput->console);
    232         console_set_style(tinput->console, STYLE_NORMAL);
     230        tinput_set_prompt(tinput, usr->prompt);
    233231
    234232        rc = tinput_read(tinput, &str);
     
    263261        }
    264262
     263        tinput_set_compl_ops(tinput, &compl_ops);
     264
    265265        return 0;
    266266}
  • uspace/app/bdsh/scli.h

    r27eddb52 r4069f5c  
    3232#include "config.h"
    3333#include <stdint.h>
     34#include <stdio.h>
    3435
    3536typedef struct {
  • uspace/app/sbi/src/input.c

    r27eddb52 r4069f5c  
    176176int input_get_line(input_t *input, char **line)
    177177{
     178        const char *prompt;
    178179        const char *sp;
    179180        char *dp;
     
    212213                /* Interactive mode */
    213214                if (input->line_no == 0)
    214                         printf("sbi> ");
     215                        prompt = "sbi> ";
    215216                else
    216                         printf("...  ");
     217                        prompt = "...  ";
    217218
    218219                fflush(stdout);
    219                 if (os_input_line(&line_p) != EOK)
     220                if (os_input_line(prompt, &line_p) != EOK)
    220221                        return EIO;
    221222
  • uspace/app/sbi/src/os/helenos.c

    r27eddb52 r4069f5c  
    210210 * @param ptr   Place to store pointer to new string.
    211211 */
    212 int os_input_line(char **ptr)
     212int os_input_line(const char *prompt, char **ptr)
    213213{
    214214        char *line;
     
    219219                if (tinput == NULL)
    220220                        return EIO;
     221
     222                tinput_set_prompt(tinput, prompt);
    221223        }
    222224
  • uspace/app/sbi/src/os/os.h

    r27eddb52 r4069f5c  
    3838char *os_chr_to_astr(wchar_t chr);
    3939void os_input_disp_help(void);
    40 int os_input_line(char **ptr);
     40int os_input_line(const char *prompt, char **ptr);
    4141int os_exec(char * const cmd[]);
    4242
  • uspace/app/sbi/src/os/posix.c

    r27eddb52 r4069f5c  
    193193 * @param ptr   Place to store pointer to new string.
    194194 */
    195 int os_input_line(char **ptr)
    196 {
     195int os_input_line(const char *prompt, char **ptr)
     196{
     197        printf("%s", prompt);
     198
    197199        if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL)
    198200                os_input_buffer[0] = '\0';
  • uspace/drv/bus/isa/isa.c

    r27eddb52 r4069f5c  
    352352                    str_error(rc));
    353353        }
     354
     355        free(id);
    354356}
    355357
  • uspace/drv/bus/pci/pciintel/pci.c

    r27eddb52 r4069f5c  
    342342        }
    343343       
     344        free(match_id_str);
     345       
    344346        /* TODO add more ids (with subsys ids, using class id etc.) */
    345347}
  • uspace/drv/bus/usb/ohci/hc.c

    r27eddb52 r4069f5c  
    4646#define OHCI_USED_INTERRUPTS \
    4747    (I_SO | I_WDH | I_UE | I_RHSC)
    48 static int interrupt_emulator(hc_t *instance);
     48
     49static const irq_cmd_t ohci_irq_commands[] =
     50{
     51        { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ },
     52        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
     53        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
     54        { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
     55        { .cmd = CMD_ACCEPT },
     56};
     57
    4958static void hc_gain_control(hc_t *instance);
     59static void hc_start(hc_t *instance);
    5060static int hc_init_transfer_lists(hc_t *instance);
    5161static int hc_init_memory(hc_t *instance);
     62static int interrupt_emulator(hc_t *instance);
     63
     64/*----------------------------------------------------------------------------*/
     65/** Get number of commands used in IRQ code.
     66 * @return Number of commands.
     67 */
     68size_t hc_irq_cmd_count(void)
     69{
     70        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
     71}
     72/*----------------------------------------------------------------------------*/
     73/** Generate IRQ code commands.
     74 * @param[out] cmds Place to store the commands.
     75 * @param[in] cmd_size Size of the place (bytes).
     76 * @param[in] regs Physical address of device's registers.
     77 * @param[in] reg_size Size of the register area (bytes).
     78 *
     79 * @return Error code.
     80 */
     81int hc_get_irq_commands(
     82    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
     83{
     84        if (cmd_size < sizeof(ohci_irq_commands)
     85            || reg_size < sizeof(ohci_regs_t))
     86                return EOVERFLOW;
     87
     88        /* Create register mapping to use in IRQ handler.
     89         * This mapping should be present in kernel only.
     90         * Remove it from here when kernel knows how to create mappings
     91         * and accepts physical addresses in IRQ code.
     92         * TODO: remove */
     93        ohci_regs_t *registers;
     94        const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
     95        if (ret != EOK)
     96                return ret;
     97
     98        /* Some bogus access to force create mapping. DO NOT remove,
     99         * unless whole virtual addresses in irq is replaced
     100         * NOTE: Compiler won't remove this as ohci_regs_t members
     101         * are declared volatile.
     102         *
     103         * Introducing CMD_MEM set of IRQ code commands broke
     104         * assumption that IRQ code does not cause page faults.
     105         * If this happens during idling (THREAD == NULL)
     106         * it causes kernel panic.
     107         */
     108        registers->revision;
     109
     110        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
     111
     112        void *address = (void*)&registers->interrupt_status;
     113        cmds[0].addr = address;
     114        cmds[3].addr = address;
     115        return EOK;
     116}
    52117/*----------------------------------------------------------------------------*/
    53118/** Announce OHCI root hub to the DDF
     
    83148        int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
    84149            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    85         CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret);
    86 
    87         char *match_str = NULL;
    88         /* DDF needs heap allocated string */
    89         ret = asprintf(&match_str, "usb&class=hub");
    90         ret = ret > 0 ? 0 : ret;
    91         CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
    92 
    93         ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
    94         CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
     150        CHECK_RET_RELEASE(ret,
     151            "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret));
     152
     153        ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
     154        CHECK_RET_RELEASE(ret,
     155            "Failed to add root hub match-id: %s.\n", str_error(ret));
    95156
    96157        ret = ddf_fun_bind(hub_fun);
    97         CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
     158        CHECK_RET_RELEASE(ret,
     159            "Failed to bind root hub function: %s.\n", str_error(ret));
    98160
    99161        return EOK;
     
    112174{
    113175        assert(instance);
    114         int ret = EOK;
     176
    115177#define CHECK_RET_RETURN(ret, message...) \
    116178if (ret != EOK) { \
     
    119181} else (void)0
    120182
    121         ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
     183        int ret =
     184            pio_enable((void*)regs, reg_size, (void**)&instance->registers);
    122185        CHECK_RET_RETURN(ret,
    123             "Failed(%d) to gain access to device registers: %s.\n",
    124             ret, str_error(ret));
     186            "Failed to gain access to device registers: %s.\n", str_error(ret));
    125187
    126188        list_initialize(&instance->pending_batches);
    127189        usb_device_keeper_init(&instance->manager);
     190
    128191        ret = usb_endpoint_manager_init(&instance->ep_manager,
    129192            BANDWIDTH_AVAILABLE_USB11);
     
    137200
    138201        fibril_mutex_initialize(&instance->guard);
     202
    139203        hc_gain_control(instance);
    140 
    141         rh_init(&instance->rh, instance->registers);
    142204
    143205        if (!interrupts) {
     
    147209        }
    148210
    149         return EOK;
    150 }
    151 /*----------------------------------------------------------------------------*/
    152 /** Create end register endpoint structures
     211        rh_init(&instance->rh, instance->registers);
     212        hc_start(instance);
     213
     214        return EOK;
     215}
     216/*----------------------------------------------------------------------------*/
     217/** Create and register endpoint structures.
    153218 *
    154219 * @param[in] instance OHCI driver structure.
     
    168233    size_t mps, size_t size, unsigned interval)
    169234{
    170         endpoint_t *ep = malloc(sizeof(endpoint_t));
     235        endpoint_t *ep =
     236            endpoint_get(address, endpoint, direction, type, speed, mps);
    171237        if (ep == NULL)
    172238                return ENOMEM;
    173         int ret =
    174             endpoint_init(ep, address, endpoint, direction, type, speed, mps);
    175         if (ret != EOK) {
    176                 free(ep);
    177                 return ret;
    178         }
    179239
    180240        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     
    184244        }
    185245
    186         ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     246        int ret =
     247            usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
    187248        if (ret != EOK) {
    188249                hcd_endpoint_clear(ep);
     
    212273                    &instance->lists[ep->transfer_type], hcd_ep);
    213274                instance->registers->control |= C_PLE | C_IE;
    214                 break;
    215         default:
    216275                break;
    217276        }
     
    312371        /* Check for root hub communication */
    313372        if (batch->ep->address == instance->rh.address) {
    314                 return rh_request(&instance->rh, batch);
     373                rh_request(&instance->rh, batch);
     374                return EOK;
    315375        }
    316376
     
    374434
    375435        if (status & I_UE) {
    376                 hc_start_hw(instance);
     436                hc_start(instance);
    377437        }
    378438
     
    399459/** Turn off any (BIOS)driver that might be in control of the device.
    400460 *
     461 * This function implements routines described in chapter 5.1.1.3 of the OHCI
     462 * specification (page 40, pdf page 54).
     463 *
    401464 * @param[in] instance OHCI hc driver structure.
    402465 */
     
    404467{
    405468        assert(instance);
     469
    406470        usb_log_debug("Requesting OHCI control.\n");
    407         /* Turn off legacy emulation */
    408         volatile uint32_t *ohci_emulation_reg =
    409             (uint32_t*)((char*)instance->registers + 0x100);
    410         usb_log_debug("OHCI legacy register %p: %x.\n",
    411             ohci_emulation_reg, *ohci_emulation_reg);
    412         /* Do not change A20 state */
    413         *ohci_emulation_reg &= 0x100;
    414         usb_log_debug("OHCI legacy register %p: %x.\n",
    415             ohci_emulation_reg, *ohci_emulation_reg);
     471        if (instance->registers->revision & R_LEGACY_FLAG) {
     472                /* Turn off legacy emulation, it should be enough to zero
     473                 * the lowest bit, but it caused problems. Thus clear all
     474                 * except GateA20 (causes restart on some hw).
     475                 * See page 145 of the specs for details.
     476                 */
     477                volatile uint32_t *ohci_emulation_reg =
     478                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
     479                usb_log_debug("OHCI legacy register %p: %x.\n",
     480                    ohci_emulation_reg, *ohci_emulation_reg);
     481                /* Zero everything but A20State */
     482                *ohci_emulation_reg &= 0x100;
     483                usb_log_debug(
     484                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
     485                    ohci_emulation_reg, *ohci_emulation_reg);
     486        }
    416487
    417488        /* Interrupt routing enabled => smm driver is active */
     
    419490                usb_log_debug("SMM driver: request ownership change.\n");
    420491                instance->registers->command_status |= CS_OCR;
     492                /* Hope that SMM actually knows its stuff or we can hang here */
    421493                while (instance->registers->control & C_IR) {
    422494                        async_usleep(1000);
    423495                }
    424496                usb_log_info("SMM driver: Ownership taken.\n");
    425                 instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
     497                C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
    426498                async_usleep(50000);
    427499                return;
    428500        }
    429501
    430         const unsigned hc_status =
    431             (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
     502        const unsigned hc_status = C_HCFS_GET(instance->registers->control);
    432503        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    433504        if (hc_status != C_HCFS_RESET) {
     
    437508                        return;
    438509                }
    439                 /* HC is suspended assert resume for 20ms */
    440                 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
     510                /* HC is suspended assert resume for 20ms, */
     511                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    441512                async_usleep(20000);
    442513                usb_log_info("BIOS driver: HC resumed.\n");
     
    454525 * @param[in] instance OHCI hc driver structure.
    455526 */
    456 void hc_start_hw(hc_t *instance)
     527void hc_start(hc_t *instance)
    457528{
    458529        /* OHCI guide page 42 */
     
    516587            instance->registers->periodic_start, frame_length);
    517588
    518         instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
     589        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    519590        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    520591            instance->registers->control);
     
    534605        int ret = endpoint_list_init(&instance->lists[type], name); \
    535606        if (ret != EOK) { \
    536                 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    537                     ret, name); \
     607                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
     608                    name, str_error(ret)); \
    538609                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
    539610                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     
    587658            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    588659
    589         /* Init interrupt code */
    590         instance->interrupt_code.cmds = instance->interrupt_commands;
    591         instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
    592         {
    593                 /* Read status register */
    594                 instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
    595                 instance->interrupt_commands[0].dstarg = 1;
    596                 instance->interrupt_commands[0].addr =
    597                     (void*)&instance->registers->interrupt_status;
    598 
    599                 /* Test whether we are the interrupt cause */
    600                 instance->interrupt_commands[1].cmd = CMD_BTEST;
    601                 instance->interrupt_commands[1].value =
    602                     OHCI_USED_INTERRUPTS;
    603                 instance->interrupt_commands[1].srcarg = 1;
    604                 instance->interrupt_commands[1].dstarg = 2;
    605 
    606                 /* Predicate cleaning and accepting */
    607                 instance->interrupt_commands[2].cmd = CMD_PREDICATE;
    608                 instance->interrupt_commands[2].value = 2;
    609                 instance->interrupt_commands[2].srcarg = 2;
    610 
    611                 /* Write-clean status register */
    612                 instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
    613                 instance->interrupt_commands[3].srcarg = 1;
    614                 instance->interrupt_commands[3].addr =
    615                     (void*)&instance->registers->interrupt_status;
    616 
    617                 /* Accept interrupt */
    618                 instance->interrupt_commands[4].cmd = CMD_ACCEPT;
    619         }
    620 
    621         return EOK;
    622 }
     660        return EOK;
     661}
     662
    623663/**
    624664 * @}
  • uspace/drv/bus/usb/ohci/hc.h

    r27eddb52 r4069f5c  
    5151#include "hw_struct/hcca.h"
    5252
    53 #define OHCI_NEEDED_IRQ_COMMANDS 5
    54 
    55 /** Main OHCI drier structure */
     53/** Main OHCI driver structure */
    5654typedef struct hc {
    5755        /** USB bus driver, devices and addresses */
     
    7674        fibril_mutex_t guard;
    7775
    78         /** Code to be executed in kernel interrupt handler */
    79         irq_code_t interrupt_code;
    80 
    81         /** Commands that form interrupt code */
    82         irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
    83 
    8476        /** USB hub emulation structure */
    8577        rh_t rh;
    8678} hc_t;
    8779
     80size_t hc_irq_cmd_count(void);
     81int hc_get_irq_commands(
     82    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
     83int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    8884int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    89 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    90 void hc_start_hw(hc_t *instance);
    9185
    9286/** Safely dispose host controller internal structures
  • uspace/drv/bus/usb/ohci/ohci.c

    r27eddb52 r4069f5c  
    5858{
    5959        assert(dev);
    60         assert(dev->driver_data);
    6160        return dev->driver_data;
    6261}
    63 
    6462/** IRQ handling callback, identifies device
    6563 *
     
    7068static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    7169{
    72         hc_t *hc = &dev_to_ohci(dev)->hc;
    73         assert(hc);
     70        assert(dev);
     71
     72        ohci_t *ohci = dev_to_ohci(dev);
     73        if (!ohci) {
     74                usb_log_warning("Interrupt on device that is not ready.\n");
     75                return;
     76        }
    7477        const uint16_t status = IPC_GET_ARG1(*call);
    75         hc_interrupt(hc, status);
     78        hc_interrupt(&ohci->hc, status);
    7679}
    7780/*----------------------------------------------------------------------------*/
     
    166169        } \
    167170        free(instance); \
     171        device->driver_data = NULL; \
    168172        usb_log_error(message); \
    169173        return ret; \
     
    173177        instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
    174178        int ret = instance->hc_fun ? EOK : ENOMEM;
    175         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
     179        CHECK_RET_DEST_FREE_RETURN(ret,
     180            "Failed to create OHCI HC function: %s.\n", str_error(ret));
    176181        instance->hc_fun->ops = &hc_ops;
    177182        instance->hc_fun->driver_data = &instance->hc;
     
    179184        instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
    180185        ret = instance->rh_fun ? EOK : ENOMEM;
    181         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
     186        CHECK_RET_DEST_FREE_RETURN(ret,
     187            "Failed to create OHCI RH function: %s.\n", str_error(ret));
    182188        instance->rh_fun->ops = &rh_ops;
    183189
     
    193199            (void *) reg_base, reg_size, irq);
    194200
     201        const size_t cmd_count = hc_irq_cmd_count();
     202        irq_cmd_t irq_cmds[cmd_count];
     203        ret =
     204            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     205        CHECK_RET_DEST_FREE_RETURN(ret,
     206            "Failed to generate IRQ commands: %s.\n", str_error(ret));
     207
     208        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     209
     210        /* Register handler to avoid interrupt lockup */
     211        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
     212        CHECK_RET_DEST_FREE_RETURN(ret,
     213            "Failed to register interrupt handler: %s.\n", str_error(ret));
     214
     215        /* Try to enable interrupts */
    195216        bool interrupts = false;
    196 #ifdef CONFIG_USBHC_NO_INTERRUPTS
    197         usb_log_warning("Interrupts disabled in OS config, "
    198             "falling back to polling.\n");
    199 #else
    200217        ret = pci_enable_interrupts(device);
    201218        if (ret != EOK) {
    202                 usb_log_warning("Failed to enable interrupts: %s.\n",
    203                     str_error(ret));
    204                 usb_log_info("HW interrupts not available, "
    205                     "falling back to polling.\n");
     219                usb_log_warning("Failed to enable interrupts: %s."
     220                    " Falling back to polling\n", str_error(ret));
     221                /* We don't need that handler */
     222                unregister_interrupt_handler(device, irq);
    206223        } else {
    207224                usb_log_debug("Hw interrupts enabled.\n");
    208225                interrupts = true;
    209226        }
    210 #endif
    211227
    212228        ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
    213         CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
     229        CHECK_RET_DEST_FREE_RETURN(ret,
     230            "Failed to init ohci_hcd: %s.\n", str_error(ret));
     231
     232        device->driver_data = instance;
    214233
    215234#define CHECK_RET_FINI_RETURN(ret, message...) \
    216235if (ret != EOK) { \
     236        unregister_interrupt_handler(device, irq); \
    217237        hc_fini(&instance->hc); \
    218238        CHECK_RET_DEST_FREE_RETURN(ret, message); \
    219239} else (void)0
    220240
    221         /* It does no harm if we register this on polling */
    222         ret = register_interrupt_handler(device, irq, irq_handler,
    223             &instance->hc.interrupt_code);
    224         CHECK_RET_FINI_RETURN(ret,
    225             "Failed(%d) to register interrupt handler.\n", ret);
    226241
    227242        ret = ddf_fun_bind(instance->hc_fun);
    228243        CHECK_RET_FINI_RETURN(ret,
    229             "Failed(%d) to bind OHCI device function: %s.\n",
    230             ret, str_error(ret));
     244            "Failed to bind OHCI device function: %s.\n", str_error(ret));
    231245
    232246        ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
     
    234248            "Failed to add OHCI to HC class: %s.\n", str_error(ret));
    235249
    236         device->driver_data = instance;
    237 
    238         hc_start_hw(&instance->hc);
    239250        hc_register_hub(&instance->hc, instance->rh_fun);
    240251        return EOK;
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r27eddb52 r4069f5c  
    3434#ifndef DRV_OHCI_OHCI_REGS_H
    3535#define DRV_OHCI_OHCI_REGS_H
    36 #include <stdint.h>
     36#include <sys/types.h>
     37
     38#define LEGACY_REGS_OFFSET 0x100
    3739
    3840/** OHCI memory mapped registers structure */
    3941typedef struct ohci_regs {
    40         const volatile uint32_t revision;
    41         volatile uint32_t control;
    42 #define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
    43 #define C_CSBR_1_1  (0x0)
    44 #define C_CSBR_1_2  (0x1)
    45 #define C_CSBR_1_3  (0x2)
    46 #define C_CSBR_1_4  (0x3)
    47 #define C_CSBR_SHIFT (0)
     42        const ioport32_t revision;
     43#define R_REVISION_MASK (0x3f)
     44#define R_REVISION_SHIFT (0)
     45#define R_LEGACY_FLAG   (0x80)
     46
     47        ioport32_t control;
     48#define C_CBSR_MASK (0x3) /* Control-bulk service ratio */
     49#define C_CBSR_1_1  (0x0)
     50#define C_CBSR_1_2  (0x1)
     51#define C_CBSR_1_3  (0x2)
     52#define C_CBSR_1_4  (0x3)
     53#define C_CBSR_SHIFT (0)
    4854
    4955#define C_PLE (1 << 2)   /* Periodic list enable */
     
    5965#define C_HCFS_SHIFT       (6)
    6066
     67#define C_HCFS_GET(reg) \
     68        ((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
     69#define C_HCFS_SET(reg, hcfs_state) \
     70do { \
     71        reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
     72            | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
     73} while (0)
     74
     75
    6176#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
    6277#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
    6378#define C_RWE (1 << 10)  /* Remote wakeup enable */
    6479
    65         volatile uint32_t command_status;
     80        ioport32_t command_status;
    6681#define CS_HCR (1 << 0)   /* Host controller reset */
    6782#define CS_CLF (1 << 1)   /* Control list filled */
     
    7590         * writing causes enable/disable,
    7691         * status is write-clean (writing 1 clears the bit*/
    77         volatile uint32_t interrupt_status;
    78         volatile uint32_t interrupt_enable;
    79         volatile uint32_t interrupt_disable;
     92        ioport32_t interrupt_status;
     93        ioport32_t interrupt_enable;
     94        ioport32_t interrupt_disable;
    8095#define I_SO   (1 << 0)   /* Scheduling overrun */
    8196#define I_WDH  (1 << 1)   /* Done head write-back */
     
    89104
    90105        /** HCCA pointer (see hw_struct hcca.h) */
    91         volatile uint32_t hcca;
     106        ioport32_t hcca;
    92107#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
    93108
    94109        /** Currently executed periodic endpoint */
    95         const volatile uint32_t periodic_current;
     110        const ioport32_t periodic_current;
    96111
    97112        /** The first control endpoint */
    98         volatile uint32_t control_head;
     113        ioport32_t control_head;
    99114
    100115        /** Currently executed control endpoint */
    101         volatile uint32_t control_current;
     116        ioport32_t control_current;
    102117
    103118        /** The first bulk endpoint */
    104         volatile uint32_t bulk_head;
     119        ioport32_t bulk_head;
    105120
    106121        /** Currently executed bulk endpoint */
    107         volatile uint32_t bulk_current;
     122        ioport32_t bulk_current;
    108123
    109124        /** Done TD list, this value is periodically written to HCCA */
    110         const volatile uint32_t done_head;
     125        const ioport32_t done_head;
    111126
    112127        /** Frame time and max packet size for all transfers */
    113         volatile uint32_t fm_interval;
     128        ioport32_t fm_interval;
    114129#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
    115130#define FMI_FI_SHIFT (0)
     
    119134
    120135        /** Bit times remaining in current frame */
    121         const volatile uint32_t fm_remaining;
     136        const ioport32_t fm_remaining;
    122137#define FMR_FR_MASK FMI_FI_MASK
    123138#define FMR_FR_SHIFT FMI_FI_SHIFT
     
    125140
    126141        /** Frame number */
    127         const volatile uint32_t fm_number;
     142        const ioport32_t fm_number;
    128143#define FMN_NUMBER_MASK (0xffff)
    129144
    130145        /** Remaining bit time in frame to start periodic transfers */
    131         volatile uint32_t periodic_start;
     146        ioport32_t periodic_start;
    132147#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
    133148
    134149        /** Threshold for starting LS transaction */
    135         volatile uint32_t ls_threshold;
     150        ioport32_t ls_threshold;
    136151#define LST_LST_MASK (0x7fff)
    137152
    138153        /** The first root hub control register */
    139         volatile uint32_t rh_desc_a;
     154        ioport32_t rh_desc_a;
    140155#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
    141156#define RHDA_NDS_SHIFT (0)
     
    144159#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
    145160#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
    146 #define RHDA_NOCP      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
     161#define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
    147162#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
    148163#define RHDA_POTPGT_SHIFT (24)
    149164
    150165        /** The other root hub control register */
    151         volatile uint32_t rh_desc_b;
     166        ioport32_t rh_desc_b;
    152167#define RHDB_DR_MASK (0xffff) /* Device removable mask */
    153168#define RHDB_DR_SHIFT (0)
     
    161176
    162177        /** Root hub status register */
    163         volatile uint32_t rh_status;
     178        ioport32_t rh_status;
    164179#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
    165180                                * write: 0-no effect,
     
    167182                                *        specified in PPCM(RHDB), or all ports,
    168183                                *        if power is set globally */
    169 #define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
     184#define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */
    170185#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
    171186#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
     
    178193                                *        specified in PPCM(RHDB), or all ports,
    179194                                *        if power is set globally */
    180 #define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
     195#define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
    181196#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
    182197#define RHS_CLEAR_DRWE (1 << 31)
    183198
    184199        /** Root hub per port status */
    185         volatile uint32_t rh_port_status[];
     200        ioport32_t rh_port_status[];
    186201#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
    187202                                * w: 1-clear port enable, 0-nothing */
  • uspace/drv/bus/usb/ohci/root_hub.c

    r27eddb52 r4069f5c  
    4040#include "root_hub.h"
    4141#include <usb/classes/classes.h>
     42#include <usb/classes/hub.h>
    4243#include <usb/dev/driver.h>
    4344#include "ohci_regs.h"
     
    5657        .device_subclass = 0,
    5758        .device_version = 0,
    58         .length = sizeof (usb_standard_device_descriptor_t),
    59         .max_packet_size = 8,
    60         .vendor_id = 0x16db,
     59        .length = sizeof(usb_standard_device_descriptor_t),
     60        .max_packet_size = 64,
     61        .vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/
    6162        .product_id = 0x0001,
    6263        .str_serial_number = 0,
     
    7374        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7475        .interface_count = 1,
    75         .length = sizeof (usb_standard_configuration_descriptor_t),
    76         .max_power = 100,
     76        .length = sizeof(usb_standard_configuration_descriptor_t),
     77        .max_power = 0, /* root hubs don't need no power */
    7778        .str_configuration = 0,
    7879};
     
    8990        .interface_protocol = 0,
    9091        .interface_subclass = 0,
    91         .length = sizeof (usb_standard_interface_descriptor_t),
     92        .length = sizeof(usb_standard_interface_descriptor_t),
    9293        .str_interface = 0,
    9394};
     
    100101        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    101102        .endpoint_address = 1 + (1 << 7),
    102         .length = sizeof (usb_standard_endpoint_descriptor_t),
    103         .max_packet_size = 8,
     103        .length = sizeof(usb_standard_endpoint_descriptor_t),
     104        .max_packet_size = 2,
    104105        .poll_interval = 255,
    105106};
    106107
    107 /**
    108  * bitmask of hub features that are valid to be cleared
    109  */
    110 static const uint32_t hub_clear_feature_valid_mask =
    111     RHS_OCIC_FLAG |
    112     RHS_CLEAR_PORT_POWER;
    113 
    114 /**
    115  * bitmask of hub features that are cleared by writing 1 (and not 0)
    116  */
    117 static const uint32_t hub_clear_feature_by_writing_one_mask =
    118     RHS_CLEAR_PORT_POWER;
    119 
    120 /**
    121  * bitmask of hub features that are valid to be set
    122  */
    123 static const uint32_t hub_set_feature_valid_mask =
    124     RHS_LPSC_FLAG |
    125     RHS_OCIC_FLAG;
    126 
    127 /**
    128  * bitmask of hub features that are set by writing 1 and cleared by writing 0
    129  */
    130 static const uint32_t hub_set_feature_direct_mask =
    131     RHS_SET_PORT_POWER;
    132 
    133 /**
    134  * bitmask of port features that are valid to be set
    135  */
    136 static const uint32_t port_set_feature_valid_mask =
    137     RHPS_SET_PORT_ENABLE |
    138     RHPS_SET_PORT_SUSPEND |
    139     RHPS_SET_PORT_RESET |
    140     RHPS_SET_PORT_POWER;
    141 
    142 /**
    143  * bitmask of port features that can be cleared
    144  */
    145 static const uint32_t port_clear_feature_valid_mask =
    146     RHPS_CCS_FLAG |
    147     RHPS_SET_PORT_SUSPEND |
    148     RHPS_POCI_FLAG |
    149     RHPS_SET_PORT_POWER |
    150     RHPS_CSC_FLAG |
    151     RHPS_PESC_FLAG |
    152     RHPS_PSSC_FLAG |
    153     RHPS_OCIC_FLAG |
    154     RHPS_PRSC_FLAG;
    155 
    156 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into
    157 //USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
    158 
    159 /**
    160  * bitmask with port status changes
    161  */
    162 static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
    163 
    164 static int create_serialized_hub_descriptor(rh_t *instance);
    165 
    166 static int rh_init_descriptors(rh_t *instance);
    167 
    168 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    169     usb_transfer_batch_t * request);
    170 
    171 static int process_get_hub_status_request(rh_t *instance,
    172     usb_transfer_batch_t * request);
    173 
    174 static int process_get_status_request(rh_t *instance,
    175     usb_transfer_batch_t * request);
    176 
    177 static void create_interrupt_mask_in_instance(rh_t *instance);
    178 
    179 static int process_get_descriptor_request(rh_t *instance,
    180     usb_transfer_batch_t *request);
    181 
    182 static int process_get_configuration_request(rh_t *instance,
    183     usb_transfer_batch_t *request);
    184 
    185 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
    186 
    187 static int process_hub_feature_clear_request(rh_t *instance,
    188     uint16_t feature);
    189 
    190 static int process_port_feature_set_request(rh_t *instance,
    191     uint16_t feature, uint16_t port);
    192 
    193 static int process_port_feature_clear_request(rh_t *instance,
    194     uint16_t feature, uint16_t port);
    195 
    196 static int process_address_set_request(rh_t *instance,
    197     uint16_t address);
    198 
    199 static int process_request_with_output(rh_t *instance,
    200     usb_transfer_batch_t *request);
    201 
    202 static int process_request_with_input(rh_t *instance,
    203     usb_transfer_batch_t *request);
    204 
    205 static int process_request_without_data(rh_t *instance,
    206     usb_transfer_batch_t *request);
    207 
    208 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    209 
    210 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
    211 
    212 static bool is_zeros(void * buffer, size_t size);
    213 
    214 /** Root hub initialization
    215  * @return Error code.
    216  */
    217 int rh_init(rh_t *instance, ohci_regs_t *regs) {
    218         assert(instance);
     108static void create_serialized_hub_descriptor(rh_t *instance);
     109static void rh_init_descriptors(rh_t *instance);
     110static uint16_t create_interrupt_mask(rh_t *instance);
     111static int get_status(rh_t *instance, usb_transfer_batch_t *request);
     112static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request);
     113static int set_feature(rh_t *instance, usb_transfer_batch_t *request);
     114static int clear_feature(rh_t *instance, usb_transfer_batch_t *request);
     115static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
     116static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
     117static int control_request(rh_t *instance, usb_transfer_batch_t *request);
     118static inline void interrupt_request(
     119    usb_transfer_batch_t *request, uint16_t mask, size_t size)
     120{
     121        assert(request);
     122
     123        memcpy(request->data_buffer, &mask, size);
     124        request->transfered_size = size;
     125        usb_transfer_batch_finish_error(request, EOK);
     126}
     127
     128#define TRANSFER_OK(bytes) \
     129do { \
     130        request->transfered_size = bytes; \
     131        return EOK; \
     132} while (0)
     133
     134/** Root Hub driver structure initialization.
     135 *
     136 * Reads info registers and prepares descriptors. Sets power mode.
     137 */
     138void rh_init(rh_t *instance, ohci_regs_t *regs)
     139{
     140        assert(instance);
     141        assert(regs);
     142
    219143        instance->registers = regs;
    220144        instance->port_count =
    221145            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    222         int opResult = rh_init_descriptors(instance);
    223         if (opResult != EOK) {
    224                 return opResult;
    225         }
    226         // set port power mode to no-power-switching
     146        if (instance->port_count > 15) {
     147                usb_log_warning("OHCI specification does not allow more than 15"
     148                    " ports. Max 15 ports will be used");
     149                instance->port_count = 15;
     150        }
     151
     152        /* Don't forget the hub status bit and round up */
     153        instance->interrupt_mask_size = 1 + (instance->port_count / 8);
     154        instance->unfinished_interrupt_transfer = NULL;
     155
     156#ifdef OHCI_POWER_SWITCH_no
     157        /* Set port power mode to no power-switching. (always on) */
    227158        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    228         instance->unfinished_interrupt_transfer = NULL;
    229         instance->interrupt_mask_size = (instance->port_count + 8) / 8;
    230         instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
    231         if (!instance->interrupt_buffer)
    232                 return ENOMEM;
     159        /* Set to no over-current reporting */
     160        instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
     161#elif defined OHCI_POWER_SWITCH_ganged
     162        /* Set port power mode to no ganged power-switching. */
     163        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     164        instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
     165        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     166        /* Set to global over-current */
     167        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     168        instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
     169#else
     170        /* Set port power mode to no per port power-switching. */
     171        instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
     172        instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
     173
     174        /* Control all ports by global switch and turn them off */
     175        instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
     176        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     177        /* Return control to per port state */
     178        instance->registers->rh_desc_b |=
     179                ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
     180        /* Set per port over-current */
     181        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     182        instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
     183#endif
     184
     185        rh_init_descriptors(instance);
    233186
    234187        usb_log_info("Root hub (%zu ports) initialized.\n",
    235188            instance->port_count);
    236 
    237         return EOK;
    238 }
    239 /*----------------------------------------------------------------------------*/
    240 
    241 /**
    242  * process root hub request
    243  *
    244  * @param instance root hub instance
    245  * @param request structure containing both request and response information
    246  * @return error code
    247  */
    248 int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
     189}
     190/*----------------------------------------------------------------------------*/
     191/**
     192 * Process root hub request.
     193 *
     194 * @param instance Root hub instance
     195 * @param request Structure containing both request and response information
     196 * @return Error code
     197 */
     198void rh_request(rh_t *instance, usb_transfer_batch_t *request)
     199{
    249200        assert(instance);
    250201        assert(request);
    251         int opResult;
    252         if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
     202
     203        switch (request->ep->transfer_type)
     204        {
     205        case USB_TRANSFER_CONTROL:
    253206                usb_log_debug("Root hub got CONTROL packet\n");
    254                 opResult = process_ctrl_request(instance, request);
    255                 usb_transfer_batch_finish_error(request, opResult);
    256         } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     207                const int ret = control_request(instance, request);
     208                usb_transfer_batch_finish_error(request, ret);
     209                break;
     210        case USB_TRANSFER_INTERRUPT:
    257211                usb_log_debug("Root hub got INTERRUPT packet\n");
    258                 create_interrupt_mask_in_instance(instance);
    259                 if (is_zeros(instance->interrupt_buffer,
    260                     instance->interrupt_mask_size)) {
     212                const uint16_t mask = create_interrupt_mask(instance);
     213                if (mask == 0) {
    261214                        usb_log_debug("No changes..\n");
     215                        assert(instance->unfinished_interrupt_transfer == NULL);
    262216                        instance->unfinished_interrupt_transfer = request;
    263                         //will be finished later
    264                 } else {
    265                         usb_log_debug("Processing changes..\n");
    266                         process_interrupt_mask_in_instance(instance, request);
     217                        break;
    267218                }
    268                 opResult = EOK;
    269         } else {
    270 
    271                 opResult = EINVAL;
    272                 usb_transfer_batch_finish_error(request, opResult);
    273         }
    274         return EOK;
    275 }
    276 
    277 /*----------------------------------------------------------------------------*/
    278 
    279 /**
    280  * process interrupt on a hub
     219                usb_log_debug("Processing changes...\n");
     220                interrupt_request(request, mask, instance->interrupt_mask_size);
     221                break;
     222
     223        default:
     224                usb_log_error("Root hub got unsupported request.\n");
     225                usb_transfer_batch_finish_error(request, EINVAL);
     226        }
     227}
     228/*----------------------------------------------------------------------------*/
     229/**
     230 * Process interrupt on a hub device.
    281231 *
    282232 * If there is no pending interrupt transfer, nothing happens.
    283233 * @param instance
    284234 */
    285 void rh_interrupt(rh_t *instance) {
    286         if (!instance->unfinished_interrupt_transfer) {
     235void rh_interrupt(rh_t *instance)
     236{
     237        assert(instance);
     238
     239        if (!instance->unfinished_interrupt_transfer)
    287240                return;
    288         }
     241
    289242        usb_log_debug("Finalizing interrupt transfer\n");
    290         create_interrupt_mask_in_instance(instance);
    291         process_interrupt_mask_in_instance(instance,
    292             instance->unfinished_interrupt_transfer);
    293 }
    294 /*----------------------------------------------------------------------------*/
    295 
    296 /**
    297  * Create hub descriptor used in hub-driver <-> hub communication
    298  *
    299  * This means creating byt array from data in root hub registers. For more
    300  * info see usb hub specification.
    301  *
     243        const uint16_t mask = create_interrupt_mask(instance);
     244        interrupt_request(instance->unfinished_interrupt_transfer,
     245            mask, instance->interrupt_mask_size);
     246
     247        instance->unfinished_interrupt_transfer = NULL;
     248}
     249/*----------------------------------------------------------------------------*/
     250/**
     251 * Create hub descriptor.
     252 *
     253 * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263)
     254 *
     255 * @param instance Root hub instance
     256 * @return Error code
     257 */
     258void create_serialized_hub_descriptor(rh_t *instance)
     259{
     260        assert(instance);
     261
     262        /* 7 bytes + 2 port bit fields (port count + global bit) */
     263        const size_t size = 7 + (instance->interrupt_mask_size * 2);
     264        assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
     265        instance->hub_descriptor_size = size;
     266
     267        const uint32_t hub_desc = instance->registers->rh_desc_a;
     268        const uint32_t port_desc = instance->registers->rh_desc_b;
     269
     270        /* bDescLength */
     271        instance->descriptors.hub[0] = size;
     272        /* bDescriptorType */
     273        instance->descriptors.hub[1] = USB_DESCTYPE_HUB;
     274        /* bNmbrPorts */
     275        instance->descriptors.hub[2] = instance->port_count;
     276        /* wHubCharacteristics */
     277        instance->descriptors.hub[3] = 0 |
     278            /* The lowest 2 bits indicate power switching mode */
     279            (((hub_desc & RHDA_PSM_FLAG)  ? 1 : 0) << 0) |
     280            (((hub_desc & RHDA_NPS_FLAG)  ? 1 : 0) << 1) |
     281            /* Bit 3 indicates device type (compound device) */
     282            (((hub_desc & RHDA_DT_FLAG)   ? 1 : 0) << 2) |
     283            /* Bits 4,5 indicate over-current protection mode */
     284            (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) |
     285            (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4);
     286
     287        /* Reserved */
     288        instance->descriptors.hub[4] = 0;
     289        /* bPwrOn2PwrGood */
     290        instance->descriptors.hub[5] =
     291            (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
     292        /* bHubContrCurrent, root hubs don't need no power. */
     293        instance->descriptors.hub[6] = 0;
     294
     295        /* Device Removable and some legacy 1.0 stuff*/
     296        instance->descriptors.hub[7] =
     297            (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
     298        instance->descriptors.hub[8] = 0xff;
     299        if (instance->interrupt_mask_size == 2) {
     300                instance->descriptors.hub[8] =
     301                    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
     302                instance->descriptors.hub[9]  = 0xff;
     303                instance->descriptors.hub[10] = 0xff;
     304        }
     305}
     306/*----------------------------------------------------------------------------*/
     307/** Initialize hub descriptors.
     308 *
     309 * A full configuration descriptor is assembled. The configuration and endpoint
     310 * descriptors have local modifications.
     311 * @param instance Root hub instance
     312 * @return Error code
     313 */
     314void rh_init_descriptors(rh_t *instance)
     315{
     316        assert(instance);
     317
     318        instance->descriptors.configuration = ohci_rh_conf_descriptor;
     319        instance->descriptors.interface = ohci_rh_iface_descriptor;
     320        instance->descriptors.endpoint = ohci_rh_ep_descriptor;
     321        create_serialized_hub_descriptor(instance);
     322
     323        instance->descriptors.endpoint.max_packet_size =
     324            instance->interrupt_mask_size;
     325
     326        instance->descriptors.configuration.total_length =
     327            sizeof(usb_standard_configuration_descriptor_t) +
     328            sizeof(usb_standard_endpoint_descriptor_t) +
     329            sizeof(usb_standard_interface_descriptor_t) +
     330            instance->hub_descriptor_size;
     331}
     332/*----------------------------------------------------------------------------*/
     333/**
     334 * Create bitmap of changes to answer status interrupt.
     335 *
     336 * Result contains bitmap where bit 0 indicates change on hub and
     337 * bit i indicates change on i`th port (i>0). For more info see
     338 * Hub and Port status bitmap specification in USB specification
     339 * (chapter 11.13.4).
    302340 * @param instance root hub instance
    303  * @return error code
    304  */
    305 static int create_serialized_hub_descriptor(rh_t *instance) {
    306         size_t size = 7 +
    307             ((instance->port_count + 7) / 8) * 2;
    308         size_t var_size = (instance->port_count + 7) / 8;
    309         uint8_t * result = (uint8_t*) malloc(size);
    310         if (!result) return ENOMEM;
    311 
    312         bzero(result, size);
    313         //size
    314         result[0] = size;
    315         //descriptor type
    316         result[1] = USB_DESCTYPE_HUB;
    317         result[2] = instance->port_count;
    318         uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    319         result[3] =
    320             ((hub_desc_reg >> 8) % 2) +
    321             (((hub_desc_reg >> 9) % 2) << 1) +
    322             (((hub_desc_reg >> 10) % 2) << 2) +
    323             (((hub_desc_reg >> 11) % 2) << 3) +
    324             (((hub_desc_reg >> 12) % 2) << 4);
    325         result[4] = 0;
    326         result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
    327         result[6] = 50;
    328 
    329         size_t port;
    330         for (port = 1; port <= instance->port_count; ++port) {
    331                 uint8_t is_non_removable =
    332                     instance->registers->rh_desc_b >> port % 2;
    333                 result[7 + port / 8] +=
    334                     is_non_removable << (port % 8);
    335         }
    336         size_t i;
    337         for (i = 0; i < var_size; ++i) {
    338                 result[7 + var_size + i] = 255;
    339         }
    340         instance->hub_descriptor = result;
    341         instance->descriptor_size = size;
    342 
    343         return EOK;
    344 }
    345 /*----------------------------------------------------------------------------*/
    346 
    347 /** initialize hub descriptors
    348  *
    349  * Initialized are device and full configuration descriptor. These need to
    350  * be initialized only once per hub.
    351  * @instance root hub instance
    352  * @return error code
    353  */
    354 static int rh_init_descriptors(rh_t *instance) {
    355         memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    356             sizeof (ohci_rh_device_descriptor)
    357             );
    358         usb_standard_configuration_descriptor_t descriptor;
    359         memcpy(&descriptor, &ohci_rh_conf_descriptor,
    360             sizeof (ohci_rh_conf_descriptor));
    361 
    362         int opResult = create_serialized_hub_descriptor(instance);
    363         if (opResult != EOK) {
    364                 return opResult;
    365         }
    366         descriptor.total_length =
    367             sizeof (usb_standard_configuration_descriptor_t) +
    368             sizeof (usb_standard_endpoint_descriptor_t) +
    369             sizeof (usb_standard_interface_descriptor_t) +
    370             instance->descriptor_size;
    371 
    372         uint8_t * full_config_descriptor =
    373             (uint8_t*) malloc(descriptor.total_length);
    374         if (!full_config_descriptor) {
    375                 return ENOMEM;
    376         }
    377         memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    378         memcpy(full_config_descriptor + sizeof (descriptor),
    379             &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
    380         memcpy(full_config_descriptor + sizeof (descriptor) +
    381             sizeof (ohci_rh_iface_descriptor),
    382             &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
    383         memcpy(full_config_descriptor + sizeof (descriptor) +
    384             sizeof (ohci_rh_iface_descriptor) +
    385             sizeof (ohci_rh_ep_descriptor),
    386             instance->hub_descriptor, instance->descriptor_size);
    387 
    388         instance->descriptors.configuration = full_config_descriptor;
    389         instance->descriptors.configuration_size = descriptor.total_length;
    390 
    391         return EOK;
    392 }
    393 /*----------------------------------------------------------------------------*/
    394 
    395 /**
    396  * create answer to port status_request
    397  *
    398  * Copy content of corresponding port status register to answer buffer. The
    399  * format of the port status register and port status data is the same (
    400  * see OHCI root hub and USB hub documentation).
    401  *
    402  * @param instance root hub instance
    403  * @param port port number, counted from 1
    404  * @param request structure containing both request and response information
    405  * @return error code
    406  */
    407 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    408     usb_transfer_batch_t * request) {
    409         if (port < 1 || port > instance->port_count)
    410                 return EINVAL;
    411         request->transfered_size = 4;
    412         uint32_t data = instance->registers->rh_port_status[port - 1];
    413         memcpy(request->data_buffer, &data, 4);
    414         return EOK;
    415 }
    416 /*----------------------------------------------------------------------------*/
    417 
    418 /**
    419  * create answer to port status_request
    420  *
    421  * This copies flags in hub status register into the buffer. The format of the
    422  * status register and status message is the same, according to USB hub
    423  * specification and OHCI root hub specification.
    424  *
    425  * @param instance root hub instance
    426  * @param request structure containing both request and response information
    427  * @return error code
    428  */
    429 static int process_get_hub_status_request(rh_t *instance,
    430     usb_transfer_batch_t * request) {
    431         request->transfered_size = 4;
    432         //bits, 0,1,16,17
    433         uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
    434         uint32_t data = mask & instance->registers->rh_status;
    435         memcpy(request->data_buffer, &data, 4);
    436 
    437         return EOK;
    438 }
    439 /*----------------------------------------------------------------------------*/
    440 
    441 /**
    442  * create answer to status request
     341 * @return Mask of changes.
     342 */
     343uint16_t create_interrupt_mask(rh_t *instance)
     344{
     345        assert(instance);
     346        uint16_t mask = 0;
     347
     348        /* Only local power source change and over-current change can happen */
     349        if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
     350                mask |= 1;
     351        }
     352        size_t port = 1;
     353        for (; port <= instance->port_count; ++port) {
     354                /* Write-clean bits are those that indicate change */
     355                if (RHPS_CHANGE_WC_MASK
     356                    & instance->registers->rh_port_status[port - 1]) {
     357
     358                        mask |= (1 << port);
     359                }
     360        }
     361        /* USB is little endian */
     362        return host2uint32_t_le(mask);
     363}
     364/*----------------------------------------------------------------------------*/
     365/**
     366 * Create answer to status request.
    443367 *
    444368 * This might be either hub status or port status request. If neither,
     
    448372 * @return error code
    449373 */
    450 static int process_get_status_request(rh_t *instance,
    451     usb_transfer_batch_t * request) {
    452         size_t buffer_size = request->buffer_size;
    453         usb_device_request_setup_packet_t * request_packet =
    454             (usb_device_request_setup_packet_t*)
    455             request->setup_buffer;
    456 
    457         usb_hub_bm_request_type_t request_type = request_packet->request_type;
    458         if (buffer_size < 4) {
    459                 usb_log_warning("Requested more data than buffer size\n");
    460                 return EINVAL;
    461         }
    462 
    463         if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
    464                 return process_get_hub_status_request(instance, request);
    465         if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
    466                 return process_get_port_status_request(instance,
    467             request_packet->index,
    468             request);
     374int get_status(rh_t *instance, usb_transfer_batch_t *request)
     375{
     376        assert(instance);
     377        assert(request);
     378
     379        const usb_device_request_setup_packet_t *request_packet =
     380            (usb_device_request_setup_packet_t*)request->setup_buffer;
     381
     382        if (request->buffer_size < 4) {
     383                usb_log_error("Buffer too small for get status request.\n");
     384                return EOVERFLOW;
     385        }
     386
     387        /* Hub status: just filter relevant info from rh_status reg */
     388        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
     389                const uint32_t data = instance->registers->rh_status &
     390                    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
     391                memcpy(request->data_buffer, &data, 4);
     392                TRANSFER_OK(4);
     393        }
     394
     395        /* Copy appropriate rh_port_status register, OHCI designers were
     396         * kind enough to make those bit values match USB specification */
     397        if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
     398                const unsigned port = request_packet->index;
     399                if (port < 1 || port > instance->port_count)
     400                        return EINVAL;
     401
     402                const uint32_t data =
     403                    instance->registers->rh_port_status[port - 1];
     404                memcpy(request->data_buffer, &data, 4);
     405                TRANSFER_OK(4);
     406        }
    469407
    470408        return ENOTSUP;
    471409}
    472410/*----------------------------------------------------------------------------*/
    473 
    474 /**
    475  * create answer to status interrupt consisting of change bitmap
    476  *
    477  * Result contains bitmap where bit 0 indicates change on hub and
    478  * bit i indicates change on i`th port (i>0). For more info see
    479  * Hub and Port status bitmap specification in USB specification
    480  * (chapter 11.13.4).
    481  * Uses instance`s interrupt buffer to store the interrupt information.
    482  * @param instance root hub instance
    483  */
    484 static void create_interrupt_mask_in_instance(rh_t * instance) {
    485         uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
    486         uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    487             | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    488         bzero(bitmap, instance->interrupt_mask_size);
    489         if ((instance->registers->rh_status & mask) != 0) {
    490                 bitmap[0] = 1;
    491         }
    492         size_t port;
    493         mask = port_status_change_mask;
    494         for (port = 1; port <= instance->port_count; ++port) {
    495                 if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
    496 
    497                         bitmap[(port) / 8] += 1 << (port % 8);
    498                 }
    499         }
    500 }
    501 /*----------------------------------------------------------------------------*/
    502 
    503 /**
    504  * create answer to a descriptor request
     411/**
     412 * Create answer to a descriptor request.
    505413 *
    506414 * This might be a request for standard (configuration, device, endpoint or
    507415 * interface) or device specific (hub) descriptor.
    508  * @param instance root hub instance
    509  * @param request structure containing both request and response information
    510  * @return error code
    511  */
    512 static int process_get_descriptor_request(rh_t *instance,
    513     usb_transfer_batch_t *request) {
    514         usb_device_request_setup_packet_t * setup_request =
    515             (usb_device_request_setup_packet_t*) request->setup_buffer;
     416 * @param instance Root hub instance
     417 * @param request Structure containing both request and response information
     418 * @return Error code
     419 */
     420int get_descriptor(rh_t *instance, usb_transfer_batch_t *request)
     421{
     422        assert(instance);
     423        assert(request);
     424
     425        const usb_device_request_setup_packet_t *setup_request =
     426            (usb_device_request_setup_packet_t *) request->setup_buffer;
    516427        size_t size;
    517         const void * result_descriptor = NULL;
     428        const void *descriptor = NULL;
    518429        const uint16_t setup_request_value = setup_request->value_high;
    519430        //(setup_request->value_low << 8);
    520         switch (setup_request_value) {
    521                 case USB_DESCTYPE_HUB:
    522                 {
    523                         usb_log_debug2("USB_DESCTYPE_HUB\n");
    524                         result_descriptor = instance->hub_descriptor;
    525                         size = instance->descriptor_size;
    526                         break;
    527                 }
    528                 case USB_DESCTYPE_DEVICE:
    529                 {
    530                         usb_log_debug2("USB_DESCTYPE_DEVICE\n");
    531                         result_descriptor = &ohci_rh_device_descriptor;
    532                         size = sizeof (ohci_rh_device_descriptor);
    533                         break;
    534                 }
    535                 case USB_DESCTYPE_CONFIGURATION:
    536                 {
    537                         usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
    538                         result_descriptor = instance->descriptors.configuration;
    539                         size = instance->descriptors.configuration_size;
    540                         break;
    541                 }
    542                 case USB_DESCTYPE_INTERFACE:
    543                 {
    544                         usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
    545                         result_descriptor = &ohci_rh_iface_descriptor;
    546                         size = sizeof (ohci_rh_iface_descriptor);
    547                         break;
    548                 }
    549                 case USB_DESCTYPE_ENDPOINT:
    550                 {
    551                         usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
    552                         result_descriptor = &ohci_rh_ep_descriptor;
    553                         size = sizeof (ohci_rh_ep_descriptor);
    554                         break;
    555                 }
    556                 default:
    557                 {
    558                         usb_log_debug2("USB_DESCTYPE_EINVAL %d \n",
    559                             setup_request->value);
    560                         usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue "
    561                             "%d\n\tindex %d\n\tlen %d\n ",
    562                             setup_request->request_type,
    563                             setup_request->request,
    564                             setup_request_value,
    565                             setup_request->index,
    566                             setup_request->length
    567                             );
    568                         return EINVAL;
    569                 }
     431        switch (setup_request_value)
     432        {
     433        case USB_DESCTYPE_HUB:
     434                usb_log_debug2("USB_DESCTYPE_HUB\n");
     435                /* Hub descriptor was generated locally */
     436                descriptor = instance->descriptors.hub;
     437                size = instance->hub_descriptor_size;
     438                break;
     439
     440        case USB_DESCTYPE_DEVICE:
     441                usb_log_debug2("USB_DESCTYPE_DEVICE\n");
     442                /* Device descriptor is shared (No one should ask for it)*/
     443                descriptor = &ohci_rh_device_descriptor;
     444                size = sizeof(ohci_rh_device_descriptor);
     445                break;
     446
     447        case USB_DESCTYPE_CONFIGURATION:
     448                usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
     449                /* Start with configuration and add others depending on
     450                 * request size */
     451                descriptor = &instance->descriptors;
     452                size = instance->descriptors.configuration.total_length;
     453                break;
     454
     455        case USB_DESCTYPE_INTERFACE:
     456                usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
     457                /* Use local interface descriptor. There is one and it
     458                 * might be modified */
     459                descriptor = &instance->descriptors.interface;
     460                size = sizeof(instance->descriptors.interface);
     461                break;
     462
     463        case USB_DESCTYPE_ENDPOINT:
     464                /* Use local endpoint descriptor. There is one
     465                 * it might have max_packet_size field modified*/
     466                usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
     467                descriptor = &instance->descriptors.endpoint;
     468                size = sizeof(instance->descriptors.endpoint);
     469                break;
     470
     471        default:
     472                usb_log_debug2("USB_DESCTYPE_EINVAL %d \n"
     473                    "\ttype %d\n\trequest %d\n\tvalue "
     474                    "%d\n\tindex %d\n\tlen %d\n ",
     475                    setup_request->value,
     476                    setup_request->request_type, setup_request->request,
     477                    setup_request_value, setup_request->index,
     478                    setup_request->length);
     479                return EINVAL;
    570480        }
    571481        if (request->buffer_size < size) {
    572482                size = request->buffer_size;
    573483        }
    574         request->transfered_size = size;
    575         memcpy(request->data_buffer, result_descriptor, size);
    576 
    577         return EOK;
    578 }
    579 /*----------------------------------------------------------------------------*/
    580 
    581 /**
    582  * answer to get configuration request
    583  *
    584  * Root hub works independently on the configuration.
    585  * @param instance root hub instance
    586  * @param request structure containing both request and response information
    587  * @return error code
    588  */
    589 static int process_get_configuration_request(rh_t *instance,
    590     usb_transfer_batch_t *request) {
    591         //set and get configuration requests do not have any meaning, only dummy
    592         //values are returned
    593         if (request->buffer_size != 1)
    594                 return EINVAL;
    595         request->data_buffer[0] = 1;
    596         request->transfered_size = 1;
    597 
    598         return EOK;
    599 }
    600 /*----------------------------------------------------------------------------*/
    601 
    602 /**
    603  * process feature-enabling request on hub
    604  *
    605  * @param instance root hub instance
    606  * @param feature feature selector
    607  * @return error code
    608  */
    609 static int process_hub_feature_set_request(rh_t *instance,
    610     uint16_t feature) {
    611         if (!((1 << feature) & hub_set_feature_valid_mask))
    612                 return EINVAL;
    613         if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
    614                 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
    615         instance->registers->rh_status =
    616             (instance->registers->rh_status | (1 << feature))
    617             & (~hub_clear_feature_by_writing_one_mask);
    618 
    619         return EOK;
    620 }
    621 /*----------------------------------------------------------------------------*/
    622 
    623 /**
    624  * process feature-disabling request on hub
    625  *
    626  * @param instance root hub instance
    627  * @param feature feature selector
    628  * @return error code
    629  */
    630 static int process_hub_feature_clear_request(rh_t *instance,
    631     uint16_t feature) {
    632         if (!((1 << feature) & hub_clear_feature_valid_mask))
    633                 return EINVAL;
    634         //is the feature cleared directly?
    635         if ((1 << feature) & hub_set_feature_direct_mask) {
    636                 instance->registers->rh_status =
    637                     (instance->registers->rh_status & (~(1 << feature)))
    638                     & (~hub_clear_feature_by_writing_one_mask);
    639         } else {//the feature is cleared by writing '1'
    640 
    641                 instance->registers->rh_status =
    642                     (instance->registers->rh_status
    643                     & (~hub_clear_feature_by_writing_one_mask))
    644                     | (1 << feature);
    645         }
    646         return EOK;
    647 }
    648 /*----------------------------------------------------------------------------*/
    649 
     484
     485        memcpy(request->data_buffer, descriptor, size);
     486        TRANSFER_OK(size);
     487}
     488/*----------------------------------------------------------------------------*/
    650489/**
    651490 * process feature-enabling request on hub
     
    657496 * @return error code
    658497 */
    659 static int process_port_feature_set_request(rh_t *instance,
    660     uint16_t feature, uint16_t port) {
    661         if (!((1 << feature) & port_set_feature_valid_mask))
    662                 return EINVAL;
     498int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     499{
     500        assert(instance);
     501
    663502        if (port < 1 || port > instance->port_count)
    664503                return EINVAL;
    665         instance->registers->rh_port_status[port - 1] =
    666             (instance->registers->rh_port_status[port - 1] | (1 << feature))
    667             & (~port_clear_feature_valid_mask);
    668         return EOK;
    669 }
    670 /*----------------------------------------------------------------------------*/
    671 
    672 /**
    673  * process feature-disabling request on hub
     504
     505        switch (feature)
     506        {
     507        case USB_HUB_FEATURE_PORT_POWER:   //8
     508                /* No power switching */
     509                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     510                        return EOK;
     511                /* Ganged power switching */
     512                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     513                        instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
     514                        return EOK;
     515                }
     516        case USB_HUB_FEATURE_PORT_ENABLE:  //1
     517        case USB_HUB_FEATURE_PORT_SUSPEND: //2
     518        case USB_HUB_FEATURE_PORT_RESET:   //4
     519                /* Nice thing is that these shifts correspond to the position
     520                 * of control bits in register */
     521                instance->registers->rh_port_status[port - 1] = (1 << feature);
     522                return EOK;
     523        default:
     524                return ENOTSUP;
     525        }
     526}
     527/*----------------------------------------------------------------------------*/
     528/**
     529 * Process feature clear request.
    674530 *
    675531 * @param instance root hub instance
     
    679535 * @return error code
    680536 */
    681 static int process_port_feature_clear_request(rh_t *instance,
    682     uint16_t feature, uint16_t port) {
    683         if (!((1 << feature) & port_clear_feature_valid_mask))
    684                 return EINVAL;
     537int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     538{
     539        assert(instance);
     540
    685541        if (port < 1 || port > instance->port_count)
    686542                return EINVAL;
    687         if (feature == USB_HUB_FEATURE_PORT_POWER)
    688                 feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    689         if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
    690                 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    691         instance->registers->rh_port_status[port - 1] =
    692             (instance->registers->rh_port_status[port - 1]
    693             & (~port_clear_feature_valid_mask))
    694             | (1 << feature);
    695 
    696         return EOK;
    697 }
    698 /*----------------------------------------------------------------------------*/
    699 
    700 /**
    701  * register address to this device
    702  *
    703  * @param instance root hub instance
    704  * @param address new address
    705  * @return error code
    706  */
    707 static int process_address_set_request(rh_t *instance,
    708     uint16_t address) {
    709         return ENOTSUP;
    710 }
    711 /*----------------------------------------------------------------------------*/
    712 
    713 /**
    714  * process one of requests that requere output data
    715  *
    716  * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
    717  * USB_DEVREQ_GET_CONFIGURATION.
    718  * @param instance root hub instance
    719  * @param request structure containing both request and response information
    720  * @return error code
    721  */
    722 static int process_request_with_output(rh_t *instance,
    723     usb_transfer_batch_t *request) {
    724         usb_device_request_setup_packet_t * setup_request =
    725             (usb_device_request_setup_packet_t*) request->setup_buffer;
    726         if (setup_request->request == USB_DEVREQ_GET_STATUS) {
    727                 usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    728                 return process_get_status_request(instance, request);
    729         }
    730         if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
    731                 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    732                 return process_get_descriptor_request(instance, request);
    733         }
    734         if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
    735                 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    736 
    737                 return process_get_configuration_request(instance, request);
    738         }
    739         return ENOTSUP;
    740 }
    741 /*----------------------------------------------------------------------------*/
    742 
    743 /**
    744  * process one of requests that carry input data
    745  *
    746  * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
    747  * USB_DEVREQ_SET_CONFIGURATION.
    748  * @param instance root hub instance
    749  * @param request structure containing both request and response information
    750  * @return error code
    751  */
    752 static int process_request_with_input(rh_t *instance,
    753     usb_transfer_batch_t *request) {
    754         usb_device_request_setup_packet_t * setup_request =
    755             (usb_device_request_setup_packet_t*) request->setup_buffer;
    756         request->transfered_size = 0;
    757         if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
     543
     544        /* Enabled features to clear: see page 269 of USB specs */
     545        switch (feature)
     546        {
     547        case USB_HUB_FEATURE_PORT_POWER:          //8
     548                /* No power switching */
     549                if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
     550                        return ENOTSUP;
     551                /* Ganged power switching */
     552                if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
     553                        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     554                        return EOK;
     555                }
     556                instance->registers->rh_port_status[port - 1] =
     557                        RHPS_CLEAR_PORT_POWER;
     558                return EOK;
     559
     560        case USB_HUB_FEATURE_PORT_ENABLE:         //1
     561                instance->registers->rh_port_status[port - 1] =
     562                        RHPS_CLEAR_PORT_ENABLE;
     563                return EOK;
     564
     565        case USB_HUB_FEATURE_PORT_SUSPEND:        //2
     566                instance->registers->rh_port_status[port - 1] =
     567                        RHPS_CLEAR_PORT_SUSPEND;
     568                return EOK;
     569
     570        case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
     571        case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
     572        case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
     573        case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
     574        case USB_HUB_FEATURE_C_PORT_RESET:        //20
     575                /* Nice thing is that these shifts correspond to the position
     576                 * of control bits in register */
     577                instance->registers->rh_port_status[port - 1] = (1 << feature);
     578                return EOK;
     579
     580        default:
    758581                return ENOTSUP;
    759582        }
    760         if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
    761                 //set and get configuration requests do not have any meaning,
    762                 //only dummy values are returned
    763 
    764                 return EOK;
    765         }
    766         return ENOTSUP;
    767 }
    768 /*----------------------------------------------------------------------------*/
    769 
     583}
     584/*----------------------------------------------------------------------------*/
    770585/**
    771586 * process one of requests that do not request nor carry additional data
     
    777592 * @return error code
    778593 */
    779 static int process_request_without_data(rh_t *instance,
    780     usb_transfer_batch_t *request) {
    781         usb_device_request_setup_packet_t * setup_request =
    782             (usb_device_request_setup_packet_t*) request->setup_buffer;
    783         request->transfered_size = 0;
    784         if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
    785                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    786                         usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    787                         return process_hub_feature_clear_request(instance,
    788                             setup_request->value);
    789                 }
    790                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    791                         usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    792                         return process_port_feature_clear_request(instance,
    793                             setup_request->value,
    794                             setup_request->index);
    795                 }
    796                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     594int set_feature(rh_t *instance, usb_transfer_batch_t *request)
     595{
     596        assert(instance);
     597        assert(request);
     598
     599        const usb_device_request_setup_packet_t *setup_request =
     600            (usb_device_request_setup_packet_t *) request->setup_buffer;
     601        switch (setup_request->request_type)
     602        {
     603        case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
     604                usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
     605                return set_feature_port(instance,
     606                    setup_request->value, setup_request->index);
     607
     608        case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
     609                /* Chapter 11.16.2 specifies that hub can be recipient
     610                 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT
     611                 * features. It makes no sense to SET either. */
     612                usb_log_error("Invalid HUB set feature request.\n");
     613                return ENOTSUP;
     614        default:
     615                usb_log_error("Invalid set feature request type: %d\n",
    797616                    setup_request->request_type);
    798617                return EINVAL;
    799618        }
    800         if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
    801                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    802                         usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    803                         return process_hub_feature_set_request(instance,
    804                             setup_request->value);
     619}
     620/*----------------------------------------------------------------------------*/
     621/**
     622 * process one of requests that do not request nor carry additional data
     623 *
     624 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
     625 * USB_DEVREQ_SET_ADDRESS.
     626 * @param instance root hub instance
     627 * @param request structure containing both request and response information
     628 * @return error code
     629 */
     630int clear_feature(rh_t *instance, usb_transfer_batch_t *request)
     631{
     632        assert(instance);
     633        assert(request);
     634
     635        const usb_device_request_setup_packet_t *setup_request =
     636            (usb_device_request_setup_packet_t *) request->setup_buffer;
     637        request->transfered_size = 0;
     638        switch (setup_request->request_type)
     639        {
     640        case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
     641                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
     642                return clear_feature_port(instance,
     643                    setup_request->value, setup_request->index);
     644
     645        case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
     646                usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n");
     647                /*
     648                 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
     649                 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented
     650                 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported
     651                 * as root hubs do not support local power status feature.
     652                 * (OHCI pg. 127) */
     653                if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
     654                        instance->registers->rh_status = RHS_OCIC_FLAG;
     655                        TRANSFER_OK(0);
    805656                }
    806                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    807                         usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    808                         return process_port_feature_set_request(instance,
    809                             setup_request->value,
    810                             setup_request->index);
    811                 }
    812                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     657        default:
     658                usb_log_error("Invalid clear feature request type: %d\n",
    813659                    setup_request->request_type);
    814660                return EINVAL;
    815661        }
    816         if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
    817                 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    818                 return process_address_set_request(instance,
    819                     setup_request->value);
    820         }
    821         usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
    822             setup_request->request_type);
    823 
    824         return ENOTSUP;
    825 }
    826 /*----------------------------------------------------------------------------*/
    827 
    828 /**
    829  * process hub control request
     662}
     663/*----------------------------------------------------------------------------*/
     664/**
     665 * Process hub control request.
    830666 *
    831667 * If needed, writes answer into the request structure.
     
    844680 * @return error code
    845681 */
    846 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
     682int control_request(rh_t *instance, usb_transfer_batch_t *request)
     683{
     684        assert(instance);
     685        assert(request);
     686
    847687        if (!request->setup_buffer) {
    848                 usb_log_error("root hub received empty transaction?");
     688                usb_log_error("Root hub received empty transaction!");
    849689                return EINVAL;
    850690        }
    851         int opResult;
    852         if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
     691
     692        if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
    853693                usb_log_error("Setup packet too small\n");
    854                 return EINVAL;
    855         }
    856         usb_log_debug("CTRL packet: %s.\n",
    857             usb_debug_str_buffer(
    858             (const uint8_t *) request->setup_buffer, 8, 8));
    859         usb_device_request_setup_packet_t * setup_request =
    860             (usb_device_request_setup_packet_t*)
    861             request->setup_buffer;
    862         switch (setup_request->request) {
    863                 case USB_DEVREQ_GET_STATUS:
    864                 case USB_DEVREQ_GET_DESCRIPTOR:
    865                 case USB_DEVREQ_GET_CONFIGURATION:
    866                         usb_log_debug2("Processing request with output\n");
    867                         opResult = process_request_with_output(
    868                             instance, request);
    869                         break;
    870                 case USB_DEVREQ_CLEAR_FEATURE:
    871                 case USB_DEVREQ_SET_FEATURE:
    872                 case USB_DEVREQ_SET_ADDRESS:
    873                         usb_log_debug2("Processing request without "
    874                             "additional data\n");
    875                         opResult = process_request_without_data(
    876                             instance, request);
    877                         break;
    878                 case USB_DEVREQ_SET_DESCRIPTOR:
    879                 case USB_DEVREQ_SET_CONFIGURATION:
    880                         usb_log_debug2("Processing request with input\n");
    881                         opResult = process_request_with_input(
    882                             instance, request);
    883 
    884                         break;
    885                 default:
    886                         usb_log_warning("Received unsupported request: %d.\n",
    887                             setup_request->request);
    888                         opResult = ENOTSUP;
    889         }
    890         return opResult;
    891 }
    892 /*----------------------------------------------------------------------------*/
    893 
    894 /**
    895  * process hanging interrupt request
    896  *
    897  * If an interrupt transfer has been received and there was no change,
    898  * the driver stores the transfer information and waits for change to occcur.
    899  * This routine is called when that happens and it finalizes the interrupt
    900  * transfer.
    901  *
    902  * @param instance hub instance
    903  * @param request batch request to be processed
    904  *
    905  * @return
    906  */
    907 static int process_interrupt_mask_in_instance(rh_t *instance,
    908     usb_transfer_batch_t * request) {
    909         memcpy(request->data_buffer, instance->interrupt_buffer,
    910             instance->interrupt_mask_size);
    911         request->transfered_size = instance->interrupt_mask_size;
    912         instance->unfinished_interrupt_transfer = NULL;
    913         usb_transfer_batch_finish_error(request, EOK);
    914 
    915         return EOK;
    916 }
    917 
    918 /*----------------------------------------------------------------------------*/
    919 
    920 /**
    921  * return whether the buffer is full of zeros
    922  *
    923  * Convenience function.
    924  * @param buffer
    925  * @param size
    926  * @return
    927  */
    928 static bool is_zeros(void *buffer, size_t size) {
    929         if (!buffer) return true;
    930         if (!size) return true;
    931         size_t i;
    932         for (i = 0; i < size; ++i) {
    933                 if (((char*) buffer)[i])
    934                         return false;
    935         }
    936         return true;
     694                return EOVERFLOW;
     695        }
     696
     697        usb_log_debug2("CTRL packet: %s.\n",
     698            usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
     699        const usb_device_request_setup_packet_t *setup_request =
     700            (usb_device_request_setup_packet_t *) request->setup_buffer;
     701        switch (setup_request->request)
     702        {
     703        case USB_DEVREQ_GET_STATUS:
     704                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
     705                return get_status(instance, request);
     706
     707        case USB_DEVREQ_GET_DESCRIPTOR:
     708                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
     709                return get_descriptor(instance, request);
     710
     711        case USB_DEVREQ_GET_CONFIGURATION:
     712                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
     713                if (request->buffer_size != 1)
     714                        return EINVAL;
     715                request->data_buffer[0] = 1;
     716                TRANSFER_OK(1);
     717
     718        case USB_DEVREQ_CLEAR_FEATURE:
     719                usb_log_debug2("Processing request without "
     720                    "additional data\n");
     721                return clear_feature(instance, request);
     722        case USB_DEVREQ_SET_FEATURE:
     723                usb_log_debug2("Processing request without "
     724                    "additional data\n");
     725                return set_feature(instance, request);
     726
     727        case USB_DEVREQ_SET_ADDRESS:
     728                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
     729                instance->address = setup_request->value;
     730                TRANSFER_OK(0);
     731
     732        case USB_DEVREQ_SET_CONFIGURATION:
     733                usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
     734                /* We don't need to do anything */
     735                TRANSFER_OK(0);
     736
     737        case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
     738        default:
     739                usb_log_error("Received unsupported request: %d.\n",
     740                    setup_request->request);
     741                return ENOTSUP;
     742        }
    937743}
    938744
  • uspace/drv/bus/usb/ohci/root_hub.h

    r27eddb52 r4069f5c  
    4141#include "batch.h"
    4242
     43#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
     44
    4345/**
    4446 * ohci root hub representation
     
    5153        /** hub port count */
    5254        size_t port_count;
    53         /** hubs descriptors */
    54         usb_device_descriptors_t descriptors;
    5555        /** interrupt transfer waiting for an actual interrupt to occur */
    56         usb_transfer_batch_t * unfinished_interrupt_transfer;
    57         /** pre-allocated interrupt mask
    58          *
    59          * This is allocated when initializing instance, so that memory
    60          * allocation is not needed when processing request. Buffer is used for
    61          * interrupt bitmask.
    62          */
    63         uint8_t * interrupt_buffer;
     56        usb_transfer_batch_t *unfinished_interrupt_transfer;
    6457        /** size of interrupt buffer */
    6558        size_t interrupt_mask_size;
    66         /** instance`s descriptor*/
    67         uint8_t * hub_descriptor;
     59        /** Descriptors */
     60        struct {
     61                usb_standard_configuration_descriptor_t configuration;
     62                usb_standard_interface_descriptor_t interface;
     63                usb_standard_endpoint_descriptor_t endpoint;
     64                uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE];
     65        } __attribute__ ((packed)) descriptors;
    6866        /** size of hub descriptor */
    69         size_t descriptor_size;
    70 
     67        size_t hub_descriptor_size;
    7168
    7269} rh_t;
    7370
    74 int rh_init(rh_t *instance, ohci_regs_t *regs);
     71void rh_init(rh_t *instance, ohci_regs_t *regs);
    7572
    76 int rh_request(rh_t *instance, usb_transfer_batch_t *request);
     73void rh_request(rh_t *instance, usb_transfer_batch_t *request);
    7774
    7875void rh_interrupt(rh_t *instance);
  • uspace/drv/bus/usb/uhci/hc.c

    r27eddb52 r4069f5c  
    4747    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4848
     49static const irq_cmd_t uhci_irq_commands[] =
     50{
     51        { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
     52        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
     53          .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
     54        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
     55        { .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
     56        { .cmd = CMD_ACCEPT },
     57};
    4958
    5059static int hc_init_transfer_lists(hc_t *instance);
     
    5463static int hc_interrupt_emulator(void *arg);
    5564static int hc_debug_checker(void *arg);
     65
     66/*----------------------------------------------------------------------------*/
     67/** Get number of commands used in IRQ code.
     68 * @return Number of commands.
     69 */
     70size_t hc_irq_cmd_count(void)
     71{
     72        return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
     73}
     74/*----------------------------------------------------------------------------*/
     75/** Generate IRQ code commands.
     76 * @param[out] cmds Place to store the commands.
     77 * @param[in] cmd_size Size of the place (bytes).
     78 * @param[in] regs Physical address of device's registers.
     79 * @param[in] reg_size Size of the register area (bytes).
     80 *
     81 * @return Error code.
     82 */
     83int hc_get_irq_commands(
     84    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
     85{
     86        if (cmd_size < sizeof(uhci_irq_commands)
     87            || reg_size < sizeof(uhci_regs_t))
     88                return EOVERFLOW;
     89
     90        uhci_regs_t *registers = (uhci_regs_t*)regs;
     91
     92        memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
     93
     94        cmds[0].addr = (void*)&registers->usbsts;
     95        cmds[3].addr = (void*)&registers->usbsts;
     96        return EOK;
     97}
    5698/*----------------------------------------------------------------------------*/
    5799/** Initialize UHCI hc driver structure
     
    69111int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
    70112{
    71         assert(reg_size >= sizeof(regs_t));
     113        assert(reg_size >= sizeof(uhci_regs_t));
    72114        int ret;
    73115
     
    82124
    83125        /* allow access to hc control registers */
    84         regs_t *io;
     126        uhci_regs_t *io;
    85127        ret = pio_enable(regs, reg_size, (void **)&io);
    86         CHECK_RET_RETURN(ret,
    87             "Failed(%d) to gain access to registers at %p: %s.\n",
    88             ret, io, str_error(ret));
     128        CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
     129            io, str_error(ret));
    89130        instance->registers = io;
    90         usb_log_debug("Device registers at %p (%zuB) accessible.\n",
    91             io, reg_size);
     131        usb_log_debug(
     132            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    92133
    93134        ret = hc_init_mem_structures(instance);
    94135        CHECK_RET_RETURN(ret,
    95             "Failed(%d) to initialize UHCI memory structures: %s.\n",
    96             ret, str_error(ret));
     136            "Failed to initialize UHCI memory structures: %s.\n",
     137            str_error(ret));
    97138
    98139        hc_init_hw(instance);
     
    116157{
    117158        assert(instance);
    118         regs_t *registers = instance->registers;
     159        uhci_regs_t *registers = instance->registers;
    119160
    120161        /* Reset everything, who knows what touched it before us */
    121162        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    122         async_usleep(10000); /* 10ms according to USB spec */
     163        async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
    123164        pio_write_16(&registers->usbcmd, 0);
    124165
    125         /* Reset hc, all states and counters */
     166        /* Reset hc, all states and counters. Hope that hw is not broken */
    126167        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    127168        do { async_usleep(10); }
     
    141182        }
    142183
    143         const uint16_t status = pio_read_16(&registers->usbcmd);
    144         if (status != 0)
    145                 usb_log_warning("Previous command value: %x.\n", status);
     184        const uint16_t cmd = pio_read_16(&registers->usbcmd);
     185        if (cmd != 0)
     186                usb_log_warning("Previous command value: %x.\n", cmd);
    146187
    147188        /* Start the hc with large(64B) packet FSBR */
     
    170211        } else (void) 0
    171212
    172         /* Init interrupt code */
    173         instance->interrupt_code.cmds = instance->interrupt_commands;
    174         {
    175                 /* Read status register */
    176                 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
    177                 instance->interrupt_commands[0].dstarg = 1;
    178                 instance->interrupt_commands[0].addr =
    179                     &instance->registers->usbsts;
    180 
    181                 /* Test whether we are the interrupt cause */
    182                 instance->interrupt_commands[1].cmd = CMD_BTEST;
    183                 instance->interrupt_commands[1].value =
    184                     UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
    185                 instance->interrupt_commands[1].srcarg = 1;
    186                 instance->interrupt_commands[1].dstarg = 2;
    187 
    188                 /* Predicate cleaning and accepting */
    189                 instance->interrupt_commands[2].cmd = CMD_PREDICATE;
    190                 instance->interrupt_commands[2].value = 2;
    191                 instance->interrupt_commands[2].srcarg = 2;
    192 
    193                 /* Write clean status register */
    194                 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
    195                 instance->interrupt_commands[3].srcarg = 1;
    196                 instance->interrupt_commands[3].addr =
    197                     &instance->registers->usbsts;
    198 
    199                 /* Accept interrupt */
    200                 instance->interrupt_commands[4].cmd = CMD_ACCEPT;
    201 
    202                 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
    203         }
    204 
    205213        /* Init transfer lists */
    206214        int ret = hc_init_transfer_lists(instance);
    207         CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
     215        CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
    208216        usb_log_debug("Initialized transfer lists.\n");
    209 
    210         /* Init USB frame list page*/
    211         instance->frame_list = get_page();
    212         ret = instance->frame_list ? EOK : ENOMEM;
    213         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
    214         usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    215 
    216         /* Set all frames to point to the first queue head */
    217         const uint32_t queue = LINK_POINTER_QH(
    218                 addr_to_phys(instance->transfers_interrupt.queue_head));
    219 
    220         unsigned i = 0;
    221         for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
    222                 instance->frame_list[i] = queue;
    223         }
    224217
    225218        /* Init device keeper */
    226219        usb_device_keeper_init(&instance->manager);
    227         usb_log_debug("Initialized device manager.\n");
     220        usb_log_debug("Initialized device keeper.\n");
    228221
    229222        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    232225            str_error(ret));
    233226
     227        /* Init USB frame list page*/
     228        instance->frame_list = get_page();
     229        if (!instance->frame_list) {
     230                usb_log_error("Failed to get frame list page.\n");
     231                usb_endpoint_manager_destroy(&instance->ep_manager);
     232                return ENOMEM;
     233        }
     234        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
     235
     236        /* Set all frames to point to the first queue head */
     237        const uint32_t queue = LINK_POINTER_QH(
     238                addr_to_phys(instance->transfers_interrupt.queue_head));
     239        unsigned i = 0;
     240        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     241                instance->frame_list[i] = queue;
     242        }
     243
    234244        return EOK;
    235245#undef CHECK_RET_RETURN
     
    252262        int ret = transfer_list_init(&instance->transfers_##type, name); \
    253263        if (ret != EOK) { \
    254                 usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
    255                     ret, name, str_error(ret)); \
     264                usb_log_error("Failed to setup %s transfer list: %s.\n", \
     265                    name, str_error(ret)); \
    256266                transfer_list_fini(&instance->transfers_bulk_full); \
    257267                transfer_list_fini(&instance->transfers_control_full); \
  • uspace/drv/bus/usb/uhci/hc.h

    r27eddb52 r4069f5c  
    8484        /** SOF modification to match external timers */
    8585        uint8_t sofmod;
    86 } regs_t;
     86} uhci_regs_t;
    8787
    8888#define UHCI_FRAME_LIST_COUNT 1024
     
    100100
    101101        /** Addresses of I/O registers */
    102         regs_t *registers;
     102        uhci_regs_t *registers;
    103103
    104104        /** Frame List contains 1024 link pointers */
     
    116116        /** Pointer table to the above lists, helps during scheduling */
    117117        transfer_list_t *transfers[2][4];
    118 
    119         /** Code to be executed in kernel interrupt handler */
    120         irq_code_t interrupt_code;
    121 
    122         /** Commands that form interrupt code */
    123         irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
    124 
    125118        /** Fibril periodically checking status register*/
    126119        fid_t interrupt_emulator;
    127 
    128120        /** Indicator of hw interrupts availability */
    129121        bool hw_interrupts;
     
    132124        unsigned hw_failures;
    133125} hc_t;
    134 
     126size_t hc_irq_cmd_count(void);
     127int hc_get_irq_commands(
     128    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
    135129int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
    136 
    137130int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    138 
    139131void hc_interrupt(hc_t *instance, uint16_t status);
    140132
  • uspace/drv/bus/usb/uhci/root_hub.c

    r27eddb52 r4069f5c  
    5050int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
    5151{
     52        int ret;
     53
    5254        assert(fun);
    5355
    54         char *match_str = NULL;
    55         int ret = asprintf(&match_str, "usb&uhci&root-hub");
    56         if (ret < 0) {
    57                 usb_log_error(
    58                     "Failed(%d) to create root hub match string: %s.\n",
    59                     ret, str_error(ret));
    60                 return ret;
    61         }
    62         assert(match_str);
    63 
    64         ret = ddf_fun_add_match_id(fun, match_str, 100);
     56        ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    6557        if (ret != EOK) {
    66                 free(match_str);
    67                 usb_log_error("Failed(%d) to add root hub match id: %s\n",
    68                     ret, str_error(ret));
     58                usb_log_error("Failed to add root hub match id: %s\n",
     59                    str_error(ret));
    6960                return ret;
    7061        }
  • uspace/drv/bus/usb/uhci/uhci.c

    r27eddb52 r4069f5c  
    6464{
    6565        assert(dev);
    66         assert(dev->driver_data);
    6766        return dev->driver_data;
    6867}
     
    7877        assert(dev);
    7978        uhci_t *uhci = dev_to_uhci(dev);
    80         hc_t *hc = &uhci->hc;
     79        if (!uhci) {
     80                usb_log_error("Interrupt on not yet initialized device.\n");
     81                return;
     82        }
    8183        const uint16_t status = IPC_GET_ARG1(*call);
    82         assert(hc);
    83         hc_interrupt(hc, status);
     84        hc_interrupt(&uhci->hc, status);
    8485}
    8586/*----------------------------------------------------------------------------*/
     
    192193        } \
    193194        free(instance); \
     195        device->driver_data = NULL; \
    194196        usb_log_error(message); \
    195197        return ret; \
     
    222224        ret = pci_disable_legacy(device);
    223225        CHECK_RET_DEST_FREE_RETURN(ret,
    224             "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
     226            "Failed to disable legacy USB: %s.\n", str_error(ret));
     227
     228        const size_t cmd_count = hc_irq_cmd_count();
     229        irq_cmd_t irq_cmds[cmd_count];
     230        ret =
     231            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     232        CHECK_RET_DEST_FREE_RETURN(ret,
     233            "Failed to generate IRQ commands: %s.\n", str_error(ret));
     234
     235        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     236
     237        /* Register handler to avoid interrupt lockup */
     238        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
     239        CHECK_RET_DEST_FREE_RETURN(ret,
     240            "Failed to register interrupt handler: %s.\n", str_error(ret));
    225241
    226242        bool interrupts = false;
    227 #ifdef CONFIG_USBHC_NO_INTERRUPTS
    228         usb_log_warning("Interrupts disabled in OS config, " \
    229             "falling back to polling.\n");
    230 #else
    231243        ret = pci_enable_interrupts(device);
    232244        if (ret != EOK) {
    233                 usb_log_warning("Failed to enable interrupts: %s.\n",
    234                     str_error(ret));
    235                 usb_log_info("HW interrupts not available, " \
    236                     "falling back to polling.\n");
     245                usb_log_warning("Failed to enable interrupts: %s."
     246                    " Falling back to polling.\n", str_error(ret));
    237247        } else {
    238248                usb_log_debug("Hw interrupts enabled.\n");
    239249                interrupts = true;
    240250        }
    241 #endif
    242 
    243251
    244252        ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
    245253        CHECK_RET_DEST_FREE_RETURN(ret,
    246             "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
     254            "Failed to init uhci_hcd: %s.\n", str_error(ret));
     255
     256        device->driver_data = instance;
    247257
    248258#define CHECK_RET_FINI_RETURN(ret, message...) \
     
    253263} else (void)0
    254264
    255         /* It does no harm if we register this on polling */
    256         ret = register_interrupt_handler(device, irq, irq_handler,
    257             &instance->hc.interrupt_code);
    258         CHECK_RET_FINI_RETURN(ret,
    259             "Failed(%d) to register interrupt handler: %s.\n",
    260             ret, str_error(ret));
    261 
    262265        ret = ddf_fun_bind(instance->hc_fun);
    263         CHECK_RET_FINI_RETURN(ret,
    264             "Failed(%d) to bind UHCI device function: %s.\n",
    265             ret, str_error(ret));
     266        CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
     267            str_error(ret));
    266268
    267269        ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
     
    272274            (uintptr_t)instance->hc.registers + 0x10, 4);
    273275        CHECK_RET_FINI_RETURN(ret,
    274             "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
     276            "Failed to setup UHCI root hub: %s.\n", str_error(ret));
    275277
    276278        ret = ddf_fun_bind(instance->rh_fun);
    277279        CHECK_RET_FINI_RETURN(ret,
    278             "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
    279 
    280         device->driver_data = instance;
     280            "Failed to register UHCI root hub: %s.\n", str_error(ret));
     281
    281282        return EOK;
    282283#undef CHECK_RET_FINI_RETURN
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r27eddb52 r4069f5c  
    220220 * @return error code
    221221 */
    222 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
     222int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
     223{
    223224        // get hub descriptor
    224         usb_log_debug("Creating serialized descriptor\n");
     225        usb_log_debug("Retrieving descriptor\n");
    225226        uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
    226         usb_hub_descriptor_t * descriptor;
    227227        int opResult;
    228228
     
    234234
    235235        if (opResult != EOK) {
    236                 usb_log_error("Failed when receiving hub descriptor, "
    237                     "%s\n",
    238                     str_error(opResult));
    239                 free(serialized_descriptor);
     236                usb_log_error("Failed to receive hub descriptor: %s.\n",
     237                    str_error(opResult));
    240238                return opResult;
    241239        }
    242         usb_log_debug2("Deserializing descriptor\n");
    243         descriptor = usb_create_deserialized_hub_desriptor(
    244             serialized_descriptor);
    245         if (descriptor == NULL) {
    246                 usb_log_warning("could not deserialize descriptor \n");
    247                 return ENOMEM;
    248         }
    249         usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    250         hub_info->port_count = descriptor->ports_count;
    251         bool is_power_switched =
    252             ((descriptor->hub_characteristics & 1) == 0);
    253         bool has_individual_port_powering =
    254             ((descriptor->hub_characteristics & 1) != 0);
    255         hub_info->ports = malloc(
    256             sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
     240        usb_log_debug2("Parsing descriptor\n");
     241        usb_hub_descriptor_t descriptor;
     242        opResult = usb_deserialize_hub_desriptor(
     243                serialized_descriptor, received_size, &descriptor);
     244        if (opResult != EOK) {
     245                usb_log_error("Could not parse descriptor: %s\n",
     246                    str_error(opResult));
     247                return opResult;
     248        }
     249        usb_log_debug("Setting port count to %d.\n", descriptor.ports_count);
     250        hub_info->port_count = descriptor.ports_count;
     251
     252        hub_info->ports =
     253            malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
    257254        if (!hub_info->ports) {
    258255                return ENOMEM;
    259256        }
     257
    260258        size_t port;
    261259        for (port = 0; port < hub_info->port_count + 1; ++port) {
    262260                usb_hub_port_init(&hub_info->ports[port]);
    263261        }
     262
     263        const bool is_power_switched =
     264            !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    264265        if (is_power_switched) {
    265266                usb_log_debug("Hub power switched\n");
    266 
    267                 if (!has_individual_port_powering) {
    268                         //this setting actually makes no difference
    269                         usb_log_debug("Hub has global powering\n");
    270                 }
     267                const bool per_port_power = descriptor.hub_characteristics
     268                    & HUB_CHAR_POWER_PER_PORT_FLAG;
    271269
    272270                for (port = 1; port <= hub_info->port_count; ++port) {
    273271                        usb_log_debug("Powering port %zu.\n", port);
    274                         opResult = usb_hub_set_port_feature(hub_info->control_pipe,
     272                        opResult = usb_hub_set_port_feature(
     273                            hub_info->control_pipe,
    275274                            port, USB_HUB_FEATURE_PORT_POWER);
    276275                        if (opResult != EOK) {
    277276                                usb_log_error("Cannot power on port %zu: %s.\n",
    278277                                    port, str_error(opResult));
     278                        } else {
     279                                if (!per_port_power) {
     280                                        usb_log_debug(
     281                                            "Ganged power switching mode, "
     282                                            "one port is enough.\n");
     283                                        break;
     284                                }
    279285                        }
    280286                }
     
    283289                usb_log_debug("Power not switched, not going to be powered\n");
    284290        }
    285         usb_log_debug2("Freeing data\n");
    286         free(descriptor);
    287291        return EOK;
    288292}
  • uspace/drv/bus/usb/usbhub/usbhub_private.h

    r27eddb52 r4069f5c  
    171171    void * serialized_descriptor);
    172172
    173 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
    174     void * serialized_descriptor);
    175 
    176 void usb_deserialize_hub_desriptor(void * serialized_descriptor,
    177     usb_hub_descriptor_t * descriptor);
     173int usb_deserialize_hub_desriptor(
     174    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
    178175
    179176
  • uspace/drv/bus/usb/usbhub/utils.c

    r27eddb52 r4069f5c  
    110110}
    111111
     112/*----------------------------------------------------------------------------*/
    112113/**
    113  * create deserialized desriptor structure out of serialized descriptor
     114 * Deserialize descriptor into given pointer
    114115 *
    115  * The serialized descriptor must be proper usb hub descriptor,
    116  * otherwise an eerror might occur.
    117  *
    118  * @param sdescriptor serialized descriptor
    119  * @return newly created deserialized descriptor pointer
    120  */
    121 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
    122     void *serialized_descriptor) {
    123         uint8_t * sdescriptor = serialized_descriptor;
    124 
    125         if (sdescriptor[1] != USB_DESCTYPE_HUB) {
    126                 usb_log_warning("trying to deserialize wrong descriptor %x\n",
    127                     sdescriptor[1]);
    128                 return NULL;
    129         }
    130 
    131         usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));
    132         if (result)
    133                 usb_deserialize_hub_desriptor(serialized_descriptor, result);
    134         return result;
    135 }
    136 
    137 /**
    138  * deserialize descriptor into given pointer
    139  *
    140116 * @param serialized_descriptor
    141117 * @param descriptor
    142118 * @return
    143119 */
    144 void usb_deserialize_hub_desriptor(
    145     void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
     120int usb_deserialize_hub_desriptor(
     121    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor)
     122{
    146123        uint8_t * sdescriptor = serialized_descriptor;
     124
     125        if (sdescriptor[1] != USB_DESCTYPE_HUB) {
     126                usb_log_error("Trying to deserialize wrong descriptor %x\n",
     127                    sdescriptor[1]);
     128                return EINVAL;
     129        }
     130        if (size < 7) {
     131                usb_log_error("Serialized descriptor too small.\n");
     132                return EOVERFLOW;
     133        }
     134
    147135        descriptor->ports_count = sdescriptor[2];
    148         /// @fixme handling of endianness??
    149         descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
     136        descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
    150137        descriptor->pwr_on_2_good_time = sdescriptor[5];
    151138        descriptor->current_requirement = sdescriptor[6];
    152         size_t var_size = (descriptor->ports_count + 7) / 8;
     139        const size_t var_size = (descriptor->ports_count + 7) / 8;
    153140        //descriptor->devices_removable = (uint8_t*) malloc(var_size);
    154141
    155         size_t i;
    156         for (i = 0; i < var_size; ++i) {
     142        if (size < (7 + var_size)) {
     143                usb_log_error("Serialized descriptor too small.\n");
     144                return EOVERFLOW;
     145        }
     146        size_t i = 0;
     147        for (; i < var_size; ++i) {
    157148                descriptor->devices_removable[i] = sdescriptor[7 + i];
    158149        }
     150        return EOK;
    159151}
    160 
     152/*----------------------------------------------------------------------------*/
    161153/**
    162154 * @}
  • uspace/drv/bus/usb/usbmast/Makefile

    r27eddb52 r4069f5c  
    4444
    4545SOURCES = \
    46         cmds.c \
     46        bo_trans.c \
     47        cmdw.c \
    4748        main.c \
    48         mast.c \
    4949        scsi_ms.c
    5050
  • uspace/drv/bus/usb/usbmast/bo_trans.c

    r27eddb52 r4069f5c  
    3232/**
    3333 * @file
    34  * Generic functions for USB mass storage (implementation).
    35  */
    36 #include "mast.h"
    37 #include "cmds.h"
     34 * USB mass storage bulk-only transport.
     35 */
    3836#include <bool.h>
    3937#include <errno.h>
     
    4139#include <usb/debug.h>
    4240#include <usb/dev/request.h>
     41
     42#include "bo_trans.h"
     43#include "cmdw.h"
     44#include "usbmast.h"
    4345
    4446bool usb_mast_verbose = false;
     
    5355/** Send command via bulk-only transport.
    5456 *
     57 * @param mfun          Mass storage function
    5558 * @param tag           Command block wrapper tag (automatically compared
    5659 *                      with answer)
    57  * @param lun           LUN
    5860 * @param cmd           Command block
    5961 * @param cmd_size      Command block size in bytes
     
    6567 * @return              Error code
    6668 */
    67 static int usb_massstor_cmd(usb_device_t *dev, uint32_t tag, uint8_t lun,
    68     const void *cmd, size_t cmd_size, usb_direction_t ddir, void *dbuf,
    69     size_t dbuf_size, size_t *xferred_size)
     69static int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
     70    size_t cmd_size, usb_direction_t ddir, void *dbuf, size_t dbuf_size,
     71    size_t *xferred_size)
    7072{
    7173        int rc;
    7274        size_t act_size;
    73         usb_pipe_t *bulk_in_pipe = dev->pipes[BULK_IN_EP].pipe;
    74         usb_pipe_t *bulk_out_pipe = dev->pipes[BULK_OUT_EP].pipe;
     75        usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
     76        usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
    7577
    7678        /* Prepare CBW - command block wrapper */
    7779        usb_massstor_cbw_t cbw;
    78         usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, lun, cmd_size,
    79             cmd);
     80        usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun,
     81            cmd_size, cmd);
    8082
    8183        /* Send the CBW. */
     
    164166/** Perform data-in command.
    165167 *
     168 * @param mfun          Mass storage function
    166169 * @param tag           Command block wrapper tag (automatically compared with
    167170 *                      answer)
    168  * @param lun           LUN
    169171 * @param cmd           CDB (Command Descriptor)
    170172 * @param cmd_size      CDB length in bytes
     
    175177 * @return Error code
    176178 */
    177 int usb_massstor_data_in(usb_device_t *dev, uint32_t tag, uint8_t lun,
    178     const void *cmd, size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)
    179 {
    180         return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_IN,
     179int usb_massstor_data_in(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
     180    size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)
     181{
     182        return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_IN,
    181183            dbuf, dbuf_size, proc_size);
    182184}
     
    184186/** Perform data-out command.
    185187 *
     188 * @param mfun          Mass storage function
    186189 * @param tag           Command block wrapper tag (automatically compared with
    187190 *                      answer)
    188  * @param lun           LUN
    189191 * @param cmd           CDB (Command Descriptor)
    190192 * @param cmd_size      CDB length in bytes
     
    195197 * @return Error code
    196198 */
    197 int usb_massstor_data_out(usb_device_t *dev, uint32_t tag, uint8_t lun,
    198     const void *cmd, size_t cmd_size, const void *data, size_t data_size,
    199     size_t *proc_size)
    200 {
    201         return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_OUT,
     199int usb_massstor_data_out(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
     200    size_t cmd_size, const void *data, size_t data_size, size_t *proc_size)
     201{
     202        return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_OUT,
    202203            (void *) data, data_size, proc_size);
    203204}
     
    205206/** Perform bulk-only mass storage reset.
    206207 *
    207  * @param dev Device to be reseted.
    208  * @return Error code.
    209  */
    210 int usb_massstor_reset(usb_device_t *dev)
    211 {
    212         return usb_control_request_set(&dev->ctrl_pipe,
     208 * @param mfun          Mass storage function
     209 * @return              Error code
     210 */
     211int usb_massstor_reset(usbmast_dev_t *mdev)
     212{
     213        return usb_control_request_set(&mdev->usb_dev->ctrl_pipe,
    213214            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    214             0xFF, 0, dev->interface_no, NULL, 0);
     215            0xFF, 0, mdev->usb_dev->interface_no, NULL, 0);
    215216}
    216217
     
    220221 * would reappear on next transaction somehow.
    221222 *
    222  * @param dev Device to be reseted.
    223  */
    224 void usb_massstor_reset_recovery(usb_device_t *dev)
     223 * @param mfun          Mass storage function
     224 */
     225void usb_massstor_reset_recovery(usbmast_dev_t *mdev)
    225226{
    226227        /* We would ignore errors here because if this fails
    227228         * we are doomed anyway and any following transaction would fail.
    228229         */
    229         usb_massstor_reset(dev);
    230         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_IN_EP].pipe);
    231         usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_OUT_EP].pipe);
     230        usb_massstor_reset(mdev);
     231        usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
     232            mdev->usb_dev->pipes[BULK_IN_EP].pipe);
     233        usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
     234            mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
    232235}
    233236
     
    240243 * You shall rather use usb_masstor_get_lun_count.
    241244 *
    242  * @param dev Mass storage device.
    243  * @return Error code of maximum LUN (index, not count).
    244  */
    245 int usb_massstor_get_max_lun(usb_device_t *dev)
     245 * @param mfun          Mass storage function
     246 * @return              Error code of maximum LUN (index, not count)
     247 */
     248int usb_massstor_get_max_lun(usbmast_dev_t *mdev)
    246249{
    247250        uint8_t max_lun;
    248251        size_t data_recv_len;
    249         int rc = usb_control_request_get(&dev->ctrl_pipe,
     252        int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe,
    250253            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    251             0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
     254            0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len);
    252255        if (rc != EOK) {
    253256                return rc;
     
    264267 * (typically that shall not be a problem).
    265268 *
    266  * @param dev Mass storage device.
    267  * @return Number of LUNs.
    268  */
    269 size_t usb_masstor_get_lun_count(usb_device_t *dev)
    270 {
    271         int max_lun = usb_massstor_get_max_lun(dev);
     269 * @param mfun          Mass storage function
     270 * @return              Number of LUNs
     271 */
     272size_t usb_masstor_get_lun_count(usbmast_dev_t *mdev)
     273{
     274        int max_lun = usb_massstor_get_max_lun(mdev);
    272275        if (max_lun < 0) {
    273276                max_lun = 1;
  • uspace/drv/bus/usb/usbmast/bo_trans.h

    r27eddb52 r4069f5c  
    3131 */
    3232/** @file
    33  * Generic functions for USB mass storage.
     33 * USB mass storage bulk-only transport.
    3434 */
    3535
    36 #ifndef USB_USBMAST_MAST_H_
    37 #define USB_USBMAST_MAST_H_
     36#ifndef BO_TRANS_H_
     37#define BO_TRANS_H_
    3838
    3939#include <scsi/spc.h>
     
    4242#include <usb/dev/pipes.h>
    4343#include <usb/dev/driver.h>
     44#include "usbmast.h"
    4445
    4546#define BULK_IN_EP 0
    4647#define BULK_OUT_EP 1
    4748
    48 extern int usb_massstor_data_in(usb_device_t *, uint32_t, uint8_t, const void *,
     49extern int usb_massstor_data_in(usbmast_fun_t *, uint32_t, const void *,
    4950    size_t, void *, size_t, size_t *);
    50 extern int usb_massstor_data_out(usb_device_t *, uint32_t, uint8_t, const void *,
     51extern int usb_massstor_data_out(usbmast_fun_t *, uint32_t, const void *,
    5152    size_t, const void *, size_t, size_t *);
    52 extern int usb_massstor_reset(usb_device_t *);
    53 extern void usb_massstor_reset_recovery(usb_device_t *);
    54 extern int usb_massstor_get_max_lun(usb_device_t *);
    55 extern size_t usb_masstor_get_lun_count(usb_device_t *);
     53extern int usb_massstor_reset(usbmast_dev_t *);
     54extern void usb_massstor_reset_recovery(usbmast_dev_t *);
     55extern int usb_massstor_get_max_lun(usbmast_dev_t *);
     56extern size_t usb_masstor_get_lun_count(usbmast_dev_t *);
    5657
    5758#endif
  • uspace/drv/bus/usb/usbmast/cmdw.c

    r27eddb52 r4069f5c  
    3838#include <sys/types.h>
    3939#include <usb/usb.h>
    40 #include "cmds.h"
     40#include "cmdw.h"
    4141
    4242void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
  • uspace/drv/bus/usb/usbmast/cmdw.h

    r27eddb52 r4069f5c  
    3434 */
    3535
    36 #ifndef USB_USBMAST_CMDS_H_
    37 #define USB_USBMAST_CMDS_H_
     36#ifndef CMDW_H_
     37#define CMDW_H_
    3838
    3939#include <sys/types.h>
  • uspace/drv/bus/usb/usbmast/main.c

    r27eddb52 r4069f5c  
    4545#include <errno.h>
    4646#include <str_error.h>
    47 #include "cmds.h"
    48 #include "mast.h"
     47#include "cmdw.h"
     48#include "bo_trans.h"
    4949#include "scsi_ms.h"
     50#include "usbmast.h"
    5051
    5152#define NAME "usbmast"
     
    7778};
    7879
    79 /** Mass storage function.
    80  *
    81  * Serves as soft state for function/LUN.
    82  */
    83 typedef struct {
    84         /** DDF function */
    85         ddf_fun_t *ddf_fun;
    86         /** Total number of blocks. */
    87         uint64_t nblocks;
    88         /** Block size in bytes. */
    89         size_t block_size;
    90         /** USB device function belongs to */
    91         usb_device_t *usb_dev;
    92 } usbmast_fun_t;
    93 
     80static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
    9481static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
    9582    void *arg);
     
    10390{
    10491        int rc;
    105         const char *fun_name = "a";
    106         ddf_fun_t *fun = NULL;
    107         usbmast_fun_t *msfun = NULL;
     92        usbmast_dev_t *mdev = NULL;
     93        unsigned i;
    10894
    10995        /* Allocate softstate */
    110         msfun = calloc(1, sizeof(usbmast_fun_t));
    111         if (msfun == NULL) {
     96        mdev = calloc(1, sizeof(usbmast_dev_t));
     97        if (mdev == NULL) {
    11298                usb_log_error("Failed allocating softstate.\n");
    11399                rc = ENOMEM;
     
    115101        }
    116102
    117         fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name);
    118         if (fun == NULL) {
    119                 usb_log_error("Failed to create DDF function %s.\n", fun_name);
    120                 rc = ENOMEM;
    121                 goto error;
    122         }
    123 
    124         /* Set up a connection handler. */
    125         fun->conn_handler = usbmast_bd_connection;
    126         fun->driver_data = msfun;
     103        mdev->ddf_dev = dev->ddf_dev;
     104        mdev->usb_dev = dev;
    127105
    128106        usb_log_info("Initializing mass storage `%s'.\n",
     
    136114
    137115        usb_log_debug("Get LUN count...\n");
    138         size_t lun_count = usb_masstor_get_lun_count(dev);
    139 
    140         /* XXX Handle more than one LUN properly. */
    141         if (lun_count > 1) {
    142                 usb_log_warning ("Mass storage has %zu LUNs. Ignoring all "
    143                     "but first.\n", lun_count);
    144         }
     116        mdev->luns = usb_masstor_get_lun_count(mdev);
     117
     118        for (i = 0; i < mdev->luns; i++) {
     119                rc = usbmast_fun_create(mdev, i);
     120                if (rc != EOK)
     121                        goto error;
     122        }
     123
     124        return EOK;
     125error:
     126        /* XXX Destroy functions */
     127        if (mdev != NULL)
     128                free(mdev);
     129        return rc;
     130}
     131
     132/** Create mass storage function.
     133 *
     134 * Called once for each LUN.
     135 *
     136 * @param mdev          Mass storage device
     137 * @param lun           LUN
     138 * @return              EOK on success or negative error code.
     139 */
     140static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun)
     141{
     142        int rc;
     143        char *fun_name = NULL;
     144        ddf_fun_t *fun = NULL;
     145        usbmast_fun_t *mfun = NULL;
     146
     147        /* Allocate softstate */
     148        mfun = calloc(1, sizeof(usbmast_fun_t));
     149        if (mfun == NULL) {
     150                usb_log_error("Failed allocating softstate.\n");
     151                rc = ENOMEM;
     152                goto error;
     153        }
     154
     155        mfun->mdev = mdev;
     156        mfun->lun = lun;
     157
     158        if (asprintf(&fun_name, "l%u", lun) < 0) {
     159                usb_log_error("Out of memory.\n");
     160                rc = ENOMEM;
     161                goto error;
     162        }
     163
     164        fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
     165        if (fun == NULL) {
     166                usb_log_error("Failed to create DDF function %s.\n", fun_name);
     167                rc = ENOMEM;
     168                goto error;
     169        }
     170
     171        free(fun_name);
     172        fun_name = NULL;
     173
     174        /* Set up a connection handler. */
     175        fun->conn_handler = usbmast_bd_connection;
     176        fun->driver_data = mfun;
    145177
    146178        usb_log_debug("Inquire...\n");
    147179        usbmast_inquiry_data_t inquiry;
    148         rc = usbmast_inquiry(dev, &inquiry);
     180        rc = usbmast_inquiry(mfun, &inquiry);
    149181        if (rc != EOK) {
    150182                usb_log_warning("Failed to inquire device `%s': %s.\n",
    151                     dev->ddf_dev->name, str_error(rc));
     183                    mdev->ddf_dev->name, str_error(rc));
    152184                rc = EIO;
    153185                goto error;
    154186        }
    155187
    156         usb_log_info("Mass storage `%s': " \
    157             "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
    158             dev->ddf_dev->name,
     188        usb_log_info("Mass storage `%s' LUN %u: " \
     189            "%s by %s rev. %s is %s (%s).\n",
     190            mdev->ddf_dev->name,
     191            lun,
    159192            inquiry.product,
    160193            inquiry.vendor,
    161194            inquiry.revision,
    162195            usbmast_scsi_dev_type_str(inquiry.device_type),
    163             inquiry.removable ? "removable" : "non-removable",
    164             lun_count);
     196            inquiry.removable ? "removable" : "non-removable");
    165197
    166198        uint32_t nblocks, block_size;
    167199
    168         rc = usbmast_read_capacity(dev, &nblocks, &block_size);
     200        rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
    169201        if (rc != EOK) {
    170202                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    171                     dev->ddf_dev->name, str_error(rc));
     203                    mdev->ddf_dev->name, str_error(rc));
    172204                rc = EIO;
    173205                goto error;
     
    177209            "block_size=%" PRIu32 "\n", nblocks, block_size);
    178210
    179         msfun->nblocks = nblocks;
    180         msfun->block_size = block_size;
    181         msfun->usb_dev = dev;
     211        mfun->nblocks = nblocks;
     212        mfun->block_size = block_size;
    182213
    183214        rc = ddf_fun_bind(fun);
     
    194225        if (fun != NULL)
    195226                ddf_fun_destroy(fun);
    196         if (msfun != NULL)
    197                 free(msfun);
     227        if (fun_name != NULL)
     228                free(fun_name);
     229        if (mfun != NULL)
     230                free(mfun);
    198231        return rc;
    199232}
     
    203236    void *arg)
    204237{
    205         usbmast_fun_t *msfun;
     238        usbmast_fun_t *mfun;
    206239        void *comm_buf = NULL;
    207240        size_t comm_size;
     
    229262        (void) async_share_out_finalize(callid, comm_buf);
    230263
    231         msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
     264        mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
    232265
    233266        while (true) {
     
    243276                switch (method) {
    244277                case BD_GET_BLOCK_SIZE:
    245                         async_answer_1(callid, EOK, msfun->block_size);
     278                        async_answer_1(callid, EOK, mfun->block_size);
    246279                        break;
    247280                case BD_GET_NUM_BLOCKS:
    248                         async_answer_2(callid, EOK, LOWER32(msfun->nblocks),
    249                             UPPER32(msfun->nblocks));
     281                        async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
     282                            UPPER32(mfun->nblocks));
    250283                        break;
    251284                case BD_READ_BLOCKS:
    252285                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    253286                        cnt = IPC_GET_ARG3(call);
    254                         retval = usbmast_read(msfun->usb_dev, ba, cnt,
    255                             msfun->block_size, comm_buf);
     287                        retval = usbmast_read(mfun, ba, cnt, comm_buf);
    256288                        async_answer_0(callid, retval);
    257289                        break;
     
    259291                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    260292                        cnt = IPC_GET_ARG3(call);
    261                         retval = usbmast_write(msfun->usb_dev, ba, cnt,
    262                             msfun->block_size, comm_buf);
     293                        retval = usbmast_write(mfun, ba, cnt, comm_buf);
    263294                        async_answer_0(callid, retval);
    264295                        break;
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    r27eddb52 r4069f5c  
    4646#include <scsi/sbc.h>
    4747#include <scsi/spc.h>
    48 #include "cmds.h"
    49 #include "mast.h"
     48#include "cmdw.h"
     49#include "bo_trans.h"
    5050#include "scsi_ms.h"
     51#include "usbmast.h"
    5152
    5253/** Get string representation for SCSI peripheral device type.
     
    6263/** Perform SCSI Inquiry command on USB mass storage device.
    6364 *
    64  * @param dev           USB device.
    65  * @param inquiry_result Where to store parsed inquiry result.
    66  * @return              Error code.
    67  */
    68 int usbmast_inquiry(usb_device_t *dev, usbmast_inquiry_data_t *inq_res)
     65 * @param mfun          Mass storage function
     66 * @param inquiry_result Where to store parsed inquiry result
     67 * @return              Error code
     68 */
     69int usbmast_inquiry(usbmast_fun_t *mfun, usbmast_inquiry_data_t *inq_res)
    6970{
    7071        scsi_std_inquiry_data_t inq_data;
     
    7778        cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
    7879
    79         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     80        rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    8081            sizeof(cdb), &inq_data, sizeof(inq_data), &response_len);
    8182
    8283        if (rc != EOK) {
    8384                usb_log_error("Inquiry failed, device %s: %s.\n",
    84                    dev->ddf_dev->name, str_error(rc));
     85                   mfun->mdev->ddf_dev->name, str_error(rc));
    8586                return rc;
    8687        }
     
    118119/** Perform SCSI Request Sense command on USB mass storage device.
    119120 *
    120  * @param dev           USB device
     121 * @param mfun          Mass storage function
    121122 * @param buf           Destination buffer
    122123 * @param size          Size of @a buf
     
    124125 * @return              Error code.
    125126 */
    126 int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size)
     127int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
    127128{
    128129        scsi_cdb_request_sense_t cdb;
     
    134135        cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
    135136
    136         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     137        rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    137138            sizeof(cdb), buf, size, &data_len);
    138139
    139140        if (rc != EOK) {
    140141                usb_log_error("Request Sense failed, device %s: %s.\n",
    141                    dev->ddf_dev->name, str_error(rc));
     142                   mfun->mdev->ddf_dev->name, str_error(rc));
    142143                return rc;
    143144        }
     
    154155/** Perform SCSI Read Capacity command on USB mass storage device.
    155156 *
    156  * @param dev           USB device.
    157  * @param nblocks       Output, number of blocks.
    158  * @param block_size    Output, block size in bytes.
     157 * @param mfun          Mass storage function
     158 * @param nblocks       Output, number of blocks
     159 * @param block_size    Output, block size in bytes
    159160 *
    160161 * @return              Error code.
    161162 */
    162 int usbmast_read_capacity(usb_device_t *dev, uint32_t *nblocks,
     163int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks,
    163164    uint32_t *block_size)
    164165{
     
    171172        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    172173
    173         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     174        rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    174175            sizeof(cdb), &data, sizeof(data), &data_len);
    175176
    176177        if (rc != EOK) {
    177178                usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
    178                    dev->ddf_dev->name, str_error(rc));
     179                   mfun->mdev->ddf_dev->name, str_error(rc));
    179180                return rc;
    180181        }
     
    194195/** Perform SCSI Read command on USB mass storage device.
    195196 *
    196  * @param dev           USB device.
    197  * @param ba            Address of first block.
    198  * @param nblocks       Number of blocks to read.
    199  * @param bsize         Block size.
    200  *
    201  * @return              Error code.
    202  */
    203 int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
    204     void *buf)
     197 * @param mfun          Mass storage function
     198 * @param ba            Address of first block
     199 * @param nblocks       Number of blocks to read
     200 *
     201 * @return              Error code
     202 */
     203int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf)
    205204{
    206205        scsi_cdb_read_12_t cdb;
     
    213212                return ELIMIT;
    214213
    215         if ((uint64_t)nblocks * bsize > UINT32_MAX)
     214        if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
    216215                return ELIMIT;
    217216
     
    221220        cdb.xfer_len = host2uint32_t_be(nblocks);
    222221
    223         rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    224             sizeof(cdb), buf, nblocks * bsize, &data_len);
     222        rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
     223            sizeof(cdb), buf, nblocks * mfun->block_size, &data_len);
    225224
    226225        if (rc != EOK) {
    227226                usb_log_error("Read (12) failed, device %s: %s.\n",
    228                    dev->ddf_dev->name, str_error(rc));
    229                 return rc;
    230         }
    231 
    232         if (data_len < nblocks * bsize) {
     227                   mfun->mdev->ddf_dev->name, str_error(rc));
     228                return rc;
     229        }
     230
     231        if (data_len < nblocks * mfun->block_size) {
    233232                usb_log_error("SCSI Read response too short (%zu).\n",
    234233                    data_len);
     
    241240/** Perform SCSI Write command on USB mass storage device.
    242241 *
    243  * @param dev           USB device
     242 * @param mfun          Mass storage function
    244243 * @param ba            Address of first block
    245244 * @param nblocks       Number of blocks to read
    246  * @param bsize         Block size
    247245 * @param data          Data to write
    248246 *
    249247 * @return              Error code
    250248 */
    251 int usbmast_write(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
     249int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks,
    252250    const void *data)
    253251{
     
    256254        int rc;
    257255
    258         /* XXX Need softstate to store block size. */
    259 
    260256        if (ba > UINT32_MAX)
    261257                return ELIMIT;
    262258
    263         if ((uint64_t)nblocks * bsize > UINT32_MAX)
     259        if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
    264260                return ELIMIT;
    265261
     
    269265        cdb.xfer_len = host2uint32_t_be(nblocks);
    270266
    271         rc = usb_massstor_data_out(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    272             sizeof(cdb), data, nblocks * bsize, &sent_len);
     267        rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
     268            sizeof(cdb), data, nblocks * mfun->block_size, &sent_len);
    273269
    274270        if (rc != EOK) {
    275271                usb_log_error("Write (12) failed, device %s: %s.\n",
    276                    dev->ddf_dev->name, str_error(rc));
    277                 return rc;
    278         }
    279 
    280         if (sent_len < nblocks * bsize) {
     272                   mfun->mdev->ddf_dev->name, str_error(rc));
     273                return rc;
     274        }
     275
     276        if (sent_len < nblocks * mfun->block_size) {
    281277                usb_log_error("SCSI Write not all bytes transferred (%zu).\n",
    282278                    sent_len);
  • uspace/drv/bus/usb/usbmast/scsi_ms.h

    r27eddb52 r4069f5c  
    5959} usbmast_inquiry_data_t;
    6060
    61 extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *);
    62 extern int usbmast_request_sense(usb_device_t *, void *, size_t);
    63 extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *);
    64 extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *);
    65 extern int usbmast_write(usb_device_t *, uint64_t, size_t, size_t,
    66     const void *);
     61extern int usbmast_inquiry(usbmast_fun_t *, usbmast_inquiry_data_t *);
     62extern int usbmast_request_sense(usbmast_fun_t *, void *, size_t);
     63extern int usbmast_read_capacity(usbmast_fun_t *, uint32_t *, uint32_t *);
     64extern int usbmast_read(usbmast_fun_t *, uint64_t, size_t, void *);
     65extern int usbmast_write(usbmast_fun_t *, uint64_t, size_t, const void *);
    6766extern const char *usbmast_scsi_dev_type_str(unsigned);
    6867
  • uspace/drv/bus/usb/vhc/connhost.c

    r27eddb52 r4069f5c  
    141141    size_t max_packet_size, unsigned int interval)
    142142{
    143         VHC_DATA(vhc, fun);
    144 
    145         endpoint_t *ep = malloc(sizeof(endpoint_t));
     143        /* TODO: Use usb_endpoint_manager_add_ep */
     144        VHC_DATA(vhc, fun);
     145
     146        endpoint_t *ep = endpoint_get(
     147            address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
    146148        if (ep == NULL) {
    147149                return ENOMEM;
    148150        }
    149151
    150         int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
    151             USB_SPEED_FULL, 1);
    152         if (rc != EOK) {
    153                 free(ep);
    154                 return rc;
    155         }
    156 
    157         rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
     152        int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
    158153        if (rc != EOK) {
    159154                endpoint_destroy(ep);
  • uspace/drv/infrastructure/root/root.c

    r27eddb52 r4069f5c  
    176176        }
    177177
     178        free(match_id);
     179
    178180        rc = ddf_fun_bind(fun);
    179181        if (rc != EOK) {
  • uspace/drv/test/test1/test1.c

    r27eddb52 r4069f5c  
    7474        }
    7575
    76         rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
     76        rc = ddf_fun_add_match_id(fun, match_id, match_score);
    7777        if (rc != EOK) {
    7878                ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
  • uspace/lib/c/generic/io/io.c

    r27eddb52 r4069f5c  
    714714off64_t ftell(FILE *stream)
    715715{
     716        _fflushbuf(stream);
    716717        return lseek(stream->fd, 0, SEEK_CUR);
    717718}
  • uspace/lib/clui/tinput.c

    r27eddb52 r4069f5c  
    11/*
    2  * Copyright (c) 2010 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
     29#include <sort.h>
    2930#include <stdio.h>
    3031#include <stdlib.h>
     
    4243#include <tinput.h>
    4344
     45#define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols))
     46#define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols))
     47
    4448/** Seek direction */
    4549typedef enum {
     
    6165static void tinput_post_seek(tinput_t *, bool);
    6266
     67static void tinput_console_set_lpos(tinput_t *ti, unsigned lpos)
     68{
     69        console_set_pos(ti->console, LIN_TO_COL(ti, lpos),
     70            LIN_TO_ROW(ti, lpos));
     71}
     72
    6373/** Create a new text input field. */
    6474tinput_t *tinput_new(void)
     
    6676        tinput_t *ti;
    6777       
    68         ti = malloc(sizeof(tinput_t));
     78        ti = calloc(1, sizeof(tinput_t));
    6979        if (ti == NULL)
    7080                return NULL;
     
    7787void tinput_destroy(tinput_t *ti)
    7888{
     89        if (ti->prompt != NULL)
     90                free(ti->prompt);
    7991        free(ti);
     92}
     93
     94static void tinput_display_prompt(tinput_t *ti)
     95{
     96        tinput_console_set_lpos(ti, ti->prompt_coord);
     97
     98        console_set_style(ti->console, STYLE_EMPHASIS);
     99        printf("%s", ti->prompt);
     100        console_flush(ti->console);
     101        console_set_style(ti->console, STYLE_NORMAL);
    80102}
    81103
     
    88110        tinput_sel_get_bounds(ti, &sa, &sb);
    89111       
    90         console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols,
    91             ti->row0 + (ti->col0 + start) / ti->con_cols);
     112        tinput_console_set_lpos(ti, ti->text_coord + start);
    92113        console_set_style(ti->console, STYLE_NORMAL);
    93114       
     
    134155static void tinput_position_caret(tinput_t *ti)
    135156{
    136         console_set_pos(ti->console, (ti->col0 + ti->pos) % ti->con_cols,
    137             ti->row0 + (ti->col0 + ti->pos) / ti->con_cols);
    138 }
    139 
    140 /** Update row0 in case the screen could have scrolled. */
     157        tinput_console_set_lpos(ti, ti->text_coord + ti->pos);
     158}
     159
     160/** Update text_coord, prompt_coord in case the screen could have scrolled. */
    141161static void tinput_update_origin(tinput_t *ti)
    142162{
    143         sysarg_t width = ti->col0 + ti->nc;
    144         sysarg_t rows = (width / ti->con_cols) + 1;
    145        
    146         /* Update row0 if the screen scrolled. */
    147         if (ti->row0 + rows > ti->con_rows)
    148                 ti->row0 = ti->con_rows - rows;
     163        unsigned end_coord = ti->text_coord + ti->nc;
     164        unsigned end_row = LIN_TO_ROW(ti, end_coord);
     165
     166        unsigned scroll_rows;
     167
     168        /* Update coords if the screen scrolled. */
     169        if (end_row >= ti->con_rows) {
     170                scroll_rows = end_row - ti->con_rows + 1;
     171                ti->text_coord -= ti->con_cols * scroll_rows;
     172                ti->prompt_coord -= ti->con_cols * scroll_rows;
     173        }
     174}
     175
     176static void tinput_jump_after(tinput_t *ti)
     177{
     178        tinput_console_set_lpos(ti, ti->text_coord + ti->nc);
     179        console_flush(ti->console);
     180        putchar('\n');
     181}
     182
     183static int tinput_display(tinput_t *ti)
     184{
     185        sysarg_t col0, row0;
     186       
     187        if (console_get_pos(ti->console, &col0, &row0) != EOK)
     188                return EIO;
     189       
     190        ti->prompt_coord = row0 * ti->con_cols + col0;
     191        ti->text_coord = ti->prompt_coord + str_length(ti->prompt);
     192
     193        tinput_display_prompt(ti);
     194        tinput_display_tail(ti, 0, 0);
     195        tinput_position_caret(ti);
     196
     197        return EOK;
    149198}
    150199
     
    154203                return;
    155204       
    156         sysarg_t new_width = ti->col0 + ti->nc + 1;
     205        unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
    157206        if (new_width % ti->con_cols == 0) {
    158207                /* Advancing to new line. */
     
    185234                return;
    186235       
    187         sysarg_t new_width = ti->col0 + ti->nc + ilen;
    188         sysarg_t new_height = (new_width / ti->con_cols) + 1;
     236        unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + ilen;
     237        unsigned new_height = (new_width / ti->con_cols) + 1;
    189238        if (new_height >= ti->con_rows) {
    190239                /* Disallow text longer than 1 page for now. */
     
    511560}
    512561
     562/** Compare two entries in array of completions. */
     563static int compl_cmp(void *va, void *vb, void *arg)
     564{
     565        const char *a = *(const char **) va;
     566        const char *b = *(const char **) vb;
     567
     568        return str_cmp(a, b);
     569}
     570
     571static size_t common_pref_len(const char *a, const char *b)
     572{
     573        size_t i;
     574        size_t a_off, b_off;
     575        wchar_t ca, cb;
     576
     577        i = 0;
     578        a_off = 0;
     579        b_off = 0;
     580
     581        while (true) {
     582                ca = str_decode(a, &a_off, STR_NO_LIMIT);
     583                cb = str_decode(b, &b_off, STR_NO_LIMIT);
     584
     585                if (ca == '\0' || cb == '\0' || ca != cb)
     586                        break;
     587                ++i;
     588        }
     589
     590        return i;
     591}
     592
     593static void tinput_text_complete(tinput_t *ti)
     594{
     595        void *state;
     596        size_t cstart;
     597        char *ctmp;
     598        char **compl;           /* Array of completions */
     599        size_t compl_len;       /* Current length of @c compl array */
     600        size_t cnum;
     601        size_t i;
     602        int rc;
     603
     604        if (ti->compl_ops == NULL)
     605                return;
     606
     607        /*
     608         * Obtain list of all possible completions (growing array).
     609         */
     610
     611        rc = (*ti->compl_ops->init)(ti->buffer, ti->pos, &cstart, &state);
     612        if (rc != EOK)
     613                return;
     614
     615        cnum = 0;
     616
     617        compl_len = 1;
     618        compl = malloc(compl_len * sizeof(char *));
     619        if (compl == NULL) {
     620                printf("Error: Out of memory.\n");
     621                return;
     622        }
     623
     624        while (true) {
     625                rc = (*ti->compl_ops->get_next)(state, &ctmp);
     626                if (rc != EOK)
     627                        break;
     628
     629                if (cnum >= compl_len) {
     630                        /* Extend array */
     631                        compl_len = 2 * compl_len;
     632                        compl = realloc(compl, compl_len * sizeof(char *));
     633                        if (compl == NULL) {
     634                                printf("Error: Out of memory.\n");
     635                                break;
     636                        }
     637                }
     638
     639                compl[cnum] = str_dup(ctmp);
     640                if (compl[cnum] == NULL) {
     641                        printf("Error: Out of memory.\n");
     642                        break;
     643                }
     644                cnum++;
     645        }
     646
     647        (*ti->compl_ops->fini)(state);
     648
     649        if (cnum > 1) {
     650                /*
     651                 * More than one match. Determine maximum common prefix.
     652                 */
     653                size_t cplen;
     654
     655                cplen = str_length(compl[0]);
     656                for (i = 1; i < cnum; i++)
     657                        cplen = min(cplen, common_pref_len(compl[0], compl[i]));
     658
     659                /* Compute how many bytes we should skip. */
     660                size_t istart = str_lsize(compl[0], ti->pos - cstart);
     661
     662                if (cplen > istart) {
     663                        /* Insert common prefix. */
     664
     665                        /* Copy remainder of common prefix. */
     666                        char *cpref = str_ndup(compl[0] + istart,
     667                            str_lsize(compl[0], cplen - istart));
     668
     669                        /* Insert it. */
     670                        tinput_insert_string(ti, cpref);
     671                        free(cpref);
     672                } else {
     673                        /* No common prefix. Sort and display all entries. */
     674
     675                        qsort(compl, cnum, sizeof(char *), compl_cmp, NULL);
     676
     677                        tinput_jump_after(ti);
     678                        for (i = 0; i < cnum; i++)
     679                                printf("%s\n", compl[i]);
     680                        tinput_display(ti);
     681                }
     682        } else if (cnum == 1) {
     683                /*
     684                 * We have exactly one match. Insert it.
     685                 */
     686
     687                /* Compute how many bytes of completion string we should skip. */
     688                size_t istart = str_lsize(compl[0], ti->pos - cstart);
     689
     690                /* Insert remainder of completion string at current position. */
     691                tinput_insert_string(ti, compl[0] + istart);
     692        }
     693
     694        for (i = 0; i < cnum; i++)
     695                free(compl[i]);
     696        free(compl);
     697}
     698
    513699/** Initialize text input field.
    514700 *
     
    521707        ti->hpos = 0;
    522708        ti->history[0] = NULL;
     709}
     710
     711/** Set prompt string.
     712 *
     713 * @param ti            Text input
     714 * @param prompt        Prompt string
     715 *
     716 * @return              EOK on success, ENOMEM if out of memory.
     717 */
     718int tinput_set_prompt(tinput_t *ti, const char *prompt)
     719{
     720        if (ti->prompt != NULL)
     721                free(ti->prompt);
     722       
     723        ti->prompt = str_dup(prompt);
     724        if (ti->prompt == NULL)
     725                return ENOMEM;
     726       
     727        return EOK;
     728}
     729
     730/** Set completion ops.
     731 *
     732 * Set pointer to completion ops structure that will be used for text
     733 * completion.
     734 */
     735void tinput_set_compl_ops(tinput_t *ti, tinput_compl_ops_t *compl_ops)
     736{
     737        ti->compl_ops = compl_ops;
    523738}
    524739
     
    539754                return EIO;
    540755       
    541         if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK)
    542                 return EIO;
    543        
    544756        ti->pos = 0;
    545757        ti->sel_start = 0;
     
    549761        ti->exit_clui = false;
    550762       
     763        if (tinput_display(ti) != EOK)
     764                return EIO;
     765       
    551766        while (!ti->done) {
    552767                console_flush(ti->console);
     
    714929                tinput_history_seek(ti, -1);
    715930                break;
     931        case KC_TAB:
     932                tinput_text_complete(ti);
     933                break;
    716934        default:
    717935                break;
  • uspace/lib/clui/tinput.h

    r27eddb52 r4069f5c  
    11/*
    2  * Copyright (c) 2010 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737#define LIBCLUI_TINPUT_H_
    3838
    39 #include <stdio.h>
     39#include <adt/list.h>
    4040#include <async.h>
    4141#include <inttypes.h>
    4242#include <io/console.h>
     43#include <stdio.h>
    4344
    4445#define HISTORY_LEN     10
    4546#define INPUT_MAX_SIZE  1024
     47
     48/** Begin enumeration of text completions.
     49 *
     50 * When user requests text completion, tinput will call this function to start
     51 * text completion operation. @a *cstart should be set to the position
     52 * (character index) of the first character of the 'word' that is being
     53 * completed. The resulting text is obtained by replacing the range of text
     54 * starting at @a *cstart and ending at @a pos with the completion text.
     55 *
     56 * The function can pass information to the get_next and fini functions
     57 * via @a state. The init function allocates the state object and stores
     58 * a pointer to it to @a *state. The fini function destroys the state object.
     59 *
     60 * @param text          Current contents of edit buffer (null-terminated).
     61 * @param pos           Current caret position.
     62 * @param cstart        Output, position in text where completion begins from.
     63 * @param state         Output, pointer to a client state object.
     64 *
     65 * @return              EOK on success, negative error code on failure.
     66 */
     67typedef int (*tinput_compl_init_fn)(wchar_t *text, size_t pos, size_t *cstart,
     68    void **state);
     69
     70/** Obtain one text completion alternative.
     71 *
     72 * Upon success the function sets @a *compl to point to a string, the
     73 * completion text. The caller (Tinput) should not modify or free the text.
     74 * The pointer is only valid until the next invocation of any completion
     75 * function.
     76 *
     77 * @param state         Pointer to state object created by the init funtion.
     78 * @param compl         Output, the completion text, ownership retained.
     79 *
     80 * @return              EOK on success, negative error code on failure.
     81 */
     82typedef int (*tinput_compl_get_next_fn)(void *state, char **compl);
     83
     84
     85/** Finish enumeration of text completions.
     86 *
     87 * The function must deallocate any state information allocated by the init
     88 * function or temporary data allocated by the get_next function.
     89 *
     90 * @param state         Pointer to state object created by the init funtion.
     91 */
     92typedef void (*tinput_compl_fini_fn)(void *state);
     93
     94/** Text completion ops. */
     95typedef struct {
     96        tinput_compl_init_fn init;
     97        tinput_compl_get_next_fn get_next;
     98        tinput_compl_fini_fn fini;
     99} tinput_compl_ops_t;
    46100
    47101/** Text input field (command line).
     
    53107        console_ctrl_t *console;
    54108       
     109        /** Prompt string */
     110        char *prompt;
     111       
     112        /** Completion ops. */
     113        tinput_compl_ops_t *compl_ops;
     114       
    55115        /** Buffer holding text currently being edited */
    56116        wchar_t buffer[INPUT_MAX_SIZE + 1];
    57117       
    58         /** Screen coordinates of the top-left corner of the text field */
    59         sysarg_t col0;
    60         sysarg_t row0;
     118        /** Linear position on screen where the prompt starts */
     119        unsigned prompt_coord;
     120        /** Linear position on screen where the text field starts */
     121        unsigned text_coord;
    61122       
    62123        /** Screen dimensions */
     
    90151
    91152extern tinput_t *tinput_new(void);
     153extern int tinput_set_prompt(tinput_t *, const char *);
     154extern void tinput_set_compl_ops(tinput_t *, tinput_compl_ops_t *);
    92155extern void tinput_destroy(tinput_t *);
    93156extern int tinput_read(tinput_t *, char **);
  • uspace/lib/drv/generic/driver.c

    r27eddb52 r4069f5c  
    620620                return ENOMEM;
    621621       
    622         match_id->id = match_id_str;
     622        match_id->id = str_dup(match_id_str);
    623623        match_id->score = 90;
    624624       
  • uspace/lib/usb/include/usb/classes/hub.h

    r27eddb52 r4069f5c  
    119119     */
    120120    uint16_t hub_characteristics;
     121#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
     122#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
    121123
    122124    /**
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r27eddb52 r4069f5c  
    6161} endpoint_t;
    6262
    63 int endpoint_init(endpoint_t *instance, usb_address_t address,
    64     usb_endpoint_t endpoint, usb_direction_t direction,
    65     usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size);
     63endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
     64    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
     65    size_t max_packet_size);
    6666
    6767void endpoint_destroy(endpoint_t *instance);
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r27eddb52 r4069f5c  
    8282    size_t data_size)
    8383{
    84         endpoint_t *ep = malloc(sizeof(endpoint_t));
    85         if (ep == NULL)
     84        endpoint_t *ep = endpoint_get(
     85            address, endpoint, direction, type, speed, max_packet_size);
     86        if (!ep)
    8687                return ENOMEM;
    8788
    88         int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
    89             max_packet_size);
    90         if (ret != EOK) {
    91                 free(ep);
    92                 return ret;
    93         }
    94 
    95         ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
     89        const int ret =
     90            usb_endpoint_manager_register_ep(instance, ep, data_size);
    9691        if (ret != EOK) {
    9792                endpoint_destroy(ep);
    98                 return ret;
    9993        }
    100         return EOK;
     94        return ret;
    10195}
    10296#endif
  • uspace/lib/usbhost/src/batch.c

    r27eddb52 r4069f5c  
    109109        assert(instance);
    110110        assert(instance->ep);
     111        assert(instance->next_step);
    111112        endpoint_release(instance->ep);
    112113        instance->next_step(instance);
  • uspace/lib/usbhost/src/endpoint.c

    r27eddb52 r4069f5c  
    3939#include <usb/host/endpoint.h>
    4040
    41 int endpoint_init(endpoint_t *instance, usb_address_t address,
    42     usb_endpoint_t endpoint, usb_direction_t direction,
    43     usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size)
     41endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
     42    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
     43    size_t max_packet_size)
    4444{
    45         assert(instance);
    46         instance->address = address;
    47         instance->endpoint = endpoint;
    48         instance->direction = direction;
    49         instance->transfer_type = type;
    50         instance->speed = speed;
    51         instance->max_packet_size = max_packet_size;
    52         instance->toggle = 0;
    53         instance->active = false;
    54         fibril_mutex_initialize(&instance->guard);
    55         fibril_condvar_initialize(&instance->avail);
    56         endpoint_clear_hc_data(instance);
    57         return EOK;
     45        endpoint_t *instance = malloc(sizeof(endpoint_t));
     46        if (instance) {
     47                instance->address = address;
     48                instance->endpoint = endpoint;
     49                instance->direction = direction;
     50                instance->transfer_type = type;
     51                instance->speed = speed;
     52                instance->max_packet_size = max_packet_size;
     53                instance->toggle = 0;
     54                instance->active = false;
     55                fibril_mutex_initialize(&instance->guard);
     56                fibril_condvar_initialize(&instance->avail);
     57                endpoint_clear_hc_data(instance);
     58        }
     59        return instance;
    5860}
    5961/*----------------------------------------------------------------------------*/
  • uspace/srv/hid/input/ctl/stty.c

    r27eddb52 r4069f5c  
    3434 * @file
    3535 * @brief Serial TTY-like keyboard controller driver.
     36 *
     37 * Keyboard emulation on a serial terminal.
    3638 */
    3739
     
    6365#include <stdio.h>
    6466
     67/**
     68 * Sequnece definitions are primarily for Xterm. Additionally we define
     69 * sequences that are unique to Gnome terminal -- most are the same but
     70 * some differ.
     71 */
    6572static int seq_defs[] = {
    6673        /* Not shifted */
     
    8188        0,      KC_MINUS,       0x2d, GSP_END,
    8289        0,      KC_EQUALS,      0x3d, GSP_END,
     90
    8391        0,      KC_BACKSPACE,   0x08, GSP_END,
    8492
     
    216224        0,      KC_RIGHT,       0x1b, 0x5b, 0x43, GSP_END,
    217225
     226        /*
     227         * Sequences specific to Gnome terminal
     228         */
     229        0,      KC_BACKSPACE,   0x7f, GSP_END, /* ASCII DEL */
     230        0,      KC_HOME,        0x1b, 0x4f, 0x48, GSP_END,
     231        0,      KC_END,         0x1b, 0x4f, 0x46, GSP_END,
     232
    218233        0,      0
    219234};
  • uspace/srv/hid/input/generic/gsp.c

    r27eddb52 r4069f5c  
    104104                if (key == 0) break;
    105105
    106                 /* Insert one sequence. */             
     106                /* Insert one sequence. */
    107107                rc = gsp_insert_seq(p, dp, mods, key);
    108108                if (rc != 0)
     
    197197
    198198        if (t == NULL) {
    199                 printf("gsp_step: not found\n");
     199                printf("gsp_step: not found, state=%d, input=0x%x\n",
     200                    state, input);
    200201                *mods = 0;
    201202                *key = 0;
     
    205206        *mods = t->out_mods;
    206207        *key = t->out_key;
     208
    207209        return t->new_state;
    208210}
  • uspace/srv/hid/input/generic/input.c

    r27eddb52 r4069f5c  
    410410#endif
    411411#if defined(MACHINE_msim)
    412         kbd_add_dev(&msim_port, &pc_ctl);
     412        kbd_add_dev(&msim_port, &stty_ctl);
    413413#endif
    414414#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
Note: See TracChangeset for help on using the changeset viewer.