Changeset 890961a in mainline for uspace/lib


Ignore:
Timestamp:
2011-04-29T12:37:42Z (15 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e67399e
Parents:
b20de1d (diff), 9d05599 (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:

Fix

Location:
uspace/lib
Files:
8 added
4 deleted
11 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/errno.h

    rb20de1d r890961a  
    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/usb/Makefile

    rb20de1d r890961a  
    4343        src/dump.c \
    4444        src/hidiface.c \
     45        src/hidpath.c \
    4546        src/hidparser.c \
     47        src/hiddescriptor.c \
    4648        src/hub.c \
    4749        src/pipepriv.c \
  • uspace/lib/usb/include/usb/classes/hid_report_items.h

    rb20de1d r890961a  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    3737
    3838#include <stdint.h>
     39
     40/**
     41 * Item prefix
     42 */
     43#define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
     44#define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
     45#define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
     46#define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
     47
     48
     49/**
     50 * Input/Output/Feature Item flags
     51 */
     52/** Constant (1) / Variable (0) */
     53#define USB_HID_ITEM_FLAG_CONSTANT(flags)       ((flags & 0x1) == 0x1)
     54/** Variable (1) / Array (0) */
     55#define USB_HID_ITEM_FLAG_VARIABLE(flags)       ((flags & 0x2) == 0x2)
     56/** Absolute / Relative*/
     57#define USB_HID_ITEM_FLAG_RELATIVE(flags)       ((flags & 0x4) == 0x4)
     58/** Wrap / No Wrap */
     59#define USB_HID_ITEM_FLAG_WRAP(flags)           ((flags & 0x8) == 0x8)
     60#define USB_HID_ITEM_FLAG_LINEAR(flags)         ((flags & 0x10) == 0x10)
     61#define USB_HID_ITEM_FLAG_PREFERRED(flags)      ((flags & 0x20) == 0x20)
     62#define USB_HID_ITEM_FLAG_POSITION(flags)       ((flags & 0x40) == 0x40)
     63#define USB_HID_ITEM_FLAG_VOLATILE(flags)       ((flags & 0x80) == 0x80)
     64#define USB_HID_ITEM_FLAG_BUFFERED(flags)       ((flags & 0x100) == 0x100)
    3965
    4066/* MAIN ITEMS */
  • uspace/lib/usb/include/usb/classes/hidparser.h

    rb20de1d r890961a  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    3939#include <adt/list.h>
    4040#include <usb/classes/hid_report_items.h>
    41 
    42 /**
    43  * Item prefix
    44  */
    45 #define USB_HID_ITEM_SIZE(data)         ((uint8_t)(data & 0x3))
    46 #define USB_HID_ITEM_TAG(data)          ((uint8_t)((data & 0xF0) >> 4))
    47 #define USB_HID_ITEM_TAG_CLASS(data)    ((uint8_t)((data & 0xC) >> 2))
    48 #define USB_HID_ITEM_IS_LONG(data)      (data == 0xFE)
    49 
    50 
    51 /**
    52  * Input/Output/Feature Item flags
    53  */
    54 /** Constant (1) / Variable (0) */
    55 #define USB_HID_ITEM_FLAG_CONSTANT(flags)       ((flags & 0x1) == 0x1)
    56 /** Variable (1) / Array (0) */
    57 #define USB_HID_ITEM_FLAG_VARIABLE(flags)       ((flags & 0x2) == 0x2)
    58 /** Absolute / Relative*/
    59 #define USB_HID_ITEM_FLAG_RELATIVE(flags)       ((flags & 0x4) == 0x4)
    60 /** Wrap / No Wrap */
    61 #define USB_HID_ITEM_FLAG_WRAP(flags)           ((flags & 0x8) == 0x8)
    62 #define USB_HID_ITEM_FLAG_LINEAR(flags)         ((flags & 0x10) == 0x10)
    63 #define USB_HID_ITEM_FLAG_PREFERRED(flags)      ((flags & 0x20) == 0x20)
    64 #define USB_HID_ITEM_FLAG_POSITION(flags)       ((flags & 0x40) == 0x40)
    65 #define USB_HID_ITEM_FLAG_VOLATILE(flags)       ((flags & 0x80) == 0x80)
    66 #define USB_HID_ITEM_FLAG_BUFFERED(flags)       ((flags & 0x100) == 0x100)
    67 
    68 
    69 /**
    70  * Description of path of usage pages and usages in report descriptor
    71  */
    72 #define USB_HID_PATH_COMPARE_STRICT                             0
    73 #define USB_HID_PATH_COMPARE_END                                1
    74 #define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY    4
    75 #define USB_HID_PATH_COMPARE_COLLECTION_ONLY    2 /* porovnava jenom cestu z Kolekci */
    76 
    77 
    78 #define USB_HID_MAX_USAGES      20
    79 
    80 typedef 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 */
    87 typedef struct {
    88         /** */
    89         uint32_t usage_page;
    90         /** */ 
    91         uint32_t usage;
    92 
    93         uint8_t flags;
    94         /** */
    95         link_t link;
    96 } usb_hid_report_usage_path_t;
    97 
    98 /** */
    99 typedef struct {
    100         /** */ 
    101         int depth;     
    102         uint8_t report_id;
    103        
    104         /** */ 
    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 
    112 typedef 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 
    125 typedef 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 
    134         link_t link;
    135 } usb_hid_report_description_t;
    136 
    137 typedef 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  */
    168 typedef struct {
    169         /** report id */       
    170         int32_t id;
    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;
    184         /** */ 
    185         int32_t logical_minimum;
    186         /** */ 
    187         int32_t logical_maximum;
    188         /** */ 
    189         int32_t size;
    190         /** */ 
    191         int32_t count;
    192         /** */ 
    193         size_t offset;
    194         /** */ 
    195         int32_t unit_exponent;
    196         /** */ 
    197         int32_t unit;
    198 
    199         /** */
    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;
    211         /** */ 
    212         int32_t physical_minimum;
    213         /** */ 
    214         int32_t physical_maximum;
    215 
    216         /** */ 
    217         uint8_t item_flags;
    218 
    219         usb_hid_report_type_t type;
    220 
    221         /** current collection path*/   
    222         usb_hid_report_path_t *usage_path;
    223         /** */ 
    224         link_t link;
    225 } usb_hid_report_item_t;
    226 
    227 /** HID parser callbacks for IN items. */
    228 typedef struct {
    229         /** Callback for keyboard.
    230          *
    231          * @param key_codes Array of pressed key (including modifiers).
    232          * @param count Length of @p key_codes.
    233          * @param arg Custom argument.
    234          */
    235         void (*keyboard)(const uint8_t *key_codes, size_t count, const uint8_t report_id, void *arg);
    236 } usb_hid_report_in_callbacks_t;
    237 
    238 
    239 typedef enum {
    240         USB_HID_MOD_LCTRL = 0x01,
    241         USB_HID_MOD_LSHIFT = 0x02,
    242         USB_HID_MOD_LALT = 0x04,
    243         USB_HID_MOD_LGUI = 0x08,
    244         USB_HID_MOD_RCTRL = 0x10,
    245         USB_HID_MOD_RSHIFT = 0x20,
    246         USB_HID_MOD_RALT = 0x40,
    247         USB_HID_MOD_RGUI = 0x80,
    248         USB_HID_MOD_COUNT = 8
    249 } usb_hid_modifiers_t;
    250 
    251 static const usb_hid_modifiers_t
    252     usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
    253         USB_HID_MOD_LCTRL,
    254         USB_HID_MOD_LSHIFT,
    255         USB_HID_MOD_LALT,
    256         USB_HID_MOD_LGUI,
    257         USB_HID_MOD_RCTRL,
    258         USB_HID_MOD_RSHIFT,
    259         USB_HID_MOD_RALT,
    260         USB_HID_MOD_RGUI
    261 };
    262 
    263 /*
    264  * Descriptor parser functions
    265  */
    266 
    267 /** */
    268 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    269     const uint8_t *data, size_t size);
    270 
    271 /** */
    272 void usb_hid_free_report(usb_hid_report_t *report);
    273 
    274 /** */
    275 void usb_hid_descriptor_print(usb_hid_report_t *report);
     41#include <usb/classes/hidpath.h>
     42#include <usb/classes/hidtypes.h>
     43#include <usb/classes/hiddescriptor.h>
    27644
    27745
     
    28048 */
    28149/** */
    282 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
     50int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
     51                         size_t size, uint8_t *report_id);
    28352
    28453/** */
     
    28655        usb_hid_report_path_t *path, int flags);
    28756
    288 
    289 
    290 /*
    291  * usage path functions
    292  */
    293 /** */
    294 usb_hid_report_path_t *usb_hid_report_path(void);
    295 
    296 /** */
    297 void usb_hid_report_path_free(usb_hid_report_path_t *path);
    298 
    299 /** */
    300 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path, uint8_t report_id);
    301 
    302 /** */
    303 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
    304 
    305 /** */
    306 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
    307 
    308 /** */
    309 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
    310 
    311 /** */
    312 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
    313 
    314 /** */
    315 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
    316 
    317 /** */
    318 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    319 
    320 usb_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 
    322 uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
    323 
    324 
    32557/*
    32658 * Output report parser functions
    32759 */
    32860/** Allocates output report buffer*/
    329 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id);
     61uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
     62                               uint8_t report_id);
    33063
    33164/** Frees output report buffer*/
     
    33669                                  usb_hid_report_path_t *path, int flags);
    33770
    338 /** Sets data in report structure */
    339 int 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);
     71/** Makes the output report buffer by translated given data */
     72int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id,
     73                                    uint8_t *buffer, size_t size);
    34274
    343 /** Makes the output report buffer by translated given data */
    344 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size);
     75/** */
     76usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     77                                                   usb_hid_report_field_t *field,
     78                                                   usb_hid_report_path_t *path,
     79                                                   int flags,
     80                                                   usb_hid_report_type_t type);
     81
     82/** */
     83uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report,
     84                                     uint8_t report_id,
     85                                     usb_hid_report_type_t type);
     86
    34587#endif
    34688/**
  • uspace/lib/usb/include/usb/usb.h

    rb20de1d r890961a  
    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

    rb20de1d r890961a  
    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/hidparser.c

    rb20de1d r890961a  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Matej Klonfar
    33 * All rights reserved.
    44 *
     
    4141#include <assert.h>
    4242
    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  */
    46 #define USB_HID_NEW_REPORT_ITEM 1
    47 
    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*/
    56 #define USB_HID_UNKNOWN_TAG             -99
    57 
    58 /*
    59  * Private descriptor parser functions
    60  */
    61 int usb_hid_report_init(usb_hid_report_t *report);
    62 int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item);
    63 usb_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);
    64 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    65                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    66 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    67                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    68 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    69                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    70 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    71                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
    72 
    73 void usb_hid_print_usage_path(usb_hid_report_path_t *path);
    74 void usb_hid_descriptor_print_list(link_t *head);
    75 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
    76 void usb_hid_free_report_list(link_t *head);
    77 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item);
     43
    7844/*
    7945 * Data translation private functions
     
    8551int usb_pow(int a, int b);
    8652
    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))
     53
    8954// TODO: tohle ma bejt asi jinde
    9055int usb_pow(int a, int b)
     
    10368}
    10469
    105 /**
    106  * Initialize the report descriptor parser structure
    107  *
    108  * @param parser Report descriptor parser structure
    109  * @return Error code
    110  */
    111 int usb_hid_report_init(usb_hid_report_t *report)
    112 {
    113         if(report == NULL) {
    114                 return EINVAL;
    115         }
    116 
    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;
    122     return EOK;   
    123 }
    124 
    125 int 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 
    253 usb_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 }
    270 
    271 /** Parse HID report descriptor.
    272  *
    273  * @param parser Opaque HID report parser structure.
    274  * @param data Data describing the report.
    275  * @return Error code.
    276  */
    277 int usb_hid_parse_report_descriptor(usb_hid_report_t *report,
    278     const uint8_t *data, size_t size)
    279 {
    280         size_t i=0;
    281         uint8_t tag=0;
    282         uint8_t item_size=0;
    283         int class=0;
    284         int ret;
    285         usb_hid_report_item_t *report_item=0;
    286         usb_hid_report_item_t *new_report_item;
    287         usb_hid_report_path_t *usage_path;
    288 
    289         size_t offset_input=0;
    290         size_t offset_output=0;
    291         size_t offset_feature=0;
    292 
    293         link_t stack;
    294         list_initialize(&stack);       
    295 
    296         /* parser structure initialization*/
    297         if(usb_hid_report_init(report) != EOK) {
    298                 return EINVAL;
    299         }
    300        
    301         /*report item initialization*/
    302         if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
    303                 return ENOMEM;
    304         }
    305         memset(report_item, 0, sizeof(usb_hid_report_item_t));
    306         list_initialize(&(report_item->link)); 
    307 
    308         /* usage path context initialization */
    309         if(!(usage_path=usb_hid_report_path())){
    310                 return ENOMEM;
    311         }
    312        
    313         while(i<size){ 
    314                 if(!USB_HID_ITEM_IS_LONG(data[i])){
    315 
    316                         if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
    317                                 return EINVAL;
    318                         }
    319                        
    320                         tag = USB_HID_ITEM_TAG(data[i]);
    321                         item_size = USB_HID_ITEM_SIZE(data[i]);
    322                         class = USB_HID_ITEM_TAG_CLASS(data[i]);
    323                        
    324                         ret = usb_hid_report_parse_tag(tag,class,data+i+1,
    325                                                        item_size,report_item, usage_path);
    326                         switch(ret){
    327                                 case USB_HID_NEW_REPORT_ITEM:
    328                                         // store report item to report and create the new one
    329                                         // store current collection path
    330                                         report_item->usage_path = usage_path;
    331                                        
    332                                         usb_hid_report_path_set_report_id(report_item->usage_path, report_item->id);   
    333                                         if(report_item->id != 0){
    334                                                 report->use_report_ids = 1;
    335                                         }
    336                                        
    337                                         switch(tag) {
    338                                                 case USB_HID_REPORT_TAG_INPUT:
    339                                                         report_item->type = USB_HID_REPORT_TYPE_INPUT;
    340                                                         report_item->offset = offset_input;
    341                                                         offset_input += report_item->count * report_item->size;
    342                                                         break;
    343                                                 case USB_HID_REPORT_TAG_OUTPUT:
    344                                                         report_item->type = USB_HID_REPORT_TYPE_OUTPUT;
    345                                                         report_item->offset = offset_output;
    346                                                         offset_output += report_item->count * report_item->size;
    347 
    348                                                         break;
    349                                                 case USB_HID_REPORT_TAG_FEATURE:
    350                                                         report_item->type = USB_HID_REPORT_TYPE_FEATURE;
    351                                                         report_item->offset = offset_feature;
    352                                                         offset_feature += report_item->count * report_item->size;
    353                                                         break;
    354                                                 default:
    355                                                     usb_log_debug("\tjump over - tag %X\n", tag);
    356                                                     break;
    357                                         }
    358                                        
    359                                         /*
    360                                          * append new fields to the report
    361                                          * structure                                     
    362                                          */
    363                                         usb_hid_report_append_fields(report, report_item);
    364 
    365                                         /* reset local items */
    366                                         usb_hid_report_reset_local_items (report_item);
    367 
    368                                         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 
    377                                 case USB_HID_REPORT_TAG_PUSH:
    378                                         // push current state to stack
    379                                         new_report_item = usb_hid_report_item_clone(report_item);
    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);
    384                                         break;
    385                                 case USB_HID_REPORT_TAG_POP:
    386                                         // restore current state from stack
    387                                         if(list_empty (&stack)) {
    388                                                 return EINVAL;
    389                                         }
    390                                         free(report_item);
    391                                                
    392                                         report_item = list_get_instance(stack.next, usb_hid_report_item_t, link);
    393                                        
    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);
    402                                        
    403                                         break;
    404                                        
    405                                 default:
    406                                         // nothing special to do                                       
    407                                         break;
    408                         }
    409 
    410                         /* jump over the processed block */
    411                         i += 1 + USB_HID_ITEM_SIZE(data[i]);
    412                 }
    413                 else{
    414                         // TBD
    415                         i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
    416                 }
    417                
    418 
    419         }
    420        
    421         return EOK;
    422 }
    423 
    424 
    425 /**
    426  * Parse one tag of the report descriptor
    427  *
    428  * @param Tag to parse
    429  * @param Report descriptor buffer
    430  * @param Size of data belongs to this tag
    431  * @param Current report item structe
    432  * @return Code of action to be done next
    433  */
    434 int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
    435                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    436 {       
    437         int ret;
    438        
    439         switch(class){
    440                 case USB_HID_TAG_CLASS_MAIN:
    441 
    442                         if((ret=usb_hid_report_parse_main_tag(tag,data,item_size,report_item, usage_path)) == EOK) {
    443                                 return USB_HID_NEW_REPORT_ITEM;
    444                         }
    445                         else {
    446                                 /*TODO process the error */
    447                                 return ret;
    448                            }
    449                         break;
    450 
    451                 case USB_HID_TAG_CLASS_GLOBAL: 
    452                         return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path);
    453                         break;
    454 
    455                 case USB_HID_TAG_CLASS_LOCAL:                   
    456                         return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path);
    457                         break;
    458                 default:
    459                         return USB_HID_NO_ACTION;
    460         }
    461 }
    462 
    463 /**
    464  * Parse main tags of report descriptor
    465  *
    466  * @param Tag identifier
    467  * @param Data buffer
    468  * @param Length of data buffer
    469  * @param Current state table
    470  * @return Error code
    471  */
    472 
    473 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    474                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    475 {               
    476         switch(tag)
    477         {
    478                 case USB_HID_REPORT_TAG_INPUT:
    479                 case USB_HID_REPORT_TAG_OUTPUT:
    480                 case USB_HID_REPORT_TAG_FEATURE:
    481                         report_item->item_flags = *data;                       
    482                         return EOK;                     
    483                         break;
    484                        
    485                 case USB_HID_REPORT_TAG_COLLECTION:
    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);
    489                         return USB_HID_NO_ACTION;
    490                         break;
    491                        
    492                 case USB_HID_REPORT_TAG_END_COLLECTION:
    493                         usb_hid_report_remove_last_item(usage_path);
    494                         return USB_HID_NO_ACTION;
    495                         break;
    496                 default:
    497                         return USB_HID_NO_ACTION;
    498         }
    499 
    500         return EOK;
    501 }
    502 
    503 /**
    504  * Parse global tags of report descriptor
    505  *
    506  * @param Tag identifier
    507  * @param Data buffer
    508  * @param Length of data buffer
    509  * @param Current state table
    510  * @return Error code
    511  */
    512 int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    513                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    514 {
    515         // TODO take care about the bit length of data
    516         switch(tag)
    517         {
    518                 case USB_HID_REPORT_TAG_USAGE_PAGE:
    519                         report_item->usage_page = usb_hid_report_tag_data_uint32(data, item_size);
    520                         break;
    521                 case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
    522                         report_item->logical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    523                         break;
    524                 case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
    525                         report_item->logical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    526                         break;
    527                 case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
    528                         report_item->physical_minimum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    529                         break;                 
    530                 case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
    531                         report_item->physical_maximum = USB_HID_UINT32_TO_INT32(usb_hid_report_tag_data_uint32(data,item_size), item_size * 8);
    532 
    533                         break;
    534                 case USB_HID_REPORT_TAG_UNIT_EXPONENT:
    535                         report_item->unit_exponent = usb_hid_report_tag_data_uint32(data,item_size);
    536                         break;
    537                 case USB_HID_REPORT_TAG_UNIT:
    538                         report_item->unit = usb_hid_report_tag_data_uint32(data,item_size);
    539                         break;
    540                 case USB_HID_REPORT_TAG_REPORT_SIZE:
    541                         report_item->size = usb_hid_report_tag_data_uint32(data,item_size);
    542                         break;
    543                 case USB_HID_REPORT_TAG_REPORT_COUNT:
    544                         report_item->count = usb_hid_report_tag_data_uint32(data,item_size);
    545                         break;
    546                 case USB_HID_REPORT_TAG_REPORT_ID:
    547                         report_item->id = usb_hid_report_tag_data_uint32(data,item_size);
    548                         return USB_HID_RESET_OFFSET;
    549                         break;
    550                 case USB_HID_REPORT_TAG_PUSH:
    551                 case USB_HID_REPORT_TAG_POP:
    552                         /*
    553                          * stack operations are done in top level parsing
    554                          * function
    555                          */
    556                         return tag;
    557                         break;
    558                        
    559                 default:
    560                         return USB_HID_NO_ACTION;
    561         }
    562 
    563         return EOK;
    564 }
    565 
    566 /**
    567  * Parse local tags of report descriptor
    568  *
    569  * @param Tag identifier
    570  * @param Data buffer
    571  * @param Length of data buffer
    572  * @param Current state table
    573  * @return Error code
    574  */
    575 int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, size_t item_size,
    576                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
    577 {
    578         switch(tag)
    579         {
    580                 case USB_HID_REPORT_TAG_USAGE:
    581                         report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
    582                         report_item->usages_count++;
    583                         break;
    584                 case USB_HID_REPORT_TAG_USAGE_MINIMUM:
    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                         }
    593                         break;
    594                 case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
    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                         }
    603                         break;
    604                 case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
    605                         report_item->designator_index = usb_hid_report_tag_data_uint32(data,item_size);
    606                         break;
    607                 case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
    608                         report_item->designator_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    609                         break;
    610                 case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
    611                         report_item->designator_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    612                         break;
    613                 case USB_HID_REPORT_TAG_STRING_INDEX:
    614                         report_item->string_index = usb_hid_report_tag_data_uint32(data,item_size);
    615                         break;
    616                 case USB_HID_REPORT_TAG_STRING_MINIMUM:
    617                         report_item->string_minimum = usb_hid_report_tag_data_uint32(data,item_size);
    618                         break;
    619                 case USB_HID_REPORT_TAG_STRING_MAXIMUM:
    620                         report_item->string_maximum = usb_hid_report_tag_data_uint32(data,item_size);
    621                         break;                 
    622                 case USB_HID_REPORT_TAG_DELIMITER:
    623                         //report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
    624                         //TODO:
    625                         //      DELIMITER STUFF
    626                         break;
    627                
    628                 default:
    629                         return USB_HID_NO_ACTION;
    630         }
    631        
    632         return EOK;
    633 }
    634 
    635 /**
    636  * Converts raw data to uint32 (thats the maximum length of short item data)
    637  *
    638  * @param Data buffer
    639  * @param Size of buffer
    640  * @return Converted int32 number
    641  */
    642 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
    643 {
    644         unsigned int i;
    645         uint32_t result;
    646 
    647         result = 0;
    648         for(i=0; i<size; i++) {
    649                 result = (result | (data[i]) << (i*8));
    650         }
    651 
    652         return result;
    653 }
    654 
    655 /**
    656  * Prints content of given list of report items.
    657  *
    658  * @param List of report items (usb_hid_report_item_t)
    659  * @return void
    660  */
    661 void usb_hid_descriptor_print_list(link_t *head)
    662 {
    663         usb_hid_report_field_t *report_item;
    664         link_t *item;
    665 
    666 
    667         if(head == NULL || list_empty(head)) {
    668             usb_log_debug("\tempty\n");
    669             return;
    670         }
    671        
    672         for(item = head->next; item != head; item = item->next) {
    673                
    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");           
    690 
    691         }
    692 
    693 
    694 }
    695 /**
    696  * Prints content of given report descriptor in human readable format.
    697  *
    698  * @param parser Parsed descriptor to print
    699  * @return void
    700  */
    701 void usb_hid_descriptor_print(usb_hid_report_t *report)
    702 {
    703         if(report == NULL) {
    704                 return;
    705         }
    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         }
    728 }
    729 
    730 /**
    731  * Releases whole linked list of report items
    732  *
    733  * @param head Head of list of report descriptor items (usb_hid_report_item_t)
    734  * @return void
    735  */
    736 void usb_hid_free_report_list(link_t *head)
    737 {
    738         return;
    739        
    740         usb_hid_report_item_t *report_item;
    741         link_t *next;
    742        
    743         if(head == NULL || list_empty(head)) {         
    744             return;
    745         }
    746        
    747         next = head->next;
    748         while(next != head) {
    749        
    750             report_item = list_get_instance(next, usb_hid_report_item_t, link);
    751 
    752                 while(!list_empty(&report_item->usage_path->link)) {
    753                         usb_hid_report_remove_last_item(report_item->usage_path);
    754                 }
    755 
    756                
    757             next = next->next;
    758            
    759             free(report_item);
    760         }
    761        
    762         return;
    763        
    764 }
    765 
    766 /** Frees the HID report descriptor parser structure
    767  *
    768  * @param parser Opaque HID report parser structure
    769  * @return void
    770  */
    771 void usb_hid_free_report(usb_hid_report_t *report)
    772 {
    773         if(report == NULL){
    774                 return;
    775         }
    776 
    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        
    801         return;
    802 }
     70
     71
    80372
    80473/** Parse and act upon a HID report.
     
    980249        return ret;
    981250        }
    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
    992  */
    993 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
    994                                     int32_t usage_page, int32_t usage)
    995 {       
    996         usb_hid_report_usage_path_t *item;
    997 
    998         if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
    999                 return ENOMEM;
    1000         }
    1001         list_initialize(&item->link);
    1002 
    1003         item->usage = usage;
    1004         item->usage_page = usage_page;
    1005         item->flags = 0;
    1006        
    1007         list_append (&item->link, &usage_path->head);
    1008         usage_path->depth++;
    1009         return EOK;
    1010 }
    1011 
    1012 /**
    1013  * Removes last item from the usage path structure
    1014  * @param usage_path
    1015  * @return void
    1016  */
    1017 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
    1018 {
    1019         usb_hid_report_usage_path_t *item;
    1020        
    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);
    1024                 usage_path->depth--;
    1025                 free(item);
    1026         }
    1027 }
    1028 
    1029 /**
    1030  * Nulls last item of the usage path structure.
    1031  *
    1032  * @param usage_path
    1033  * @return void
    1034  */
    1035 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
    1036 {
    1037         usb_hid_report_usage_path_t *item;
    1038        
    1039         if(!list_empty(&usage_path->head)){     
    1040                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    1041                 memset(item, 0, sizeof(usb_hid_report_usage_path_t));
    1042         }
    1043 }
    1044 
    1045 /**
    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
    1053  */
    1054 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
    1055 {
    1056         usb_hid_report_usage_path_t *item;
    1057        
    1058         if(!list_empty(&usage_path->head)){     
    1059                 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
    1060 
    1061                 switch(tag) {
    1062                         case USB_HID_TAG_CLASS_GLOBAL:
    1063                                 item->usage_page = data;
    1064                                 break;
    1065                         case USB_HID_TAG_CLASS_LOCAL:
    1066                                 item->usage = data;
    1067                                 break;
    1068                 }
    1069         }
    1070        
    1071 }
    1072 
    1073 
    1074 void 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
    1101  */
    1102 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
    1103                                       usb_hid_report_path_t *path,
    1104                                       int flags)
    1105 {
    1106         usb_hid_report_usage_path_t *report_item;
    1107         usb_hid_report_usage_path_t *path_item;
    1108 
    1109         link_t *report_link;
    1110         link_t *path_link;
    1111 
    1112         int only_page;
    1113 
    1114         if(report_path->report_id != path->report_id) {
    1115                 return 1;
    1116         }
    1117 
    1118         if(path->depth == 0){
    1119                 return EOK;
    1120         }
    1121 
    1122 
    1123         if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
    1124                 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
    1125         }
    1126        
    1127         switch(flags){
    1128                 /* path must be completly identical */
    1129                 case USB_HID_PATH_COMPARE_STRICT:
    1130                                 if(report_path->depth != path->depth){
    1131                                         return 1;
    1132                                 }
    1133 
    1134                                 report_link = report_path->head.next;
    1135                                 path_link = path->head.next;
    1136                        
    1137                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
    1138                                         report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    1139                                         path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
    1140 
    1141                                         if((report_item->usage_page != path_item->usage_page) ||
    1142                                            ((only_page == 0) && (report_item->usage != path_item->usage))) {
    1143                                                    return 1;
    1144                                         } else {
    1145                                                 report_link = report_link->next;
    1146                                                 path_link = path_link->next;                   
    1147                                         }
    1148                        
    1149                                 }
    1150 
    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))) {
    1153                                         return EOK;
    1154                                 }
    1155                                 else {
    1156                                         return 1;
    1157                                 }                                               
    1158                         break;
    1159 
    1160                 /* compare with only the end of path*/
    1161                 case USB_HID_PATH_COMPARE_END:
    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)){
    1172                                         return EOK;
    1173                                 }
    1174                        
    1175                                 while((report_link != &report_path->head) && (path_link != &path->head)) {
    1176                                         report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
    1177                                         path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);           
    1178 
    1179                                         if((report_item->usage_page != path_item->usage_page) ||
    1180                                            ((only_page == 0) && (report_item->usage != path_item->usage))) {
    1181                                                    return 1;
    1182                                         } else {
    1183                                                 report_link = report_link->prev;
    1184                                                 path_link = path_link->prev;                   
    1185                                         }
    1186                        
    1187                                 }
    1188 
    1189                                 if(path_link == &path->head) {
    1190                                         return EOK;
    1191                                 }
    1192                                 else {
    1193                                         return 1;
    1194                                 }                                               
    1195                        
    1196                         break;
    1197 
    1198                 default:
    1199                         return EINVAL;
    1200         }
    1201        
    1202        
    1203        
    1204        
    1205 }
    1206 
    1207 /**
    1208  * Allocates and initializes new usage path structure.
    1209  *
    1210  * @return Initialized usage path structure
    1211  */
    1212 usb_hid_report_path_t *usb_hid_report_path(void)
    1213 {
    1214         usb_hid_report_path_t *path;
    1215         path = malloc(sizeof(usb_hid_report_path_t));
    1216         if(path == NULL){
    1217                 return NULL;
    1218         }
    1219         else {
    1220                 path->depth = 0;
    1221                 path->report_id = 0;
    1222                 list_initialize(&path->link);
    1223                 list_initialize(&path->head);
    1224                 return path;
    1225         }
    1226 }
    1227 
    1228 /**
    1229  * Releases given usage path structure.
    1230  *
    1231  * @param path usage path structure to release
    1232  * @return void
    1233  */
    1234 void usb_hid_report_path_free(usb_hid_report_path_t *path)
    1235 {
    1236         while(!list_empty(&path->head)){
    1237                 usb_hid_report_remove_last_item(path);
    1238         }
    1239 
    1240         list_remove(&path->link);
    1241         free(path);
    1242 }
    1243 
    1244 
    1245 /**
    1246  * Clone content of given usage path to the new one
    1247  *
    1248  * @param usage_path Usage path structure to clone
    1249  * @return New copy of given usage path structure
    1250  */
    1251 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
    1252 {
    1253         link_t *path_link;
    1254         usb_hid_report_usage_path_t *path_item;
    1255         usb_hid_report_usage_path_t *new_path_item;
    1256         usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
    1257 
    1258         if(new_usage_path == NULL){
    1259                 return NULL;
    1260         }
    1261 
    1262         new_usage_path->report_id = usage_path->report_id;
    1263        
    1264         if(list_empty(&usage_path->head)){
    1265                 return new_usage_path;
    1266         }
    1267 
    1268         path_link = usage_path->head.next;
    1269         while(path_link != &usage_path->head) {
    1270                 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
    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++;
    1283 
    1284                 path_link = path_link->next;
    1285         }
    1286 
    1287         return new_usage_path;
    1288 }
    1289 
    1290251
    1291252/*** OUTPUT API **/
     
    1543504}
    1544505
    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  */
    1552 int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
    1553 {
    1554         if(path == NULL){
    1555                 return EINVAL;
    1556         }
    1557 
    1558         path->report_id = report_id;
    1559         return EOK;
    1560 }
    1561 
    1562 /**
    1563  *
    1564  *
    1565  *
    1566  *
    1567  *
    1568  */
    1569 int 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 
    1614         return EOK;
    1615 }
    1616 
    1617 
    1618506usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    1619507{
  • uspace/lib/usbvirt/Makefile

    rb20de1d r890961a  
    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

    rb20de1d r890961a  
    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

    rb20de1d r890961a  
    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

    rb20de1d r890961a  
    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

    rb20de1d r890961a  
    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.