Changeset 890961a in mainline for uspace/lib
- Timestamp:
- 2011-04-29T12:37:42Z (15 years ago)
- 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. - Location:
- uspace/lib
- Files:
-
- 8 added
- 4 deleted
- 11 edited
- 1 moved
-
c/include/errno.h (modified) (1 diff)
-
usb/Makefile (modified) (1 diff)
-
usb/include/usb/classes/hid_report_items.h (modified) (2 diffs)
-
usb/include/usb/classes/hiddescriptor.h (added)
-
usb/include/usb/classes/hidparser.h (modified) (5 diffs)
-
usb/include/usb/classes/hidpath.h (added)
-
usb/include/usb/classes/hidtypes.h (added)
-
usb/include/usb/usb.h (modified) (1 diff)
-
usb/src/debug.c (modified) (6 diffs)
-
usb/src/hiddescriptor.c (added)
-
usb/src/hidparser.c (modified) (6 diffs)
-
usb/src/hidpath.c (added)
-
usbvirt/Makefile (modified) (2 diffs)
-
usbvirt/include/usbvirt/device.h (modified) (3 diffs)
-
usbvirt/include/usbvirt/ipc.h (moved) (moved from uspace/lib/usbvirt/include/usbvirt/hub.h ) (1 diff)
-
usbvirt/src/callback.c (deleted)
-
usbvirt/src/ctrlpipe.c (deleted)
-
usbvirt/src/ctrltransfer.c (added)
-
usbvirt/src/ipc.c (added)
-
usbvirt/src/main.c (deleted)
-
usbvirt/src/private.h (modified) (1 diff)
-
usbvirt/src/stdreq.c (modified) (7 diffs)
-
usbvirt/src/transaction.c (deleted)
-
usbvirt/src/transfer.c (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/errno.h
rb20de1d r890961a 65 65 #define EEMPTY (-302) 66 66 67 /** Negative acknowledgment. */ 68 #define ENAK (-303) 69 67 70 /** An API function is called while another blocking function is in progress. */ 68 71 #define EINPROGRESS (-10036) -
uspace/lib/usb/Makefile
rb20de1d r890961a 43 43 src/dump.c \ 44 44 src/hidiface.c \ 45 src/hidpath.c \ 45 46 src/hidparser.c \ 47 src/hiddescriptor.c \ 46 48 src/hub.c \ 47 49 src/pipepriv.c \ -
uspace/lib/usb/include/usb/classes/hid_report_items.h
rb20de1d r890961a 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 37 37 38 38 #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) 39 65 40 66 /* MAIN ITEMS */ -
uspace/lib/usb/include/usb/classes/hidparser.h
rb20de1d r890961a 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 39 39 #include <adt/list.h> 40 40 #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> 276 44 277 45 … … 280 48 */ 281 49 /** */ 282 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id); 50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 51 size_t size, uint8_t *report_id); 283 52 284 53 /** */ … … 286 55 usb_hid_report_path_t *path, int flags); 287 56 288 289 290 /*291 * usage path functions292 */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 325 57 /* 326 58 * Output report parser functions 327 59 */ 328 60 /** Allocates output report buffer*/ 329 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id); 61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 62 uint8_t report_id); 330 63 331 64 /** Frees output report buffer*/ … … 336 69 usb_hid_report_path_t *path, int flags); 337 70 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 */ 72 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, 73 uint8_t *buffer, size_t size); 342 74 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 /** */ 76 usb_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 /** */ 83 uint8_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 345 87 #endif 346 88 /** -
uspace/lib/usb/include/usb/usb.h
rb20de1d r890961a 96 96 USB_REQUEST_RECIPIENT_DEVICE = 0, 97 97 USB_REQUEST_RECIPIENT_INTERFACE = 1, 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2, 99 USB_REQUEST_RECIPIENT_OTHER = 3 99 100 } usb_request_recipient_t; 100 101 -
uspace/lib/usb/src/debug.c
rb20de1d r890961a 158 158 159 159 /** Fibril local storage for the dumped buffer. */ 160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN]; 160 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN]; 161 /** Fibril local storage for buffer switching. */ 162 static fibril_local int buffer_dump_index = 0; 161 163 162 164 /** Dump buffer into string. … … 167 169 * can not do that) and you do not have to guard it against concurrent 168 170 * 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). 170 173 * Thus, it is necessary to copy the buffer elsewhere (that includes printing 171 174 * to screen or writing to file). … … 173 176 * that is not a big limitation. 174 177 * 175 * @warning You cannot use this function twice in the same printf178 * @warning You cannot use this function more than twice in the same printf 176 179 * (see detailed explanation). 177 180 * … … 185 188 { 186 189 /* 187 * Remove previous string (that might also reveal double usage of 188 * this function). 190 * Remove previous string. 189 191 */ 190 bzero(buffer_dump , BUFFER_DUMP_LEN);192 bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN); 191 193 192 194 if (buffer == NULL) { … … 202 204 /* How many bytes are available in the output buffer. */ 203 205 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]; 205 207 206 208 size_t index = 0; … … 253 255 } 254 256 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]; 256 262 } 257 263 -
uspace/lib/usb/src/hidparser.c
rb20de1d r890961a 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2011 Matej Klonfar 3 3 * All rights reserved. 4 4 * … … 41 41 #include <assert.h> 42 42 43 /** The new report item flag. Used to determine when the item is completly 44 * configured and should be added to the report structure 45 */ 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 78 44 /* 79 45 * Data translation private functions … … 85 51 int usb_pow(int a, int b); 86 52 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 89 54 // TODO: tohle ma bejt asi jinde 90 55 int usb_pow(int a, int b) … … 103 68 } 104 69 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 803 72 804 73 /** Parse and act upon a HID report. … … 980 249 return ret; 981 250 } 982 983 984 /**985 * Appends one item (couple of usage_path and usage) into the usage path986 * structure987 *988 * @param usage_path Usage path structure989 * @param usage_page Usage page constant990 * @param usage Usage constant991 * @return Error code992 */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 structure1014 * @param usage_path1015 * @return void1016 */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_path1033 * @return void1034 */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 usage1047 *1048 * @param usage_path Opaque usage path structure1049 * @param tag Class of currently processed tag (Usage page tag falls into Global1050 * class but Usage tag into the Local)1051 * @param data Value of the processed tag1052 * @return void1053 */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 structures1094 *1095 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten1096 *1097 * @param report_path usage path structure to compare1098 * @param path usage patrh structure to compare1099 * @param flags Flags determining the mode of comparison1100 * @return EOK if both paths are identical, non zero number otherwise1101 */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 structure1211 */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 release1232 * @return void1233 */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 one1247 *1248 * @param usage_path Usage path structure to clone1249 * @return New copy of given usage path structure1250 */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 1290 251 1291 252 /*** OUTPUT API **/ … … 1543 504 } 1544 505 1545 /**1546 * Sets report id in usage path structure1547 *1548 * @param path Usage path structure1549 * @param report_id Report id to set1550 * @return Error code1551 */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 1618 506 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 1619 507 { -
uspace/lib/usbvirt/Makefile
rb20de1d r890961a 1 1 # 2 # Copyright (c) 201 0Vojtech Horky2 # Copyright (c) 2011 Vojtech Horky 3 3 # All rights reserved. 4 4 # … … 33 33 34 34 SOURCES = \ 35 src/callback.c \ 36 src/ctrlpipe.c \ 37 src/debug.c \ 38 src/main.c \ 35 src/ipc.c \ 36 src/ctrltransfer.c \ 39 37 src/stdreq.c \ 40 src/trans action.c38 src/transfer.c 41 39 42 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbvirt/include/usbvirt/device.h
rb20de1d r890961a 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 38 38 #include <usb/usb.h> 39 39 #include <usb/request.h> 40 #include <usb/descriptor.h>41 40 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 73 42 74 43 typedef struct usbvirt_device usbvirt_device_t; 75 struct usbvirt_control_transfer;76 44 77 typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev, 78 usb_device_request_setup_packet_t *request, 79 uint8_t *data); 45 typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t, 46 usb_transfer_type_t, void *, size_t); 47 typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t, 48 usb_transfer_type_t, void *, size_t, size_t *); 49 typedef int (*usbvirt_on_control_t)(usbvirt_device_t *, 50 const usb_device_request_setup_packet_t *, uint8_t *, size_t *); 80 51 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. */93 52 typedef 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; 99 56 uint8_t request; 100 /** Request name for debugging. */101 57 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; 156 60 157 61 /** Extra configuration data for GET_CONFIGURATION request. */ … … 179 83 */ 180 84 usb_standard_device_descriptor_t *device; 181 85 182 86 /** Configurations. */ 183 87 usbvirt_device_configuration_t *configuration; 184 88 /** Number of configurations. */ 185 89 size_t configuration_count; 186 /** Index of currently selected configuration. */187 uint8_t current_configuration;188 90 } usbvirt_descriptors_t; 189 91 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. 191 94 */ 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; 95 typedef 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; 204 103 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; 104 typedef 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; 211 111 212 /** Virtual USB device. */213 112 struct usbvirt_device { 214 /** Callback device operations. */ 113 const char *name; 114 void *device_data; 215 115 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 }; 219 120 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 }; 121 int usbvirt_device_plug(usbvirt_device_t *, const char *); 122 123 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *, 124 uint8_t *, size_t *, void *, size_t); 125 126 int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t); 127 int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *); 128 int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 129 void *, size_t); 130 int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 131 void *, size_t, size_t *); 132 281 133 282 134 #endif -
uspace/lib/usbvirt/include/usbvirt/ipc.h
rb20de1d r890961a 33 33 * @brief Virtual USB device. 34 34 */ 35 #ifndef LIBUSBVIRT_ HUB_H_36 #define LIBUSBVIRT_ HUB_H_35 #ifndef LIBUSBVIRT_IPC_H_ 36 #define LIBUSBVIRT_IPC_H_ 37 37 38 #include "device.h" 38 #include <ipc/common.h> 39 #include <usb/usb.h> 40 #include <bool.h> 39 41 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 identify43 * their direction (and tag).44 */45 42 typedef 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; 50 49 51 const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type); 50 int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t, 51 void *, size_t, size_t *); 52 int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t, 53 void *, size_t); 54 int usbvirt_ipc_send_data_in(int, usb_endpoint_t, usb_transfer_type_t, 55 void *, size_t, size_t *); 56 int usbvirt_ipc_send_data_out(int, usb_endpoint_t, usb_transfer_type_t, 57 void *, size_t); 52 58 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); 59 bool usbvirt_is_usbvirt_method(sysarg_t); 60 bool usbvirt_ipc_handle_call(usbvirt_device_t *, ipc_callid_t, ipc_call_t *); 64 61 65 62 #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> 28 2 29 /** @addtogroup libusbvirt 30 * @{ 31 */ 32 /** @file 33 * @brief Virtual USB private header. 34 */ 35 #ifndef LIBUSBVIRT_PRIVATE_H_ 36 #define LIBUSBVIRT_PRIVATE_H_ 3 int process_control_transfer(usbvirt_device_t *, 4 usbvirt_control_request_handler_t *, 5 usb_device_request_setup_packet_t *, 6 uint8_t *, size_t *); 37 7 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 */ 8 extern 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> 28 5 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> 6 void 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 } 39 14 40 #include "private.h" 15 memcpy(data, actual_data, actual_data_size); 41 16 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 49 22 /** 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)23 static 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) 52 25 { 53 26 uint8_t type = setup_packet->value_high; 54 27 uint8_t index = setup_packet->value_low; 55 28 56 /* 29 /* 57 30 * Standard device descriptor. 58 31 */ 59 32 if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) { 60 33 if (device->descriptors && device->descriptors->device) { 61 return device->control_transfer_reply(device, 0,34 usbvirt_control_reply_helper(setup_packet, data, act_size, 62 35 device->descriptors->device, 63 36 device->descriptors->device->length); 37 return EOK; 64 38 } else { 65 39 return EFORWARD; 66 40 } 67 41 } 68 42 69 43 /* 70 44 * Configuration descriptor together with interface, endpoint and … … 85 59 return ENOMEM; 86 60 } 87 61 88 62 uint8_t *ptr = all_data; 89 63 memcpy(ptr, config->descriptor, config->descriptor->length); … … 96 70 ptr += extra->length; 97 71 } 98 99 int rc = device->control_transfer_reply(device, 0,72 73 usbvirt_control_reply_helper(setup_packet, data, act_size, 100 74 all_data, config->descriptor->total_length); 101 75 102 76 free(all_data); 103 104 return rc;77 78 return EOK; 105 79 } 106 80 107 81 return EFORWARD; 108 82 } 109 83 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) 84 static 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) 113 86 { 114 87 uint16_t new_address = setup_packet->value; … … 119 92 return EINVAL; 120 93 } 121 94 122 95 if (new_address > 127) { 123 96 return EINVAL; 124 97 } 125 126 device-> new_address = new_address;127 98 99 device->address = new_address; 100 128 101 return EOK; 129 102 } 130 103 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) 104 static 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) 134 106 { 135 107 uint16_t configuration_value = setup_packet->value; … … 140 112 return EINVAL; 141 113 } 142 114 143 115 /* 144 116 * Configuration value is 1 byte information. … … 147 119 return EINVAL; 148 120 } 149 121 150 122 /* 151 123 * Do nothing when in default state. According to specification, … … 155 127 return EOK; 156 128 } 157 129 130 usbvirt_device_state_t new_state; 158 131 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; 164 133 } 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; 178 136 } 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 180 143 return EOK; 181 144 } 182 145 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[] = { 146 usbvirt_control_request_handler_t library_handlers[] = { 191 147 { 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 196 154 }, 197 155 { 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 202 162 }, 203 163 { 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, 205 167 .request = USB_DEVREQ_SET_CONFIGURATION, 206 .name = "SetConfiguration ()",207 .callback = handle_set_configuration168 .name = "SetConfiguration", 169 .callback = req_set_configuration 208 170 }, 209 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 171 172 { .callback = NULL } 210 173 }; 211 174 212 /**213 * @}214 */
Note:
See TracChangeset
for help on using the changeset viewer.
