Changes in / [160b75e:293de44] in mainline


Ignore:
Files:
6 added
15 deleted
43 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r160b75e r293de44  
    5353./uspace/app/klog/klog
    5454./uspace/app/lsusb/lsusb
     55./uspace/app/mkbd/mkbd
    5556./uspace/app/mkfat/mkfat
    5657./uspace/app/netstart/netstart
  • boot/Makefile.common

    r160b75e r293de44  
    157157        $(USPACE_PATH)/app/usbinfo/usbinfo \
    158158        $(USPACE_PATH)/app/vuhid/vuh \
     159        $(USPACE_PATH)/app/mkbd/mkbd \
    159160        $(USPACE_PATH)/app/websrv/websrv
    160161
  • boot/arch/amd64/Makefile.inc

    r160b75e r293de44  
    4949        usbflbk \
    5050        usbhub \
    51         usbkbd \
    5251        usbhid \
    5352        usbmast \
  • kernel/generic/src/ipc/irq.c

    r160b75e r293de44  
    370370        if (AS != irq->driver_as) \
    371371                as_switch(AS, irq->driver_as); \
    372         printf("Copying data from address: %p.\n", va); \
    373372        memcpy_from_uspace(&target, va, (sizeof(target))); \
    374373        if (dstarg) \
     
    381380        if (AS != irq->driver_as) \
    382381                as_switch(AS, irq->driver_as); \
    383         printf("Writing data to address: %p.\n", va); \
    384382        memcpy_to_uspace(va, &val, sizeof(val)); \
    385383} while (0)
     
    457455                        uint32_t val;
    458456                        CMD_MEM_READ(val);
    459                         printf("mem READ value: %x.\n", val);
    460457                        break;
    461458                        }
  • uspace/Makefile

    r160b75e r293de44  
    5959        app/websrv \
    6060        app/sysinfo \
     61        app/mkbd \
    6162        srv/clip \
    6263        srv/devmap \
     
    122123                drv/uhci-rhd \
    123124                drv/usbflbk \
    124                 drv/usbkbd \
    125125                drv/usbhid \
    126126                drv/usbhub \
     
    144144                drv/uhci-rhd \
    145145                drv/usbflbk \
    146                 drv/usbkbd \
    147146                drv/usbhid \
    148147                drv/usbhub \
  • uspace/drv/ohci/batch.c

    r160b75e r293de44  
    4444#include "hw_struct/transfer_descriptor.h"
    4545
     46/** OHCI specific data required for USB transfer */
    4647typedef struct ohci_transfer_batch {
     48        /** Endpoint descriptor of the target endpoint. */
    4749        ed_t *ed;
     50        /** List of TDs needed for the transfer */
    4851        td_t **tds;
     52        /** Number of TDs used by the transfer */
    4953        size_t td_count;
     54        /** Dummy TD to be left at the ED and used by the next transfer */
    5055        size_t leave_td;
    51         char *device_buffer;
     56        /** Data buffer, must be accessible byb the OHCI hw. */
     57        void *device_buffer;
    5258} ohci_transfer_batch_t;
    53 
     59/*----------------------------------------------------------------------------*/
     60static void batch_control(usb_transfer_batch_t *instance,
     61    usb_direction_t data_dir, usb_direction_t status_dir);
     62static void batch_data(usb_transfer_batch_t *instance);
     63/*----------------------------------------------------------------------------*/
     64/** Safely destructs ohci_transfer_batch_t structure
     65 *
     66 * @param[in] ohci_batch Instance to destroy.
     67 */
    5468static void ohci_transfer_batch_dispose(void *ohci_batch)
    5569{
     
    6983}
    7084/*----------------------------------------------------------------------------*/
    71 static void batch_control(usb_transfer_batch_t *instance,
    72     usb_direction_t data_dir, usb_direction_t status_dir);
    73 static void batch_data(usb_transfer_batch_t *instance);
    74 /*----------------------------------------------------------------------------*/
     85/** Allocate memory initialize internal structures
     86 *
     87 * @param[in] fun DDF function to pass to callback.
     88 * @param[in] ep Communication target
     89 * @param[in] buffer Data source/destination.
     90 * @param[in] buffer_size Size of the buffer.
     91 * @param[in] setup_buffer Setup data source (if not NULL)
     92 * @param[in] setup_size Size of setup_buffer (should be always 8)
     93 * @param[in] func_in function to call on inbound transfer completion
     94 * @param[in] func_out function to call on outbound transfer completion
     95 * @param[in] arg additional parameter to func_in or func_out
     96 * @return Valid pointer if all structures were successfully created,
     97 * NULL otherwise.
     98 *
     99 * Allocates and initializes structures needed by the OHCI hw for the transfer.
     100 */
    75101usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    76     char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     102    char *buffer, size_t buffer_size,
     103    const char *setup_buffer, size_t setup_size,
    77104    usbhc_iface_transfer_in_callback_t func_in,
    78105    usbhc_iface_transfer_out_callback_t func_out, void *arg)
     
    94121            ohci_transfer_batch_dispose);
    95122
    96         hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     123        const hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
    97124        assert(hcd_ep);
    98125
     
    103130        data->td_count =
    104131            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
     132        /* Control transfer need Setup and Status stage */
    105133        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    106134                data->td_count += 2;
    107135        }
    108136
    109         /* we need one extra place for td that is currently assigned to hcd_ep*/
     137        /* We need an extra place for TD that is currently assigned to hcd_ep*/
    110138        data->tds = calloc(sizeof(td_t*), data->td_count + 1);
    111139        CHECK_NULL_DISPOSE_RETURN(data->tds,
    112140            "Failed to allocate transfer descriptors.\n");
    113141
     142        /* Add TD left over by the previous transfer */
    114143        data->tds[0] = hcd_ep->td;
    115144        data->leave_td = 0;
     
    123152        data->ed = hcd_ep->ed;
    124153
     154        /* NOTE: OHCI is capable of handling buffer that crosses page boundaries
     155         * it is, however, not capable of handling buffer that occupies more
     156         * than two pages (the first page is computed using start pointer, the
     157         * other using the end pointer) */
    125158        if (setup_size + buffer_size > 0) {
    126159                data->device_buffer = malloc32(setup_size + buffer_size);
     
    135168}
    136169/*----------------------------------------------------------------------------*/
     170/** Check batch TDs' status.
     171 *
     172 * @param[in] instance Batch structure to use.
     173 * @return False, if there is an active TD, true otherwise.
     174 *
     175 * Walk all TDs (usually there is just one). Stop with false if there is an
     176 * active TD. Stop with true if an error is found. Return true if the walk
     177 * completes with the last TD.
     178 */
    137179bool batch_is_complete(usb_transfer_batch_t *instance)
    138180{
     
    140182        ohci_transfer_batch_t *data = instance->private_data;
    141183        assert(data);
    142         size_t tds = data->td_count;
    143184        usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
    144             instance, tds);
     185            instance, data->td_count);
    145186        usb_log_debug("ED: %x:%x:%x:%x.\n",
    146187            data->ed->status, data->ed->td_head, data->ed->td_tail,
     
    148189        size_t i = 0;
    149190        instance->transfered_size = instance->buffer_size;
    150         for (; i < tds; ++i) {
     191        for (; i < data->td_count; ++i) {
    151192                assert(data->tds[i] != NULL);
    152193                usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     
    173214        assert(hcd_ep);
    174215        hcd_ep->td = data->tds[i];
    175         if (i > 0)
    176                 instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     216        assert(i > 0);
     217        for (--i;i < data->td_count; ++i)
     218                instance->transfered_size -= td_remain_size(data->tds[i]);
    177219
    178220        /* Clear possible ED HALT */
    179221        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    180         uint32_t pa = addr_to_phys(hcd_ep->td);
     222        const uint32_t pa = addr_to_phys(hcd_ep->td);
    181223        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
    182224        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     
    185227}
    186228/*----------------------------------------------------------------------------*/
     229/** Starts execution of the TD list
     230 *
     231 * @param[in] instance Batch structure to use
     232 */
    187233void batch_commit(usb_transfer_batch_t *instance)
    188234{
     
    193239}
    194240/*----------------------------------------------------------------------------*/
     241/** Prepares control write transfer.
     242 *
     243 * @param[in] instance Batch structure to use.
     244 *
     245 * Uses generic control transfer using direction OUT(data stage) and
     246 * IN(status stage).
     247 */
    195248void batch_control_write(usb_transfer_batch_t *instance)
    196249{
     
    203256}
    204257/*----------------------------------------------------------------------------*/
     258/** Prepares control read transfer.
     259 *
     260 * @param[in] instance Batch structure to use.
     261 *
     262 * Uses generic control transfer using direction IN(data stage) and
     263 * OUT(status stage).
     264 */
    205265void batch_control_read(usb_transfer_batch_t *instance)
    206266{
     
    211271}
    212272/*----------------------------------------------------------------------------*/
     273/** Prepare interrupt in transfer.
     274 *
     275 * @param[in] instance Batch structure to use.
     276 *
     277 * Data transfer.
     278 */
    213279void batch_interrupt_in(usb_transfer_batch_t *instance)
    214280{
     
    219285}
    220286/*----------------------------------------------------------------------------*/
     287/** Prepare interrupt out transfer.
     288 *
     289 * @param[in] instance Batch structure to use.
     290 *
     291 * Data transfer.
     292 */
    221293void batch_interrupt_out(usb_transfer_batch_t *instance)
    222294{
     
    229301}
    230302/*----------------------------------------------------------------------------*/
     303/** Prepare bulk in transfer.
     304 *
     305 * @param[in] instance Batch structure to use.
     306 *
     307 * Data transfer.
     308 */
    231309void batch_bulk_in(usb_transfer_batch_t *instance)
    232310{
     
    237315}
    238316/*----------------------------------------------------------------------------*/
     317/** Prepare bulk out transfer.
     318 *
     319 * @param[in] instance Batch structure to use.
     320 *
     321 * Data transfer.
     322 */
    239323void batch_bulk_out(usb_transfer_batch_t *instance)
    240324{
     
    247331}
    248332/*----------------------------------------------------------------------------*/
    249 ed_t * batch_ed(usb_transfer_batch_t *instance)
    250 {
    251         assert(instance);
    252         ohci_transfer_batch_t *data = instance->private_data;
    253         assert(data);
    254         return data->ed;
    255 }
    256 /*----------------------------------------------------------------------------*/
     333/** Prepare generic control transfer
     334 *
     335 * @param[in] instance Batch structure to use.
     336 * @param[in] data_dir Direction to use for data stage.
     337 * @param[in] status_dir Direction to use for status stage.
     338 *
     339 * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
     340 * Data stage with alternating toggle and direction supplied by parameter.
     341 * Status stage with toggle 1 and direction supplied by parameter.
     342 */
    257343void batch_control(usb_transfer_batch_t *instance,
    258344    usb_direction_t data_dir, usb_direction_t status_dir)
     
    303389}
    304390/*----------------------------------------------------------------------------*/
     391/** Prepare generic data transfer
     392 *
     393 * @param[in] instance Batch structure to use.
     394 *
     395 * Direction is supplied by the associated ep and toggle is maintained by the
     396 * OHCI hw in ED.
     397 */
    305398void batch_data(usb_transfer_batch_t *instance)
    306399{
     
    316409        char *buffer = instance->data_buffer;
    317410        while (remain_size > 0) {
    318                 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
    319                     OHCI_TD_MAX_TRANSFER : remain_size;
     411                const size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER
     412                    ? OHCI_TD_MAX_TRANSFER : remain_size;
    320413
    321414                td_init(data->tds[td_current], instance->ep->direction,
  • uspace/drv/ohci/batch.h

    r160b75e r293de44  
    4141#include <usb/host/batch.h>
    4242
    43 #include "hw_struct/endpoint_descriptor.h"
    44 
    4543usb_transfer_batch_t * batch_get(
    4644    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
    47     char *setup_buffer, size_t setup_size,
     45    const char *setup_buffer, size_t setup_size,
    4846    usbhc_iface_transfer_in_callback_t func_in,
    4947    usbhc_iface_transfer_out_callback_t func_out,
     
    6563
    6664void batch_bulk_out(usb_transfer_batch_t *instance);
    67 
    68 ed_t * batch_ed(usb_transfer_batch_t *instance);
    6965#endif
    7066/**
  • uspace/drv/ohci/endpoint_list.c

    r160b75e r293de44  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "endpoint_list.h"
     
    4344 * @return Error code
    4445 *
    45  * Allocates memory for internal qh_t structure.
     46 * Allocates memory for internal ed_t structure.
    4647 */
    4748int endpoint_list_init(endpoint_list_t *instance, const char *name)
     
    6869 * @param[in] instance List to lead.
    6970 * @param[in] next List to append.
    70  * @return Error code
    7171 *
    72  * Does not check whether this replaces an existing list .
     72 * Does not check whether this replaces an existing list.
    7373 */
    7474void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     
    7979}
    8080/*----------------------------------------------------------------------------*/
    81 /** Submit transfer endpoint to the list and queue.
     81/** Add endpoint to the list and queue.
    8282 *
    8383 * @param[in] instance List to use.
    84  * @param[in] endpoint Transfer endpoint to submit.
    85  * @return Error code
     84 * @param[in] endpoint Endpoint to add.
    8685 *
    8786 * The endpoint is added to the end of the list and queue.
     
    9998        /* Add to the hardware queue. */
    10099        if (list_empty(&instance->endpoint_list)) {
    101                 /* There is nothing scheduled */
     100                /* There are no active EDs */
    102101                last_ed = instance->list_head;
    103102        } else {
    104                 /* There is something scheduled */
     103                /* There are active EDs, get the last one */
    105104                hcd_endpoint_t *last = list_get_instance(
    106105                    instance->endpoint_list.prev, hcd_endpoint_t, link);
     106                assert(last);
    107107                last_ed = last->ed;
    108108        }
    109         /* keep link */
     109        /* Keep link */
    110110        hcd_ep->ed->next = last_ed->next;
     111        /* Make sure ED is written to the memory */
     112        write_barrier();
     113
     114        /* Add ed to the hw queue */
    111115        ed_append_ed(last_ed, hcd_ep->ed);
     116        /* Make sure ED is updated */
     117        write_barrier();
    112118
    113         asm volatile ("": : :"memory");
    114 
    115         /* Add to the driver list */
     119        /* Add to the sw list */
    116120        list_append(&hcd_ep->link, &instance->endpoint_list);
    117121
     
    129133}
    130134/*----------------------------------------------------------------------------*/
    131 #if 0
    132 /** Create list for finished endpoints.
     135/** Remove endpoint from the list and queue.
    133136 *
    134137 * @param[in] instance List to use.
    135  * @param[in] done list to fill
    136  */
    137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
    138 {
    139         assert(instance);
    140         assert(done);
    141 
    142         fibril_mutex_lock(&instance->guard);
    143         usb_log_debug2("Checking list %s for completed endpointes(%d).\n",
    144             instance->name, list_count(&instance->endpoint_list));
    145         link_t *current = instance->endpoint_list.next;
    146         while (current != &instance->endpoint_list) {
    147                 link_t *next = current->next;
    148                 hcd_endpoint_t *endpoint =
    149                     list_get_instance(current, hcd_endpoint_t, link);
    150 
    151                 if (endpoint_is_complete(endpoint)) {
    152                         /* Save for post-processing */
    153                         endpoint_list_remove_endpoint(instance, endpoint);
    154                         list_append(current, done);
    155                 }
    156                 current = next;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all endpointes.
    162  *
    163  * @param[in] instance List to use.
    164  */
    165 void endpoint_list_abort_all(endpoint_list_t *instance)
    166 {
    167         fibril_mutex_lock(&instance->guard);
    168         while (!list_empty(&instance->endpoint_list)) {
    169                 link_t *current = instance->endpoint_list.next;
    170                 hcd_endpoint_t *endpoint =
    171                     list_get_instance(current, hcd_endpoint_t, link);
    172                 endpoint_list_remove_endpoint(instance, endpoint);
    173                 hcd_endpoint_finish_error(endpoint, EIO);
    174         }
    175         fibril_mutex_unlock(&instance->guard);
    176 }
    177 #endif
    178 /*----------------------------------------------------------------------------*/
    179 /** Remove a transfer endpoint from the list and queue.
    180  *
    181  * @param[in] instance List to use.
    182  * @param[in] endpoint Transfer endpoint to remove.
    183  * @return Error code
    184  *
    185  * Does not lock the transfer list, caller is responsible for that.
     138 * @param[in] endpoint Endpoint to remove.
    186139 */
    187140void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     
    212165        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
    213166        prev_ed->next = hcd_ep->ed->next;
     167        /* Make sure ED is updated */
     168        write_barrier();
    214169
    215         asm volatile ("": : :"memory");
    216170        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
    217171            hcd_ep, qpos, instance->name, hcd_ep->ed->next);
  • uspace/drv/ohci/endpoint_list.h

    r160b75e r293de44  
    4141#include "utils/malloc32.h"
    4242
     43/** Structure maintains both OHCI queue and software list of active endpoints.*/
    4344typedef struct endpoint_list {
     45        /** Guard against add/remove races */
    4446        fibril_mutex_t guard;
     47        /** OHCI hw structure at the beginning of the queue */
    4548        ed_t *list_head;
     49        /** Physical address of the first(dummy) ED */
    4650        uint32_t list_head_pa;
     51        /** Assigned name, provides nicer debug output */
    4752        const char *name;
     53        /** Sw list of all active EDs */
    4854        link_t endpoint_list;
    4955} endpoint_list_t;
     
    5359 * @param[in] instance Memory place to use.
    5460 *
    55  * Frees memory for internal qh_t structure.
     61 * Frees memory of the internal ed_t structure.
    5662 */
    5763static inline void endpoint_list_fini(endpoint_list_t *instance)
     
    6268
    6369int endpoint_list_init(endpoint_list_t *instance, const char *name);
    64 
    6570void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
    66 
    6771void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    68 
    6972void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    70 #if 0
    71 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
    72 
    73 void endpoint_list_abort_all(endpoint_list_t *instance);
    74 #endif
    7573#endif
    7674/**
  • uspace/drv/ohci/hc.c

    r160b75e r293de44  
    5151static int hc_init_memory(hc_t *instance);
    5252/*----------------------------------------------------------------------------*/
     53/** Announce OHCI root hub to the DDF
     54 *
     55 * @param[in] instance OHCI driver intance
     56 * @param[in] hub_fun DDF fuction representing OHCI root hub
     57 * @return Error code
     58 */
    5359int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
    5460{
     
    5662        assert(hub_fun);
    5763
    58         int ret;
    59 
    60         usb_address_t hub_address =
     64        const usb_address_t hub_address =
    6165            device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
    6266        if (hub_address <= 0) {
    63                 usb_log_error("Failed to get OHCI root hub address.\n");
     67                usb_log_error("Failed(%d) to get OHCI root hub address.\n",
     68                    hub_address);
    6469                return hub_address;
    6570        }
     
    6873            &instance->manager, hub_address, hub_fun->handle);
    6974
    70         ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     75#define CHECK_RET_RELEASE(ret, message...) \
     76if (ret != EOK) { \
     77        usb_log_error(message); \
     78        hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
     79        usb_device_keeper_release(&instance->manager, hub_address); \
     80        return ret; \
     81} else (void)0
     82
     83        int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
    7184            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    72         if (ret != EOK) {
    73                 usb_log_error("Failed to add OHCI rh endpoint 0.\n");
    74                 usb_device_keeper_release(&instance->manager, hub_address);
    75                 return ret;
    76         }
     85        CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret);
    7786
    7887        char *match_str = NULL;
    7988        /* DDF needs heap allocated string */
    8089        ret = asprintf(&match_str, "usb&class=hub");
    81         if (ret < 0) {
    82                 usb_log_error(
    83                     "Failed(%d) to create root hub match-id string.\n", ret);
    84                 usb_device_keeper_release(&instance->manager, hub_address);
    85                 return ret;
    86         }
     90        ret = ret > 0 ? 0 : ret;
     91        CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
    8792
    8893        ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
    89         if (ret != EOK) {
    90                 usb_log_error("Failed add root hub match-id.\n");
    91         }
     94        CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
     95
    9296        ret = ddf_fun_bind(hub_fun);
    93         return ret;
    94 }
    95 /*----------------------------------------------------------------------------*/
     97        CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
     98
     99        return EOK;
     100#undef CHECK_RET_RELEASE
     101}
     102/*----------------------------------------------------------------------------*/
     103/** Initialize OHCI hc driver structure
     104 *
     105 * @param[in] instance Memory place for the structure.
     106 * @param[in] regs Address of the memory mapped I/O registers.
     107 * @param[in] reg_size Size of the memory mapped area.
     108 * @param[in] interrupts True if w interrupts should be used
     109 * @return Error code
     110 */
    96111int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
    97112{
     
    121136#undef CHECK_RET_RETURN
    122137
    123 
    124 //      hc_init_hw(instance);
     138        fibril_mutex_initialize(&instance->guard);
    125139        hc_gain_control(instance);
    126         fibril_mutex_initialize(&instance->guard);
    127140
    128141        rh_init(&instance->rh, instance->registers);
     
    137150}
    138151/*----------------------------------------------------------------------------*/
     152/** Create end register endpoint structures
     153 *
     154 * @param[in] instance OHCI driver structure.
     155 * @param[in] address USB address of the device.
     156 * @param[in] endpoint USB endpoint number.
     157 * @param[in] speed Communication speeed of the device.
     158 * @param[in] type Endpoint's transfer type.
     159 * @param[in] direction Endpoint's direction.
     160 * @param[in] mps Maximum packet size the endpoint accepts.
     161 * @param[in] size Maximum allowed buffer size.
     162 * @param[in] interval Time between transfers(interrupt transfers only).
     163 * @return Error code
     164 */
    139165int hc_add_endpoint(
    140166    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
     
    194220}
    195221/*----------------------------------------------------------------------------*/
     222/** Dequeue and delete endpoint structures
     223 *
     224 * @param[in] instance OHCI hc driver structure.
     225 * @param[in] address USB address of the device.
     226 * @param[in] endpoint USB endpoint number.
     227 * @param[in] direction Direction of the endpoint.
     228 * @return Error code
     229 */
    196230int hc_remove_endpoint(hc_t *instance, usb_address_t address,
    197231    usb_endpoint_t endpoint, usb_direction_t direction)
     
    244278}
    245279/*----------------------------------------------------------------------------*/
     280/** Get access to endpoint structures
     281 *
     282 * @param[in] instance OHCI hc driver structure.
     283 * @param[in] address USB address of the device.
     284 * @param[in] endpoint USB endpoint number.
     285 * @param[in] direction Direction of the endpoint.
     286 * @param[out] bw Reserved bandwidth.
     287 * @return Error code
     288 */
    246289endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
    247290    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     
    255298}
    256299/*----------------------------------------------------------------------------*/
     300/** Add USB transfer to the schedule.
     301 *
     302 * @param[in] instance OHCI hc driver structure.
     303 * @param[in] batch Batch representing the transfer.
     304 * @return Error code.
     305 */
    257306int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    258307{
     
    261310        assert(batch->ep);
    262311
    263         /* check for root hub communication */
     312        /* Check for root hub communication */
    264313        if (batch->ep->address == instance->rh.address) {
    265314                return rh_request(&instance->rh, batch);
     
    269318        list_append(&batch->link, &instance->pending_batches);
    270319        batch_commit(batch);
    271         switch (batch->ep->transfer_type) {
     320
     321        /* Control and bulk schedules need a kick to start working */
     322        switch (batch->ep->transfer_type)
     323        {
    272324        case USB_TRANSFER_CONTROL:
    273325                instance->registers->command_status |= CS_CLF;
     
    279331                break;
    280332        }
    281 
    282333        fibril_mutex_unlock(&instance->guard);
    283334        return EOK;
    284335}
    285336/*----------------------------------------------------------------------------*/
     337/** Interrupt handling routine
     338 *
     339 * @param[in] instance OHCI hc driver structure.
     340 * @param[in] status Value of the status register at the time of interrupt.
     341 */
    286342void hc_interrupt(hc_t *instance, uint32_t status)
    287343{
     
    292348        if (status & I_RHSC)
    293349                rh_interrupt(&instance->rh);
    294 
    295350
    296351        if (status & I_WDH) {
     
    316371                fibril_mutex_unlock(&instance->guard);
    317372        }
    318 }
    319 /*----------------------------------------------------------------------------*/
     373
     374        if (status & I_UE) {
     375                hc_start_hw(instance);
     376        }
     377
     378}
     379/*----------------------------------------------------------------------------*/
     380/** Check status register regularly
     381 *
     382 * @param[in] instance OHCI hc driver structure.
     383 * @return Error code
     384 */
    320385int interrupt_emulator(hc_t *instance)
    321386{
     
    326391                instance->registers->interrupt_status = status;
    327392                hc_interrupt(instance, status);
    328                 async_usleep(50000);
     393                async_usleep(10000);
    329394        }
    330395        return EOK;
    331396}
    332397/*----------------------------------------------------------------------------*/
     398/** Turn off any (BIOS)driver that might be in control of the device.
     399 *
     400 * @param[in] instance OHCI hc driver structure.
     401 */
    333402void hc_gain_control(hc_t *instance)
    334403{
     
    380449}
    381450/*----------------------------------------------------------------------------*/
     451/** OHCI hw initialization routine.
     452 *
     453 * @param[in] instance OHCI hc driver structure.
     454 */
    382455void hc_start_hw(hc_t *instance)
    383456{
     
    447520}
    448521/*----------------------------------------------------------------------------*/
     522/** Initialize schedule queues
     523 *
     524 * @param[in] instance OHCI hc driver structure
     525 * @return Error code
     526 */
    449527int hc_init_transfer_lists(hc_t *instance)
    450528{
    451529        assert(instance);
    452 
    453530#define SETUP_ENDPOINT_LIST(type) \
    454531do { \
     
    458535                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    459536                    ret, name); \
    460                 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     537                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
    461538                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
    462539                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
    463540                endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
     541                return ret; \
    464542        } \
    465543} while (0)
     
    476554}
    477555/*----------------------------------------------------------------------------*/
     556/** Initialize memory structures used by the OHCI hcd.
     557 *
     558 * @param[in] instance OHCI hc driver structure.
     559 * @return Error code.
     560 */
    478561int hc_init_memory(hc_t *instance)
    479562{
     
    502585        /* Init interrupt code */
    503586        instance->interrupt_code.cmds = instance->interrupt_commands;
     587        instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
    504588        {
    505589                /* Read status register */
     
    521605                instance->interrupt_commands[2].srcarg = 2;
    522606
    523                 /* Write clean status register */
     607                /* Write-clean status register */
    524608                instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
    525609                instance->interrupt_commands[3].srcarg = 1;
     
    529613                /* Accept interrupt */
    530614                instance->interrupt_commands[4].cmd = CMD_ACCEPT;
    531 
    532                 instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
    533615        }
    534616
  • uspace/drv/ohci/hc.h

    r160b75e r293de44  
    5353#define OHCI_NEEDED_IRQ_COMMANDS 5
    5454
     55/** Main OHCI drier structure */
    5556typedef struct hc {
     57        /** USB bus driver, devices and addresses */
     58        usb_device_keeper_t manager;
     59        /** USB bus driver, endpoints */
     60        usb_endpoint_manager_t ep_manager;
     61
     62        /** Memory mapped I/O registers area */
    5663        ohci_regs_t *registers;
     64        /** Host controller communication area structure */
    5765        hcca_t *hcca;
    5866
    59         usb_address_t rh_address;
    60         rh_t rh;
    61 
     67        /** Transfer schedules */
    6268        endpoint_list_t lists[4];
     69        /** List of active transfers */
    6370        link_t pending_batches;
    6471
    65         usb_device_keeper_t manager;
    66         usb_endpoint_manager_t ep_manager;
     72        /** Fibril for periodic checks if interrupts can't be used */
    6773        fid_t interrupt_emulator;
     74
     75        /** Guards schedule and endpoint manipulation */
    6876        fibril_mutex_t guard;
    6977
     
    7381        /** Commands that form interrupt code */
    7482        irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
     83
     84        /** USB hub emulation structure */
     85        rh_t rh;
    7586} hc_t;
    7687
    7788int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    78 
    7989int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    80 
    8190void hc_start_hw(hc_t *instance);
    8291
     
    8594 * @param[in] instance Host controller structure to use.
    8695 */
    87 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     96static inline void hc_fini(hc_t *instance)
     97        { /* TODO: implement*/ };
    8898
    8999int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
    90100    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
    91101    size_t max_packet_size, size_t size, unsigned interval);
    92 
    93102int hc_remove_endpoint(hc_t *instance, usb_address_t address,
    94103    usb_endpoint_t endpoint, usb_direction_t direction);
    95 
    96104endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
    97105    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
    98106
    99107int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    100 
    101108void hc_interrupt(hc_t *instance, uint32_t status);
    102109
     
    107114 */
    108115static inline hc_t * fun_to_hc(ddf_fun_t *fun)
    109         { return (hc_t*)fun->driver_data; }
     116        { return fun->driver_data; }
    110117#endif
    111118/**
  • uspace/drv/ohci/hcd_endpoint.c

    r160b75e r293de44  
    3535#include "hcd_endpoint.h"
    3636
     37/** Callback to set toggle on ED.
     38 *
     39 * @param[in] hcd_ep hcd endpoint structure
     40 * @param[in] toggle new value of toggle bit
     41 */
    3742static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
    3843{
     
    4247        ed_toggle_set(instance->ed, toggle);
    4348}
     49/*----------------------------------------------------------------------------*/
     50/** Callback to get value of toggle bit.
     51 *
     52 * @param[in] hcd_ep hcd endpoint structure
     53 * @return Current value of toggle bit.
     54 */
    4455static int hcd_ep_toggle_get(void *hcd_ep)
    4556{
     
    4960        return ed_toggle_get(instance->ed);
    5061}
    51 
    52 
     62/*----------------------------------------------------------------------------*/
     63/** Creates new hcd endpoint representation.
     64 *
     65 * @param[in] ep USBD endpoint structure
     66 * @return pointer to a new hcd endpoint structure, NULL on failure.
     67 */
    5368hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
    5469{
     
    7893}
    7994/*----------------------------------------------------------------------------*/
    80 hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
    81 {
    82         assert(ep);
    83         return ep->hc_data.data;
    84 }
    85 /*----------------------------------------------------------------------------*/
     95/** Disposes assigned hcd endpoint structure
     96 *
     97 * @param[in] ep USBD endpoint structure
     98 */
    8699void hcd_endpoint_clear(endpoint_t *ep)
    87100{
  • uspace/drv/ohci/hcd_endpoint.h

    r160b75e r293de44  
    3737#include <assert.h>
    3838#include <adt/list.h>
    39 
    4039#include <usb/host/endpoint.h>
    4140
     
    4342#include "hw_struct/transfer_descriptor.h"
    4443
     44/** Connector structure linking ED to to prepared TD. */
    4545typedef struct hcd_endpoint {
     46        /** OHCI endpoint descriptor */
    4647        ed_t *ed;
     48        /** Currently enqueued transfer descriptor */
    4749        td_t *td;
     50        /** Linked list used by driver software */
    4851        link_t link;
    4952} hcd_endpoint_t;
    5053
    5154hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
     55void hcd_endpoint_clear(endpoint_t *ep);
    5256
    53 hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep);
     57/** Get and convert assigned hcd_endpoint_t structure
     58 * @param[in] ep USBD endpoint structure.
     59 * @return Pointer to assigned hcd endpoint structure
     60 */
     61static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
     62{
     63        assert(ep);
     64        return ep->hc_data.data;
     65}
    5466
    55 void hcd_endpoint_clear(endpoint_t *ep);
    5667#endif
    5768/**
  • uspace/drv/ohci/hw_struct/transfer_descriptor.c

    r160b75e r293de44  
    4444        assert(instance);
    4545        bzero(instance, sizeof(td_t));
    46         instance-> status = 0
     46        instance->status = 0
    4747            | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
    4848            | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    r160b75e r293de44  
    4141#include "completion_codes.h"
    4242
    43 /* OHCI TDs can handle up to 8KB buffers */
    44 #define OHCI_TD_MAX_TRANSFER (8 * 1024)
     43/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
     44 * Using 4KB buffers guarantees the page count condition.
     45 * (OHCI assumes 4KB pages) */
     46#define OHCI_TD_MAX_TRANSFER (4 * 1024)
    4547
    4648typedef struct td {
  • uspace/drv/ohci/ohci_regs.h

    r160b75e r293de44  
    3636#include <stdint.h>
    3737
    38 typedef struct ohci_regs
    39 {
     38/** OHCI memory mapped registers structure */
     39typedef struct ohci_regs {
    4040        const volatile uint32_t revision;
    4141        volatile uint32_t control;
  • uspace/drv/uhci-hcd/batch.c

    r160b75e r293de44  
    4545#define DEFAULT_ERROR_COUNT 3
    4646
     47/** UHCI specific data required for USB transfer */
    4748typedef struct uhci_transfer_batch {
     49        /** Queue head
     50         * This QH is used to maintain UHCI schedule structure and the element
     51         * pointer points to the first TD of this batch.
     52         */
    4853        qh_t *qh;
     54        /** List of TDs needed for the transfer */
    4955        td_t *tds;
     56        /** Number of TDs used by the transfer */
     57        size_t td_count;
     58        /** Data buffer, must be accessible by the UHCI hw */
    5059        void *device_buffer;
    51         size_t td_count;
    5260} uhci_transfer_batch_t;
    5361/*----------------------------------------------------------------------------*/
    54 static void uhci_transfer_batch_dispose(void *uhci_batch)
    55 {
    56         uhci_transfer_batch_t *instance = uhci_batch;
    57         assert(instance);
    58         free32(instance->device_buffer);
    59         free(instance);
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 
    6362static void batch_control(usb_transfer_batch_t *instance,
    6463    usb_packet_id data_stage, usb_packet_id status_stage);
    6564static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    66 
     65/*----------------------------------------------------------------------------*/
     66/** Safely destructs uhci_transfer_batch_t structure
     67 *
     68 * @param[in] uhci_batch Instance to destroy.
     69 */
     70static void uhci_transfer_batch_dispose(void *uhci_batch)
     71{
     72        uhci_transfer_batch_t *instance = uhci_batch;
     73        assert(instance);
     74        free32(instance->device_buffer);
     75        free(instance);
     76}
     77/*----------------------------------------------------------------------------*/
    6778/** Allocate memory and initialize internal data structure.
    6879 *
     
    8495 */
    8596usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    86     char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     97    char *buffer, size_t buffer_size,
     98    const char* setup_buffer, size_t setup_size,
    8799    usbhc_iface_transfer_in_callback_t func_in,
    88100    usbhc_iface_transfer_out_callback_t func_out, void *arg)
     
    173185                instance->error = td_status(&data->tds[i]);
    174186                if (instance->error != EOK) {
    175                         usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n",
    176                             instance, i, data->tds[i].status);
     187                        usb_log_debug("Batch(%p) found error TD(%zu):%"
     188                            PRIx32 ".\n", instance, i, data->tds[i].status);
    177189                        td_print_status(&data->tds[i]);
    178190
     
    397409/*----------------------------------------------------------------------------*/
    398410/** Provides access to QH data structure.
     411 *
    399412 * @param[in] instance Batch pointer to use.
    400413 * @return Pointer to the QH used by the batch.
  • uspace/drv/uhci-hcd/batch.h

    r160b75e r293de44  
    4545usb_transfer_batch_t * batch_get(
    4646    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
    47     char *setup_buffer, size_t setup_size,
     47    const char *setup_buffer, size_t setup_size,
    4848    usbhc_iface_transfer_in_callback_t func_in,
    4949    usbhc_iface_transfer_out_callback_t func_out,
     
    5555
    5656void batch_control_write(usb_transfer_batch_t *instance);
    57 
    5857void batch_control_read(usb_transfer_batch_t *instance);
    5958
    6059void batch_interrupt_in(usb_transfer_batch_t *instance);
    61 
    6260void batch_interrupt_out(usb_transfer_batch_t *instance);
    6361
    6462void batch_bulk_in(usb_transfer_batch_t *instance);
    65 
    6663void batch_bulk_out(usb_transfer_batch_t *instance);
    6764
  • uspace/drv/uhci-hcd/hc.c

    r160b75e r293de44  
    5757static int hc_debug_checker(void *arg);
    5858/*----------------------------------------------------------------------------*/
    59 /** Initialize UHCI hcd driver structure
     59/** Initialize UHCI hc driver structure
    6060 *
    6161 * @param[in] instance Memory place to initialize.
  • uspace/drv/uhci-hcd/hc.h

    r160b75e r293de44  
    9595#define UHCI_NEEDED_IRQ_COMMANDS 5
    9696
    97 /* Main HC driver structure */
     97/** Main UHCI driver structure */
    9898typedef struct hc {
    9999        /** USB bus driver, devices and addresses */
  • uspace/drv/uhci-hcd/transfer_list.c

    r160b75e r293de44  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "transfer_list.h"
     
    7172 * @param[in] instance Memory place to use.
    7273 *
    73  * Frees memory for internal qh_t structure.
     74 * Frees memory of the internal qh_t structure.
    7475 */
    7576void transfer_list_fini(transfer_list_t *instance)
     
    126127        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    127128
     129        /* Make sure all data in the batch are written */
     130        write_barrier();
     131
    128132        /* keep link */
    129133        batch_qh(batch)->next = last_qh->next;
    130134        qh_set_next_qh(last_qh, batch_qh(batch));
    131135
    132         asm volatile ("": : :"memory");
     136        /* Make sure the pointer is updated */
     137        write_barrier();
    133138
    134139        /* Add to the driver list */
     
    222227            == addr_to_phys(batch_qh(batch)));
    223228        prev_qh->next = batch_qh(batch)->next;
    224         asm volatile ("": : :"memory");
     229
     230        /* Make sure the pointer is updated */
     231        write_barrier();
     232
    225233        /* Remove from the batch list */
    226234        list_remove(&batch->link);
  • uspace/drv/uhci-hcd/transfer_list.h

    r160b75e r293de44  
    4343 * of currently executed transfers
    4444 */
    45 typedef struct transfer_list
    46 {
     45typedef struct transfer_list {
    4746        /** Guard against multiple add/remove races */
    4847        fibril_mutex_t guard;
  • uspace/drv/uhci-hcd/utils/malloc32.h

    r160b75e r293de44  
    7474        if (size <= SLAB_ELEMENT_SIZE)
    7575                return slab_malloc_g();
    76         assert(false);
     76        usb_log_warning("Requested %zu bytes, current allocator can't handle "
     77            "that amount, pray that the standard malloc will suffice.", size);
    7778        return memalign(UHCI_STRCUTURES_ALIGNMENT, size);
    7879}
  • uspace/drv/uhci-rhd/port.c

    r160b75e r293de44  
    227227                while (uhci_port_read_status(port) & STATUS_IN_RESET);
    228228        }
     229        /* PIO delay, should not be longer than 3ms as the device might
     230         * enter suspend state. */
    229231        udelay(10);
    230232        /* Enable the port. */
    231233        uhci_port_set_enabled(port, true);
    232 
    233         /* Reset recovery period,
    234          * devices do not have to respond during this period
    235          */
    236         async_usleep(10000);
    237234        return EOK;
    238235}
  • uspace/drv/usbhid/Makefile

    r160b75e r293de44  
    5757        generic/hiddev.c \
    5858        mouse/mousedev.c \
    59         lgtch-ultrax/lgtch-ultrax.c \
    60         lgtch-ultrax/keymap.c \
     59        multimedia/multimedia.c \
     60        multimedia/keymap.c \
    6161        $(STOLEN_LAYOUT_SOURCES)
    6262
  • uspace/drv/usbhid/generic/hiddev.c

    r160b75e r293de44  
    162162/*----------------------------------------------------------------------------*/
    163163
    164 int usb_generic_hid_init(usb_hid_dev_t *hid_dev)
     164int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
    165165{
    166166        if (hid_dev == NULL) {
     
    173173/*----------------------------------------------------------------------------*/
    174174
    175 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
     175bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data,
    176176    uint8_t *buffer, size_t buffer_size)
    177177{
  • uspace/drv/usbhid/generic/hiddev.h

    r160b75e r293de44  
    4848/*----------------------------------------------------------------------------*/
    4949
    50 int usb_generic_hid_init(struct usb_hid_dev *hid_dev);
     50int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
    5151
    52 bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     52bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, void *data,
    5353    uint8_t *buffer, size_t buffer_size);
    5454
  • uspace/drv/usbhid/kbd/kbddev.c

    r160b75e r293de44  
    252252        sysarg_t method = IPC_GET_IMETHOD(*icall);
    253253       
    254         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    255        
    256         if (hid_dev == NULL || hid_dev->data == NULL) {
     254        usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
     255        if (kbd_dev == NULL) {
    257256                usb_log_debug("default_connection_handler: "
    258257                    "Missing parameter.\n");
     
    260259                return;
    261260        }
    262        
    263         assert(hid_dev != NULL);
    264         assert(hid_dev->data != NULL);
    265         usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
    266261
    267262        if (method == IPC_M_CONNECT_TO_ME) {
     
    313308        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    314309            hid_dev->report, NULL, kbd_dev->led_path,
    315             USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END,
     310            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    316311            USB_HID_REPORT_TYPE_OUTPUT);
    317312       
    318         while (field != NULL) {
    319 
     313        while (field != NULL) {         
     314               
    320315                if ((field->usage == USB_HID_LED_NUM_LOCK)
    321316                    && (kbd_dev->mods & KM_NUM_LOCK)){
     
    334329               
    335330                field = usb_hid_report_get_sibling(hid_dev->report, field,
    336                     kbd_dev->led_path, USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY
    337                     | USB_HID_PATH_COMPARE_END, USB_HID_REPORT_TYPE_OUTPUT);
     331                    kbd_dev->led_path, 
     332                USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     333                        USB_HID_REPORT_TYPE_OUTPUT);
    338334        }
    339335       
     
    662658 *     usb_hid_parse_report().
    663659 */
    664 static void usb_kbd_process_data(usb_hid_dev_t *hid_dev,
     660static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
    665661                                 uint8_t *buffer, size_t actual_size)
    666662{
    667663        assert(hid_dev->report != NULL);
    668664        assert(hid_dev != NULL);
    669         assert(hid_dev->data != NULL);
    670        
    671         usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
     665        assert(kbd_dev != NULL);
    672666
    673667        usb_log_debug("Calling usb_hid_parse_report() with "
     
    774768/*----------------------------------------------------------------------------*/
    775769
    776 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev)
     770static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    777771{
    778772        assert(hid_dev != NULL);
    779773        assert(hid_dev->usb_dev != NULL);
     774        assert(kbd_dev != NULL);
    780775       
    781776        /* Create the function exposed under /dev/devices. */
     
    792787         * to the DDF function.
    793788         */
    794         fun->ops = &hid_dev->ops;
    795         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     789        fun->ops = &kbd_dev->ops;
     790        fun->driver_data = kbd_dev;
    796791
    797792        int rc = ddf_fun_bind(fun);
     
    840835 * @return Other value inherited from function usbhid_dev_init().
    841836 */
    842 int usb_kbd_init(usb_hid_dev_t *hid_dev)
     837int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
    843838{
    844839        usb_log_debug("Initializing HID/KBD structure...\n");
     
    865860        usb_hid_report_path_set_report_id(path, 0);
    866861       
    867         kbd_dev->key_count = usb_hid_report_input_length(
    868             hid_dev->report, path,
    869             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     862        kbd_dev->key_count = usb_hid_report_size(
     863            hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
    870864        usb_hid_report_path_free(path);
    871865       
     
    908902            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    909903       
    910         kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report,
    911             kbd_dev->led_path,
    912             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
     904        kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report,
     905            0, USB_HID_REPORT_TYPE_OUTPUT);
    913906       
    914907        usb_log_debug("Output report size (in items): %zu\n",
     
    955948       
    956949        // save the KBD device structure into the HID device structure
    957         hid_dev->data = kbd_dev;
     950        //hid_dev->data = kbd_dev;
     951        *data = kbd_dev;
    958952       
    959953        // set handler for incoming calls
    960         hid_dev->ops.default_handler = default_connection_handler;
     954        kbd_dev->ops.default_handler = default_connection_handler;
    961955       
    962956        /*
     
    983977       
    984978        usb_log_debug("Creating KBD function...\n");
    985         int rc = usb_kbd_create_function(hid_dev);
     979        int rc = usb_kbd_create_function(hid_dev, kbd_dev);
    986980        if (rc != EOK) {
    987981                usb_kbd_free(&kbd_dev);
     
    994988/*----------------------------------------------------------------------------*/
    995989
    996 bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
    997      size_t buffer_size)
    998 {
    999         if (hid_dev == NULL || buffer == NULL) {
     990bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data,
     991     uint8_t *buffer, size_t buffer_size)
     992{
     993        if (hid_dev == NULL || buffer == NULL || data == NULL) {
    1000994                // do not continue polling (???)
    1001995                return false;
    1002996        }
    1003997       
     998        usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     999        assert(kbd_dev != NULL);
     1000       
    10041001        // TODO: add return value from this function
    1005         usb_kbd_process_data(hid_dev, buffer, buffer_size);
     1002        usb_kbd_process_data(hid_dev, kbd_dev, buffer, buffer_size);
    10061003       
    10071004        return true;
     
    10661063/*----------------------------------------------------------------------------*/
    10671064
    1068 void usb_kbd_deinit(usb_hid_dev_t *hid_dev)
     1065void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
    10691066{
    10701067        if (hid_dev == NULL) {
     
    10721069        }
    10731070       
    1074         if (hid_dev->data != NULL) {
    1075                 usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
     1071        if (data != NULL) {
     1072                usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    10761073                if (usb_kbd_is_initialized(kbd_dev)) {
    10771074                        usb_kbd_mark_unusable(kbd_dev);
    10781075                } else {
    10791076                        usb_kbd_free(&kbd_dev);
    1080                         hid_dev->data = NULL;
    10811077                }
    10821078        }
  • uspace/drv/usbhid/kbd/kbddev.h

    r160b75e r293de44  
    8383        int console_phone;
    8484       
     85        /** @todo What is this actually? */
     86        ddf_dev_ops_t ops;
     87       
    8588        /** Information for auto-repeat of keys. */
    8689        usb_kbd_repeat_t repeat;
     
    117120/*----------------------------------------------------------------------------*/
    118121
    119 int usb_kbd_init(struct usb_hid_dev *hid_dev);
     122int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
    120123
    121 bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
    122     size_t buffer_size);
     124bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, void *data,
     125                              uint8_t *buffer, size_t buffer_size);
    123126
    124127int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
     
    131134    int type, unsigned int key);
    132135
    133 void usb_kbd_deinit(struct usb_hid_dev *hid_dev);
     136void usb_kbd_deinit(struct usb_hid_dev *hid_dev, void *data);
    134137
    135138int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
  • uspace/drv/usbhid/mouse/mousedev.c

    r160b75e r293de44  
    122122        sysarg_t method = IPC_GET_IMETHOD(*icall);
    123123       
    124         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    125        
    126         if (hid_dev == NULL || hid_dev->data == NULL) {
     124        usb_mouse_t *mouse_dev = (usb_mouse_t *)fun->driver_data;
     125       
     126        if (mouse_dev == NULL) {
    127127                usb_log_debug("default_connection_handler: Missing "
    128128                    "parameters.\n");
     
    131131        }
    132132       
    133         assert(hid_dev != NULL);
    134         assert(hid_dev->data != NULL);
    135         usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
     133        usb_log_debug("default_connection_handler: fun->name: %s\n",
     134                      fun->name);
     135        usb_log_debug("default_connection_handler: mouse_phone: %d, wheel "
     136            "phone: %d\n", mouse_dev->mouse_phone, mouse_dev->wheel_phone);
    136137       
    137138        int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0)
     
    145146                            "phone to mouse already set.\n");
    146147                        async_answer_0(icallid, ELIMIT);
    147                         //async_answer_0(icallid, EOK);
    148148                        return;
    149149                }
    150150
    151151                *phone = callback;
    152                 usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
     152                usb_log_debug("Console phone to mouse set ok (%d).\n", *phone);
    153153                async_answer_0(icallid, EOK);
    154154                return;
     
    224224/*----------------------------------------------------------------------------*/
    225225
    226 static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev, uint8_t *buffer,
    227     size_t buffer_size)
    228 {
    229         usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
     226static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
     227                                     usb_mouse_t *mouse_dev, uint8_t *buffer,
     228                                     size_t buffer_size)
     229{
     230        assert(mouse_dev != NULL);
    230231       
    231232        usb_log_debug2("got buffer: %s.\n",
     
    378379/*----------------------------------------------------------------------------*/
    379380
    380 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev)
    381 {
     381static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
     382{
     383        assert(hid_dev != NULL);
     384        assert(mouse != NULL);
     385       
    382386        /* Create the function exposed under /dev/devices. */
    383387        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
     
    389393        }
    390394       
    391         /*
    392          * Store the initialized HID device and HID ops
    393          * to the DDF function.
    394          */
    395         fun->ops = &hid_dev->ops;
    396         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     395        fun->ops = &mouse->ops;
     396        fun->driver_data = mouse;   // TODO: maybe change to hid_dev->data
    397397
    398398        int rc = ddf_fun_bind(fun);
     
    431431         * to the DDF function.
    432432         */
    433         fun->ops = &hid_dev->ops;
    434         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
     433        fun->ops = &mouse->ops;
     434        fun->driver_data = mouse;   // TODO: maybe change to hid_dev->data
    435435
    436436        rc = ddf_fun_bind(fun);
     
    458458/*----------------------------------------------------------------------------*/
    459459
    460 int usb_mouse_init(usb_hid_dev_t *hid_dev)
     460int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    461461{
    462462        usb_log_debug("Initializing HID/Mouse structure...\n");
     
    485485       
    486486        // save the Mouse device structure into the HID device structure
    487         hid_dev->data = mouse_dev;
     487        *data = mouse_dev;
    488488       
    489489        // set handler for incoming calls
    490         hid_dev->ops.default_handler = default_connection_handler;
     490        // TODO: must be one for each subdriver!!
     491        mouse_dev->ops.default_handler = default_connection_handler;
    491492       
    492493        // TODO: how to know if the device supports the request???
     
    494495//          hid_dev->usb_dev->interface_no, IDLE_RATE);
    495496       
    496         int rc = usb_mouse_create_function(hid_dev);
     497        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    497498        if (rc != EOK) {
    498499                usb_mouse_free(&mouse_dev);
     
    505506/*----------------------------------------------------------------------------*/
    506507
    507 bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
    508      size_t buffer_size)
     508bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data,
     509     uint8_t *buffer, size_t buffer_size)
    509510{
    510511        usb_log_debug("usb_mouse_polling_callback()\n");
    511512        usb_debug_str_buffer(buffer, buffer_size, 0);
    512513       
    513         if (hid_dev == NULL) {
     514        if (hid_dev == NULL || data == NULL) {
    514515                usb_log_error("Missing argument to the mouse polling callback."
    515516                    "\n");
     
    517518        }
    518519       
    519         if (hid_dev->data == NULL) {
    520                 usb_log_error("Wrong argument to the mouse polling callback."
    521                     "\n");
    522                 return false;
    523         }
    524        
    525         return usb_mouse_process_report(hid_dev, buffer, buffer_size);
    526 }
    527 
    528 /*----------------------------------------------------------------------------*/
    529 
    530 void usb_mouse_deinit(usb_hid_dev_t *hid_dev)
    531 {
    532         usb_mouse_free((usb_mouse_t **)&hid_dev->data);
     520        usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
     521               
     522        return usb_mouse_process_report(hid_dev, mouse_dev, buffer,
     523                                        buffer_size);
     524}
     525
     526/*----------------------------------------------------------------------------*/
     527
     528void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
     529{
     530        if (data != NULL) {
     531                usb_mouse_free((usb_mouse_t **)&data);
     532        }
    533533}
    534534
  • uspace/drv/usbhid/mouse/mousedev.h

    r160b75e r293de44  
    5252       
    5353        int32_t *buttons;
     54       
     55        ddf_dev_ops_t ops;
    5456} usb_mouse_t;
    5557
     
    6365/*----------------------------------------------------------------------------*/
    6466
    65 int usb_mouse_init(struct usb_hid_dev *hid_dev);
     67int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
    6668
    67 bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
    68     size_t buffer_size);
     69bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, void *data,
     70    uint8_t *buffer, size_t buffer_size);
    6971
    70 void usb_mouse_deinit(struct usb_hid_dev *hid_dev);
     72void usb_mouse_deinit(struct usb_hid_dev *hid_dev, void *data);
    7173
    7274int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
  • uspace/drv/usbhid/subdrivers.c

    r160b75e r293de44  
    3838#include <usb/hid/hidpath.h>
    3939
    40 #include "lgtch-ultrax/lgtch-ultrax.h"
     40//#include "lgtch-ultrax/lgtch-ultrax.h"
     41#include "multimedia/multimedia.h"
    4142#include "mouse/mousedev.h"
    4243
    4344static usb_hid_subdriver_usage_t path_kbd[] = {
    44         {USB_HIDUT_PAGE_KEYBOARD, 0},
     45        {USB_HIDUT_PAGE_GENERIC_DESKTOP,
     46         USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD},
    4547        {0, 0}
    4648};
    4749
    48 static usb_hid_subdriver_usage_t path_mouse2[] = {
    49         {USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_X},
     50static usb_hid_subdriver_usage_t path_mouse[] = {
     51        {USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE},
    5052        {0, 0}
    5153};
    5254
    53 static usb_hid_subdriver_usage_t lgtch_path[] = {
    54         {0xc, 0},
     55static usb_hid_subdriver_usage_t multim_key_path[] = {
     56        {USB_HIDUT_PAGE_CONSUMER, USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL},
    5557        {0, 0}
    5658};
     
    6062                path_kbd,
    6163                -1,
    62                 USB_HID_PATH_COMPARE_END
    63                 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     64                USB_HID_PATH_COMPARE_BEGIN,
    6465                -1,
    6566                -1,
     
    7374        },
    7475        {
    75                 lgtch_path,
     76                multim_key_path,
    7677                1,
    77                 USB_HID_PATH_COMPARE_END
    78                 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    79                 0x046d,
    80                 0xc30e,
     78                USB_HID_PATH_COMPARE_BEGIN,
     79                -1,
     80                -1,
    8181                {
    82                         .init = usb_lgtch_init,
    83                         .deinit = usb_lgtch_deinit,
    84                         .poll = usb_lgtch_polling_callback,
     82                        .init = usb_multimedia_init,
     83                        .deinit = usb_multimedia_deinit,
     84                        .poll = usb_multimedia_polling_callback,
    8585                        .poll_end = NULL
    8686                }
    8787        },
    8888        {
    89                 path_mouse2,
     89                path_mouse,
    9090                -1,
    91                 USB_HID_PATH_COMPARE_END
    92                 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     91                USB_HID_PATH_COMPARE_BEGIN,
    9392                -1,
    9493                -1,
     
    10099                }
    101100        },
    102         {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}}
     101        {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
    103102};
    104103
  • uspace/drv/usbhid/usbhid.c

    r160b75e r293de44  
    203203       
    204204        usb_log_debug("Compare flags: %d\n", mapping->compare);
    205         size_t size = usb_hid_report_input_length(hid_dev->report, usage_path,
    206             mapping->compare);
     205//      size_t size = usb_hid_report_size(hid_dev->report, 0,
     206//          USB_HID_REPORT_TYPE_INPUT);
     207        size_t size = 0;
     208        usb_hid_report_field_t *field = usb_hid_report_get_sibling (hid_dev->report,
     209                NULL, usage_path, mapping->compare, USB_HID_REPORT_TYPE_INPUT);
     210        while(field != NULL) {
     211                size++;
     212                field = usb_hid_report_get_sibling (hid_dev->report,
     213                                        field, usage_path, mapping->compare,
     214                            USB_HID_REPORT_TYPE_INPUT);
     215        }
     216       
    207217        usb_log_debug("Size of the input report: %zuB\n", size);
    208        
    209218        usb_hid_report_path_free(usage_path);
    210219       
     
    457466                        if (hid_dev->subdrivers[i].init != NULL) {
    458467                                usb_log_debug("Initializing subdriver %d.\n",i);
    459                                 rc = hid_dev->subdrivers[i].init(hid_dev);
     468                                rc = hid_dev->subdrivers[i].init(hid_dev,
     469                                    &hid_dev->subdrivers[i].data);
    460470                                if (rc != EOK) {
    461471                                        usb_log_warning("Failed to initialize"
     
    522532        for (i = 0; i < hid_dev->subdriver_count; ++i) {
    523533                if (hid_dev->subdrivers[i].poll != NULL
    524                     && hid_dev->subdrivers[i].poll(hid_dev, buffer,
    525                     buffer_size)) {
     534                    && hid_dev->subdrivers[i].poll(hid_dev,
     535                        hid_dev->subdrivers[i].data, buffer, buffer_size)) {
    526536                        cont = true;
    527537                }
     
    546556        for (i = 0; i < hid_dev->subdriver_count; ++i) {
    547557                if (hid_dev->subdrivers[i].poll_end != NULL) {
    548                         hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     558                        hid_dev->subdrivers[i].poll_end(hid_dev,
     559                            hid_dev->subdrivers[i].data, reason);
    549560                }
    550561        }
     
    627638        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
    628639                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
    629                         (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     640                        (*hid_dev)->subdrivers[i].deinit(*hid_dev,
     641                            (*hid_dev)->subdrivers[i].data);
    630642                }
    631643        }
  • uspace/drv/usbhid/usbhid.h

    r160b75e r293de44  
    4848struct usb_hid_dev;
    4949
    50 typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *);
    51 typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *);
    52 typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, uint8_t *, size_t);
    53 typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, bool reason);
     50typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *, void **data);
     51typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *, void *data);
     52typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, void *data, uint8_t *,
     53                                    size_t);
     54typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, void *data,
     55                                         bool reason);
    5456
    5557// TODO: add function and class name??
     
    6365        /** Function to be called when polling ends. */
    6466        usb_hid_driver_poll_ended poll_end;
     67        /** Arbitrary data needed by the subdriver. */
     68        void *data;
    6569} usb_hid_subdriver_t;
    6670
     
    7276        /** Structure holding generic USB device information. */
    7377        usb_device_t *usb_dev;
    74        
    75         /** @todo What is this actually? */
    76         ddf_dev_ops_t ops;
    7778       
    7879        /** Index of the polling pipe in usb_hid_endpoints array. */
     
    9798       
    9899        size_t input_report_size;
    99        
    100         /** Arbitrary data (e.g. a special structure for handling keyboard). */
    101         void *data;
    102100} usb_hid_dev_t;
    103101
  • uspace/lib/usbdev/src/hub.c

    r160b75e r293de44  
    4141#include <assert.h>
    4242#include <usb/debug.h>
     43#include <time.h>
    4344
    4445/** How much time to wait between attempts to register endpoint 0:0.
     
    218219
    219220        int rc;
     221        struct timeval start_time;
     222
     223        rc = gettimeofday(&start_time, NULL);
     224        if (rc != EOK) {
     225                return rc;
     226        }
    220227
    221228        rc = usb_hc_connection_open(&hc_conn);
     
    264271                }
    265272        } while (rc != EOK);
     273        struct timeval end_time;
     274
     275        rc = gettimeofday(&end_time, NULL);
     276        if (rc != EOK) {
     277                goto leave_release_default_address;
     278        }
     279
     280        /* According to the USB spec part 9.1.2 host allows 100ms time for
     281         * the insertion process to complete. According to 7.1.7.1 this is the
     282         * time between attach detected and port reset. However, the setup done
     283         * above might use much of this time so we should only wait to fill
     284         * up the 100ms quota*/
     285        suseconds_t elapsed = tv_sub(&end_time, &start_time);
     286        if (elapsed < 100000) {
     287                async_usleep(100000 - elapsed);
     288        }
    266289
    267290        /*
     
    273296                goto leave_release_default_address;
    274297        }
     298        /* USB spec 7.1.7.1: The USB System Software guarantees a minimum of
     299         * 10ms for reset recovery. Device response to any bus transactions
     300         * addressed to the default device address during the reset recovery
     301         * time is undefined.
     302         */
     303        async_usleep(10000);
    275304
    276305        rc = usb_pipe_probe_default_control(&ctrl_pipe);
  • uspace/lib/usbhid/include/usb/hid/hid_report_items.h

    r160b75e r293de44  
    4646#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
    4747
     48
     49/**
     50 * Extended usage macros
     51 */
     52#define USB_HID_IS_EXTENDED_USAGE(usage)        ((usage & 0xFFFF0000) != 0)
     53#define USB_HID_EXTENDED_USAGE_PAGE(usage)      ((usage & 0xFFFF0000) >> 16)
     54#define USB_HID_EXTENDED_USAGE(usage)           (usage & 0xFFFF)
    4855
    4956/**
  • uspace/lib/usbhid/include/usb/hid/hidparser.h

    r160b75e r293de44  
    5151                         size_t size, uint8_t *report_id);
    5252
    53 /** */
    54 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    55         usb_hid_report_path_t *path, int flags);
    56 
    5753/*
    5854 * Output report parser functions
     
    6561void usb_hid_report_output_free(uint8_t *output);
    6662
    67 /** Returns size of output for given usage path */
    68 size_t usb_hid_report_output_size(usb_hid_report_t *report,
    69                                   usb_hid_report_path_t *path, int flags);
     63/** Returns size of report in items */
     64size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
     65                           usb_hid_report_type_t type);
    7066
    7167/** Makes the output report buffer by translated given data */
  • uspace/lib/usbhid/include/usb/hid/hidtypes.h

    r160b75e r293de44  
    3939#include <adt/list.h>
    4040
    41 #define USB_HID_MAX_USAGES      20
     41#define USB_HID_MAX_USAGES      0xffff
    4242
    4343#define USB_HID_UINT32_TO_INT32(x, size)        ((((x) & (1 << ((size) - 1))) != 0) ? -(~(x - 1) & ((1 << size) - 1)) : (x)) //(-(~((x) - 1)))
     
    9292        int32_t physical_minimum;
    9393        int32_t physical_maximum;
    94         uint32_t usage_minimum;
    95         uint32_t usage_maximum;
     94        int32_t usage_minimum;
     95        int32_t usage_maximum;
    9696        uint32_t unit;
    9797        uint32_t unit_exponent;
    98        
     98
     99        uint32_t *usages;
     100        size_t usages_count;
    99101
    100102        int32_t value;
     
    121123
    122124        /** */ 
    123         uint32_t usage_minimum;
    124         /** */ 
    125         uint32_t usage_maximum;
     125        int32_t usage_minimum;
     126        /** */ 
     127        int32_t usage_maximum;
    126128        /** */ 
    127129        int32_t logical_minimum;
  • uspace/lib/usbhid/include/usb/hid/usages/core.h

    r160b75e r293de44  
    6767} usb_hidut_usage_generic_desktop_t;
    6868
     69typedef enum {
     70        USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL = 1
     71} usb_hidut_usage_consumer_t;
     72
    6973
    7074#endif
  • uspace/lib/usbhid/src/hiddescriptor.c

    r160b75e r293de44  
    6464{
    6565        /* find or append current collection path to the list */
    66         link_t *path_it = report->collection_paths.next;
     66        //link_t *path_it = report->collection_paths.next;
     67        link_t *path_it = report->collection_paths.prev->next;
    6768        usb_hid_report_path_t *path = NULL;
     69       
     70       
    6871        while(path_it != &report->collection_paths) {
    6972                path = list_get_instance(path_it, usb_hid_report_path_t, link);
     
    116119        int i;
    117120
    118         for(i=0; i<report_item->usages_count; i++){
    119                 usb_log_debug("usages (%d) - %x\n", i, report_item->usages[i]);
    120         }
    121 
     121        uint32_t *usages;
     122        int usages_used=0;
     123        if(report_item->usages_count > 0){
     124                usages = malloc(sizeof(int32_t) * report_item->usages_count);
     125                memcpy(usages, report_item->usages, sizeof(int32_t) * report_item->usages_count);
     126        }
     127        else {
     128                usages = NULL;
     129        }
     130       
    122131        usb_hid_report_path_t *path = report_item->usage_path; 
    123132        for(i=0; i<report_item->count; i++){
     
    133142                field->physical_maximum = report_item->physical_maximum;
    134143
    135                 field->usage_minimum = report_item->usage_minimum;
    136                 field->usage_maximum = report_item->usage_maximum;
    137                 if(report_item->extended_usage_page != 0){
    138                         field->usage_page = report_item->extended_usage_page;
     144                if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0){
     145                        /*
     146                                Store usage array. The Correct Usage Page and Usage is depending
     147                                on data in report and will be filled later
     148                        */
     149                        field->usage = 0;
     150                        field->usage_page = 0; //report_item->usage_page;
     151
     152                        field->usages_count = report_item->usages_count;
     153                        field->usages = usages;
     154                        usages_used = 1;
    139155                }
    140156                else {
    141                         field->usage_page = report_item->usage_page;
    142                 }
    143 
    144                 if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
    145                         uint32_t usage;
    146                         if(i < report_item->usages_count){
     157
     158                        /* Fill the correct Usage and Usage Page */
     159                        int32_t usage;
     160                        if(i < report_item->usages_count) {
    147161                                usage = report_item->usages[i];
    148162                        }
     
    151165                        }
    152166
    153                                                
    154                         if((usage & 0xFFFF0000) != 0){
    155                                 field->usage_page = (usage >> 16);                                     
    156                                 field->usage = (usage & 0xFFFF);
     167                        if(USB_HID_IS_EXTENDED_USAGE(usage)){
     168                                field->usage = USB_HID_EXTENDED_USAGE(usage);
     169                                field->usage_page = USB_HID_EXTENDED_USAGE_PAGE(usage);
    157170                        }
    158171                        else {
     172                                // should not occur
    159173                                field->usage = usage;
    160                         }
    161 
    162                        
    163                 }       
    164 
    165                 if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
    166                         field->usage = report_item->usage_minimum + i;                                 
     174                                field->usage_page = report_item->usage_page;
     175                        }
    167176                }
    168177               
     
    209218        }
    210219
     220        // free only when not used!!!
     221        if(usages && usages_used == 0) {
     222                free(usages);
     223        }
    211224
    212225        return EOK;
     
    450463                       
    451464                case USB_HID_REPORT_TAG_COLLECTION:
     465
    452466                        // store collection atributes
    453467                        path_item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
     
    455469                       
    456470                        // set last item
    457                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, report_item->usage_page);
    458                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, report_item->usages[report_item->usages_count-1]);
     471                        usb_hid_report_set_last_item(usage_path,
     472                                                     USB_HID_TAG_CLASS_GLOBAL,
     473                                                     USB_HID_EXTENDED_USAGE_PAGE(report_item->usages[report_item->usages_count-1]));
     474                        usb_hid_report_set_last_item(usage_path,
     475                                                     USB_HID_TAG_CLASS_LOCAL,
     476                                                     USB_HID_EXTENDED_USAGE(report_item->usages[report_item->usages_count-1]));
    459477                       
    460478                        // append the new one which will be set by common
     
    551569                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    552570{
     571        int32_t extended_usage;
     572       
    553573        switch(tag) {
    554574                case USB_HID_REPORT_TAG_USAGE:
     
    560580                                        report_item->in_delimiter = INSIDE_DELIMITER_SET;
    561581                                case OUTSIDE_DELIMITER_SET:
    562                                         report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
     582                                        extended_usage = ((report_item->usage_page) << 16);
     583                                        extended_usage += usb_hid_report_tag_data_uint32(data,item_size);
     584                                        report_item->usages[report_item->usages_count] = extended_usage;
    563585                                        report_item->usages_count++;
    564586                                        break;
    565587                        }
    566588                        break;
    567                 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
     589                case USB_HID_REPORT_TAG_USAGE_MINIMUM:                 
    568590                        if (item_size == 3) {
    569591                                // usage extended usages
     
    577599                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    578600                        if (item_size == 3) {
     601
     602                                if(report_item->extended_usage_page != ((usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16)) {
     603                                        return EINVAL;
     604                                }
     605                               
    579606                                // usage extended usages
    580607                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     
    584611                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    585612                        }
     613
     614                        // vlozit zaznamy do pole usages
     615                        int32_t i;
     616                        for(i=report_item->usage_minimum; i<=report_item->usage_maximum; i++) {
     617                                if(report_item->extended_usage_page) {
     618                                        report_item->usages[report_item->usages_count++] = (report_item->extended_usage_page << 16) + i;
     619                                }
     620                                else {
     621                                       
     622                                        report_item->usages[report_item->usages_count++] = (report_item->usage_page << 16) + i;
     623                                }
     624                        }
     625                        report_item->extended_usage_page = 0;
     626                       
    586627                        break;
    587628                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
     
    663704                usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
    664705                usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
     706                usb_log_debug("\t\tUSAGES COUNT: %zu\n", report_item->usages_count);
    665707
    666708                usb_log_debug("\t\tVALUE: %X\n", report_item->value);
     
    668710                usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
    669711               
    670                 //usb_hid_print_usage_path(report_item->collection_path);
     712                usb_hid_print_usage_path(report_item->collection_path);
    671713
    672714                usb_log_debug("\n");           
     
    700742                usb_hid_descriptor_print_list(&report_des->report_items);
    701743
    702 
     744/*
    703745                link_t *path_it = report->collection_paths.next;
    704746                while(path_it != &report->collection_paths) {
     
    706748                        path_it = path_it->next;
    707749                }
    708                
     750*/             
    709751                report_it = report_it->next;
    710752        }
  • uspace/lib/usbhid/src/hidparser.c

    r160b75e r293de44  
    6969
    7070
     71/** Returns size of report of specified report id and type in items
     72 *
     73 * @param parser Opaque report parser structure
     74 * @param report_id
     75 * @param type
     76 * @return Number of items in specified report
     77 */
     78size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
     79                           usb_hid_report_type_t type)
     80{
     81        usb_hid_report_description_t *report_des;
     82
     83        if(report == NULL) {
     84                return 0;
     85        }
     86
     87        report_des = usb_hid_report_find_description (report, report_id, type);
     88        if(report_des == NULL){
     89                return 0;
     90        }
     91        else {
     92                return report_des->item_length;
     93        }
     94}
    7195
    7296
     
    87111        usb_hid_report_description_t *report_des;
    88112        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
    89 
     113       
    90114        if(report == NULL) {
    91115                return EINVAL;
     
    114138                                // array
    115139                                item->value = usb_hid_translate_data(item, data);
    116                             item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     140               
     141                                item->usage = USB_HID_EXTENDED_USAGE(item->usages[item->value - item->physical_minimum]);
     142                                item->usage_page = USB_HID_EXTENDED_USAGE_PAGE(item->usages[item->value - item->physical_minimum]);                             
     143
     144                                usb_hid_report_set_last_item (item->collection_path,
     145                                                              USB_HID_TAG_CLASS_GLOBAL,
     146                                                              item->usage_page);
     147                                usb_hid_report_set_last_item (item->collection_path,
     148                                                              USB_HID_TAG_CLASS_LOCAL,
     149                                                              item->usage);
     150                               
    117151                        }
    118152                        else {
     
    123157                list_item = list_item->next;
    124158        }
    125            
     159       
    126160        return EOK;
    127161       
     
    206240}
    207241
    208 /**
    209  * Returns number of items in input report which are accessible by given usage path
    210  *
    211  * @param parser Opaque report descriptor structure
    212  * @param path Usage path specification
    213  * @param flags Usage path comparison flags
    214  * @return Number of items in input report
    215  */
    216 size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    217         usb_hid_report_path_t *path, int flags)
    218 {       
    219        
    220         size_t ret = 0;
    221 
    222         if(report == NULL) {
    223                 return 0;
    224         }
    225 
    226         usb_hid_report_description_t *report_des;
    227         report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
    228         if(report_des == NULL) {
    229                 return 0;
    230         }
    231 
    232         link_t *field_it = report_des->report_items.next;
    233         usb_hid_report_field_t *field;
    234         while(field_it != &report_des->report_items) {
    235 
    236                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
    237                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
    238                        
    239                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    240                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    241                                 ret++;
    242                         }
    243                         usb_hid_report_remove_last_item (field->collection_path);
    244                 }
    245                
    246                 field_it = field_it->next;
    247         }
    248 
    249         return ret;
    250         }
    251 
    252242/*** OUTPUT API **/
    253243
     
    304294}
    305295
    306 /** Returns size of output for given usage path
    307  *
    308  * @param parser Opaque report parser structure
    309  * @param path Usage path specified which items will be thought for the output
    310  * @param flags Flags of usage path structure comparison
    311  * @return Number of items matching the given usage path
    312  */
    313 size_t usb_hid_report_output_size(usb_hid_report_t *report,
    314                                   usb_hid_report_path_t *path, int flags)
    315 {
    316         size_t ret = 0;
    317         usb_hid_report_description_t *report_des;
    318 
    319         if(report == NULL) {
    320                 return 0;
    321         }
    322 
    323         report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
    324         if(report_des == NULL){
    325                 return 0;
    326         }
    327        
    328         link_t *field_it = report_des->report_items.next;
    329         usb_hid_report_field_t *field;
    330         while(field_it != &report_des->report_items) {
    331 
    332                 field = list_get_instance(field_it, usb_hid_report_field_t, link);
    333                 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
    334                         usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    335                         if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    336                                 ret++;
    337                         }
    338                         usb_hid_report_remove_last_item (field->collection_path);
    339                 }
    340                
    341                 field_it = field_it->next;
    342         }
    343 
    344         return ret;
    345        
    346 }
    347 
    348296/** Makes the output report buffer for data given in the report structure
    349297 *
     
    385333                report_item = list_get_instance(item, usb_hid_report_field_t, link);
    386334
    387                         if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
     335                usb_log_debug("OUTPUT ITEM usage(%x), value(%x)\n", report_item->usage, report_item->value);
     336               
     337                if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    388338                                       
    389                                 // array
    390                                 value = usb_hid_translate_data_reverse(report_item, report_item->value);
    391                                 offset = report_item->offset;
    392                                 length = report_item->size;
    393                         }
    394                         else {
    395                                 // variable item
    396                                 value  = usb_hid_translate_data_reverse(report_item, report_item->value);
    397                                 offset = report_item->offset;
    398                                 length = report_item->size;
    399                         }
    400 
    401                         if((offset/8) == ((offset+length-1)/8)) {
    402                                 // je to v jednom bytu
    403                                 if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) {
    404                                         break; // TODO ErrorCode
     339                        // array
     340                        value = usb_hid_translate_data_reverse(report_item, report_item->value);
     341                        offset = report_item->offset;
     342                        length = report_item->size;
     343                }
     344                else {
     345                        // variable item
     346                        value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     347                        offset = report_item->offset;
     348                        length = report_item->size;
     349                }
     350
     351                usb_log_debug("\ttranslated value: %x\n", value);
     352
     353                if((offset/8) == ((offset+length-1)/8)) {
     354                        // je to v jednom bytu
     355                        if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) {
     356                                break; // TODO ErrorCode
     357                        }
     358                        size_t shift = 8 - offset%8 - length;
     359                        value = value << shift;                                                 
     360                        value = value & (((1 << length)-1) << shift);
     361                               
     362                        uint8_t mask = 0;
     363                        mask = 0xff - (((1 << length) - 1) << shift);
     364                        buffer[offset/8] = (buffer[offset/8] & mask) | value;
     365                }
     366                else {
     367                        int i = 0;
     368                        uint8_t mask = 0;
     369                        for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     370                                if(i == (offset/8)) {
     371                                        tmp_value = value;
     372                                        tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     373                                        tmp_value = tmp_value << (offset%8);
     374       
     375                                        mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     376                                        buffer[i] = (buffer[i] & mask) | tmp_value;                     
    405377                                }
    406 
    407                                 size_t shift = 8 - offset%8 - length;
    408 
    409                                 value = value << shift;                                                 
    410                                 value = value & (((1 << length)-1) << shift);
     378                                else if (i == ((offset + length -1)/8)) {
     379                                       
     380                                        value = value >> (length - ((offset + length) % 8));
     381                                        value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    411382                               
    412                                 uint8_t mask = 0;
    413                                 mask = 0xff - (((1 << length) - 1) << shift);
    414                                 buffer[offset/8] = (buffer[offset/8] & mask) | value;
    415                         }
    416                         else {
    417                                 int i = 0;
    418                                 uint8_t mask = 0;
    419                                 for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
    420                                         if(i == (offset/8)) {
    421                                                 tmp_value = value;
    422                                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    423                                                 tmp_value = tmp_value << (offset%8);
    424        
    425                                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    426                                                 buffer[i] = (buffer[i] & mask) | tmp_value;                     
    427                                         }
    428                                         else if (i == ((offset + length -1)/8)) {
    429                                                
    430                                                 value = value >> (length - ((offset + length) % 8));
    431                                                 value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    432                                
    433                                                 mask = (1 << (length - ((offset + length) % 8))) - 1;
    434                                                 buffer[i] = (buffer[i] & mask) | value;
    435                                         }
    436                                         else {
    437                                                 buffer[i] = value & (0xFF << i);
    438                                         }
     383                                        mask = (1 << (length - ((offset + length) % 8))) - 1;
     384                                        buffer[i] = (buffer[i] & mask) | value;
    439385                                }
    440                         }
    441 
     386                                else {
     387                                        buffer[i] = value & (0xFF << i);
     388                                }
     389                        }
     390                }
    442391
    443392                // reset value
     
    472421        }
    473422       
    474 
    475         if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    476 
    477                 // variable item
    478                 if(item->physical_maximum == item->physical_minimum){
    479                     resolution = 1;
    480                 }
    481                 else {
    482                     resolution = (item->logical_maximum - item->logical_minimum) /
    483                         ((item->physical_maximum - item->physical_minimum) *
    484                         (usb_pow(10,(item->unit_exponent))));
    485                 }
    486 
    487                 ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum;
    488         }
    489         else {
    490                 // bitmapa
    491                 if(value == 0) {
    492                         ret = 0;
    493                 }
    494                 else {
    495                         size_t bitmap_idx = (value - item->usage_minimum);
    496                         ret = 1 << bitmap_idx;
    497                 }
    498         }
    499 
     423        // variable item
     424        if(item->physical_maximum == item->physical_minimum){
     425            resolution = 1;
     426        }
     427        else {
     428            resolution = (item->logical_maximum - item->logical_minimum) /
     429                ((item->physical_maximum - item->physical_minimum) *
     430                (usb_pow(10,(item->unit_exponent))));
     431        }
     432
     433        ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum;
     434        usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), ret(%x)\n", value, resolution, item->physical_minimum, item->logical_minimum, ret);
     435       
    500436        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
    501437                return USB_HID_INT32_TO_UINT32(ret, item->size);
    502438        }
    503         return (int32_t)ret;
     439        return (int32_t)0 + ret;
    504440}
    505441
  • uspace/lib/usbhid/src/hidpath.c

    r160b75e r293de44  
    4242
    4343
     44#define USB_HID_SAME_USAGE(usage1, usage2)      ((usage1 == usage2) || (usage1 == 0) || (usage2 == 0))
     45#define USB_HID_SAME_USAGE_PAGE(page1, page2)   ((page1 == page2) || (page1 == 0) || (page2 == 0))
     46
    4447/**
    4548 * Appends one item (couple of usage_path and usage) into the usage path
     
    203206                        while(report_link != &report_path->head) {
    204207                                report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    205                                 if(report_item->usage_page == path_item->usage_page){
     208                                if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page, path_item->usage_page)){
    206209                                        if(only_page == 0){
    207                                                 if(report_item->usage == path_item->usage) {
     210                                                if(USB_HID_SAME_USAGE(report_item->usage, path_item->usage)) {
    208211                                                        return EOK;
    209212                                                }
     
    242245                                                                      link);           
    243246
    244                                         if((report_item->usage_page != path_item->usage_page) ||
     247                                        if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, path_item->usage_page) ||
    245248                                           ((only_page == 0) &&
    246                                             (report_item->usage != path_item->usage))) {
     249                                            !USB_HID_SAME_USAGE(report_item->usage, path_item->usage))) {
    247250                                                       
    248251                                                   return 1;
     
    282285                                                                      usb_hid_report_usage_path_t,
    283286                                                                      link);           
    284 
    285                                         if((report_item->usage_page != path_item->usage_page) ||
     287                                                 
     288                                        if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, path_item->usage_page) ||
    286289                                           ((only_page == 0) &&
    287                                             (report_item->usage != path_item->usage))) {
    288                                                    return 1;
     290                                            !USB_HID_SAME_USAGE(report_item->usage, path_item->usage))) {
     291                                                        return 1;
    289292                                        } else {
    290293                                                report_link = report_link->prev;
  • uspace/lib/usbhost/src/device_keeper.c

    r160b75e r293de44  
    158158}
    159159
    160 /** Find devman handled assigned to USB address.
     160/** Find devman handle assigned to USB address.
     161 * Intentionally refuse to find handle of default address.
    161162 *
    162163 * @param[in] instance Device keeper structure to use.
     
    170171        assert(instance);
    171172        fibril_mutex_lock(&instance->guard);
    172         if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
     173        if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
    173174                fibril_mutex_unlock(&instance->guard);
    174175                return false;
Note: See TracChangeset for help on using the changeset viewer.