Changeset e1dbcbc in mainline for uspace/lib


Ignore:
Timestamp:
2011-04-29T13:43:01Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a81a1d09
Parents:
380e0364 (diff), f19f1b7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

Location:
uspace/lib
Files:
9 added
4 deleted
51 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/mips32/include/atomic.h

    r380e0364 re1dbcbc  
    7070                "       sc %0, %1\n"
    7171                "       beq %0, %4, 1b\n"       /* if the atomic operation failed, try again */
    72                 /*      nop     */              /* nop is inserted automatically by compiler */
    7372                "       nop\n"
    7473                : "=&r" (tmp),
  • uspace/lib/c/generic/adt/measured_strings.c

    r380e0364 re1dbcbc  
    7474        new->length = length;
    7575        new->value = ((uint8_t *) new) + sizeof(measured_string_t);
    76         // append terminating zero explicitly - to be safe
     76        /* Append terminating zero explicitly - to be safe */
    7777        memcpy(new->value, string, new->length);
    7878        new->value[new->length] = '\0';
  • uspace/lib/c/generic/async.c

    r380e0364 re1dbcbc  
    15861586 * @param dst     Address of the beginning of the destination buffer.
    15871587 * @param size    Size of the destination buffer.
     1588 * @param flags   Flags to control the data transfer.
    15881589 *
    15891590 * @return Zero on success or a negative error code from errno.h.
    15901591 *
    15911592 */
    1592 int async_data_read_start(int phoneid, void *dst, size_t size)
    1593 {
    1594         return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
    1595             (sysarg_t) size);
     1593int
     1594async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
     1595{
     1596        return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
     1597            (sysarg_t) size, (sysarg_t) flags);
    15961598}
    15971599
     
    16831685 * @param src     Address of the beginning of the source buffer.
    16841686 * @param size    Size of the source buffer.
     1687 * @param flags   Flags to control the data transfer.
    16851688 *
    16861689 * @return Zero on success or a negative error code from errno.h.
    16871690 *
    16881691 */
    1689 int async_data_write_start(int phoneid, const void *src, size_t size)
    1690 {
    1691         return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
    1692             (sysarg_t) size);
     1692int
     1693async_data_write_start_generic(int phoneid, const void *src, size_t size,
     1694    int flags)
     1695{
     1696        return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
     1697            (sysarg_t) size, (sysarg_t) flags);
    16931698}
    16941699
  • uspace/lib/c/generic/vfs/vfs.c

    r380e0364 re1dbcbc  
    378378       
    379379        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
    380         rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
     380        rc = async_data_read_start_generic(vfs_phone, (void *) buf, nbyte,
     381            IPC_XF_RESTRICT);
    381382        if (rc != EOK) {
    382383                vfs_exchange_end(vfs_phone);
     
    407408       
    408409        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
    409         rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
     410        rc = async_data_write_start_generic(vfs_phone, (void *) buf, nbyte,
     411            IPC_XF_RESTRICT);
    410412        if (rc != EOK) {
    411413                vfs_exchange_end(vfs_phone);
  • uspace/lib/c/include/async.h

    r380e0364 re1dbcbc  
    341341
    342342extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
    343 extern int async_data_read_start(int, void *, size_t);
     343#define async_data_read_start(p, buf, len) \
     344        async_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
     345
     346extern int async_data_read_start_generic(int, void *, size_t, int);
    344347extern bool async_data_read_receive(ipc_callid_t *, size_t *);
    345348extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
     
    380383            (arg4), (answer))
    381384
    382 extern int async_data_write_start(int, const void *, size_t);
     385#define async_data_write_start(p, buf, len) \
     386        async_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
     387
     388extern int async_data_write_start_generic(int, const void *, size_t, int);
    383389extern bool async_data_write_receive(ipc_callid_t *, size_t *);
    384390extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
  • uspace/lib/c/include/errno.h

    r380e0364 re1dbcbc  
    6565#define EEMPTY (-302)
    6666
     67/** Negative acknowledgment. */
     68#define ENAK (-303)
     69
    6770/** An API function is called while another blocking function is in progress. */
    6871#define EINPROGRESS  (-10036)
  • uspace/lib/c/include/ipc/dev_iface.h

    r380e0364 re1dbcbc  
    4545        /** Interface provided by USB host controller. */
    4646        USBHC_DEV_IFACE,
     47        /** Interface provided by USB HID devices. */
     48        USBHID_DEV_IFACE,
    4749
    4850        DEV_IFACE_MAX
  • uspace/lib/drv/generic/dev_iface.c

    r380e0364 re1dbcbc  
    4343#include "remote_usb.h"
    4444#include "remote_usbhc.h"
     45#include "remote_usbhid.h"
    4546#include "remote_pci.h"
    4647
     
    5152                &remote_pci_iface,
    5253                &remote_usb_iface,
    53                 &remote_usbhc_iface
     54                &remote_usbhc_iface,
     55                &remote_usbhid_iface
    5456        }
    5557};
  • uspace/lib/drv/generic/driver.c

    r380e0364 re1dbcbc  
    4747#include <stdlib.h>
    4848#include <str.h>
     49#include <str_error.h>
    4950#include <ctype.h>
    5051#include <errno.h>
     
    402403                            get_remote_method(rem_iface, iface_method_idx);
    403404                        if (iface_method_ptr == NULL) {
    404                                 // the interface has not such method
     405                                /* The interface has not such method */
    405406                                printf("%s: driver_connection_gen error - "
    406407                                    "invalid interface method.", driver->name);
     
    655656int ddf_driver_main(driver_t *drv)
    656657{
     658        int rc;
     659
    657660        /*
    658661         * Remember the driver structure - driver_ops will be called by generic
     
    668671       
    669672        /*
    670          * Register driver by device manager with generic handler for incoming
    671          * connections.
     673         * Register driver with device manager using generic handler for
     674         * incoming connections.
    672675         */
    673         devman_driver_register(driver->name, driver_connection);
    674        
     676        rc = devman_driver_register(driver->name, driver_connection);
     677        if (rc != EOK) {
     678                printf("Error: Failed to register driver with device manager "
     679                    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
     680                    str_error(rc));
     681               
     682                return 1;
     683        }
     684       
     685        /* Return success from the task since server has started. */
     686        rc = task_retval(0);
     687        if (rc != EOK)
     688                return 1;
     689
    675690        async_manager();
    676691       
  • uspace/lib/net/generic/generic.c

    r380e0364 re1dbcbc  
    106106                return EBADMEM;
    107107
    108         // request the address
     108        /* Request the address */
    109109        message_id = async_send_1(phone, (sysarg_t) message,
    110110            (sysarg_t) device_id, NULL);
     
    112112        async_wait_for(message_id, &result);
    113113
    114         // if not successful
     114        /* If not successful */
    115115        if ((string == EOK) && (result != EOK)) {
    116                 // clear the data
     116                /* Clear the data */
    117117                free(*address);
    118118                free(*data);
     
    242242                return EBADMEM;
    243243
    244         // request the translation
     244        /* Request the translation */
    245245        message_id = async_send_3(phone, (sysarg_t) message,
    246246            (sysarg_t) device_id, (sysarg_t) count, (sysarg_t) service, NULL);
     
    249249        async_wait_for(message_id, &result);
    250250
    251         // if not successful
     251        /* If not successful */
    252252        if ((string == EOK) && (result != EOK)) {
    253                 // clear the data
     253                /* Clear the data */
    254254                free(*translation);
    255255                free(*data);
  • uspace/lib/net/generic/net_checksum.c

    r380e0364 re1dbcbc  
    5252uint16_t compact_checksum(uint32_t sum)
    5353{
    54         // shorten to the 16 bits
     54        /* Shorten to the 16 bits */
    5555        while (sum >> 16)
    5656                sum = (sum & 0xffff) + (sum >> 16);
     
    7272        size_t index;
    7373
    74         // sum all the 16 bit fields
     74        /* Sum all the 16 bit fields */
    7575        for (index = 0; index + 1 < length; index += 2)
    7676                seed += (data[index] << 8) + data[index + 1];
    7777
    78         // last odd byte with zero padding
     78        /* Last odd byte with zero padding */
    7979        if (index + 1 == length)
    8080                seed += data[index] << 8;
     
    9494        size_t index;
    9595
    96         // process full bytes
     96        /* Process full bytes */
    9797        while (length >= 8) {
    98                 // add the data
     98                /* Add the data */
    9999                seed ^= (*data) << 24;
    100100               
    101                 // for each added bit
     101                /* For each added bit */
    102102                for (index = 0; index < 8; ++index) {
    103                         // if the first bit is set
     103                        /* If the first bit is set */
    104104                        if (seed & 0x80000000) {
    105                                 // shift and divide the checksum
     105                                /* Shift and divide the checksum */
    106106                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    107107                        } else {
    108                                 // shift otherwise
     108                                /* Shift otherwise */
    109109                                seed <<= 1;
    110110                        }
    111111                }
    112112               
    113                 // move to the next byte
     113                /* Move to the next byte */
    114114                ++data;
    115115                length -= 8;
    116116        }
    117117
    118         // process the odd bits
     118        /* Process the odd bits */
    119119        if (length > 0) {
    120                 // add the data with zero padding
     120                /* Add the data with zero padding */
    121121                seed ^= ((*data) & (0xff << (8 - length))) << 24;
    122122               
    123                 // for each added bit
     123                /* For each added bit */
    124124                for (index = 0; index < length; ++index) {
    125                         // if the first bit is set
     125                        /* If the first bit is set */
    126126                        if (seed & 0x80000000) {
    127                                 // shift and divide the checksum
     127                                /* Shift and divide the checksum */
    128128                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    129129                        } else {
    130                                 // shift otherwise
     130                                /* Shift otherwise */
    131131                                seed <<= 1;
    132132                        }
     
    148148        size_t index;
    149149
    150         // process full bytes
     150        /* Process full bytes */
    151151        while (length >= 8) {
    152                 // add the data
     152                /* Add the data */
    153153                seed ^= (*data);
    154154               
    155                 // for each added bit
     155                /* For each added bit */
    156156                for (index = 0; index < 8; ++index) {
    157                         // if the last bit is set
     157                        /* If the last bit is set */
    158158                        if (seed & 1) {
    159                                 // shift and divide the checksum
     159                                /* Shift and divide the checksum */
    160160                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    161161                        } else {
    162                                 // shift otherwise
     162                                /* Shift otherwise */
    163163                                seed >>= 1;
    164164                        }
    165165                }
    166166               
    167                 // move to the next byte
     167                /* Move to the next byte */
    168168                ++data;
    169169                length -= 8;
    170170        }
    171171
    172         // process the odd bits
     172        /* Process the odd bits */
    173173        if (length > 0) {
    174                 // add the data with zero padding
     174                /* Add the data with zero padding */
    175175                seed ^= (*data) >> (8 - length);
    176176               
    177177                for (index = 0; index < length; ++index) {
    178                         // if the last bit is set
     178                        /* If the last bit is set */
    179179                        if (seed & 1) {
    180                                 // shift and divide the checksum
     180                                /* Shift and divide the checksum */
    181181                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    182182                        } else {
    183                                 // shift otherwise
     183                                /* Shift otherwise */
    184184                                seed >>= 1;
    185185                        }
     
    198198uint16_t flip_checksum(uint16_t checksum)
    199199{
    200         // flip, zero is returned as 0xFFFF (not flipped)
     200        /* Flip, zero is returned as 0xFFFF (not flipped) */
    201201        checksum = ~checksum;
    202202        return checksum ? checksum : IP_CHECKSUM_ZERO;
     
    216216uint16_t ip_checksum(uint8_t *data, size_t length)
    217217{
    218         // compute, compact and flip the data checksum
     218        /* Compute, compact and flip the data checksum */
    219219        return flip_checksum(compact_checksum(compute_checksum(0, data,
    220220            length)));
  • uspace/lib/net/generic/packet_client.c

    r380e0364 re1dbcbc  
    267267                return NULL;
    268268
    269         // get a new packet
     269        /* Get a new packet */
    270270        copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet),
    271271            PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
     
    274274                return NULL;
    275275
    276         // get addresses
     276        /* Get addresses */
    277277        addrlen = packet_get_addr(packet, &src, &dest);
    278         // copy data
     278        /* Copy data */
    279279        if ((packet_copy_data(copy, packet_get_data(packet),
    280280            PACKET_DATA_LENGTH(packet)) == EOK) &&
    281             // copy addresses if present
     281            /* Copy addresses if present */
    282282            ((addrlen <= 0) ||
    283283            (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
  • uspace/lib/net/il/ip_client.c

    r380e0364 re1dbcbc  
    124124
    125125        // TODO IPv6
    126 /*      case AF_INET6:
     126#if 0
     127        case AF_INET6:
    127128                if (addrlen != sizeof(struct sockaddr_in6))
    128129                        return EINVAL;
     
    130131                address_in6 = (struct sockaddr_in6 *) addr;
    131132                return EOK;
    132 */
     133#endif
    133134
    134135        default:
     
    159160        size_t padding;
    160161
    161         // compute the padding if IP options are set
    162         // multiple of 4 bytes
     162        /*
     163         * Compute the padding if IP options are set
     164         * multiple of 4 bytes
     165         */
    163166        padding =  ipopt_length % 4;
    164167        if (padding) {
     
    167170        }
    168171
    169         // prefix the header
     172        /* Prefix the header */
    170173        data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
    171174        if (!data)
    172175                return ENOMEM;
    173176
    174         // add the padding
     177        /* Add the padding */
    175178        while (padding--)
    176179                data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
    177180
    178         // set the header
     181        /* Set the header */
    179182        header = (ip_header_t *) data;
    180183        header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) +
  • uspace/lib/net/tl/icmp_client.c

    r380e0364 re1dbcbc  
    8181                *mtu = header->un.frag.mtu;
    8282
    83         // remove debug dump
     83        /* Remove debug dump */
    8484#ifdef CONFIG_DEBUG
    8585        printf("ICMP error %d (%d) in packet %d\n", header->type, header->code,
  • uspace/lib/net/tl/socket_core.c

    r380e0364 re1dbcbc  
    9191        int packet_id;
    9292
    93         // if bound
     93        /* If bound */
    9494        if (socket->port) {
    95                 // release the port
     95                /* Release the port */
    9696                socket_port_release(global_sockets, socket);
    9797        }
    9898       
    99         // release all received packets
     99        /* Release all received packets */
    100100        while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
    101101                pq_release_remote(packet_phone, packet_id);
     
    166166        int rc;
    167167
    168         // create a wrapper
     168        /* Create a wrapper */
    169169        socket_ref = malloc(sizeof(*socket_ref));
    170170        if (!socket_ref)
     
    172172
    173173        *socket_ref = socket;
    174         // add the wrapper
     174        /* Add the wrapper */
    175175        rc = socket_port_map_add(&socket_port->map, key, key_length,
    176176            socket_ref);
     
    206206        int rc;
    207207
    208         // create a wrapper
     208        /* Create a wrapper */
    209209        socket_port = malloc(sizeof(*socket_port));
    210210        if (!socket_port)
     
    221221                goto fail;
    222222       
    223         // register the incomming port
     223        /* Register the incoming port */
    224224        rc = socket_ports_add(global_sockets, port, socket_port);
    225225        if (rc < 0)
     
    277277               
    278278                address_in = (struct sockaddr_in *) addr;
    279                 // find the socket
     279                /* Find the socket */
    280280                socket = socket_cores_find(local_sockets, socket_id);
    281281                if (!socket)
    282282                        return ENOTSOCK;
    283283               
    284                 // bind a free port?
     284                /* Bind a free port? */
    285285                if (address_in->sin_port <= 0)
    286286                        return socket_bind_free_port(global_sockets, socket,
    287287                             free_ports_start, free_ports_end, last_used_port);
    288288               
    289                 // try to find the port
     289                /* Try to find the port */
    290290                socket_port = socket_ports_find(global_sockets,
    291291                    ntohs(address_in->sin_port));
    292292                if (socket_port) {
    293                         // already used
     293                        /* Already used */
    294294                        return EADDRINUSE;
    295295                }
    296296               
    297                 // if bound
     297                /* If bound */
    298298                if (socket->port) {
    299                         // release the port
     299                        /* Release the port */
    300300                        socket_port_release(global_sockets, socket);
    301301                }
     
    333333        int index;
    334334
    335         // from the last used one
     335        /* From the last used one */
    336336        index = last_used_port;
    337337       
     
    339339                ++index;
    340340               
    341                 // til the range end
     341                /* Till the range end */
    342342                if (index >= free_ports_end) {
    343                         // start from the range beginning
     343                        /* Start from the range beginning */
    344344                        index = free_ports_start - 1;
    345345                        do {
    346346                                ++index;
    347                                 // til the last used one
     347                                /* Till the last used one */
    348348                                if (index >= last_used_port) {
    349                                         // none found
     349                                        /* None found */
    350350                                        return ENOTCONN;
    351351                                }
    352352                        } while (socket_ports_find(global_sockets, index));
    353353                       
    354                         // found, break immediately
     354                        /* Found, break immediately */
    355355                        break;
    356356                }
     
    376376
    377377        count = 0;
    378 //      socket_id = socket_globals.last_id;
     378#if 0
     379        socket_id = socket_globals.last_id;
     380#endif
    379381        do {
    380382                if (count < SOCKET_ID_TRIES) {
     
    384386                        socket_id = 1;
    385387                        ++count;
    386                 // only this branch for last_id
     388                /* Only this branch for last_id */
    387389                } else {
    388390                        if (socket_id < INT_MAX) {
    389391                                ++ socket_id;
    390 /*                      } else if(socket_globals.last_id) {
    391 *                               socket_globals.last_id = 0;
    392 *                               socket_id = 1;
    393 */                      } else {
     392#if 0
     393                        } else if(socket_globals.last_id) {
     394                                socket_globals.last_id = 0;
     395                                socket_id = 1;
     396#endif
     397                        } else {
    394398                                return ELIMIT;
    395399                        }
     
    425429                return EINVAL;
    426430       
    427         // store the socket
     431        /* Store the socket */
    428432        if (*socket_id <= 0) {
    429433                positive = (*socket_id == 0);
     
    441445                return ENOMEM;
    442446       
    443         // initialize
     447        /* Initialize */
    444448        socket->phone = app_phone;
    445449        socket->port = -1;
     
    493497        int accepted_id;
    494498
    495         // find the socket
     499        /* Find the socket */
    496500        socket = socket_cores_find(local_sockets, socket_id);
    497501        if (!socket)
    498502                return ENOTSOCK;
    499503       
    500         // destroy all accepted sockets
     504        /* Destroy all accepted sockets */
    501505        while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
    502506                socket_destroy(packet_phone, accepted_id, local_sockets,
     
    535539        next_packet = pq_next(packet);
    536540        if (!next_packet) {
    537                 // write all if only one fragment
     541                /* Write all if only one fragment */
    538542                rc = data_reply(packet_get_data(packet),
    539543                    packet_get_data_length(packet));
    540544                if (rc != EOK)
    541545                        return rc;
    542                 // store the total length
     546                /* Store the total length */
    543547                *length = packet_get_data_length(packet);
    544548        } else {
    545                 // count the packet fragments
     549                /* Count the packet fragments */
    546550                fragments = 1;
    547551                next_packet = pq_next(packet);
     
    549553                        ++fragments;
    550554               
    551                 // compute and store the fragment lengths
     555                /* Compute and store the fragment lengths */
    552556                lengths = (size_t *) malloc(sizeof(size_t) * fragments +
    553557                    sizeof(size_t));
     
    565569                }
    566570               
    567                 // write the fragment lengths
     571                /* Write the fragment lengths */
    568572                rc = data_reply(lengths, sizeof(int) * (fragments + 1));
    569573                if (rc != EOK) {
     
    573577                next_packet = packet;
    574578               
    575                 // write the fragments
     579                /* Write the fragments */
    576580                for (index = 0; index < fragments; ++index) {
    577581                        rc = data_reply(packet_get_data(next_packet),
     
    584588                }
    585589               
    586                 // store the total length
     590                /* Store the total length */
    587591                *length = lengths[fragments];
    588592                free(lengths);
     
    636640                return;
    637641       
    638         // find ports
     642        /* Find ports */
    639643        socket_port = socket_ports_find(global_sockets, socket->port);
    640644        if (socket_port) {
    641                 // find the socket
     645                /* Find the socket */
    642646                socket_ref = socket_port_map_find(&socket_port->map,
    643647                    socket->key, socket->key_length);
     
    646650                        --socket_port->count;
    647651                       
    648                         // release if empty
     652                        /* Release if empty */
    649653                        if (socket_port->count <= 0) {
    650                                 // destroy the map
     654                                /* Destroy the map */
    651655                                socket_port_map_destroy(&socket_port->map, free);
    652                                 // release the port
     656                                /* Release the port */
    653657                                socket_ports_exclude(global_sockets,
    654658                                    socket->port, free);
    655659                        } else {
    656                                 // remove
     660                                /* Remove */
    657661                                socket_port_map_exclude(&socket_port->map,
    658662                                    socket->key, socket->key_length, free);
     
    685689        int rc;
    686690
    687         // find ports
     691        /* Find ports */
    688692        socket_port = socket_ports_find(global_sockets, port);
    689693        if (!socket_port)
    690694                return ENOENT;
    691695       
    692         // add the socket
     696        /* Add the socket */
    693697        rc = socket_port_add_core(socket_port, socket, key, key_length);
    694698        if (rc != EOK)
  • uspace/lib/net/tl/tl_common.c

    r380e0364 re1dbcbc  
    255255        int length;
    256256
    257         // detach the first packet and release the others
     257        /* Detach the first packet and release the others */
    258258        next = pq_detach(packet);
    259259        if (next)
     
    262262        length = packet_get_addr(packet, &src, NULL);
    263263        if ((length > 0) && (!error) && (icmp_phone >= 0) &&
    264             // set both addresses to the source one (avoids the source address
    265             // deletion before setting the destination one)
     264            /*
     265             * Set both addresses to the source one (avoids the source address
     266             * deletion before setting the destination one)
     267             */
    266268            (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
    267269                return EOK;
     
    299301                return EINVAL;
    300302
    301         // get the data length
     303        /* Get the data length */
    302304        if (!async_data_write_receive(&callid, &length))
    303305                return EINVAL;
    304306
    305         // get a new packet
     307        /* Get a new packet */
    306308        *packet = packet_get_4_remote(packet_phone, length, dimension->addr_len,
    307309            prefix + dimension->prefix, dimension->suffix);
     
    309311                return ENOMEM;
    310312
    311         // allocate space in the packet
     313        /* Allocate space in the packet */
    312314        data = packet_suffix(*packet, length);
    313315        if (!data) {
     
    316318        }
    317319
    318         // read the data into the packet
     320        /* Read the data into the packet */
    319321        rc = async_data_write_finalize(callid, data, length);
    320322        if (rc != EOK) {
     
    323325        }
    324326       
    325         // set the packet destination address
     327        /* Set the packet destination address */
    326328        rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
    327329        if (rc != EOK) {
  • uspace/lib/packet/generic/packet_server.c

    r380e0364 re1dbcbc  
    112112    size_t max_content, size_t max_suffix)
    113113{
    114         // clear the packet content
     114        /* Clear the packet content */
    115115        bzero(((void *) packet) + sizeof(packet_t),
    116116            packet->length - sizeof(packet_t));
    117117       
    118         // clear the packet header
     118        /* Clear the packet header */
    119119        packet->order = 0;
    120120        packet->metric = 0;
     
    151151        assert(fibril_mutex_is_locked(&ps_globals.lock));
    152152
    153         // already locked
     153        /* Already locked */
    154154        packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
    155155            MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  • uspace/lib/softint/generic/multiplication.c

    r380e0364 re1dbcbc  
    109109         * result does not fit in signed one */
    110110        if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) {
    111                 // error, overflow
     111                /* Error, overflow */
    112112                return (neg ? INT64_MIN : INT64_MAX);
    113113        }
  • uspace/lib/usb/Makefile

    r380e0364 re1dbcbc  
    4242        src/dp.c \
    4343        src/dump.c \
     44        src/hidiface.c \
    4445        src/hidparser.c \
    4546        src/hub.c \
  • uspace/lib/usb/include/usb/classes/hid.h

    r380e0364 re1dbcbc  
    5050        USB_HIDREQ_SET_PROTOCOL = 11
    5151} usb_hid_request_t;
    52 
    53 typedef enum {
    54         USB_HID_REPORT_TYPE_INPUT = 1,
    55         USB_HID_REPORT_TYPE_OUTPUT = 2,
    56         USB_HID_REPORT_TYPE_FEATURE = 3
    57 } usb_hid_report_type_t;
    5852
    5953typedef enum {
  • uspace/lib/usb/include/usb/classes/hidparser.h

    r380e0364 re1dbcbc  
    7373#define USB_HID_PATH_COMPARE_END                                1
    7474#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
    75 
    76 /** */
    77 typedef struct {
    78         /** */
    79         int32_t usage_page;
    80         /** */ 
    81         int32_t usage;
     75#define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
     76
     77
     78#define USB_HID_MAX_USAGES      20
     79
     80typedef enum {
     81        USB_HID_REPORT_TYPE_INPUT = 1,
     82        USB_HID_REPORT_TYPE_OUTPUT = 2,
     83        USB_HID_REPORT_TYPE_FEATURE = 3
     84} usb_hid_report_type_t;
     85
     86/** Collection usage path structure */
     87typedef struct {
     88        /** */
     89        uint32_t usage_page;
     90        /** */ 
     91        uint32_t usage;
     92
     93        uint8_t flags;
    8294        /** */
    8395        link_t link;
     
    91103       
    92104        /** */ 
     105        link_t link; /* list */
     106
     107        link_t head; /* head of list of usage paths */
     108
     109} usb_hid_report_path_t;
     110
     111
     112typedef struct {
     113        /** */
     114        int report_count;
     115        link_t reports;         /** list of usb_hid_report_description_t */
     116
     117        link_t collection_paths;
     118        int collection_paths_count;
     119
     120        int use_report_ids;
     121        uint8_t last_report_id;
     122       
     123} usb_hid_report_t;
     124
     125typedef struct {
     126        uint8_t report_id;
     127        usb_hid_report_type_t type;
     128
     129        size_t bit_length;
     130        size_t item_length;
     131       
     132        link_t report_items;    /** list of report items (fields) */
     133
    93134        link_t link;
    94 
    95 } usb_hid_report_path_t;
    96 
    97 /**
    98  * Description of report items
    99  */
    100 typedef struct {
    101         /** */ 
     135} usb_hid_report_description_t;
     136
     137typedef struct {
     138
     139        int offset;
     140        size_t size;
     141
     142        uint16_t usage_page;
     143        uint16_t usage;
     144
     145        uint8_t item_flags;
     146        usb_hid_report_path_t *collection_path;
     147
     148        int32_t logical_minimum;
     149        int32_t logical_maximum;
     150        int32_t physical_minimum;
     151        int32_t physical_maximum;
     152        uint32_t usage_minimum;
     153        uint32_t usage_maximum;
     154        uint32_t unit;
     155        uint32_t unit_exponent;
     156       
     157
     158        int32_t value;
     159
     160        link_t link;
     161} usb_hid_report_field_t;
     162
     163
     164
     165/**
     166 * state table
     167 */
     168typedef struct {
     169        /** report id */       
    102170        int32_t id;
    103         /** */ 
    104         int32_t usage_minimum;
    105         /** */ 
    106         int32_t usage_maximum;
     171       
     172        /** */
     173        uint16_t extended_usage_page;
     174        uint32_t usages[USB_HID_MAX_USAGES];
     175        int usages_count;
     176
     177        /** */
     178        uint32_t usage_page;
     179
     180        /** */ 
     181        uint32_t usage_minimum;
     182        /** */ 
     183        uint32_t usage_maximum;
    107184        /** */ 
    108185        int32_t logical_minimum;
     
    116193        size_t offset;
    117194        /** */ 
    118         int32_t delimiter;
    119         /** */ 
    120195        int32_t unit_exponent;
    121196        /** */ 
     
    123198
    124199        /** */
    125         int32_t string_index;
    126         /** */ 
    127         int32_t string_minimum;
    128         /** */ 
    129         int32_t string_maximum;
    130         /** */ 
    131         int32_t designator_index;
    132         /** */ 
    133         int32_t designator_minimum;
    134         /** */ 
    135         int32_t designator_maximum;
     200        uint32_t string_index;
     201        /** */ 
     202        uint32_t string_minimum;
     203        /** */ 
     204        uint32_t string_maximum;
     205        /** */ 
     206        uint32_t designator_index;
     207        /** */ 
     208        uint32_t designator_minimum;
     209        /** */ 
     210        uint32_t designator_maximum;
    136211        /** */ 
    137212        int32_t physical_minimum;
     
    142217        uint8_t item_flags;
    143218
    144         /** */ 
     219        usb_hid_report_type_t type;
     220
     221        /** current collection path*/   
    145222        usb_hid_report_path_t *usage_path;
    146223        /** */ 
    147224        link_t link;
    148225} usb_hid_report_item_t;
    149 
    150 
    151 /** HID report parser structure. */
    152 typedef struct {       
    153         /** */ 
    154         link_t input;
    155         /** */ 
    156         link_t output;
    157         /** */ 
    158         link_t feature;
    159        
    160         int use_report_id;
    161 
    162         /** */
    163         link_t stack;
    164 } usb_hid_report_parser_t;     
    165 
    166226
    167227/** HID parser callbacks for IN items. */
     
    189249} usb_hid_modifiers_t;
    190250
    191 //typedef enum {
    192 //      USB_HID_LED_NUM_LOCK = 0x1,
    193 //      USB_HID_LED_CAPS_LOCK = 0x2,
    194 //      USB_HID_LED_SCROLL_LOCK = 0x4,
    195 //      USB_HID_LED_COMPOSE = 0x8,
    196 //      USB_HID_LED_KANA = 0x10,
    197 //      USB_HID_LED_COUNT = 5
    198 //} usb_hid_led_t;
    199 
    200251static const usb_hid_modifiers_t
    201252    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
     
    210261};
    211262
    212 //static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = {
    213 //      USB_HID_LED_NUM_LOCK,
    214 //      USB_HID_LED_CAPS_LOCK,
    215 //      USB_HID_LED_SCROLL_LOCK,
    216 //      USB_HID_LED_COMPOSE,
    217 //      USB_HID_LED_KANA
    218 //};
    219 
    220 //#define USB_HID_BOOT_KEYBOARD_NUM_LOCK                0x01
    221 //#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK               0x02
    222 //#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK     0x04
    223 //#define USB_HID_BOOT_KEYBOARD_COMPOSE         0x08
    224 //#define USB_HID_BOOT_KEYBOARD_KANA                    0x10
    225 
    226263/*
    227264 * Descriptor parser functions
    228265 */
    229 /** */
    230 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
    231 
    232 /** */
    233 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     266
     267/** */
     268int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    234269    const uint8_t *data, size_t size);
    235270
    236271/** */
    237 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
    238 
    239 /** */
    240 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
    241 
    242 /*
    243  * Boot protocol functions
    244  */
    245 /** */
    246 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    247         const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    248 
    249 /** */
    250 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
     272void usb_hid_free_report(usb_hid_report_t *report);
     273
     274/** */
     275void usb_hid_descriptor_print(usb_hid_report_t *report);
    251276
    252277
     
    255280 */
    256281/** */
    257 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    258     const uint8_t *data, size_t size,
    259     usb_hid_report_path_t *path, int flags,
    260     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
    261 
    262 /** */
    263 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     282int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
     283
     284/** */
     285size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    264286        usb_hid_report_path_t *path, int flags);
    265287
     
    296318usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    297319
     320usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
     321
     322uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
     323
    298324
    299325/*
     
    301327 */
    302328/** Allocates output report buffer*/
    303 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size);
     329uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
    304330
    305331/** Frees output report buffer*/
     
    307333
    308334/** Returns size of output for given usage path */
    309 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     335size_t usb_hid_report_output_size(usb_hid_report_t *report,
    310336                                  usb_hid_report_path_t *path, int flags);
    311337
    312 /** Updates the output report buffer by translated given data */
    313 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    314                                     usb_hid_report_path_t *path, int flags,
    315                                     uint8_t *buffer, size_t size,
    316                                     int32_t *data, size_t data_size);
     338/** Sets data in report structure */
     339int usb_hid_report_output_set_data(usb_hid_report_t *report,
     340                                   usb_hid_report_path_t *path, int flags,
     341                                  int *data, size_t data_size);
     342
     343/** Makes the output report buffer by translated given data */
     344int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
    317345#endif
    318346/**
  • uspace/lib/usb/include/usb/classes/hidreport.h

    r380e0364 re1dbcbc  
    5757 */
    5858int usb_hid_process_report_descriptor(usb_device_t *dev,
    59     usb_hid_report_parser_t *parser);
     59    usb_hid_report_t *report);
    6060
    6161#endif /* LIBUSB_HIDREPORT_H_ */
  • uspace/lib/usb/include/usb/classes/hidut.h

    r380e0364 re1dbcbc  
    4646        USB_HIDUT_PAGE_KEYBOARD = 7,
    4747        USB_HIDUT_PAGE_LED = 8,
    48         USB_HIDUT_PAGE_BUTTON = 9
    49         /* USB_HIDUT_PAGE_ = , */
     48        USB_HIDUT_PAGE_BUTTON = 9,
     49        USB_HIDUT_PAGE_ORDINAL = 0x0a,
     50        USB_HIDUT_PAGE_TELEPHONY_DEVICE = 0x0b,
     51        USB_HIDUT_PAGE_CONSUMER = 0x0c
    5052} usb_hidut_usage_page_t;
    5153
  • uspace/lib/usb/include/usb/classes/hub.h

    r380e0364 re1dbcbc  
    152152            maximum of 255 ports).
    153153     */
    154     uint8_t * devices_removable;
     154    uint8_t devices_removable[32];
    155155
    156156    /**
  • uspace/lib/usb/include/usb/debug.h

    r380e0364 re1dbcbc  
    3636#define LIBUSB_DEBUG_H_
    3737#include <stdio.h>
     38#include <inttypes.h>
    3839#include <usb/usb.h>
    3940#include <assert.h>
     
    8586void usb_log_enable(usb_log_level_t, const char *);
    8687
    87 void usb_log_printf(usb_log_level_t, const char *, ...);
     88void usb_log_printf(usb_log_level_t, const char *, ...)
     89        PRINTF_ATTRIBUTE(2, 3);
    8890
    8991/** Log fatal error. */
  • uspace/lib/usb/include/usb/devdrv.h

    r380e0364 re1dbcbc  
    162162    usb_endpoint_description_t **);
    163163
    164 typedef bool (*usb_polling_callback_t)(usb_device_t *,
    165     uint8_t *, size_t, void *);
    166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
    167 
    168 int usb_device_auto_poll(usb_device_t *, size_t,
    169     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
    170 
    171164int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
    172165int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
  • uspace/lib/usb/include/usb/host/batch.h

    r380e0364 re1dbcbc  
    4343typedef struct usb_transfer_batch usb_transfer_batch_t;
    4444struct usb_transfer_batch {
     45        endpoint_t *ep;
    4546        link_t link;
    46         usb_target_t target;
    47         usb_transfer_type_t transfer_type;
    48         usb_speed_t speed;
    49         usb_direction_t direction;
    5047        usbhc_iface_transfer_in_callback_t callback_in;
    5148        usbhc_iface_transfer_out_callback_t callback_out;
     49        void *arg;
    5250        char *buffer;
    53         char *transport_buffer;
     51        char *data_buffer;
    5452        size_t buffer_size;
    5553        char *setup_buffer;
    5654        size_t setup_size;
    57         size_t max_packet_size;
    5855        size_t transfered_size;
    5956        void (*next_step)(usb_transfer_batch_t *);
    6057        int error;
    6158        ddf_fun_t *fun;
    62         void *arg;
    63         endpoint_t *ep;
    6459        void *private_data;
     60        void (*private_data_dtor)(void *p_data);
    6561};
    6662
    6763void usb_transfer_batch_init(
    6864    usb_transfer_batch_t *instance,
    69     usb_target_t target,
    70     usb_transfer_type_t transfer_type,
    71     usb_speed_t speed,
    72     size_t max_packet_size,
     65    endpoint_t *ep,
    7366    char *buffer,
    74     char *transport_buffer,
     67    char *data_buffer,
    7568    size_t buffer_size,
    7669    char *setup_buffer,
     
    8073    void *arg,
    8174    ddf_fun_t *fun,
    82                 endpoint_t *ep,
    83     void *private_data
     75    void *private_data,
     76    void (*private_data_dtor)(void *p_data)
    8477);
    8578
    86 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
    87 {
    88         assert(l);
    89         return list_get_instance(l, usb_transfer_batch_t, link);
    90 }
    91 
    92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     79void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
     80void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    9481void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     82void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
    9583
    9684static inline void usb_transfer_batch_finish_error(
     
    10290}
    10391
     92static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
     93{
     94        assert(l);
     95        return list_get_instance(l, usb_transfer_batch_t, link);
     96}
     97
    10498#endif
    10599/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    r380e0364 re1dbcbc  
    5454        usb_speed_t speed;
    5555        bool occupied;
    56         link_t endpoints;
    57         uint16_t control_used;
    5856        devman_handle_t handle;
    5957};
     
    6563        struct usb_device_info devices[USB_ADDRESS_COUNT];
    6664        fibril_mutex_t guard;
    67         fibril_condvar_t change;
    6865        usb_address_t last_address;
    6966} usb_device_keeper_t;
    7067
    7168void usb_device_keeper_init(usb_device_keeper_t *instance);
    72 
    73 void usb_device_keeper_reserve_default_address(
    74     usb_device_keeper_t *instance, usb_speed_t speed);
    75 
    76 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);
    77 
    78 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
    79     usb_target_t target, const uint8_t *setup_data);
    8069
    8170usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
  • uspace/lib/usb/include/usb/host/endpoint.h

    r380e0364 re1dbcbc  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
     56        struct {
     57                void *data;
     58                int (*toggle_get)(void *);
     59                void (*toggle_set)(void *, int);
     60        } hc_data;
    5661} endpoint_t;
    5762
     
    6166
    6267void endpoint_destroy(endpoint_t *instance);
     68
     69void endpoint_set_hc_data(endpoint_t *instance,
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71
     72void endpoint_clear_hc_data(endpoint_t *instance);
    6373
    6474void endpoint_use(endpoint_t *instance);
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    r380e0364 re1dbcbc  
    6666    endpoint_t *ep, size_t data_size);
    6767
    68 int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,
    69     usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
    70     void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,
    71     size_t bw);
    72 
    7368int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
    7469    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
     
    8075void usb_endpoint_manager_reset_if_need(
    8176    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
     77
     78static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     79    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     80    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
     81    size_t data_size)
     82{
     83        endpoint_t *ep = malloc(sizeof(endpoint_t));
     84        if (ep == NULL)
     85                return ENOMEM;
     86
     87        int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
     88            max_packet_size);
     89        if (ret != EOK) {
     90                free(ep);
     91                return ret;
     92        }
     93
     94        ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
     95        if (ret != EOK) {
     96                endpoint_destroy(ep);
     97                return ret;
     98        }
     99        return EOK;
     100}
    82101#endif
    83102/**
  • uspace/lib/usb/include/usb/pipes.h

    r380e0364 re1dbcbc  
    9999        /** Number of active transfers over the pipe. */
    100100        int refcount;
     101        /** Number of failed attempts to open the HC phone.
     102         * When user requests usb_pipe_start_long_transfer() and the operation
     103         * fails, there is no way to report this to the user.
     104         * That the soft reference counter is increased to record the attempt.
     105         * When the user then request e.g. usb_pipe_read(), it will try to
     106         * add reference as well.
     107         * If that fails, it is reported to the user. If it is okay, the
     108         * real reference counter is incremented.
     109         * The problem might arise when ending the long transfer (since
     110         * the number of references would be only 1, but logically it shall be
     111         * two).
     112         * Decrementing the soft counter first shall solve this.
     113         */
     114        int refcount_soft;
     115
     116        /** Whether to automatically reset halt on the endpoint.
     117         * Valid only for control endpoint zero.
     118         */
     119        bool auto_reset_halt;
    101120} usb_pipe_t;
    102121
     
    158177int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
    159178
    160 int usb_pipe_start_session(usb_pipe_t *);
    161 int usb_pipe_end_session(usb_pipe_t *);
    162 bool usb_pipe_is_session_started(usb_pipe_t *);
    163 
    164 int usb_pipe_start_long_transfer(usb_pipe_t *);
     179void usb_pipe_start_long_transfer(usb_pipe_t *);
    165180void usb_pipe_end_long_transfer(usb_pipe_t *);
    166181
  • uspace/lib/usb/include/usb/usb.h

    r380e0364 re1dbcbc  
    9696        USB_REQUEST_RECIPIENT_DEVICE = 0,
    9797        USB_REQUEST_RECIPIENT_INTERFACE = 1,
    98         USB_REQUEST_RECIPIENT_ENDPOINT = 2
     98        USB_REQUEST_RECIPIENT_ENDPOINT = 2,
     99        USB_REQUEST_RECIPIENT_OTHER = 3
    99100} usb_request_recipient_t;
    100101
  • uspace/lib/usb/src/debug.c

    r380e0364 re1dbcbc  
    158158
    159159/** Fibril local storage for the dumped buffer. */
    160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
     160static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
     161/** Fibril local storage for buffer switching. */
     162static fibril_local int buffer_dump_index = 0;
    161163
    162164/** Dump buffer into string.
     
    167169 * can not do that) and you do not have to guard it against concurrent
    168170 * calls to it.
    169  * The only limitation is that each call rewrites the buffer again.
     171 * The only limitation is that each second call rewrites the buffer again
     172 * (internally, two buffer are used in cyclic manner).
    170173 * Thus, it is necessary to copy the buffer elsewhere (that includes printing
    171174 * to screen or writing to file).
     
    173176 * that is not a big limitation.
    174177 *
    175  * @warning You cannot use this function twice in the same printf
     178 * @warning You cannot use this function more than twice in the same printf
    176179 * (see detailed explanation).
    177180 *
     
    185188{
    186189        /*
    187          * Remove previous string (that might also reveal double usage of
    188          * this function).
     190         * Remove previous string.
    189191         */
    190         bzero(buffer_dump, BUFFER_DUMP_LEN);
     192        bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
    191193
    192194        if (buffer == NULL) {
     
    202204        /* How many bytes are available in the output buffer. */
    203205        size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
    204         char *it = buffer_dump;
     206        char *it = buffer_dump[buffer_dump_index];
    205207
    206208        size_t index = 0;
     
    253255        }
    254256
    255         return buffer_dump;
     257        /* Next time, use the other buffer. */
     258        buffer_dump_index = 1 - buffer_dump_index;
     259
     260        /* Need to take the old one due to previous line. */
     261        return buffer_dump[1 - buffer_dump_index];
    256262}
    257263
  • uspace/lib/usb/src/devdrv.c

    r380e0364 re1dbcbc  
    236236
    237237        /* It is worth to start a long transfer. */
    238         rc = usb_pipe_start_long_transfer(ctrl_pipe);
    239         if (rc != EOK) {
    240                 return rc;
    241         }
     238        usb_pipe_start_long_transfer(ctrl_pipe);
    242239
    243240        /* Get the device descriptor. */
  • uspace/lib/usb/src/devpoll.c

    r380e0364 re1dbcbc  
    3333 * USB device driver framework - automatic interrupt polling.
    3434 */
    35 #include <usb/devdrv.h>
     35#include <usb/devpoll.h>
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/classes/classes.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    4546/** Data needed for polling. */
    4647typedef struct {
     48        int debug;
     49        size_t max_failures;
     50        useconds_t delay;
     51        bool auto_clear_halt;
     52        bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
     53        void (*on_polling_end)(usb_device_t *, bool, void *);
     54        bool (*on_error)(usb_device_t *, int, void *);
     55
    4756        usb_device_t *dev;
    4857        size_t pipe_index;
    49         usb_polling_callback_t callback;
    50         usb_polling_terminted_callback_t terminated_callback;
    5158        size_t request_size;
    5259        uint8_t *buffer;
     
    5461} polling_data_t;
    5562
     63
    5664/** Polling fibril.
    5765 *
     
    6775            = polling_data->dev->pipes[polling_data->pipe_index].pipe;
    6876       
    69         usb_log_debug("Pipe interface number: %d, protocol: %d, subclass: %d, max packet size: %d\n",
    70             polling_data->dev->pipes[polling_data->pipe_index].interface_no,
    71             polling_data->dev->pipes[polling_data->pipe_index].description->interface_protocol,
    72             polling_data->dev->pipes[polling_data->pipe_index].description->interface_subclass,
    73             pipe->max_packet_size);
     77        if (polling_data->debug > 0) {
     78                usb_endpoint_mapping_t *mapping
     79                    = &polling_data->dev->pipes[polling_data->pipe_index];
     80                usb_log_debug("Poll%p: started polling of `%s' - " \
     81                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
     84                    (int) mapping->interface->interface_number,
     85                    usb_str_class(mapping->interface->interface_class),
     86                    (int) mapping->interface->interface_subclass,
     87                    (int) mapping->interface->interface_protocol,
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
    7490
    7591        size_t failed_attempts = 0;
    76         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     92        while (failed_attempts <= polling_data->max_failures) {
    7793                int rc;
    7894
     
    8197                    polling_data->request_size, &actual_size);
    8298
    83                
    84 //              if (rc == ESTALL) {
    85 //                      usb_log_debug("Seding clear feature...\n");
    86 //                      usb_request_clear_feature(pipe, USB_REQUEST_TYPE_STANDARD,
    87 //                        USB_REQUEST_RECIPIENT_ENDPOINT, 0, pipe->endpoint_no);
    88 //                      continue;
    89 //              }
     99                if (polling_data->debug > 1) {
     100                        if (rc == EOK) {
     101                                usb_log_debug(
     102                                    "Poll%p: received: '%s' (%zuB).\n",
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
     105                                        actual_size, 16),
     106                                    actual_size);
     107                        } else {
     108                                usb_log_debug(
     109                                    "Poll%p: polling failed: %s.\n",
     110                                    polling_data, str_error(rc));
     111                        }
     112                }
     113
     114                /* If the pipe stalled, we can try to reset the stall. */
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     116                        /*
     117                         * We ignore error here as this is usually a futile
     118                         * attempt anyway.
     119                         */
     120                        usb_request_clear_endpoint_halt(
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
     123                }
    90124
    91125                if (rc != EOK) {
     126                        if (polling_data->on_error != NULL) {
     127                                bool cont = polling_data->on_error(
     128                                    polling_data->dev, rc,
     129                                    polling_data->custom_arg);
     130                                if (!cont) {
     131                                        failed_attempts
     132                                            = polling_data->max_failures;
     133                                }
     134                        }
    92135                        failed_attempts++;
    93136                        continue;
     
    95138
    96139                /* We have the data, execute the callback now. */
    97                 bool carry_on = polling_data->callback(polling_data->dev,
     140                bool carry_on = polling_data->on_data(polling_data->dev,
    98141                    polling_data->buffer, actual_size,
    99142                    polling_data->custom_arg);
     
    106149                /* Reset as something might be only a temporary problem. */
    107150                failed_attempts = 0;
    108         }
    109 
    110         if (failed_attempts > 0) {
    111                 usb_log_error(
    112                     "Polling of device `%s' terminated: recurring failures.\n",
    113                     polling_data->dev->ddf_dev->name);
    114         }
    115 
    116         if (polling_data->terminated_callback != NULL) {
    117                 polling_data->terminated_callback(polling_data->dev,
     151
     152                /* Take a rest before next request. */
     153                async_usleep(polling_data->delay);
     154        }
     155
     156        if (polling_data->on_polling_end != NULL) {
     157                polling_data->on_polling_end(polling_data->dev,
    118158                    failed_attempts > 0, polling_data->custom_arg);
     159        }
     160
     161        if (polling_data->debug > 0) {
     162                if (failed_attempts > 0) {
     163                        usb_log_error(
     164                            "Polling of device `%s' terminated: %s.\n",
     165                            polling_data->dev->ddf_dev->name,
     166                            "recurring failures");
     167                } else {
     168                        usb_log_debug(
     169                            "Polling of device `%s' terminated by user.\n",
     170                            polling_data->dev->ddf_dev->name
     171                        );
     172                }
    119173        }
    120174
     
    159213        }
    160214
     215        usb_device_auto_polling_t *auto_polling
     216            = malloc(sizeof(usb_device_auto_polling_t));
     217        if (auto_polling == NULL) {
     218                return ENOMEM;
     219        }
     220
     221        auto_polling->debug = 1;
     222        auto_polling->auto_clear_halt = true;
     223        auto_polling->delay = 0;
     224        auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
     225        auto_polling->on_data = callback;
     226        auto_polling->on_polling_end = terminated_callback;
     227        auto_polling->on_error = NULL;
     228
     229        int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     230           request_size, arg);
     231
     232        free(auto_polling);
     233
     234        return rc;
     235}
     236
     237/** Start automatic device polling over interrupt in pipe.
     238 *
     239 * The polling settings is copied thus it is okay to destroy the structure
     240 * after this function returns.
     241 *
     242 * @warning There is no guarantee when the request to the device
     243 * will be sent for the first time (it is possible that this
     244 * first request would be executed prior to return from this function).
     245 *
     246 * @param dev Device to be periodically polled.
     247 * @param pipe_index Index of the endpoint pipe used for polling.
     248 * @param polling Polling settings.
     249 * @param request_size How many bytes to ask for in each request.
     250 * @param arg Custom argument (passed as is to the callbacks).
     251 * @return Error code.
     252 * @retval EOK New fibril polling the device was already started.
     253 */
     254int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     255    usb_device_auto_polling_t *polling,
     256    size_t request_size, void *arg)
     257{
     258        if (dev == NULL) {
     259                return EBADMEM;
     260        }
     261        if (pipe_index >= dev->pipes_count) {
     262                return EINVAL;
     263        }
     264        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     265            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     266                return EINVAL;
     267        }
     268        if ((polling == NULL) || (polling->on_data == NULL)) {
     269                return EBADMEM;
     270        }
     271
    161272        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    162273        if (polling_data == NULL) {
     
    164275        }
    165276
    166         /* Allocate now to prevent immediate failure in the polling fibril. */
    167         polling_data->buffer = malloc(request_size);
     277        /* Fill-in the data. */
     278        polling_data->buffer = malloc(sizeof(request_size));
    168279        if (polling_data->buffer == NULL) {
    169280                free(polling_data);
    170281                return ENOMEM;
    171282        }
     283        polling_data->request_size = request_size;
    172284        polling_data->dev = dev;
    173285        polling_data->pipe_index = pipe_index;
    174         polling_data->callback = callback;
    175         polling_data->terminated_callback = terminated_callback;
    176         polling_data->request_size = request_size;
    177286        polling_data->custom_arg = arg;
     287
     288        polling_data->debug = polling->debug;
     289        polling_data->max_failures = polling->max_failures;
     290        if (polling->delay >= 0) {
     291                polling_data->delay = (useconds_t) polling->delay;
     292        } else {
     293                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     294                    .descriptor->poll_interval;
     295        }
     296        polling_data->auto_clear_halt = polling->auto_clear_halt;
     297
     298        polling_data->on_data = polling->on_data;
     299        polling_data->on_polling_end = polling->on_polling_end;
     300        polling_data->on_error = polling->on_error;
    178301
    179302        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    181304                free(polling_data->buffer);
    182305                free(polling_data);
    183                 /* FIXME: better error code. */
    184306                return ENOMEM;
    185307        }
    186308        fibril_add_ready(fibril);
    187309
    188         /* The allocated buffer etc. will be freed by the fibril. */
     310        /* Fibril launched. That fibril will free the allocated data. */
    189311
    190312        return EOK;
  • uspace/lib/usb/src/hidparser.c

    r380e0364 re1dbcbc  
    3939#include <mem.h>
    4040#include <usb/debug.h>
    41 
    42 /** */
     41#include <assert.h>
     42
     43/** The new report item flag. Used to determine when the item is completly
     44 * configured and should be added to the report structure
     45 */
    4346#define USB_HID_NEW_REPORT_ITEM 1
    4447
    45 /** */
    46 #define USB_HID_NO_ACTION               2
    47 
    48 /** */
     48/** No special action after the report descriptor tag is processed should be
     49 * done
     50 */
     51#define USB_HID_NO_ACTION       2
     52
     53#define USB_HID_RESET_OFFSET    3
     54
     55/** Unknown tag was founded in report descriptor data*/
    4956#define USB_HID_UNKNOWN_TAG             -99
    5057
     
    5259 * Private descriptor parser functions
    5360 */
     61int usb_hid_report_init(usb_hid_report_t *report);
     62int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
     63usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    5464int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    5565                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
     
    6171                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    6272
     73void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    6374void usb_hid_descriptor_print_list(link_t *head);
    64 int usb_hid_report_reset_local_items();
     75void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
    6576void usb_hid_free_report_list(link_t *head);
    6677usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     
    6879 * Data translation private functions
    6980 */
    70 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
     81uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
    7182inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
    72 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
    73 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
     83int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
     84uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
    7485int usb_pow(int a, int b);
    7586
     87#define USB_HID_UINT32_TO_INT32(x, size)        ((((x) & (1 << ((size) - 1))) != 0) ? -(~(x - 1) & ((1 << size) - 1)) : (x)) //(-(~((x) - 1)))
     88#define USB_HID_INT32_TO_UINT32(x, size)        (((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
    7689// TODO: tohle ma bejt asi jinde
    7790int usb_pow(int a, int b)
     
    96109 * @return Error code
    97110 */
    98 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
    99 {
    100         if(parser == NULL) {
     111int usb_hid_report_init(usb_hid_report_t *report)
     112{
     113        if(report == NULL) {
    101114                return EINVAL;
    102115        }
    103116
    104         list_initialize(&(parser->input));
    105     list_initialize(&(parser->output));
    106     list_initialize(&(parser->feature));
    107 
    108         list_initialize(&(parser->stack));
    109 
    110         parser->use_report_id = 0;
     117        memset(report, 0, sizeof(usb_hid_report_t));
     118        list_initialize(&report->reports);
     119        list_initialize(&report->collection_paths);
     120
     121        report->use_report_ids = 0;
    111122    return EOK;   
    112123}
    113124
     125int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
     126{
     127        usb_hid_report_field_t *field;
     128        int i;
     129
     130
     131        /* find or append current collection path to the list */
     132        link_t *path_it = report->collection_paths.next;
     133        usb_hid_report_path_t *path = NULL;
     134        while(path_it != &report->collection_paths) {
     135                path = list_get_instance(path_it, usb_hid_report_path_t, link);
     136               
     137                if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
     138                        break;
     139                }                       
     140                path_it = path_it->next;
     141        }
     142        if(path_it == &report->collection_paths) {
     143                path = usb_hid_report_path_clone(report_item->usage_path);                     
     144                list_append(&path->link, &report->collection_paths);                                   
     145                report->collection_paths_count++;
     146        }
     147
     148        for(i=0; i<report_item->usages_count; i++){
     149                usb_log_debug("usages (%d) - %x\n", i, report_item->usages[i]);
     150        }
     151
     152       
     153        for(i=0; i<report_item->count; i++){
     154
     155                field = malloc(sizeof(usb_hid_report_field_t));
     156                memset(field, 0, sizeof(usb_hid_report_field_t));
     157                list_initialize(&field->link);
     158
     159                /* fill the attributes */               
     160                field->collection_path = path;
     161                field->logical_minimum = report_item->logical_minimum;
     162                field->logical_maximum = report_item->logical_maximum;
     163                field->physical_minimum = report_item->physical_minimum;
     164                field->physical_maximum = report_item->physical_maximum;
     165
     166                field->usage_minimum = report_item->usage_minimum;
     167                field->usage_maximum = report_item->usage_maximum;
     168                if(report_item->extended_usage_page != 0){
     169                        field->usage_page = report_item->extended_usage_page;
     170                }
     171                else {
     172                        field->usage_page = report_item->usage_page;
     173                }
     174
     175                if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     176                        uint32_t usage;
     177                        if(report_item->type != USB_HID_REPORT_TYPE_INPUT) {
     178                                if(i < report_item->usages_count){
     179                                        usage = report_item->usages[i];
     180                                }
     181                                else {
     182                                        usage = report_item->usages[report_item->usages_count - 1];
     183                                }
     184                        }
     185                        else {
     186                                if((report_item->count - i - 1) < report_item->usages_count){
     187                                        usage = report_item->usages[(report_item->count - i - 1)];
     188                                }
     189                                else {
     190                                        usage = report_item->usages[report_item->usages_count - 1];
     191                                }
     192                        }
     193
     194                                               
     195                        if((usage & 0xFFFF0000) != 0){
     196                                field->usage_page = (usage >> 16);                                     
     197                                field->usage = (usage & 0xFFFF);
     198                        }
     199                        else {
     200                                field->usage = usage;
     201                        }
     202
     203                       
     204                }       
     205
     206                if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
     207                        if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
     208                                field->usage = report_item->usage_maximum - i;
     209                        }
     210                        else {
     211                                field->usage = report_item->usage_minimum + i;                                 
     212                        }
     213
     214                }
     215               
     216                field->size = report_item->size;
     217                field->offset = report_item->offset + (i * report_item->size);
     218                if(report_item->id != 0) {
     219                        field->offset += 8;
     220                        report->use_report_ids = 1;
     221                }
     222                field->item_flags = report_item->item_flags;
     223
     224                /* find the right report list*/
     225                usb_hid_report_description_t *report_des;
     226                report_des = usb_hid_report_find_description(report, report_item->id, report_item->type);
     227                if(report_des == NULL){
     228                        report_des = malloc(sizeof(usb_hid_report_description_t));
     229                        memset(report_des, 0, sizeof(usb_hid_report_description_t));
     230
     231                        report_des->type = report_item->type;
     232                        report_des->report_id = report_item->id;
     233                        list_initialize (&report_des->link);
     234                        list_initialize (&report_des->report_items);
     235
     236                        list_append(&report_des->link, &report->reports);
     237                        report->report_count++;
     238                }
     239
     240                /* append this field to the end of founded report list */
     241                list_append (&field->link, &report_des->report_items);
     242               
     243                /* update the sizes */
     244                report_des->bit_length += field->size;
     245                report_des->item_length++;
     246
     247        }
     248
     249
     250        return EOK;
     251}
     252
     253usb_hid_report_description_t * usb_hid_report_find_description(const usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     254{
     255        link_t *report_it = report->reports.next;
     256        usb_hid_report_description_t *report_des = NULL;
     257       
     258        while(report_it != &report->reports) {
     259                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     260
     261                if((report_des->report_id == report_id) && (report_des->type == type)){
     262                        return report_des;
     263                }
     264               
     265                report_it = report_it->next;
     266        }
     267
     268        return NULL;
     269}
    114270
    115271/** Parse HID report descriptor.
     
    119275 * @return Error code.
    120276 */
    121 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser,
     277int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    122278    const uint8_t *data, size_t size)
    123279{
     
    130286        usb_hid_report_item_t *new_report_item;
    131287        usb_hid_report_path_t *usage_path;
    132         usb_hid_report_path_t *tmp_usage_path;
    133288
    134289        size_t offset_input=0;
    135290        size_t offset_output=0;
    136291        size_t offset_feature=0;
    137        
     292
     293        link_t stack;
     294        list_initialize(&stack);       
    138295
    139296        /* parser structure initialization*/
    140         if(usb_hid_parser_init(parser) != EOK) {
     297        if(usb_hid_report_init(report) != EOK) {
    141298                return EINVAL;
    142299        }
    143300       
    144 
    145301        /*report item initialization*/
    146302        if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
     
    159315
    160316                        if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    161                                 return EINVAL; // TODO ERROR CODE
     317                                return EINVAL;
    162318                        }
    163319                       
     
    165321                        item_size = USB_HID_ITEM_SIZE(data[i]);
    166322                        class = USB_HID_ITEM_TAG_CLASS(data[i]);
    167 
    168                         usb_log_debug2(
    169                                 "i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i,
    170                             data[i], usb_hid_report_tag_data_int32(data+i+1,item_size),
    171                             tag, class, item_size);
    172323                       
    173324                        ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    174325                                                       item_size,report_item, usage_path);
    175                         usb_log_debug2("ret: %u\n", ret);
    176326                        switch(ret){
    177327                                case USB_HID_NEW_REPORT_ITEM:
    178328                                        // store report item to report and create the new one
    179                                         usb_log_debug("\nNEW REPORT ITEM: %X",ret);
    180 
    181                                         // store current usage path
     329                                        // store current collection path
    182330                                        report_item->usage_path = usage_path;
    183331                                       
    184                                         // clone path to the new one
    185                                         tmp_usage_path = usb_hid_report_path_clone(usage_path);
    186 
    187                                         // swap
    188                                         usage_path = tmp_usage_path;
    189                                         tmp_usage_path = NULL;
    190 
    191332                                        usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    192333                                        if(report_item->id != 0){
    193                                                 parser->use_report_id = 1;
     334                                                report->use_report_ids = 1;
    194335                                        }
    195336                                       
    196337                                        switch(tag) {
    197338                                                case USB_HID_REPORT_TAG_INPUT:
     339                                                        report_item->type = USB_HID_REPORT_TYPE_INPUT;
    198340                                                        report_item->offset = offset_input;
    199341                                                        offset_input += report_item->count * report_item->size;
    200                                                         usb_log_debug(" - INPUT\n");
    201                                                         list_append(&(report_item->link), &(parser->input));
    202342                                                        break;
    203343                                                case USB_HID_REPORT_TAG_OUTPUT:
     344                                                        report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    204345                                                        report_item->offset = offset_output;
    205346                                                        offset_output += report_item->count * report_item->size;
    206                                                         usb_log_debug(" - OUTPUT\n");
    207                                                                 list_append(&(report_item->link), &(parser->output));
    208347
    209348                                                        break;
    210349                                                case USB_HID_REPORT_TAG_FEATURE:
     350                                                        report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    211351                                                        report_item->offset = offset_feature;
    212352                                                        offset_feature += report_item->count * report_item->size;
    213                                                         usb_log_debug(" - FEATURE\n");
    214                                                                 list_append(&(report_item->link), &(parser->feature));
    215353                                                        break;
    216354                                                default:
     
    218356                                                    break;
    219357                                        }
    220 
    221                                         /* clone current state table to the new item */
    222                                         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    223                                                 return ENOMEM;
    224                                         }                                       
    225                                         memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
    226                                         link_initialize(&(new_report_item->link));
    227358                                       
     359                                        /*
     360                                         * append new fields to the report
     361                                         * structure                                     
     362                                         */
     363                                        usb_hid_report_append_fields(report, report_item);
     364
    228365                                        /* reset local items */
    229                                         new_report_item->usage_minimum = 0;
    230                                         new_report_item->usage_maximum = 0;
    231                                         new_report_item->designator_index = 0;
    232                                         new_report_item->designator_minimum = 0;
    233                                         new_report_item->designator_maximum = 0;
    234                                         new_report_item->string_index = 0;
    235                                         new_report_item->string_minimum = 0;
    236                                         new_report_item->string_maximum = 0;
    237 
    238                                         /* reset usage from current usage path */
    239                                         usb_hid_report_usage_path_t *path = list_get_instance(&usage_path->link, usb_hid_report_usage_path_t, link);
    240                                         path->usage = 0;
    241                                        
    242                                         report_item = new_report_item;
    243                                                                                
     366                                        usb_hid_report_reset_local_items (report_item);
     367
    244368                                        break;
     369
     370                                case USB_HID_RESET_OFFSET:
     371                                        offset_input = 0;
     372                                        offset_output = 0;
     373                                        offset_feature = 0;
     374                                        usb_hid_report_path_set_report_id (usage_path, report_item->id);
     375                                        break;
     376
    245377                                case USB_HID_REPORT_TAG_PUSH:
    246378                                        // push current state to stack
    247379                                        new_report_item = usb_hid_report_item_clone(report_item);
    248                                         list_prepend (&parser->stack, &new_report_item->link);
    249                                        
     380                                        usb_hid_report_path_t *tmp_path = usb_hid_report_path_clone(usage_path);
     381                                        new_report_item->usage_path = tmp_path;
     382
     383                                        list_prepend (&new_report_item->link, &stack);
    250384                                        break;
    251385                                case USB_HID_REPORT_TAG_POP:
    252386                                        // restore current state from stack
    253                                         if(list_empty (&parser->stack)) {
     387                                        if(list_empty (&stack)) {
    254388                                                return EINVAL;
    255389                                        }
     390                                        free(report_item);
     391                                               
     392                                        report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    256393                                       
    257                                         report_item = list_get_instance(&parser->stack, usb_hid_report_item_t, link);
    258                                         list_remove (parser->stack.next);
     394                                        usb_hid_report_usage_path_t *tmp_usage_path;
     395                                        tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
     396                                       
     397                                        usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
     398
     399                                        usb_hid_report_path_free(report_item->usage_path);
     400                                        list_initialize(&report_item->usage_path->link);
     401                                        list_remove (stack.next);
    259402                                       
    260403                                        break;
     
    279422}
    280423
    281 
    282 /**
    283  * Parse input report.
    284  *
    285  * @param data Data for report
    286  * @param size Size of report
    287  * @param callbacks Callbacks for report actions
    288  * @param arg Custom arguments
    289  *
    290  * @return Error code
    291  */
    292 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
    293         const usb_hid_report_in_callbacks_t *callbacks, void *arg)
    294 {
    295         int i;
    296         usb_hid_report_item_t item;
    297 
    298         /* fill item due to the boot protocol report descriptor */
    299         // modifier keys are in the first byte
    300         uint8_t modifiers = data[0];
    301 
    302         item.offset = 2; /* second byte is reserved */
    303         item.size = 8;
    304         item.count = 6;
    305         item.usage_minimum = 0;
    306         item.usage_maximum = 255;
    307         item.logical_minimum = 0;
    308         item.logical_maximum = 255;
    309 
    310         if (size != 8) {
    311                 return -1; //ERANGE;
    312         }
    313 
    314         uint8_t keys[6];
    315         for (i = 0; i < item.count; i++) {
    316                 keys[i] = data[i + item.offset];
    317         }
    318 
    319         callbacks->keyboard(keys, 6, modifiers, arg);
    320         return EOK;
    321 }
    322 
    323 /**
    324  * Makes output report for keyboard boot protocol
    325  *
    326  * @param leds
    327  * @param output Output report data buffer
    328  * @param size Size of the output buffer
    329  * @return Error code
    330  */
    331 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
    332 {
    333         if(size != 1){
    334                 return -1;
    335         }
    336 
    337         /* used only first five bits, others are only padding*/
    338         *data = leds;
    339         return EOK;
    340 }
    341424
    342425/**
     
    401484                       
    402485                case USB_HID_REPORT_TAG_COLLECTION:
    403                         usb_hid_report_path_append_item(usage_path, 0, 0);
    404                                                
     486                        // TODO usage_path->flags = *data;
     487                        usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);                                         
     488                        usb_hid_report_reset_local_items (report_item);
    405489                        return USB_HID_NO_ACTION;
    406490                        break;
    407491                       
    408492                case USB_HID_REPORT_TAG_END_COLLECTION:
    409                         // TODO
    410                         // znici posledni uroven ve vsech usage paths
    411                         // otazka jestli nema nicit dve, respektive novou posledni vynulovat?
    412493                        usb_hid_report_remove_last_item(usage_path);
    413494                        return USB_HID_NO_ACTION;
     
    436517        {
    437518                case USB_HID_REPORT_TAG_USAGE_PAGE:
    438                         // zmeni to jenom v poslednim poli aktualni usage path
    439                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
    440                                 usb_hid_report_tag_data_int32(data,item_size));
     519                        report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size);
    441520                        break;
    442521                case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    443                         report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     522                        report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    444523                        break;
    445524                case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    446                         report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     525                        report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    447526                        break;
    448527                case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    449                         report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
     528                        report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    450529                        break;                 
    451530                case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    452                         report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
     531                        report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
     532
    453533                        break;
    454534                case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    455                         report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
     535                        report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size);
    456536                        break;
    457537                case USB_HID_REPORT_TAG_UNIT:
    458                         report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
     538                        report_item->unit = usb_hid_report_tag_data_uint32(data,item_size);
    459539                        break;
    460540                case USB_HID_REPORT_TAG_REPORT_SIZE:
    461                         report_item->size = usb_hid_report_tag_data_int32(data,item_size);
     541                        report_item->size = usb_hid_report_tag_data_uint32(data,item_size);
    462542                        break;
    463543                case USB_HID_REPORT_TAG_REPORT_COUNT:
    464                         report_item->count = usb_hid_report_tag_data_int32(data,item_size);
     544                        report_item->count = usb_hid_report_tag_data_uint32(data,item_size);
    465545                        break;
    466546                case USB_HID_REPORT_TAG_REPORT_ID:
    467                         report_item->id = usb_hid_report_tag_data_int32(data,item_size);
     547                        report_item->id = usb_hid_report_tag_data_uint32(data,item_size);
     548                        return USB_HID_RESET_OFFSET;
    468549                        break;
    469550                case USB_HID_REPORT_TAG_PUSH:
    470551                case USB_HID_REPORT_TAG_POP:
     552                        /*
     553                         * stack operations are done in top level parsing
     554                         * function
     555                         */
    471556                        return tag;
    472557                        break;
     
    475560                        return USB_HID_NO_ACTION;
    476561        }
    477        
     562
    478563        return EOK;
    479564}
     
    494579        {
    495580                case USB_HID_REPORT_TAG_USAGE:
    496                         usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
    497                                 usb_hid_report_tag_data_int32(data,item_size));
     581                        report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
     582                        report_item->usages_count++;
    498583                        break;
    499584                case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    500                         report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
     585                        if (item_size == 3) {
     586                                // usage extended usages
     587                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     588                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     589                        }
     590                        else {
     591                                report_item->usage_minimum = usb_hid_report_tag_data_uint32(data,item_size);
     592                        }
    501593                        break;
    502594                case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    503                         report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
     595                        if (item_size == 3) {
     596                                // usage extended usages
     597                                report_item->extended_usage_page = (usb_hid_report_tag_data_uint32(data,item_size) & 0xFF00) >> 16;
     598                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size) & 0xFF;
     599                        }
     600                        else {
     601                                report_item->usage_maximum = usb_hid_report_tag_data_uint32(data,item_size);
     602                        }
    504603                        break;
    505604                case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    506                         report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
     605                        report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size);
    507606                        break;
    508607                case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    509                         report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
     608                        report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    510609                        break;
    511610                case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    512                         report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
     611                        report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    513612                        break;
    514613                case USB_HID_REPORT_TAG_STRING_INDEX:
    515                         report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
     614                        report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size);
    516615                        break;
    517616                case USB_HID_REPORT_TAG_STRING_MINIMUM:
    518                         report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
     617                        report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    519618                        break;
    520619                case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    521                         report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
     620                        report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    522621                        break;                 
    523622                case USB_HID_REPORT_TAG_DELIMITER:
    524                         report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
     623                        //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
     624                        //TODO:
     625                        //      DELIMITER STUFF
    525626                        break;
    526627               
     
    533634
    534635/**
    535  * Converts raw data to int32 (thats the maximum length of short item data)
     636 * Converts raw data to uint32 (thats the maximum length of short item data)
    536637 *
    537638 * @param Data buffer
     
    539640 * @return Converted int32 number
    540641 */
    541 int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
     642uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
    542643{
    543644        unsigned int i;
    544         int32_t result;
     645        uint32_t result;
    545646
    546647        result = 0;
     
    552653}
    553654
    554 
    555 
    556655/**
    557656 * Prints content of given list of report items.
     
    562661void usb_hid_descriptor_print_list(link_t *head)
    563662{
    564         usb_hid_report_item_t *report_item;
    565         usb_hid_report_usage_path_t *path_item;
    566         link_t *path;
     663        usb_hid_report_field_t *report_item;
    567664        link_t *item;
    568        
     665
     666
    569667        if(head == NULL || list_empty(head)) {
    570668            usb_log_debug("\tempty\n");
     
    574672        for(item = head->next; item != head; item = item->next) {
    575673               
    576                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    577 
    578                 usb_log_debug("\tOFFSET: %X\n", report_item->offset);
    579                 usb_log_debug("\tCOUNT: %X\n", report_item->count);
    580                 usb_log_debug("\tSIZE: %X\n", report_item->size);
    581                 usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
    582                 usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags));
    583                 usb_log_debug("\tUSAGE PATH:\n");
    584 
    585                 path = report_item->usage_path->link.next;
    586                 while(path != &report_item->usage_path->link)   {
    587                         path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
    588                         usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
    589                         path = path->next;
    590                 }
    591                                
    592                 usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
    593                 usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);         
    594                 usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);         
    595                 usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);                         
    596                 usb_log_debug("\tUSAGEMIN: %X\n", report_item->usage_minimum);
    597                 usb_log_debug("\tUSAGEMAX: %X\n", report_item->usage_maximum);
    598                
    599                 usb_log_debug("\n");           
     674                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     675
     676                usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
     677                usb_log_debug("\t\tSIZE: %X\n", report_item->size);                             
     678                usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
     679                usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);               
     680                usb_log_debug("\t\tPHYMIN: %d\n", report_item->physical_minimum);               
     681                usb_log_debug("\t\tPHYMAX: %d\n", report_item->physical_maximum);                               
     682                usb_log_debug("\t\ttUSAGEMIN: %X\n", report_item->usage_minimum);
     683                usb_log_debug("\t\tUSAGEMAX: %X\n", report_item->usage_maximum);
     684
     685                usb_log_debug("\t\tVALUE: %X\n", report_item->value);
     686                usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
     687                usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
     688                                               
     689//              usb_log_debug("\n");           
    600690
    601691        }
     
    609699 * @return void
    610700 */
    611 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
    612 {
    613         if(parser == NULL) {
     701void usb_hid_descriptor_print(usb_hid_report_t *report)
     702{
     703        if(report == NULL) {
    614704                return;
    615705        }
    616        
    617         usb_log_debug("INPUT:\n");
    618         usb_hid_descriptor_print_list(&parser->input);
    619        
    620         usb_log_debug("OUTPUT: \n");
    621         usb_hid_descriptor_print_list(&parser->output);
    622        
    623         usb_log_debug("FEATURE:\n");   
    624         usb_hid_descriptor_print_list(&parser->feature);
    625 
     706
     707        link_t *report_it = report->reports.next;
     708        usb_hid_report_description_t *report_des;
     709
     710        while(report_it != &report->reports) {
     711                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     712                usb_log_debug("Report ID: %d\n", report_des->report_id);
     713                usb_log_debug("\tType: %d\n", report_des->type);
     714                usb_log_debug("\tLength: %d\n", report_des->bit_length);               
     715                usb_log_debug("\tItems: %d\n", report_des->item_length);               
     716
     717                usb_hid_descriptor_print_list(&report_des->report_items);
     718
     719
     720                link_t *path_it = report->collection_paths.next;
     721                while(path_it != &report->collection_paths) {
     722                        usb_hid_print_usage_path (list_get_instance(path_it, usb_hid_report_path_t, link));
     723                        path_it = path_it->next;
     724                }
     725               
     726                report_it = report_it->next;
     727        }
    626728}
    627729
     
    667769 * @return void
    668770 */
    669 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
    670 {
    671         if(parser == NULL){
     771void usb_hid_free_report(usb_hid_report_t *report)
     772{
     773        if(report == NULL){
    672774                return;
    673775        }
    674776
    675         parser->use_report_id = 0;
    676 
    677         usb_hid_free_report_list(&parser->input);
    678         usb_hid_free_report_list(&parser->output);
    679         usb_hid_free_report_list(&parser->feature);
    680 
     777        // free collection paths
     778        usb_hid_report_path_t *path;
     779        while(!list_empty(&report->collection_paths)) {
     780                path = list_get_instance(report->collection_paths.next, usb_hid_report_path_t, link);
     781                usb_hid_report_path_free(path);         
     782        }
     783       
     784        // free report items
     785        usb_hid_report_description_t *report_des;
     786        usb_hid_report_field_t *field;
     787        while(!list_empty(&report->reports)) {
     788                report_des = list_get_instance(report->reports.next, usb_hid_report_description_t, link);
     789                list_remove(&report_des->link);
     790               
     791                while(!list_empty(&report_des->report_items)) {
     792                        field = list_get_instance(report_des->report_items.next, usb_hid_report_field_t, link);
     793                        list_remove(&field->link);
     794
     795                        free(field);
     796                }
     797               
     798                free(report_des);
     799        }
     800       
    681801        return;
    682802}
     
    688808 * @param parser Opaque HID report parser structure.
    689809 * @param data Data for the report.
    690  * @param callbacks Callbacks for report actions.
    691  * @param arg Custom argument (passed through to the callbacks).
    692810 * @return Error code.
    693811 */
    694 int usb_hid_parse_report(const usb_hid_report_parser_t *parser, 
    695     const uint8_t *data, size_t size,
    696     usb_hid_report_path_t *path, int flags,
    697     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
     812int usb_hid_parse_report(const usb_hid_report_t *report, 
     813    const uint8_t *data, size_t size, uint8_t *report_id)
    698814{
    699815        link_t *list_item;
    700         usb_hid_report_item_t *item;
    701         uint8_t *keys;
    702         uint8_t item_value;
    703         size_t key_count=0;
    704         size_t i=0;
    705         size_t j=0;
    706         uint8_t report_id = 0;
    707 
    708         if(parser == NULL) {
     816        usb_hid_report_field_t *item;
     817
     818        usb_hid_report_description_t *report_des;
     819        usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
     820
     821        if(report == NULL) {
    709822                return EINVAL;
    710823        }
    711        
    712         /* get the size of result array */
    713         key_count = usb_hid_report_input_length(parser, path, flags);
    714 
    715         if(!(keys = malloc(sizeof(uint8_t) * key_count))){
    716                 return ENOMEM;
    717         }
    718 
    719         if(parser->use_report_id != 0) {
    720                 report_id = data[0];
    721                 usb_hid_report_path_set_report_id(path, report_id);
    722         }
     824
     825        if(report->use_report_ids != 0) {
     826                *report_id = data[0];
     827        }       
     828        else {
     829                *report_id = 0;
     830        }
     831
     832
     833        report_des = usb_hid_report_find_description(report, *report_id, type);
    723834
    724835        /* read data */
    725         list_item = parser->input.next;   
    726         while(list_item != &(parser->input)) {
    727 
    728                 item = list_get_instance(list_item, usb_hid_report_item_t, link);
    729 
    730                 if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
    731                    (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
    732                         for(j=0; j<(size_t)(item->count); j++) {
    733                                 if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
    734                                    ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
    735                                         // variable item
    736                                         keys[i++] = usb_hid_translate_data(item, data,j);
    737                                 }
    738                                 else {
    739                                         // bitmapa
    740                                         if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
    741                                                 keys[i++] = (item->count - 1 - j) + item->usage_minimum;
    742                                         }
    743                                         else {
    744                                                 keys[i++] = 0;
    745                                         }
    746                                 }
    747                         }
     836        list_item = report_des->report_items.next;         
     837        while(list_item != &(report_des->report_items)) {
     838
     839                item = list_get_instance(list_item, usb_hid_report_field_t, link);
     840
     841                if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
     842                       
     843                        if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
     844
     845                                // array
     846                                item->value = usb_hid_translate_data(item, data);
     847                            item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
     848                        }
     849                        else {
     850                                // variable item
     851                                item->value = usb_hid_translate_data(item, data);                               
     852                        }                               
    748853                }
    749854                list_item = list_item->next;
    750855        }
    751 
    752         callbacks->keyboard(keys, key_count, report_id, arg);
    753856           
    754         free(keys);     
    755857        return EOK;
    756858       
     
    758860
    759861/**
    760  * Translate data from the report as specified in report descriptor
     862 * Translate data from the report as specified in report descriptor item
    761863 *
    762864 * @param item Report descriptor item with definition of translation
     
    765867 * @return Translated data
    766868 */
    767 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
     869int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
    768870{
    769871        int resolution;
     
    771873        int part_size;
    772874       
    773         int32_t value;
     875        int32_t value=0;
    774876        int32_t mask;
    775877        const uint8_t *foo;
    776878
    777         // now only common numbers llowed
     879        // now only shot tags are allowed
    778880        if(item->size > 32) {
    779881                return 0;
    780882        }
    781883
    782         if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
     884        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
    783885                item->physical_minimum = item->logical_minimum;
    784                 item->physical_maximum = item->logical_maximum;         
    785         }
     886                item->physical_maximum = item->logical_maximum;                 
     887        }
     888       
    786889
    787890        if(item->physical_maximum == item->physical_minimum){
     
    794897        }
    795898
    796         offset = item->offset + (j * item->size);
    797         if(item->id != 0) {
    798                 offset += 8;
    799                 usb_log_debug("MOVED OFFSET BY 1Byte, REPORT_ID(%d)\n", item->id);
    800         }
    801        
     899        offset = item->offset;
    802900        // FIXME
    803         if((offset/8) != ((offset+item->size)/8)) {
    804                 usb_log_debug2("offset %d\n", offset);
     901        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
    805902               
    806903                part_size = ((offset+item->size)%8);
    807                 usb_log_debug2("part size %d\n",part_size);
    808 
    809                 // the higher one
    810                 foo = data+(offset/8);
    811                 mask =  ((1 << (item->size-part_size))-1);
    812                 value = (*foo & mask) << part_size;
    813 
    814                 usb_log_debug2("hfoo %x\n", *foo);
    815                 usb_log_debug2("hmaska %x\n",  mask);
    816                 usb_log_debug2("hval %d\n", value);             
    817 
    818                 // the lower one
    819                 foo = data+((offset+item->size)/8);
    820                 mask =  ((1 << part_size)-1) << (8-part_size);
    821                 value += ((*foo & mask) >> (8-part_size));
    822 
    823                 usb_log_debug2("lfoo %x\n", *foo);
    824                 usb_log_debug2("lmaska %x\n",  mask);
    825                 usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));             
    826                 usb_log_debug2("val %d\n", value);
    827                
    828                
     904
     905                size_t i=0;
     906                for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
     907                        if(i == (size_t)(offset/8)) {
     908                                // the higher one
     909                                foo = data + i;
     910                                mask =  ((1 << (item->size-part_size))-1);
     911                                value = (*foo & mask) << part_size;
     912                        }
     913                        else if(i == ((offset+item->size-1)/8)){
     914                                // the lower one
     915                                foo = data + i;
     916                                mask =  ((1 << part_size)-1) << (8-part_size);
     917                                value += ((*foo & mask) >> (8-part_size));
     918                        }
     919                        else {
     920                                value = value << 8;
     921                                value += *(data + 1);
     922                        }
     923                }
    829924        }
    830925        else {         
     
    832927                mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
    833928                value = (*foo & mask) >> (8-((offset%8)+item->size));
    834 
    835                 usb_log_debug2("offset %d\n", offset);
    836        
    837                 usb_log_debug2("foo %x\n", *foo);
    838                 usb_log_debug2("maska %x\n",  mask);
    839                 usb_log_debug2("val %d\n", value);                             
    840         }
    841 
    842         usb_log_debug2("---\n\n");
     929        }
     930
     931        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     932                value = USB_HID_UINT32_TO_INT32(value, item->size);
     933        }
    843934
    844935        return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
     
    847938
    848939/**
    849  *
    850  *
    851  * @param parser
    852  * @param path
    853  * @param flags
    854  * @return
    855  */
    856 size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
     940 * Returns number of items in input report which are accessible by given usage path
     941 *
     942 * @param parser Opaque report descriptor structure
     943 * @param path Usage path specification
     944 * @param flags Usage path comparison flags
     945 * @return Number of items in input report
     946 */
     947size_t usb_hid_report_input_length(const usb_hid_report_t *report,
    857948        usb_hid_report_path_t *path, int flags)
    858949{       
     950       
    859951        size_t ret = 0;
    860         link_t *item;
    861         usb_hid_report_item_t *report_item;
    862 
    863         if(parser == NULL) {
     952
     953        if(report == NULL) {
    864954                return 0;
    865955        }
    866        
    867         item = parser->input.next;
    868         while(&parser->input != item) {
    869                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    870                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    871                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    872                         ret += report_item->count;
    873                 }
    874 
    875                 item = item->next;
    876         }
     956
     957        usb_hid_report_description_t *report_des;
     958        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_INPUT);
     959        if(report_des == NULL) {
     960                return 0;
     961        }
     962
     963        link_t *field_it = report_des->report_items.next;
     964        usb_hid_report_field_t *field;
     965        while(field_it != &report_des->report_items) {
     966
     967                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     968                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     969                       
     970                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     971                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     972                                ret++;
     973                        }
     974                        usb_hid_report_remove_last_item (field->collection_path);
     975                }
     976               
     977                field_it = field_it->next;
     978        }
    877979
    878980        return ret;
    879 }
    880 
    881 
    882 /**
    883  *
    884  * @param usage_path
    885  * @param usage_page
    886  * @param usage
    887  * @return
     981        }
     982
     983
     984/**
     985 * Appends one item (couple of usage_path and usage) into the usage path
     986 * structure
     987 *
     988 * @param usage_path Usage path structure
     989 * @param usage_page Usage page constant
     990 * @param usage Usage constant
     991 * @return Error code
    888992 */
    889993int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
     
    8991003        item->usage = usage;
    9001004        item->usage_page = usage_page;
    901        
    902         list_append (&usage_path->link, &item->link);
     1005        item->flags = 0;
     1006       
     1007        list_append (&item->link, &usage_path->head);
    9031008        usage_path->depth++;
    9041009        return EOK;
     
    9061011
    9071012/**
    908  *
    909  * @param usage_path
    910  * @return
     1013 * Removes last item from the usage path structure
     1014 * @param usage_path 
     1015 * @return void
    9111016 */
    9121017void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
     
    9141019        usb_hid_report_usage_path_t *item;
    9151020       
    916         if(!list_empty(&usage_path->link)){
    917                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);             
    918                 list_remove(usage_path->link.prev);
     1021        if(!list_empty(&usage_path->head)){
     1022                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);             
     1023                list_remove(usage_path->head.prev);
    9191024                usage_path->depth--;
    9201025                free(item);
     
    9231028
    9241029/**
     1030 * Nulls last item of the usage path structure.
    9251031 *
    9261032 * @param usage_path
    927  * @return
     1033 * @return void
    9281034 */
    9291035void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
     
    9311037        usb_hid_report_usage_path_t *item;
    9321038       
    933         if(!list_empty(&usage_path->link)){     
    934                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1039        if(!list_empty(&usage_path->head)){     
     1040                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9351041                memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    9361042        }
     
    9381044
    9391045/**
    940  *
    941  * @param usage_path
    942  * @param tag
    943  * @param data
    944  * @return
     1046 * Modifies last item of usage path structure by given usage page or usage
     1047 *
     1048 * @param usage_path Opaque usage path structure
     1049 * @param tag Class of currently processed tag (Usage page tag falls into Global
     1050 * class but Usage tag into the Local)
     1051 * @param data Value of the processed tag
     1052 * @return void
    9451053 */
    9461054void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
     
    9481056        usb_hid_report_usage_path_t *item;
    9491057       
    950         if(!list_empty(&usage_path->link)){     
    951                 item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
     1058        if(!list_empty(&usage_path->head)){     
     1059                item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    9521060
    9531061                switch(tag) {
     
    9631071}
    9641072
    965 /**
    966  *
    967  *
    968  * @param report_path
    969  * @param path
    970  * @param flags
    971  * @return
     1073
     1074void usb_hid_print_usage_path(usb_hid_report_path_t *path)
     1075{
     1076        usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
     1077        usb_log_debug("\tLENGTH: %d\n", path->depth);
     1078
     1079        link_t *item = path->head.next;
     1080        usb_hid_report_usage_path_t *path_item;
     1081        while(item != &path->head) {
     1082
     1083                path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
     1084                usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
     1085                usb_log_debug("\tUSAGE: %X\n", path_item->usage);
     1086                usb_log_debug("\tFLAGS: %d\n", path_item->flags);               
     1087               
     1088                item = item->next;
     1089        }
     1090}
     1091
     1092/**
     1093 * Compares two usage paths structures
     1094 *
     1095 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
     1096 *
     1097 * @param report_path usage path structure to compare
     1098 * @param path usage patrh structure to compare
     1099 * @param flags Flags determining the mode of comparison
     1100 * @return EOK if both paths are identical, non zero number otherwise
    9721101 */
    9731102int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
     
    10031132                                }
    10041133
    1005                                 report_link = report_path->link.next;
    1006                                 path_link = path->link.next;
     1134                                report_link = report_path->head.next;
     1135                                path_link = path->head.next;
    10071136                       
    1008                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1137                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10091138                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10101139                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10201149                                }
    10211150
    1022                                 if((report_link == &report_path->link) && (path_link == &path->link)) {
     1151                                if(((report_link == &report_path->head) && (path_link == &path->head)) ||
     1152                                   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && (path_link = &path->head) && (report_link == report_path->head.prev))) {
    10231153                                        return EOK;
    10241154                                }
     
    10301160                /* compare with only the end of path*/
    10311161                case USB_HID_PATH_COMPARE_END:
    1032                                 report_link = report_path->link.prev;
    1033                                 path_link = path->link.prev;
    1034 
    1035                                 if(list_empty(&path->link)){
     1162
     1163                                if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
     1164                                        report_link = report_path->head.prev->prev;
     1165                                }
     1166                                else {
     1167                                        report_link = report_path->head.prev;
     1168                                }
     1169                                path_link = path->head.prev;
     1170
     1171                                if(list_empty(&path->head)){
    10361172                                        return EOK;
    10371173                                }
    10381174                       
    1039                                 while((report_link != &report_path->link) && (path_link != &path->link)) {
     1175                                while((report_link != &report_path->head) && (path_link != &path->head)) {
    10401176                                        report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    10411177                                        path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
     
    10511187                                }
    10521188
    1053                                 if(path_link == &path->link) {
     1189                                if(path_link == &path->head) {
    10541190                                        return EOK;
    10551191                                }
     
    10701206
    10711207/**
    1072  *
    1073  * @return
     1208 * Allocates and initializes new usage path structure.
     1209 *
     1210 * @return Initialized usage path structure
    10741211 */
    10751212usb_hid_report_path_t *usb_hid_report_path(void)
     
    10771214        usb_hid_report_path_t *path;
    10781215        path = malloc(sizeof(usb_hid_report_path_t));
    1079         if(!path){
     1216        if(path == NULL){
    10801217                return NULL;
    10811218        }
     
    10841221                path->report_id = 0;
    10851222                list_initialize(&path->link);
     1223                list_initialize(&path->head);
    10861224                return path;
    10871225        }
     
    10891227
    10901228/**
    1091  *
    1092  * @param path
     1229 * Releases given usage path structure.
     1230 *
     1231 * @param path usage path structure to release
    10931232 * @return void
    10941233 */
    10951234void usb_hid_report_path_free(usb_hid_report_path_t *path)
    10961235{
    1097         while(!list_empty(&path->link)){
     1236        while(!list_empty(&path->head)){
    10981237                usb_hid_report_remove_last_item(path);
    10991238        }
     1239
     1240        list_remove(&path->link);
     1241        free(path);
    11001242}
    11011243
     
    11041246 * Clone content of given usage path to the new one
    11051247 *
    1106  * @param usage_path
    1107  * @return
     1248 * @param usage_path Usage path structure to clone
     1249 * @return New copy of given usage path structure
    11081250 */
    11091251usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    11101252{
     1253        link_t *path_link;
    11111254        usb_hid_report_usage_path_t *path_item;
    1112         link_t *path_link;
     1255        usb_hid_report_usage_path_t *new_path_item;
    11131256        usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    11141257
     
    11161259                return NULL;
    11171260        }
    1118        
    1119         if(list_empty(&usage_path->link)){
     1261
     1262        new_usage_path->report_id = usage_path->report_id;
     1263       
     1264        if(list_empty(&usage_path->head)){
    11201265                return new_usage_path;
    11211266        }
    11221267
    1123         path_link = usage_path->link.next;
    1124         while(path_link != &usage_path->link) {
     1268        path_link = usage_path->head.next;
     1269        while(path_link != &usage_path->head) {
    11251270                path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    1126                 usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
     1271                new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
     1272                if(new_path_item == NULL) {
     1273                        return NULL;
     1274                }
     1275               
     1276                list_initialize (&new_path_item->link);         
     1277                new_path_item->usage_page = path_item->usage_page;
     1278                new_path_item->usage = path_item->usage;               
     1279                new_path_item->flags = path_item->flags;               
     1280               
     1281                list_append(&new_path_item->link, &new_usage_path->head);
     1282                new_usage_path->depth++;
    11271283
    11281284                path_link = path_link->next;
     
    11351291/*** OUTPUT API **/
    11361292
    1137 /** Allocates output report buffer
    1138  *
    1139  * @param parser
    1140  * @param size
    1141  * @return
    1142  */
    1143 uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
    1144 {
    1145         if(parser == NULL) {
     1293/**
     1294 * Allocates output report buffer for output report
     1295 *
     1296 * @param parser Report parsed structure
     1297 * @param size Size of returned buffer
     1298 * @param report_id Report id of created output report
     1299 * @return Returns allocated output buffer for specified output
     1300 */
     1301uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id)
     1302{
     1303        if(report == NULL) {
    11461304                *size = 0;
    11471305                return NULL;
    11481306        }
    1149        
    1150         // read the last output report item
    1151         usb_hid_report_item_t *last;
    1152         link_t *link;
    1153 
    1154         link = parser->output.prev;
    1155         if(link != &parser->output) {
    1156                 last = list_get_instance(link, usb_hid_report_item_t, link);
    1157                 *size = (last->offset + (last->size * last->count)) / 8;
    1158 
    1159                 uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));
    1160                 memset(buffer, 0, sizeof(uint8_t) * (*size));
    1161                 usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));
    1162 
    1163                 return buffer;
     1307
     1308        link_t *report_it = report->reports.next;
     1309        usb_hid_report_description_t *report_des = NULL;
     1310        while(report_it != &report->reports) {
     1311                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1312                if((report_des->report_id == report_id) && (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
     1313                        break;
     1314                }
     1315
     1316                report_it = report_it->next;
     1317        }
     1318
     1319        if(report_des == NULL){
     1320                *size = 0;
     1321                return NULL;
    11641322        }
    11651323        else {
    1166                 *size = 0;             
    1167                 return NULL;
     1324                *size = (report_des->bit_length + (8 - 1))/8;
     1325                uint8_t *ret = malloc((*size) * sizeof(uint8_t));
     1326                memset(ret, 0, (*size) * sizeof(uint8_t));
     1327                return ret;
    11681328        }
    11691329}
     
    11731333 *
    11741334 * @param output Output report buffer
    1175  * @return
     1335 * @return void
    11761336 */
    11771337void usb_hid_report_output_free(uint8_t *output)
     
    11851345/** Returns size of output for given usage path
    11861346 *
    1187  * @param parser
    1188  * @param path
    1189  * @param flags
    1190  * @return
    1191  */
    1192 size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
     1347 * @param parser Opaque report parser structure
     1348 * @param path Usage path specified which items will be thought for the output
     1349 * @param flags Flags of usage path structure comparison
     1350 * @return Number of items matching the given usage path
     1351 */
     1352size_t usb_hid_report_output_size(usb_hid_report_t *report,
    11931353                                  usb_hid_report_path_t *path, int flags)
    11941354{
    1195         size_t ret = 0;
    1196         link_t *item;
    1197         usb_hid_report_item_t *report_item;
    1198 
    1199         if(parser == NULL) {
     1355        size_t ret = 0;
     1356        usb_hid_report_description_t *report_des;
     1357
     1358        if(report == NULL) {
    12001359                return 0;
    12011360        }
    12021361
    1203         item = parser->output.next;
    1204         while(&parser->output != item) {
    1205                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1206                 if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
    1207                    (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
    1208                         ret += report_item->count;
    1209                 }
    1210 
    1211                 item = item->next;
    1212         }
     1362        report_des = usb_hid_report_find_description (report, path->report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1363        if(report_des == NULL){
     1364                return 0;
     1365        }
     1366       
     1367        link_t *field_it = report_des->report_items.next;
     1368        usb_hid_report_field_t *field;
     1369        while(field_it != &report_des->report_items) {
     1370
     1371                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1372                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1373                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1374                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1375                                ret++;
     1376                        }
     1377                        usb_hid_report_remove_last_item (field->collection_path);
     1378                }
     1379               
     1380                field_it = field_it->next;
     1381        }
    12131382
    12141383        return ret;
     
    12161385}
    12171386
    1218 /** Updates the output report buffer by translated given data
    1219  *
    1220  * @param parser
    1221  * @param path
    1222  * @param flags
    1223  * @param buffer
    1224  * @param size
    1225  * @param data
    1226  * @param data_size
    1227  * @return
    1228  */
    1229 int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
    1230                                     usb_hid_report_path_t *path, int flags,
    1231                                     uint8_t *buffer, size_t size,
    1232                                     int32_t *data, size_t data_size)
    1233 {
    1234         usb_hid_report_item_t *report_item;
     1387/** Makes the output report buffer for data given in the report structure
     1388 *
     1389 * @param parser Opaque report parser structure
     1390 * @param path Usage path specifing which parts of output will be set
     1391 * @param flags Usage path structure comparison flags
     1392 * @param buffer Output buffer
     1393 * @param size Size of output buffer
     1394 * @return Error code
     1395 */
     1396int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     1397                                    uint8_t *buffer, size_t size)
     1398{
    12351399        link_t *item;   
    1236         size_t idx=0;
    1237         int i=0;
    12381400        int32_t value=0;
    12391401        int offset;
    12401402        int length;
    12411403        int32_t tmp_value;
    1242         size_t offset_prefix = 0;
    1243        
    1244         if(parser == NULL) {
     1404       
     1405        if(report == NULL) {
    12451406                return EINVAL;
    12461407        }
    12471408
    1248         if(parser->use_report_id != 0) {
    1249                 buffer[0] = path->report_id;
    1250                 offset_prefix = 8;
     1409        if(report->use_report_ids != 0) {
     1410                buffer[0] = report_id;         
    12511411        }
    12521412
    12531413        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    1254         usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
    1255 
    1256         item = parser->output.next;     
    1257         while(item != &parser->output) {
    1258                 report_item = list_get_instance(item, usb_hid_report_item_t, link);
    1259 
    1260                 for(i=0; i<report_item->count; i++) {
    1261 
    1262                         if(idx >= data_size) {
    1263                                 break;
    1264                         }
    1265 
    1266                         if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
    1267                                 ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
     1414       
     1415        usb_hid_report_description_t *report_des;
     1416        report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
     1417        if(report_des == NULL){
     1418                return EINVAL;
     1419        }
     1420
     1421        usb_hid_report_field_t *report_item;   
     1422        item = report_des->report_items.next;   
     1423        while(item != &report_des->report_items) {
     1424                report_item = list_get_instance(item, usb_hid_report_field_t, link);
     1425
     1426                        if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
    12681427                                       
    1269 //                              // variable item
    1270                                 value = usb_hid_translate_data_reverse(report_item, data[idx++]);
    1271                                 offset = report_item->offset + (i * report_item->size) + offset_prefix;
     1428                                // array
     1429                                value = usb_hid_translate_data_reverse(report_item, report_item->value);
     1430                                offset = report_item->offset;
    12721431                                length = report_item->size;
    12731432                        }
    12741433                        else {
    1275                                 //bitmap
    1276                                 value += usb_hid_translate_data_reverse(report_item, data[idx++]);
    1277                                 offset = report_item->offset + offset_prefix;
    1278                                 length = report_item->size * report_item->count;
     1434                                // variable item
     1435                                value  = usb_hid_translate_data_reverse(report_item, report_item->value);
     1436                                offset = report_item->offset;
     1437                                length = report_item->size;
    12791438                        }
    12801439
     
    12951454                        }
    12961455                        else {
    1297                                 // je to ve dvou!! FIXME: melo by to umet delsi jak 2
    1298 
    1299                                 // konec prvniho -- dolni x bitu
    1300                                 tmp_value = value;
    1301                                 tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
    1302                                 tmp_value = tmp_value << (offset%8);
    1303 
     1456                                int i = 0;
    13041457                                uint8_t mask = 0;
    1305                                 mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
    1306                                 buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
    1307 
    1308                                 // a ted druhej -- hornich length-x bitu
    1309                                 value = value >> (8 - (offset % 8));
    1310                                 value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
     1458                                for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
     1459                                        if(i == (offset/8)) {
     1460                                                tmp_value = value;
     1461                                                tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);                             
     1462                                                tmp_value = tmp_value << (offset%8);
     1463       
     1464                                                mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
     1465                                                buffer[i] = (buffer[i] & mask) | tmp_value;                     
     1466                                        }
     1467                                        else if (i == ((offset + length -1)/8)) {
     1468                                               
     1469                                                value = value >> (length - ((offset + length) % 8));
     1470                                                value = value & ((1 << (length - ((offset + length) % 8))) - 1);
    13111471                               
    1312                                 mask = ((1 << (length - (8 - (offset % 8)))) - 1);
    1313                                 buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
    1314                         }
    1315 
    1316                 }
    1317 
     1472                                                mask = (1 << (length - ((offset + length) % 8))) - 1;
     1473                                                buffer[i] = (buffer[i] & mask) | value;
     1474                                        }
     1475                                        else {
     1476                                                buffer[i] = value & (0xFF << i);
     1477                                        }
     1478                                }
     1479                        }
     1480
     1481
     1482                // reset value
     1483                report_item->value = 0;
     1484               
    13181485                item = item->next;
    13191486        }
    1320 
     1487       
    13211488        usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
    13221489
     
    13251492
    13261493/**
    1327  *
    1328  * @param item
    1329  * @param value
    1330  * @return
    1331  */
    1332 int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
     1494 * Translate given data for putting them into the outoput report
     1495 * @param item Report item structure
     1496 * @param value Value to translate
     1497 * @return ranslated value
     1498 */
     1499uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int value)
    13331500{
    13341501        int ret=0;
     
    13391506        }
    13401507
     1508        if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
     1509                item->physical_minimum = item->logical_minimum;
     1510                item->physical_maximum = item->logical_maximum;                 
     1511        }
     1512       
     1513
    13411514        if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
    13421515
    13431516                // variable item
    1344                 if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
    1345                         item->physical_minimum = item->logical_minimum;
    1346                         item->physical_maximum = item->logical_maximum;
    1347                 }
    1348 
    13491517                if(item->physical_maximum == item->physical_minimum){
    13501518                    resolution = 1;
     
    13691537        }
    13701538
    1371 
    1372         return ret;
    1373 }
    1374 
    1375 
     1539        if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
     1540                return USB_HID_INT32_TO_UINT32(ret, item->size);
     1541        }
     1542        return (int32_t)ret;
     1543}
     1544
     1545/**
     1546 * Sets report id in usage path structure
     1547 *
     1548 * @param path Usage path structure
     1549 * @param report_id Report id to set
     1550 * @return Error code
     1551 */
    13761552int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    13771553{
     
    13811557
    13821558        path->report_id = report_id;
     1559        return EOK;
     1560}
     1561
     1562/**
     1563 *
     1564 *
     1565 *
     1566 *
     1567 *
     1568 */
     1569int usb_hid_report_output_set_data(usb_hid_report_t *report,
     1570                                   usb_hid_report_path_t *path, int flags,
     1571                                  int *data, size_t data_size)
     1572{
     1573        size_t data_idx = 0;
     1574        if(report == NULL){
     1575                return EINVAL;
     1576        }
     1577
     1578        usb_hid_report_description_t *report_des;
     1579        report_des = usb_hid_report_find_description (report, path->report_id,
     1580                                                      USB_HID_REPORT_TYPE_OUTPUT);
     1581        if(report_des == NULL){
     1582                return EINVAL;
     1583        }
     1584
     1585        usb_hid_report_field_t *field;
     1586        link_t *field_it = report_des->report_items.next;       
     1587        while(field_it != &report_des->report_items){
     1588
     1589                field = list_get_instance(field_it, usb_hid_report_field_t, link);             
     1590                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1591                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1592                        if(usb_hid_report_compare_usage_path (field->collection_path, path,
     1593                                                      flags) == EOK) {
     1594                                if(data_idx < data_size) {
     1595                                        if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {
     1596                                                field->value = data[data_idx];
     1597                                        }
     1598                                        else {
     1599                                                return ERANGE;
     1600                                        }
     1601
     1602                                        data_idx++;
     1603                                }
     1604                                else {
     1605                                        field->value = 0;
     1606                                }
     1607                        }
     1608                        usb_hid_report_remove_last_item (field->collection_path);
     1609                }
     1610               
     1611                field_it = field_it->next;
     1612        }
     1613
    13831614        return EOK;
    13841615}
     
    13981629}
    13991630
     1631
     1632usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1633                                                        usb_hid_report_field_t *field,
     1634                            usb_hid_report_path_t *path, int flags,
     1635                            usb_hid_report_type_t type)
     1636{
     1637        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1638        link_t *field_it;
     1639       
     1640        if(report_des == NULL){
     1641                return NULL;
     1642        }
     1643
     1644        if(field == NULL){
     1645                // vezmu prvni co mathuje podle path!!
     1646                field_it = report_des->report_items.next;
     1647        }
     1648        else {
     1649                field_it = field->link.next;
     1650        }
     1651
     1652        while(field_it != &report_des->report_items) {
     1653                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1654
     1655                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
     1656                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1657                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1658                                usb_hid_report_remove_last_item (field->collection_path);
     1659                                return field;
     1660                        }
     1661                        usb_hid_report_remove_last_item (field->collection_path);
     1662                }
     1663                field_it = field_it->next;
     1664        }
     1665
     1666        return NULL;
     1667}
     1668
     1669uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
     1670{
     1671        if(report == NULL){
     1672                return 0;
     1673        }
     1674
     1675        usb_hid_report_description_t *report_des;
     1676        link_t *report_it;
     1677       
     1678        if(report_id == 0) {
     1679                report_it = usb_hid_report_find_description (report, report_id, type)->link.next;               
     1680        }
     1681        else {
     1682                report_it = report->reports.next;
     1683        }
     1684
     1685        while(report_it != &report->reports) {
     1686                report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
     1687                if(report_des->type == type){
     1688                        return report_des->report_id;
     1689                }
     1690        }
     1691
     1692        return 0;
     1693}
     1694
     1695void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
     1696{
     1697        if(report_item == NULL) {
     1698                return;
     1699        }
     1700       
     1701        report_item->usages_count = 0;
     1702        memset(report_item->usages, 0, USB_HID_MAX_USAGES);
     1703       
     1704        report_item->extended_usage_page = 0;
     1705        report_item->usage_minimum = 0;
     1706        report_item->usage_maximum = 0;
     1707        report_item->designator_index = 0;
     1708        report_item->designator_minimum = 0;
     1709        report_item->designator_maximum = 0;
     1710        report_item->string_index = 0;
     1711        report_item->string_minimum = 0;
     1712        report_item->string_maximum = 0;
     1713
     1714        return;
     1715}
    14001716/**
    14011717 * @}
  • uspace/lib/usb/src/hidreport.c

    r380e0364 re1dbcbc  
    109109       
    110110        if (*d != sizeof(usb_standard_hid_descriptor_t)) {
    111                 usb_log_error("HID descriptor hass wrong size (%u, expected %u"
     111                usb_log_error("HID descriptor has wrong size (%u, expected %zu"
    112112                    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
    113113                return EINVAL;
     
    119119        uint16_t length =  hid_desc->report_desc_info.length;
    120120        size_t actual_size = 0;
    121        
    122         /*
    123          * Start session for the control transfer.
    124          */
    125         int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);
    126         if (sess_rc != EOK) {
    127                 usb_log_warning("Failed to start a session: %s.\n",
    128                     str_error(sess_rc));
    129                 return sess_rc;
    130         }
    131121
    132122        /*
     
    159149                free(*report_desc);
    160150                *report_desc = NULL;
    161                 usb_log_error("Report descriptor has wrong size (%u, expected "
     151                usb_log_error("Report descriptor has wrong size (%zu, expected "
    162152                    "%u)\n", actual_size, length);
    163153                return EINVAL;
    164154        }
    165155       
    166         /*
    167          * End session for the control transfer.
    168          */
    169         sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);
    170         if (sess_rc != EOK) {
    171                 usb_log_warning("Failed to end a session: %s.\n",
    172                     str_error(sess_rc));
    173                 free(*report_desc);
    174                 *report_desc = NULL;
    175                 return sess_rc;
    176         }
    177        
    178156        *size = length;
    179157       
     
    186164
    187165int usb_hid_process_report_descriptor(usb_device_t *dev,
    188     usb_hid_report_parser_t *parser)
     166    usb_hid_report_t *report)
    189167{
    190         if (dev == NULL || parser == NULL) {
     168        if (dev == NULL || report == NULL) {
    191169                usb_log_error("Failed to process Report descriptor: wrong "
    192170                    "parameters given.\n");
     
    211189        assert(report_desc != NULL);
    212190       
    213         rc = usb_hid_parse_report_descriptor(parser, report_desc, report_size);
     191        rc = usb_hid_parse_report_descriptor(report, report_desc, report_size);
    214192        if (rc != EOK) {
    215193                usb_log_error("Problem parsing Report descriptor: %s.\n",
     
    219197        }
    220198       
    221         usb_hid_descriptor_print(parser);
     199        usb_hid_descriptor_print(report);
    222200        free(report_desc);
    223201       
  • uspace/lib/usb/src/hidreq.c

    r380e0364 re1dbcbc  
    5656 * @retval EOK if successful.
    5757 * @retval EINVAL if no HID device is given.
    58  * @return Other value inherited from one of functions
    59  *         usb_pipe_start_session(), usb_pipe_end_session(),
    60  *         usb_control_request_set().
     58 * @return Other value inherited from function usb_control_request_set().
    6159 */
    6260int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    7977         */
    8078       
    81         int rc, sess_rc;
    82        
    83         sess_rc = usb_pipe_start_session(ctrl_pipe);
    84         if (sess_rc != EOK) {
    85                 usb_log_warning("Failed to start a session: %s.\n",
    86                     str_error(sess_rc));
    87                 return sess_rc;
    88         }
     79        int rc;
    8980       
    9081        uint16_t value = 0;
     
    9788            USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
    9889
    99         sess_rc = usb_pipe_end_session(ctrl_pipe);
    100 
    101         if (rc != EOK) {
    102                 usb_log_warning("Error sending output report to the keyboard: "
    103                     "%s.\n", str_error(rc));
    104                 return rc;
    105         }
    106 
    107         if (sess_rc != EOK) {
    108                 usb_log_warning("Error closing session: %s.\n",
    109                     str_error(sess_rc));
    110                 return sess_rc;
     90        if (rc != EOK) {
     91                usb_log_warning("Error sending output report to the keyboard: "
     92                    "%s.\n", str_error(rc));
     93                return rc;
    11194        }
    11295       
     
    123106 * @retval EOK if successful.
    124107 * @retval EINVAL if no HID device is given.
    125  * @return Other value inherited from one of functions
    126  *         usb_pipe_start_session(), usb_pipe_end_session(),
    127  *         usb_control_request_set().
     108 * @return Other value inherited from function usb_control_request_set().
    128109 */
    129110int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    146127         */
    147128       
    148         int rc, sess_rc;
    149        
    150         sess_rc = usb_pipe_start_session(ctrl_pipe);
    151         if (sess_rc != EOK) {
    152                 usb_log_warning("Failed to start a session: %s.\n",
    153                     str_error(sess_rc));
    154                 return sess_rc;
    155         }
     129        int rc;
    156130
    157131        usb_log_debug("Sending Set_Protocol request to the device ("
     
    162136            USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
    163137
    164         sess_rc = usb_pipe_end_session(ctrl_pipe);
    165 
    166         if (rc != EOK) {
    167                 usb_log_warning("Error sending output report to the keyboard: "
    168                     "%s.\n", str_error(rc));
    169                 return rc;
    170         }
    171 
    172         if (sess_rc != EOK) {
    173                 usb_log_warning("Error closing session: %s.\n",
    174                     str_error(sess_rc));
    175                 return sess_rc;
     138        if (rc != EOK) {
     139                usb_log_warning("Error sending output report to the keyboard: "
     140                    "%s.\n", str_error(rc));
     141                return rc;
    176142        }
    177143       
     
    189155 * @retval EOK if successful.
    190156 * @retval EINVAL if no HID device is given.
    191  * @return Other value inherited from one of functions
    192  *         usb_pipe_start_session(), usb_pipe_end_session(),
    193  *         usb_control_request_set().
     157 * @return Other value inherited from function usb_control_request_set().
    194158 */
    195159int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
     
    211175         */
    212176       
    213         int rc, sess_rc;
    214        
    215         sess_rc = usb_pipe_start_session(ctrl_pipe);
    216         if (sess_rc != EOK) {
    217                 usb_log_warning("Failed to start a session: %s.\n",
    218                     str_error(sess_rc));
    219                 return sess_rc;
    220         }
     177        int rc;
    221178
    222179        usb_log_debug("Sending Set_Idle request to the device ("
     
    229186            USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
    230187
    231         sess_rc = usb_pipe_end_session(ctrl_pipe);
    232 
    233         if (rc != EOK) {
    234                 usb_log_warning("Error sending output report to the keyboard: "
    235                     "%s.\n", str_error(rc));
    236                 return rc;
    237         }
    238 
    239         if (sess_rc != EOK) {
    240                 usb_log_warning("Error closing session: %s.\n",
    241                     str_error(sess_rc));
    242                 return sess_rc;
     188        if (rc != EOK) {
     189                usb_log_warning("Error sending output report to the keyboard: "
     190                    "%s.\n", str_error(rc));
     191                return rc;
    243192        }
    244193       
     
    259208 * @retval EOK if successful.
    260209 * @retval EINVAL if no HID device is given.
    261  * @return Other value inherited from one of functions
    262  *         usb_pipe_start_session(), usb_pipe_end_session(),
    263  *         usb_control_request_set().
     210 * @return Other value inherited from function usb_control_request_set().
    264211 */
    265212int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    283230         */
    284231       
    285         int rc, sess_rc;
    286        
    287         sess_rc = usb_pipe_start_session(ctrl_pipe);
    288         if (sess_rc != EOK) {
    289                 usb_log_warning("Failed to start a session: %s.\n",
    290                     str_error(sess_rc));
    291                 return sess_rc;
    292         }
     232        int rc;
    293233
    294234        uint16_t value = 0;
     
    302242            actual_size);
    303243
    304         sess_rc = usb_pipe_end_session(ctrl_pipe);
    305 
    306         if (rc != EOK) {
    307                 usb_log_warning("Error sending output report to the keyboard: "
    308                     "%s.\n", str_error(rc));
    309                 return rc;
    310         }
    311 
    312         if (sess_rc != EOK) {
    313                 usb_log_warning("Error closing session: %s.\n",
    314                     str_error(sess_rc));
    315                 return sess_rc;
     244        if (rc != EOK) {
     245                usb_log_warning("Error sending output report to the keyboard: "
     246                    "%s.\n", str_error(rc));
     247                return rc;
    316248        }
    317249       
     
    328260 * @retval EOK if successful.
    329261 * @retval EINVAL if no HID device is given.
    330  * @return Other value inherited from one of functions
    331  *         usb_pipe_start_session(), usb_pipe_end_session(),
    332  *         usb_control_request_set().
     262 * @return Other value inherited from function usb_control_request_set().
    333263 */
    334264int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    351281         */
    352282       
    353         int rc, sess_rc;
    354        
    355         sess_rc = usb_pipe_start_session(ctrl_pipe);
    356         if (sess_rc != EOK) {
    357                 usb_log_warning("Failed to start a session: %s.\n",
    358                     str_error(sess_rc));
    359                 return sess_rc;
    360         }
     283        int rc;
    361284
    362285        usb_log_debug("Sending Get_Protocol request to the device ("
     
    370293            USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
    371294
    372         sess_rc = usb_pipe_end_session(ctrl_pipe);
    373 
    374         if (rc != EOK) {
    375                 usb_log_warning("Error sending output report to the keyboard: "
    376                     "%s.\n", str_error(rc));
    377                 return rc;
    378         }
    379 
    380         if (sess_rc != EOK) {
    381                 usb_log_warning("Error closing session: %s.\n",
    382                     str_error(sess_rc));
    383                 return sess_rc;
     295        if (rc != EOK) {
     296                usb_log_warning("Error sending output report to the keyboard: "
     297                    "%s.\n", str_error(rc));
     298                return rc;
    384299        }
    385300       
     
    427342         */
    428343       
    429         int rc, sess_rc;
    430        
    431         sess_rc = usb_pipe_start_session(ctrl_pipe);
    432         if (sess_rc != EOK) {
    433                 usb_log_warning("Failed to start a session: %s.\n",
    434                     str_error(sess_rc));
    435                 return sess_rc;
    436         }
     344        int rc;
    437345
    438346        usb_log_debug("Sending Get_Idle request to the device ("
     
    448356            &actual_size);
    449357
    450         sess_rc = usb_pipe_end_session(ctrl_pipe);
    451 
    452         if (rc != EOK) {
    453                 usb_log_warning("Error sending output report to the keyboard: "
    454                     "%s.\n", str_error(rc));
    455                 return rc;
    456         }
    457 
    458         if (sess_rc != EOK) {
    459                 usb_log_warning("Error closing session: %s.\n",
    460                     str_error(sess_rc));
    461                 return sess_rc;
     358        if (rc != EOK) {
     359                usb_log_warning("Error sending output report to the keyboard: "
     360                    "%s.\n", str_error(rc));
     361                return rc;
    462362        }
    463363       
  • uspace/lib/usb/src/host/batch.c

    r380e0364 re1dbcbc  
    3939#include <usb/host/batch.h>
    4040
     41void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
     42void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     43
    4144void usb_transfer_batch_init(
    4245    usb_transfer_batch_t *instance,
    43     usb_target_t target,
    44     usb_transfer_type_t transfer_type,
    45     usb_speed_t speed,
    46     size_t max_packet_size,
     46    endpoint_t *ep,
    4747    char *buffer,
    48     char *transport_buffer,
     48    char *data_buffer,
    4949    size_t buffer_size,
    5050    char *setup_buffer,
     
    5454    void *arg,
    5555    ddf_fun_t *fun,
    56                 endpoint_t *ep,
    57     void *private_data
     56    void *private_data,
     57    void (*private_data_dtor)(void *p_data)
    5858    )
    5959{
    6060        assert(instance);
    6161        link_initialize(&instance->link);
    62         instance->target = target;
    63         instance->transfer_type = transfer_type;
    64         instance->speed = speed;
    65         instance->direction = ep->direction;
     62        instance->ep = ep;
    6663        instance->callback_in = func_in;
    6764        instance->callback_out = func_out;
    6865        instance->arg = arg;
    6966        instance->buffer = buffer;
    70         instance->transport_buffer = transport_buffer;
     67        instance->data_buffer = data_buffer;
    7168        instance->buffer_size = buffer_size;
    7269        instance->setup_buffer = setup_buffer;
    7370        instance->setup_size = setup_size;
    74         instance->max_packet_size = max_packet_size;
    7571        instance->fun = fun;
    7672        instance->private_data = private_data;
     73        instance->private_data_dtor = private_data_dtor;
    7774        instance->transfered_size = 0;
    7875        instance->next_step = NULL;
    7976        instance->error = EOK;
    80         instance->ep = ep;
    8177        endpoint_use(instance->ep);
     78}
     79/*----------------------------------------------------------------------------*/
     80/** Helper function, calls callback and correctly destroys batch structure.
     81 *
     82 * @param[in] instance Batch structure to use.
     83 */
     84void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
     85{
     86        assert(instance);
     87        usb_transfer_batch_call_in(instance);
     88        usb_transfer_batch_dispose(instance);
     89}
     90/*----------------------------------------------------------------------------*/
     91/** Helper function calls callback and correctly destroys batch structure.
     92 *
     93 * @param[in] instance Batch structure to use.
     94 */
     95void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
     96{
     97        assert(instance);
     98        usb_transfer_batch_call_out(instance);
     99        usb_transfer_batch_dispose(instance);
    82100}
    83101/*----------------------------------------------------------------------------*/
     
    105123        assert(instance);
    106124        assert(instance->callback_in);
     125        assert(instance->ep);
    107126
    108127        /* We are data in, we need data */
    109         memcpy(instance->buffer, instance->transport_buffer,
    110             instance->buffer_size);
     128        memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    111129
    112130        usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
    113             instance,
    114             instance->target.address, instance->target.endpoint,
    115             usb_str_speed(instance->speed),
    116             usb_str_transfer_type_short(instance->transfer_type),
    117             instance->transfered_size,
    118             str_error(instance->error), instance->error);
     131            instance, instance->ep->address, instance->ep->endpoint,
     132            usb_str_speed(instance->ep->speed),
     133            usb_str_transfer_type_short(instance->ep->transfer_type),
     134            instance->transfered_size, str_error(instance->error), instance->error);
    119135
    120136        instance->callback_in(instance->fun, instance->error,
     
    132148
    133149        usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
    134             instance,
    135             instance->target.address, instance->target.endpoint,
    136             usb_str_speed(instance->speed),
    137             usb_str_transfer_type_short(instance->transfer_type),
     150            instance, instance->ep->address, instance->ep->endpoint,
     151            usb_str_speed(instance->ep->speed),
     152            usb_str_transfer_type_short(instance->ep->transfer_type),
    138153            str_error(instance->error), instance->error);
    139154
     
    141156            instance->error, instance->arg);
    142157}
     158/*----------------------------------------------------------------------------*/
     159/** Correctly dispose all used data structures.
     160 *
     161 * @param[in] instance Batch structure to use.
     162 */
     163void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
     164{
     165        assert(instance);
     166        usb_log_debug("Batch(%p) disposing.\n", instance);
     167        if (instance->private_data) {
     168                assert(instance->private_data_dtor);
     169                instance->private_data_dtor(instance->private_data);
     170        }
     171        free(instance);
     172}
    143173/**
    144174 * @}
  • uspace/lib/usb/src/host/device_keeper.c

    r380e0364 re1dbcbc  
    4848{
    4949        assert(instance);
    50         fibril_mutex_initialize(&instance->guard);
    51         fibril_condvar_initialize(&instance->change);
    52         instance->last_address = 0;
    5350        unsigned i = 0;
    5451        for (; i < USB_ADDRESS_COUNT; ++i) {
     
    6057        // (it is needed to allow smooth registration at default address)
    6158        instance->devices[0].occupied = true;
     59        instance->last_address = 0;
     60        fibril_mutex_initialize(&instance->guard);
    6261}
    63 /*----------------------------------------------------------------------------*/
    64 /** Attempt to obtain address 0, blocks.
    65  *
    66  * @param[in] instance Device keeper structure to use.
    67  * @param[in] speed Speed of the device requesting default address.
    68  */
    69 void usb_device_keeper_reserve_default_address(
    70     usb_device_keeper_t *instance, usb_speed_t speed)
    71 {
    72         assert(instance);
    73         fibril_mutex_lock(&instance->guard);
    74         while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
    75                 fibril_condvar_wait(&instance->change, &instance->guard);
    76         }
    77         instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
    78         instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
    79         fibril_mutex_unlock(&instance->guard);
    80 }
    81 /*----------------------------------------------------------------------------*/
    82 /** Attempt to obtain address 0, blocks.
    83  *
    84  * @param[in] instance Device keeper structure to use.
    85  * @param[in] speed Speed of the device requesting default address.
    86  */
    87 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)
    88 {
    89         assert(instance);
    90         fibril_mutex_lock(&instance->guard);
    91         instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
    92         fibril_mutex_unlock(&instance->guard);
    93         fibril_condvar_signal(&instance->change);
    94 }
    95 /*----------------------------------------------------------------------------*/
    9662/*----------------------------------------------------------------------------*/
    9763/** Get a free USB address
     
    12086        assert(new_address != USB_ADDRESS_DEFAULT);
    12187        assert(instance->devices[new_address].occupied == false);
     88
    12289        instance->devices[new_address].occupied = true;
    12390        instance->devices[new_address].speed = speed;
    12491        instance->last_address = new_address;
     92
    12593        fibril_mutex_unlock(&instance->guard);
    12694        return new_address;
     
    138106        assert(instance);
    139107        fibril_mutex_lock(&instance->guard);
     108
    140109        assert(address > 0);
    141110        assert(address <= USB11_ADDRESS_MAX);
    142111        assert(instance->devices[address].occupied);
     112
    143113        instance->devices[address].handle = handle;
    144114        fibril_mutex_unlock(&instance->guard);
     
    159129        fibril_mutex_lock(&instance->guard);
    160130        assert(instance->devices[address].occupied);
     131
    161132        instance->devices[address].occupied = false;
    162133        fibril_mutex_unlock(&instance->guard);
     
    177148        while (address <= USB11_ADDRESS_MAX) {
    178149                if (instance->devices[address].handle == handle) {
     150                        assert(instance->devices[address].occupied);
    179151                        fibril_mutex_unlock(&instance->guard);
    180152                        return address;
     
    198170        assert(address >= 0);
    199171        assert(address <= USB11_ADDRESS_MAX);
     172
    200173        return instance->devices[address].speed;
    201174}
  • uspace/lib/usb/src/host/endpoint.c

    r380e0364 re1dbcbc  
    5353        fibril_mutex_initialize(&instance->guard);
    5454        fibril_condvar_initialize(&instance->avail);
     55        endpoint_clear_hc_data(instance);
    5556        return EOK;
    5657}
     
    6162        assert(!instance->active);
    6263        free(instance);
     64}
     65/*----------------------------------------------------------------------------*/
     66void endpoint_set_hc_data(endpoint_t *instance,
     67    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     68{
     69        assert(instance);
     70        instance->hc_data.data = data;
     71        instance->hc_data.toggle_get = toggle_get;
     72        instance->hc_data.toggle_set = toggle_set;
     73}
     74/*----------------------------------------------------------------------------*/
     75void endpoint_clear_hc_data(endpoint_t *instance)
     76{
     77        assert(instance);
     78        instance->hc_data.data = NULL;
     79        instance->hc_data.toggle_get = NULL;
     80        instance->hc_data.toggle_set = NULL;
    6381}
    6482/*----------------------------------------------------------------------------*/
     
    85103{
    86104        assert(instance);
     105        if (instance->hc_data.toggle_get)
     106                instance->toggle =
     107                    instance->hc_data.toggle_get(instance->hc_data.data);
    87108        return (int)instance->toggle;
    88109}
     
    92113        assert(instance);
    93114        assert(toggle == 0 || toggle == 1);
     115        if (instance->hc_data.toggle_set)
     116                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    94117        instance->toggle = toggle;
    95118}
     
    100123        if (instance->address == target.address &&
    101124            (instance->endpoint == target.endpoint || target.endpoint == 0))
    102                 instance->toggle = 0;
     125                endpoint_toggle_set(instance, 0);
    103126}
    104127/**
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    r380e0364 re1dbcbc  
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
     213        if (node->ep->active)
     214                return EBUSY;
     215
    213216        instance->free_bw += node->bw;
    214217        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
  • uspace/lib/usb/src/pipepriv.c

    r380e0364 re1dbcbc  
    7777 *
    7878 * @param pipe The USB pipe.
     79 * @param hide_failure Whether to hide failure when adding reference
     80 *      (use soft refcount).
    7981 * @return Error code.
    8082 * @retval EOK Currently always.
    8183 */
    82 int pipe_add_ref(usb_pipe_t *pipe)
     84int pipe_add_ref(usb_pipe_t *pipe, bool hide_failure)
    8385{
    84 another_try:
    8586        pipe_acquire(pipe);
    8687
     
    8990                int phone = devman_device_connect(pipe->wire->hc_handle, 0);
    9091                if (phone < 0) {
    91                         // TODO: treat some error as non-recoverable
    92                         // and return error from here
     92                        if (hide_failure) {
     93                                pipe->refcount_soft++;
     94                                phone = EOK;
     95                        }
    9396                        pipe_release(pipe);
    94                         goto another_try;
     97                        return phone;
    9598                }
    9699                /*
     
    114117{
    115118        pipe_acquire(pipe);
     119        if (pipe->refcount_soft > 0) {
     120                pipe->refcount_soft--;
     121                pipe_release(pipe);
     122                return;
     123        }
    116124        assert(pipe->refcount > 0);
    117125        pipe->refcount--;
  • uspace/lib/usb/src/pipepriv.h

    r380e0364 re1dbcbc  
    3737
    3838#include <usb/pipes.h>
     39#include <bool.h>
    3940
    4041void pipe_acquire(usb_pipe_t *);
     
    4445void pipe_end_transaction(usb_pipe_t *);
    4546
    46 int pipe_add_ref(usb_pipe_t *);
     47int pipe_add_ref(usb_pipe_t *, bool);
    4748void pipe_drop_ref(usb_pipe_t *);
    4849
  • uspace/lib/usb/src/pipes.c

    r380e0364 re1dbcbc  
    229229}
    230230
    231 
    232 /** Start a session on the endpoint pipe.
    233  *
    234  * A session is something inside what any communication occurs.
    235  * It is expected that sessions would be started right before the transfer
    236  * and ended - see usb_pipe_end_session() - after the last
    237  * transfer.
    238  * The reason for this is that session actually opens some communication
    239  * channel to the host controller (or to the physical hardware if you
    240  * wish) and thus it involves acquiring kernel resources.
    241  * Since they are limited, sessions shall not be longer than strictly
    242  * necessary.
    243  *
    244  * @deprecated
    245  * Obsoleted with introduction of usb_pipe_start_long_transfer
    246  *
    247  * @param pipe Endpoint pipe to start the session on.
    248  * @return Error code.
    249  */
    250 int usb_pipe_start_session(usb_pipe_t *pipe)
    251 {
    252         usb_log_warning("usb_pipe_start_session() was deprecated.\n");
    253         return EOK;
    254 }
    255 
    256 
    257 /** Ends a session on the endpoint pipe.
    258  *
    259  * @deprecated
    260  * Obsoleted with introduction of usb_pipe_end_long_transfer
    261  *
    262  * @see usb_pipe_start_session
    263  *
    264  * @param pipe Endpoint pipe to end the session on.
    265  * @return Error code.
    266  */
    267 int usb_pipe_end_session(usb_pipe_t *pipe)
    268 {
    269         usb_log_warning("usb_pipe_end_session() was deprecated.\n");
    270         return EOK;
    271 }
    272 
    273 /** Tell whether a session is started (open) on the endpoint pipe.
    274  *
    275  * The expected usage of this function is in assertions for some
    276  * nested functions.
    277  *
    278  * @param pipe Endpoint pipe in question.
    279  * @return Whether @p pipe has opened a session.
    280  */
    281 bool usb_pipe_is_session_started(usb_pipe_t *pipe)
    282 {
    283         pipe_acquire(pipe);
    284         bool started = pipe->refcount > 0;
    285         pipe_release(pipe);
    286         return started;
    287 }
    288 
    289231/** Prepare pipe for a long transfer.
    290232 *
     
    297239 * @return Error code.
    298240 */
    299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
    300 {
    301         return pipe_add_ref(pipe);
     241void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     242{
     243        (void) pipe_add_ref(pipe, true);
    302244}
    303245
  • uspace/lib/usb/src/pipesinit.c

    r380e0364 re1dbcbc  
    365365        pipe->direction = direction;
    366366        pipe->refcount = 0;
     367        pipe->refcount_soft = 0;
     368        pipe->auto_reset_halt = false;
    367369
    368370        return EOK;
     
    385387            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    386388            USB_DIRECTION_BOTH);
     389
     390        pipe->auto_reset_halt = true;
    387391
    388392        return rc;
     
    416420        int rc;
    417421
    418         rc = usb_pipe_start_long_transfer(pipe);
    419         if (rc != EOK) {
    420                 return rc;
    421         }
    422 
     422        usb_pipe_start_long_transfer(pipe);
    423423
    424424        uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
  • uspace/lib/usb/src/pipesio.c

    r380e0364 re1dbcbc  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
    5152#include "pipepriv.h"
    5253
     
    172173
    173174        int rc;
    174         rc = pipe_add_ref(pipe);
     175        rc = pipe_add_ref(pipe, false);
    175176        if (rc != EOK) {
    176177                return rc;
     
    295296        int rc;
    296297
    297         rc = pipe_add_ref(pipe);
     298        rc = pipe_add_ref(pipe, false);
    298299        if (rc != EOK) {
    299300                return rc;
     
    305306
    306307        return rc;
     308}
     309
     310/** Try to clear endpoint halt of default control pipe.
     311 *
     312 * @param pipe Pipe for control endpoint zero.
     313 */
     314static void clear_self_endpoint_halt(usb_pipe_t *pipe)
     315{
     316        assert(pipe != NULL);
     317
     318        if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     319                return;
     320        }
     321
     322
     323        /* Prevent indefinite recursion. */
     324        pipe->auto_reset_halt = false;
     325        usb_request_clear_endpoint_halt(pipe, 0);
     326        pipe->auto_reset_halt = true;
    307327}
    308328
     
    427447        int rc;
    428448
    429         rc = pipe_add_ref(pipe);
     449        rc = pipe_add_ref(pipe, false);
    430450        if (rc != EOK) {
    431451                return rc;
     
    436456            setup_buffer, setup_buffer_size,
    437457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
    438462
    439463        pipe_drop_ref(pipe);
     
    555579        int rc;
    556580
    557         rc = pipe_add_ref(pipe);
     581        rc = pipe_add_ref(pipe, false);
    558582        if (rc != EOK) {
    559583                return rc;
     
    563587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
    564588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
    565593        pipe_drop_ref(pipe);
    566594
  • uspace/lib/usbvirt/Makefile

    r380e0364 re1dbcbc  
    11#
    2 # Copyright (c) 2010 Vojtech Horky
     2# Copyright (c) 2011 Vojtech Horky
    33# All rights reserved.
    44#
     
    3333
    3434SOURCES = \
    35         src/callback.c \
    36         src/ctrlpipe.c \
    37         src/debug.c \
    38         src/main.c \
     35        src/ipc.c \
     36        src/ctrltransfer.c \
    3937        src/stdreq.c \
    40         src/transaction.c
     38        src/transfer.c
    4139
    4240include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usbvirt/include/usbvirt/device.h

    r380e0364 re1dbcbc  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3838#include <usb/usb.h>
    3939#include <usb/request.h>
    40 #include <usb/descriptor.h>
    4140
    42 /** Request type of a control transfer. */
    43 typedef enum {
    44         /** Standard USB request. */
    45         USBVIRT_REQUEST_TYPE_STANDARD = 0,
    46         /** Standard class USB request. */
    47         USBVIRT_REQUEST_TYPE_CLASS = 1
    48 } usbvirt_request_type_t;
    49 
    50 /** Recipient of control request. */
    51 typedef enum {
    52         /** Device is the recipient of the control request. */
    53         USBVIRT_REQUEST_RECIPIENT_DEVICE = 0,
    54         /** Interface is the recipient of the control request. */
    55         USBVIRT_REQUEST_RECIPIENT_INTERFACE = 1,
    56         /** Endpoint is the recipient of the control request. */
    57         USBVIRT_REQUEST_RECIPIENT_ENDPOINT = 2,
    58         /** Other part of the device is the recipient of the control request. */
    59         USBVIRT_REQUEST_RECIPIENT_OTHER = 3
    60 } usbvirt_request_recipient_t;
    61 
    62 /** Possible states of virtual USB device.
    63  * Notice that these are not 1:1 mappings to those in USB specification.
    64  */
    65 typedef enum {
    66         /** Default state, device listens at default address. */
    67         USBVIRT_STATE_DEFAULT,
    68         /** Device has non-default address assigned. */
    69         USBVIRT_STATE_ADDRESS,
    70         /** Device is configured. */
    71         USBVIRT_STATE_CONFIGURED
    72 } usbvirt_device_state_t;
     41#define USBVIRT_ENDPOINT_MAX 16
    7342
    7443typedef struct usbvirt_device usbvirt_device_t;
    75 struct usbvirt_control_transfer;
    7644
    77 typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev,
    78         usb_device_request_setup_packet_t *request,
    79         uint8_t *data);
     45typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t,
     46    usb_transfer_type_t, void *, size_t);
     47typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t,
     48    usb_transfer_type_t, void *, size_t, size_t *);
     49typedef int (*usbvirt_on_control_t)(usbvirt_device_t *,
     50    const usb_device_request_setup_packet_t *, uint8_t *, size_t *);
    8051
    81 /** Callback for control request over pipe zero.
    82  *
    83  * @param dev Virtual device answering the call.
    84  * @param request Request setup packet.
    85  * @param data Data when DATA stage is present.
    86  * @return Error code.
    87  */
    88 typedef int (*usbvirt_control_request_callback_t)(usbvirt_device_t *dev,
    89         usb_device_request_setup_packet_t *request,
    90         uint8_t *data);
    91 
    92 /** Handler for control transfer on endpoint zero. */
    9352typedef struct {
    94         /** Request type bitmap.
    95          * Use USBVIRT_MAKE_CONTROL_REQUEST_TYPE for creating the bitmap.
    96          */
    97         uint8_t request_type;
    98         /** Request code. */
     53        usb_direction_t req_direction;
     54        usb_request_recipient_t req_recipient;
     55        usb_request_type_t req_type;
    9956        uint8_t request;
    100         /** Request name for debugging. */
    10157        const char *name;
    102         /** Callback for the request.
    103          * NULL value here announces end of a list.
    104          */
    105         usbvirt_control_request_callback_t callback;
    106 } usbvirt_control_transfer_handler_t;
    107 
    108 /** Create control request type bitmap.
    109  *
    110  * @param direction Transfer direction (use usb_direction_t).
    111  * @param type Request type (use usbvirt_request_type_t).
    112  * @param recipient Recipient of the request (use usbvirt_request_recipient_t).
    113  * @return Request type bitmap.
    114  */
    115 #define USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, type, recipient) \
    116         ((((direction) == USB_DIRECTION_IN) ? 1 : 0) << 7) \
    117         | (((type) & 3) << 5) \
    118         | (((recipient) & 31))
    119 
    120 /** Create last item in an array of control request handlers. */
    121 #define USBVIRT_CONTROL_TRANSFER_HANDLER_LAST { 0, 0, NULL, NULL }
    122 
    123 /** Device operations. */
    124 typedef struct {
    125         /** Callbacks for transfers over control pipe zero. */
    126         usbvirt_control_transfer_handler_t *control_transfer_handlers;
    127 
    128         int (*on_control_transfer)(usbvirt_device_t *dev,
    129             usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer);
    130        
    131         /** Callback for all other incoming data. */
    132         int (*on_data)(usbvirt_device_t *dev,
    133             usb_endpoint_t endpoint, void *buffer, size_t size);
    134        
    135         /** Callback for host request for data. */
    136         int (*on_data_request)(usbvirt_device_t *dev,
    137             usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size);
    138        
    139         /** Decides direction of control transfer. */
    140         usb_direction_t (*decide_control_transfer_direction)(
    141             usb_endpoint_t endpoint, void *buffer, size_t size);
    142 
    143         /** Callback when device changes its state.
    144          *
    145          * It is correct that this function is called when both states
    146          * are equal (e.g. this function is called during SET_CONFIGURATION
    147          * request done on already configured device).
    148          *
    149          * @warning The value of <code>dev->state</code> before calling
    150          * this function is not specified (i.e. can be @p old_state or
    151          * @p new_state).
    152          */
    153         void (*on_state_change)(usbvirt_device_t *dev,
    154             usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
    155 } usbvirt_device_ops_t;
     58        usbvirt_on_control_t callback;
     59} usbvirt_control_request_handler_t;
    15660
    15761/** Extra configuration data for GET_CONFIGURATION request. */
     
    17983         */
    18084        usb_standard_device_descriptor_t *device;
    181        
     85
    18286        /** Configurations. */
    18387        usbvirt_device_configuration_t *configuration;
    18488        /** Number of configurations. */
    18589        size_t configuration_count;
    186         /** Index of currently selected configuration. */
    187         uint8_t current_configuration;
    18890} usbvirt_descriptors_t;
    18991
    190 /** Information about on-going control transfer.
     92/** Possible states of virtual USB device.
     93 * Notice that these are not 1:1 mappings to those in USB specification.
    19194 */
    192 typedef struct usbvirt_control_transfer {
    193         /** Transfer direction (read/write control transfer). */
    194         usb_direction_t direction;
    195         /** Request data. */
    196         void *request;
    197         /** Size of request data. */
    198         size_t request_size;
    199         /** Payload. */
    200         void *data;
    201         /** Size of payload. */
    202         size_t data_size;
    203 } usbvirt_control_transfer_t;
     95typedef enum {
     96        /** Default state, device listens at default address. */
     97        USBVIRT_STATE_DEFAULT,
     98        /** Device has non-default address assigned. */
     99        USBVIRT_STATE_ADDRESS,
     100        /** Device is configured. */
     101        USBVIRT_STATE_CONFIGURED
     102} usbvirt_device_state_t;
    204103
    205 typedef enum {
    206         USBVIRT_DEBUGTAG_BASE = 1,
    207         USBVIRT_DEBUGTAG_TRANSACTION = 2,
    208         USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO = 4,
    209         USBVIRT_DEBUGTAG_ALL = 255
    210 } usbvirt_debug_tags_t;
     104typedef struct {
     105        usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX];
     106        usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX];
     107        usbvirt_control_request_handler_t *control;
     108        void (*state_changed)(usbvirt_device_t *dev,
     109            usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
     110} usbvirt_device_ops_t;
    211111
    212 /** Virtual USB device. */
    213112struct usbvirt_device {
    214         /** Callback device operations. */
     113        const char *name;
     114        void *device_data;
    215115        usbvirt_device_ops_t *ops;
    216        
    217         /** Custom device data. */
    218         void *device_data;
     116        usbvirt_descriptors_t *descriptors;
     117        usb_address_t address;
     118        usbvirt_device_state_t state;
     119};
    219120
    220         /** Reply onto control transfer.
    221          */
    222         int (*control_transfer_reply)(usbvirt_device_t *dev,
    223             usb_endpoint_t endpoint, void *buffer, size_t size);
    224        
    225         /** Device name.
    226          * Used in debug prints and sent to virtual host controller.
    227          */
    228         const char *name;
    229        
    230         /** Standard descriptors. */
    231         usbvirt_descriptors_t *descriptors;
    232        
    233         /** Current device state. */
    234         usbvirt_device_state_t state;
    235        
    236         /** Device address. */
    237         usb_address_t address;
    238         /** New device address.
    239          * This field is used during SET_ADDRESS request.
    240          * On all other occasions, it holds invalid address (e.g. -1).
    241          */
    242         usb_address_t new_address;
    243        
    244         /** Process OUT transaction. */
    245         int (*transaction_out)(usbvirt_device_t *dev,
    246             usb_endpoint_t endpoint, void *buffer, size_t size);
    247         /** Process SETUP transaction. */
    248         int (*transaction_setup)(usbvirt_device_t *dev,
    249             usb_endpoint_t endpoint, void *buffer, size_t size);
    250         /** Process IN transaction. */
    251         int (*transaction_in)(usbvirt_device_t *dev,
    252             usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size);
    253        
    254         /** State information on control-transfer endpoints. */
    255         usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX];
    256        
    257         /* User debugging. */
    258        
    259         /** Debug print. */
    260         void (*debug)(usbvirt_device_t *dev, int level, uint8_t tag,
    261             const char *format, ...);
    262        
    263         /** Current debug level. */
    264         int debug_level;
    265        
    266         /** Bitmap of currently enabled tags. */
    267         uint8_t debug_enabled_tags;
    268        
    269         /* Library debugging. */
    270        
    271         /** Debug print. */
    272         void (*lib_debug)(usbvirt_device_t *dev, int level, uint8_t tag,
    273             const char *format, ...);
    274        
    275         /** Current debug level. */
    276         int lib_debug_level;
    277        
    278         /** Bitmap of currently enabled tags. */
    279         uint8_t lib_debug_enabled_tags;
    280 };
     121int usbvirt_device_plug(usbvirt_device_t *, const char *);
     122
     123void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *,
     124    uint8_t *, size_t *, void *, size_t);
     125
     126int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t);
     127int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *);
     128int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
     129    void *, size_t);
     130int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
     131    void *, size_t, size_t *);
     132
    281133
    282134#endif
  • uspace/lib/usbvirt/include/usbvirt/ipc.h

    r380e0364 re1dbcbc  
    3333 * @brief Virtual USB device.
    3434 */
    35 #ifndef LIBUSBVIRT_HUB_H_
    36 #define LIBUSBVIRT_HUB_H_
     35#ifndef LIBUSBVIRT_IPC_H_
     36#define LIBUSBVIRT_IPC_H_
    3737
    38 #include "device.h"
     38#include <ipc/common.h>
     39#include <usb/usb.h>
     40#include <bool.h>
    3941
    40 /** USB transaction type.
    41  * This types does not correspond directly to types in USB specification,
    42  * as actually DATA transactions are marked with these types to identify
    43  * their direction (and tag).
    44  */
    4542typedef enum {
    46         USBVIRT_TRANSACTION_SETUP,
    47         USBVIRT_TRANSACTION_IN,
    48         USBVIRT_TRANSACTION_OUT
    49 } usbvirt_transaction_type_t;
     43        IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80,
     44        IPC_M_USBVIRT_CONTROL_READ,
     45        IPC_M_USBVIRT_CONTROL_WRITE,
     46        IPC_M_USBVIRT_INTERRUPT_IN,
     47        IPC_M_USBVIRT_INTERRUPT_OUT
     48} usbvirt_ipc_t;
    5049
    51 const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type);
     50int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t,
     51    void *, size_t, size_t *);
     52int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t,
     53    void *, size_t);
     54int usbvirt_ipc_send_data_in(int, usb_endpoint_t, usb_transfer_type_t,
     55    void *, size_t, size_t *);
     56int usbvirt_ipc_send_data_out(int, usb_endpoint_t, usb_transfer_type_t,
     57    void *, size_t);
    5258
    53 /** Telephony methods of virtual devices. */
    54 typedef enum {
    55         IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD,
    56         IPC_M_USBVIRT_TRANSACTION_SETUP,
    57         IPC_M_USBVIRT_TRANSACTION_OUT,
    58         IPC_M_USBVIRT_TRANSACTION_IN,
    59 } usbvirt_device_method_t;
    60 
    61 int usbvirt_connect(usbvirt_device_t *);
    62 int usbvirt_connect_local(usbvirt_device_t *);
    63 int usbvirt_disconnect(usbvirt_device_t *dev);
     59bool usbvirt_is_usbvirt_method(sysarg_t);
     60bool usbvirt_ipc_handle_call(usbvirt_device_t *, ipc_callid_t, ipc_call_t *);
    6461
    6562#endif
  • uspace/lib/usbvirt/src/private.h

    r380e0364 re1dbcbc  
    1 /*
    2  * Copyright (c) 2010 Vojtech Horky
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * - Redistributions of source code must retain the above copyright
    10  *   notice, this list of conditions and the following disclaimer.
    11  * - Redistributions in binary form must reproduce the above copyright
    12  *   notice, this list of conditions and the following disclaimer in the
    13  *   documentation and/or other materials provided with the distribution.
    14  * - The name of the author may not be used to endorse or promote products
    15  *   derived from this software without specific prior written permission.
    16  *
    17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27  */
     1#include <usbvirt/device.h>
    282
    29 /** @addtogroup libusbvirt
    30  * @{
    31  */
    32 /** @file
    33  * @brief Virtual USB private header.
    34  */
    35 #ifndef LIBUSBVIRT_PRIVATE_H_
    36 #define LIBUSBVIRT_PRIVATE_H_
     3int process_control_transfer(usbvirt_device_t *,
     4    usbvirt_control_request_handler_t *,
     5    usb_device_request_setup_packet_t *,
     6    uint8_t *, size_t *);
    377
    38 #include <usbvirt/device.h>
    39 #include <usbvirt/hub.h>
    40 #include <assert.h>
    41 
    42 
    43 #define DEVICE_HAS_OP(dev, op) \
    44         ( \
    45                 (  ((dev)->ops) != NULL  ) \
    46                 && \
    47                 (  ((dev)->ops->op) != NULL  ) \
    48         )
    49 
    50 int usbvirt_data_to_host(struct usbvirt_device *dev,
    51     usb_endpoint_t endpoint, void *buffer, size_t size);
    52 
    53 int handle_incoming_data(struct usbvirt_device *dev,
    54     usb_endpoint_t endpoint, void *buffer, size_t size);
    55 
    56 int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer);
    57 
    58 int handle_std_request(usbvirt_device_t *device, usb_device_request_setup_packet_t *request, uint8_t *data);
    59 
    60 void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall);
    61 
    62 int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
    63     void *buffer, size_t size);
    64 int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
    65     void *buffer, size_t size);
    66 int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
    67     void *buffer, size_t size, size_t *data_size);
    68 
    69 
    70 void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
    71     const char *format, ...);
    72 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
    73     const char *format, ...);
    74    
    75 static inline const char *str_device_state(usbvirt_device_state_t state)
    76 {
    77         switch (state) {
    78                 case USBVIRT_STATE_DEFAULT:
    79                         return "default";
    80                 case USBVIRT_STATE_ADDRESS:
    81                         return "address";
    82                 case USBVIRT_STATE_CONFIGURED:
    83                         return "configured";
    84                 default:
    85                         return "unknown";
    86         }
    87 }
    88 
    89 extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[];
    90 
    91 #endif
    92 /**
    93  * @}
    94  */
     8extern usbvirt_control_request_handler_t library_handlers[];
  • uspace/lib/usbvirt/src/stdreq.c

    r380e0364 re1dbcbc  
    1 /*
    2  * Copyright (c) 2010 Vojtech Horky
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * - Redistributions of source code must retain the above copyright
    10  *   notice, this list of conditions and the following disclaimer.
    11  * - Redistributions in binary form must reproduce the above copyright
    12  *   notice, this list of conditions and the following disclaimer in the
    13  *   documentation and/or other materials provided with the distribution.
    14  * - The name of the author may not be used to endorse or promote products
    15  *   derived from this software without specific prior written permission.
    16  *
    17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27  */
     1#include "private.h"
     2#include <usb/request.h>
     3#include <assert.h>
     4#include <errno.h>
    285
    29 /** @addtogroup libusbvirt
    30  * @{
    31  */
    32 /** @file
    33  * @brief Preprocessing of standard device requests.
    34  */
    35 #include <errno.h>
    36 #include <stdlib.h>
    37 #include <mem.h>
    38 #include <usb/request.h>
     6void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
     7    uint8_t *data, size_t *act_size,
     8    void *actual_data, size_t actual_data_size)
     9{
     10        size_t expected_size = setup_packet->length;
     11        if (expected_size < actual_data_size) {
     12                actual_data_size = expected_size;
     13        }
    3914
    40 #include "private.h"
     15        memcpy(data, actual_data, actual_data_size);
    4116
    42 /*
    43  * All sub handlers must return EFORWARD to inform the caller that
    44  * they were not able to process the request (yes, it is abuse of
    45  * this error code but such error code shall not collide with anything
    46  * else in this context).
    47  */
    48  
     17        if (act_size != NULL) {
     18                *act_size = actual_data_size;
     19        }
     20}
     21
    4922/** GET_DESCRIPTOR handler. */
    50 static int handle_get_descriptor(usbvirt_device_t *device,
    51     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     23static int req_get_descriptor(usbvirt_device_t *device,
     24    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    5225{
    5326        uint8_t type = setup_packet->value_high;
    5427        uint8_t index = setup_packet->value_low;
    5528
    56         /* 
     29        /*
    5730         * Standard device descriptor.
    5831         */
    5932        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
    6033                if (device->descriptors && device->descriptors->device) {
    61                         return device->control_transfer_reply(device, 0,
     34                        usbvirt_control_reply_helper(setup_packet, data, act_size,
    6235                            device->descriptors->device,
    6336                            device->descriptors->device->length);
     37                        return EOK;
    6438                } else {
    6539                        return EFORWARD;
    6640                }
    6741        }
    68        
     42
    6943        /*
    7044         * Configuration descriptor together with interface, endpoint and
     
    8559                        return ENOMEM;
    8660                }
    87                
     61
    8862                uint8_t *ptr = all_data;
    8963                memcpy(ptr, config->descriptor, config->descriptor->length);
     
    9670                        ptr += extra->length;
    9771                }
    98                
    99                 int rc = device->control_transfer_reply(device, 0,
     72
     73                usbvirt_control_reply_helper(setup_packet, data, act_size,
    10074                    all_data, config->descriptor->total_length);
    101                
     75
    10276                free(all_data);
    103                
    104                 return rc;
     77
     78                return EOK;
    10579        }
    106        
     80
    10781        return EFORWARD;
    10882}
    10983
    110 /** SET_ADDRESS handler. */
    111 static int handle_set_address(usbvirt_device_t *device,
    112     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     84static int req_set_address(usbvirt_device_t *device,
     85    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    11386{
    11487        uint16_t new_address = setup_packet->value;
     
    11992                return EINVAL;
    12093        }
    121        
     94
    12295        if (new_address > 127) {
    12396                return EINVAL;
    12497        }
    125        
    126         device->new_address = new_address;
    127        
     98
     99        device->address = new_address;
     100
    128101        return EOK;
    129102}
    130103
    131 /** SET_CONFIGURATION handler. */
    132 static int handle_set_configuration(usbvirt_device_t *device,
    133     usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)
     104static int req_set_configuration(usbvirt_device_t *device,
     105    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
    134106{
    135107        uint16_t configuration_value = setup_packet->value;
     
    140112                return EINVAL;
    141113        }
    142        
     114
    143115        /*
    144116         * Configuration value is 1 byte information.
     
    147119                return EINVAL;
    148120        }
    149        
     121
    150122        /*
    151123         * Do nothing when in default state. According to specification,
     
    155127                return EOK;
    156128        }
    157        
     129
     130        usbvirt_device_state_t new_state;
    158131        if (configuration_value == 0) {
    159                 if (DEVICE_HAS_OP(device, on_state_change)) {
    160                         device->ops->on_state_change(device, device->state,
    161                             USBVIRT_STATE_ADDRESS);
    162                 }
    163                 device->state = USBVIRT_STATE_ADDRESS;
     132                new_state = USBVIRT_STATE_ADDRESS;
    164133        } else {
    165                 /*
    166                 * TODO: browse provided configurations and verify that
    167                 * user selected existing configuration.
    168                 */
    169                 if (DEVICE_HAS_OP(device, on_state_change)) {
    170                         device->ops->on_state_change(device, device->state,
    171                             USBVIRT_STATE_CONFIGURED);
    172                 }
    173                 device->state = USBVIRT_STATE_CONFIGURED;
    174                 if (device->descriptors) {
    175                         device->descriptors->current_configuration
    176                             = configuration_value;
    177                 }
     134                // FIXME: check that this configuration exists
     135                new_state = USBVIRT_STATE_CONFIGURED;
    178136        }
    179                
     137
     138        if (device->ops && device->ops->state_changed) {
     139                device->ops->state_changed(device, device->state, new_state);
     140        }
     141        device->state = new_state;
     142
    180143        return EOK;
    181144}
    182145
    183 
    184 #define MAKE_BM_REQUEST(direction, recipient) \
    185         USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
    186             USBVIRT_REQUEST_TYPE_STANDARD, recipient)
    187 #define MAKE_BM_REQUEST_DEV(direction) \
    188         MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE)
    189 
    190 usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
     146usbvirt_control_request_handler_t library_handlers[] = {
    191147        {
    192                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
    193                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    194                 .name = "GetDescriptor()",
    195                 .callback = handle_get_descriptor
     148                .req_direction = USB_DIRECTION_OUT,
     149                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     150                .req_type = USB_REQUEST_TYPE_STANDARD,
     151                .request = USB_DEVREQ_SET_ADDRESS,
     152                .name = "SetAddress",
     153                .callback = req_set_address
    196154        },
    197155        {
    198                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
    199                 .request = USB_DEVREQ_SET_ADDRESS,
    200                 .name = "SetAddress()",
    201                 .callback = handle_set_address
     156                .req_direction = USB_DIRECTION_IN,
     157                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     158                .req_type = USB_REQUEST_TYPE_STANDARD,
     159                .request = USB_DEVREQ_GET_DESCRIPTOR,
     160                .name = "GetDescriptor",
     161                .callback = req_get_descriptor
    202162        },
    203163        {
    204                 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
     164                .req_direction = USB_DIRECTION_OUT,
     165                .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
     166                .req_type = USB_REQUEST_TYPE_STANDARD,
    205167                .request = USB_DEVREQ_SET_CONFIGURATION,
    206                 .name = "SetConfiguration()",
    207                 .callback = handle_set_configuration
     168                .name = "SetConfiguration",
     169                .callback = req_set_configuration
    208170        },
    209         USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
     171
     172        { .callback = NULL }
    210173};
    211174
    212 /**
    213  * @}
    214  */
Note: See TracChangeset for help on using the changeset viewer.