Changes in / [890961a:b20de1d] in mainline
- Files:
-
- 13 added
- 21 deleted
- 37 edited
-
.bzrignore (modified) (1 diff)
-
boot/Makefile.common (modified) (1 diff)
-
uspace/Makefile (modified) (1 diff)
-
uspace/app/usbinfo/main.c (modified) (1 diff)
-
uspace/app/virtusbhub/Makefile (added)
-
uspace/app/virtusbhub/main.c (added)
-
uspace/app/virtusbkbd/Makefile (modified) (1 diff)
-
uspace/app/virtusbkbd/stdreq.c (modified) (1 diff)
-
uspace/app/virtusbkbd/stdreq.h (modified) (1 diff)
-
uspace/app/virtusbkbd/virtusbkbd.c (modified) (9 diffs)
-
uspace/app/vuhid/Makefile (deleted)
-
uspace/app/vuhid/device.c (deleted)
-
uspace/app/vuhid/hids/bootkbd.c (deleted)
-
uspace/app/vuhid/ifaces.c (deleted)
-
uspace/app/vuhid/ifaces.h (deleted)
-
uspace/app/vuhid/main.c (deleted)
-
uspace/app/vuhid/stdreq.c (deleted)
-
uspace/app/vuhid/stdreq.h (deleted)
-
uspace/app/vuhid/virthid.h (deleted)
-
uspace/drv/ohci/root_hub.c (modified) (15 diffs)
-
uspace/drv/ohci/root_hub.h (modified) (1 diff)
-
uspace/drv/usbhub/main.c (modified) (2 diffs)
-
uspace/drv/usbhub/ports.c (modified) (2 diffs)
-
uspace/drv/usbhub/usbhub.c (modified) (4 diffs)
-
uspace/drv/usbkbd/kbddev.c (modified) (1 diff)
-
uspace/drv/vhc/Makefile (modified) (1 diff)
-
uspace/drv/vhc/conn.h (modified) (1 diff)
-
uspace/drv/vhc/conndev.c (modified) (4 diffs)
-
uspace/drv/vhc/connhost.c (modified) (6 diffs)
-
uspace/drv/vhc/devconn.c (deleted)
-
uspace/drv/vhc/devices.c (added)
-
uspace/drv/vhc/devices.h (added)
-
uspace/drv/vhc/hc.c (added)
-
uspace/drv/vhc/hc.h (added)
-
uspace/drv/vhc/hcd.c (added)
-
uspace/drv/vhc/hub.c (modified) (2 diffs)
-
uspace/drv/vhc/hub.h (modified) (1 diff)
-
uspace/drv/vhc/hub/hub.c (modified) (9 diffs)
-
uspace/drv/vhc/hub/hub.h (modified) (3 diffs)
-
uspace/drv/vhc/hub/virthub.c (modified) (7 diffs)
-
uspace/drv/vhc/hub/virthub.h (modified) (2 diffs)
-
uspace/drv/vhc/hub/virthubops.c (modified) (17 diffs)
-
uspace/drv/vhc/main.c (deleted)
-
uspace/drv/vhc/transfer.c (deleted)
-
uspace/drv/vhc/vhcd.h (modified) (1 diff)
-
uspace/lib/c/include/errno.h (modified) (1 diff)
-
uspace/lib/usb/Makefile (modified) (1 diff)
-
uspace/lib/usb/include/usb/classes/hid_report_items.h (modified) (2 diffs)
-
uspace/lib/usb/include/usb/classes/hiddescriptor.h (deleted)
-
uspace/lib/usb/include/usb/classes/hidparser.h (modified) (5 diffs)
-
uspace/lib/usb/include/usb/classes/hidpath.h (deleted)
-
uspace/lib/usb/include/usb/classes/hidtypes.h (deleted)
-
uspace/lib/usb/include/usb/usb.h (modified) (1 diff)
-
uspace/lib/usb/src/debug.c (modified) (6 diffs)
-
uspace/lib/usb/src/hiddescriptor.c (deleted)
-
uspace/lib/usb/src/hidparser.c (modified) (6 diffs)
-
uspace/lib/usb/src/hidpath.c (deleted)
-
uspace/lib/usbvirt/Makefile (modified) (2 diffs)
-
uspace/lib/usbvirt/include/usbvirt/device.h (modified) (3 diffs)
-
uspace/lib/usbvirt/include/usbvirt/hub.h (added)
-
uspace/lib/usbvirt/include/usbvirt/ipc.h (deleted)
-
uspace/lib/usbvirt/src/callback.c (added)
-
uspace/lib/usbvirt/src/ctrlpipe.c (added)
-
uspace/lib/usbvirt/src/ctrltransfer.c (deleted)
-
uspace/lib/usbvirt/src/debug.c (added)
-
uspace/lib/usbvirt/src/ipc.c (deleted)
-
uspace/lib/usbvirt/src/main.c (added)
-
uspace/lib/usbvirt/src/private.h (modified) (1 diff)
-
uspace/lib/usbvirt/src/stdreq.c (modified) (7 diffs)
-
uspace/lib/usbvirt/src/transaction.c (added)
-
uspace/lib/usbvirt/src/transfer.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
r890961a rb20de1d 70 70 ./uspace/app/virtusbkbd/vuk 71 71 ./uspace/app/virtusbhub/vuh 72 ./uspace/app/vuhid/vuh73 72 ./uspace/app/virtusbhub/vhc_hub/* 74 73 ./uspace/app/websrv/websrv -
boot/Makefile.common
r890961a rb20de1d 144 144 $(USPACE_PATH)/app/usbinfo/usbinfo \ 145 145 $(USPACE_PATH)/app/virtusbkbd/vuk \ 146 $(USPACE_PATH)/app/v uhid/vuh \146 $(USPACE_PATH)/app/virtusbhub/vuh \ 147 147 $(USPACE_PATH)/app/websrv/websrv 148 148 -
uspace/Makefile
r890961a rb20de1d 52 52 app/usbinfo \ 53 53 app/virtusbkbd \ 54 app/v uhid\54 app/virtusbhub \ 55 55 app/netecho \ 56 56 app/nettest1 \ -
uspace/app/usbinfo/main.c
r890961a rb20de1d 55 55 if (str_cmp(devpath, "qemu") == 0) { 56 56 devpath = "/hw/pci0/00:01.2/uhci-rh/usb00_a1"; 57 }58 59 /* Hack for virtual keyboard. */60 if (str_cmp(devpath, "virt") == 0) {61 devpath = "/virt/usbhc/usb00_a1/usb00_a2";62 57 } 63 58 -
uspace/app/virtusbkbd/Makefile
r890961a rb20de1d 32 32 BINARY = vuk 33 33 34 LIBS = $(LIBUSB VIRT_PREFIX)/libusbvirt.a $(LIBUSB_PREFIX)/libusb.a34 LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a 35 35 EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include 36 36 -
uspace/app/virtusbkbd/stdreq.c
r890961a rb20de1d 39 39 #include "kbdconfig.h" 40 40 41 int req_get_descriptor(usbvirt_device_t *device, 42 const usb_device_request_setup_packet_t *setup_packet, 43 uint8_t *data, size_t *act_size) 41 int stdreq_on_get_descriptor(struct usbvirt_device *dev, 42 usb_device_request_setup_packet_t *request, uint8_t *data) 44 43 { 45 if ( setup_packet->value_high == USB_DESCTYPE_HID_REPORT) {44 if (request->value_high == USB_DESCTYPE_HID_REPORT) { 46 45 /* 47 46 * For simplicity, always return the same 48 47 * report descriptor. 49 48 */ 50 usbvirt_control_reply_helper(setup_packet, 51 data, act_size, 49 int rc = dev->control_transfer_reply(dev, 0, 52 50 report_descriptor, report_descriptor_size); 53 54 return EOK;51 52 return rc; 55 53 } 56 54 -
uspace/app/virtusbkbd/stdreq.h
r890961a rb20de1d 38 38 #include <usbvirt/device.h> 39 39 40 int req_get_descriptor(usbvirt_device_t *device, 41 const usb_device_request_setup_packet_t *setup_packet, 42 uint8_t *data, size_t *act_size); 40 int stdreq_on_get_descriptor(usbvirt_device_t *, 41 usb_device_request_setup_packet_t *, uint8_t *); 43 42 44 43 #endif -
uspace/app/virtusbkbd/virtusbkbd.c
r890961a rb20de1d 48 48 #include <usb/descriptor.h> 49 49 #include <usb/classes/hid.h> 50 #include <usb/debug.h>51 50 #include <usbvirt/device.h> 51 #include <usbvirt/hub.h> 52 52 53 53 #include "kbdconfig.h" … … 67 67 68 68 kb_status_t status; 69 70 static int on_incoming_data(struct usbvirt_device *dev, 71 usb_endpoint_t endpoint, void *buffer, size_t size) 72 { 73 printf("%s: ignoring incomming data to endpoint %d\n", NAME, endpoint); 74 75 return EOK; 76 } 77 69 78 70 79 /** Compares current and last status of pressed keys. … … 91 100 } 92 101 93 static int on_request_for_data(usbvirt_device_t *dev, 94 usb_endpoint_t endpoint, usb_transfer_type_t transfer_type, 95 void *buffer, size_t size, size_t *actual_size) 102 static int on_request_for_data(struct usbvirt_device *dev, 103 usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size) 96 104 { 97 105 static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE]; … … 114 122 if (keypress_check_with_last_request(data, last_data, 115 123 2 + KB_MAX_KEYS_AT_ONCE)) { 116 return ENAK; 124 *actual_size = 0; 125 return EOK; 117 126 } 118 127 … … 122 131 } 123 132 124 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 125 { 126 .req_direction = USB_DIRECTION_IN, 127 .req_type = USB_REQUEST_TYPE_STANDARD, 128 .req_recipient = USB_REQUEST_RECIPIENT_INTERFACE, 133 static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = { 134 { 135 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE( 136 USB_DIRECTION_IN, 137 USBVIRT_REQUEST_TYPE_STANDARD, 138 USBVIRT_REQUEST_RECIPIENT_DEVICE), 129 139 .request = USB_DEVREQ_GET_DESCRIPTOR, 130 140 .name = "GetDescriptor", 131 .callback = req_get_descriptor 132 }, 133 { 134 .callback = NULL 135 } 141 .callback = stdreq_on_get_descriptor 142 }, 143 { 144 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE( 145 USB_DIRECTION_IN, 146 USBVIRT_REQUEST_TYPE_CLASS, 147 USBVIRT_REQUEST_RECIPIENT_DEVICE), 148 .request = USB_DEVREQ_GET_DESCRIPTOR, 149 .name = "GetDescriptor", 150 .callback = stdreq_on_get_descriptor 151 }, 152 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 136 153 }; 137 154 … … 140 157 */ 141 158 static usbvirt_device_ops_t keyboard_ops = { 142 .control = endpoint_zero_handlers, 143 .data_in[1] = on_request_for_data 159 .control_transfer_handlers = endpoint_zero_handlers, 160 .on_data = on_incoming_data, 161 .on_data_request = on_request_for_data 144 162 }; 145 163 … … 179 197 .ops = &keyboard_ops, 180 198 .descriptors = &descriptors, 199 .lib_debug_level = 3, 200 .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL, 181 201 .name = "keyboard" 182 202 }; … … 242 262 243 263 244 int rc = usbvirt_ device_plug(&keyboard_dev, "/virt/usbhc/hc");264 int rc = usbvirt_connect(&keyboard_dev); 245 265 if (rc != EOK) { 246 266 printf("%s: Unable to start communication with VHCD (%s).\n", … … 258 278 printf("%s: Terminating...\n", NAME); 259 279 260 //usbvirt_disconnect(&keyboard_dev);280 usbvirt_disconnect(&keyboard_dev); 261 281 262 282 return 0; -
uspace/drv/ohci/root_hub.c
r890961a rb20de1d 149 149 150 150 151 static int create_serialized_hub_descriptor(rh_t *instance); 152 153 static int rh_init_descriptors(rh_t *instance); 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 154 156 155 157 static int process_get_port_status_request(rh_t *instance, uint16_t port, … … 162 164 usb_transfer_batch_t * request); 163 165 164 static void create_interrupt_mask_in_instance(rh_t *instance); 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 165 168 166 169 static int process_get_descriptor_request(rh_t *instance, … … 195 198 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 196 199 197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 200 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request, 201 void * change_buffer, size_t buffe_size); 198 202 199 203 static bool is_zeros(void * buffer, size_t size); … … 209 213 instance->port_count = 210 214 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 211 int opResult = rh_init_descriptors(instance); 212 if(opResult != EOK){ 213 return opResult; 214 } 215 rh_init_descriptors(instance); 215 216 // set port power mode to no-power-switching 216 217 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 217 218 instance->unfinished_interrupt_transfer = NULL; 218 instance->interrupt_mask_size = (instance->port_count + 8)/8; 219 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 220 if(!instance->interrupt_buffer) 221 return ENOMEM; 222 223 219 instance->interrupt_buffer = malloc((instance->port_count + 8)/8); 224 220 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 225 221 return EOK; … … 244 240 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 245 241 usb_log_info("Root hub got INTERRUPT packet\n"); 246 create_interrupt_mask_in_instance(instance); 247 if(is_zeros(instance->interrupt_buffer, 248 instance->interrupt_mask_size)){ 249 usb_log_debug("no changes..\n"); 250 instance->unfinished_interrupt_transfer = request; 242 void * buffer; 243 size_t buffer_size; 244 create_interrupt_mask(instance, &buffer, 245 &buffer_size); 246 if(is_zeros(buffer,buffer_size)){ 247 usb_log_debug("no changes.."); 248 instance->unfinished_interrupt_transfer= 249 request; 251 250 //will be finished later 252 251 }else{ 253 usb_log_debug("processing changes..\n"); 254 process_interrupt_mask_in_instance(instance, request); 255 } 252 usb_log_debug("processing changes.."); 253 process_interrupt(instance, request, 254 buffer, buffer_size); 255 } 256 free(buffer); 256 257 opResult = EOK; 257 258 } else { … … 264 265 /*----------------------------------------------------------------------------*/ 265 266 266 /** 267 * process interrupt on a hub 268 * 269 * If there is no pending interrupt transfer, nothing happens. 270 * @param instance 271 */ 267 272 268 void rh_interrupt(rh_t *instance) { 269 //usb_log_info("Whoa whoa wait, I`m not supposed to receive any " 270 // "interrupts, am I?\n"); 273 271 if(!instance->unfinished_interrupt_transfer){ 274 272 return; 275 273 } 276 usb_log_debug("finalizing interrupt transfer\n"); 277 create_interrupt_mask_in_instance(instance); 278 process_interrupt_mask_in_instance(instance, 279 instance->unfinished_interrupt_transfer); 274 size_t size; 275 void * buffer; 276 create_interrupt_mask(instance, &buffer, 277 &size); 278 process_interrupt(instance,instance->unfinished_interrupt_transfer, 279 buffer,size); 280 free(buffer); 280 281 } 281 282 /*----------------------------------------------------------------------------*/ … … 288 289 * 289 290 * @param instance root hub instance 290 * @return error code 291 */ 292 static int create_serialized_hub_descriptor(rh_t *instance) { 293 size_t size = 7 + 294 ((instance->port_count +7 )/ 8) * 2; 295 size_t var_size = (instance->port_count +7 )/ 8; 291 * @param@out out_result pointer to resultant serialized descriptor 292 * @param@out out_size size of serialized descriptor 293 */ 294 static void usb_create_serialized_hub_descriptor(rh_t *instance, 295 uint8_t ** out_result, 296 size_t * out_size) { 297 //base size 298 size_t size = 7; 299 //variable size according to port count 300 size_t var_size = instance->port_count / 8 + 301 ((instance->port_count % 8 > 0) ? 1 : 0); 302 size += 2 * var_size; 296 303 uint8_t * result = (uint8_t*) malloc(size); 297 if(!result) return ENOMEM;298 299 304 bzero(result, size); 300 305 //size … … 325 330 result[7 + var_size + i] = 255; 326 331 } 327 instance->hub_descriptor = result; 328 instance->descriptor_size = size; 329 return EOK; 332 (*out_result) = result; 333 (*out_size) = size; 330 334 } 331 335 /*----------------------------------------------------------------------------*/ … … 336 340 * be initialized only once per hub. 337 341 * @instance root hub instance 338 * @return error code 339 */ 340 static int rh_init_descriptors(rh_t *instance) { 342 */ 343 static void rh_init_descriptors(rh_t *instance) { 341 344 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 342 345 sizeof (ohci_rh_device_descriptor) … … 345 348 memcpy(&descriptor, &ohci_rh_conf_descriptor, 346 349 sizeof (ohci_rh_conf_descriptor)); 347 348 int opResult = create_serialized_hub_descriptor(instance);349 if(opResult != EOK){350 return opResult;351 } 350 uint8_t * hub_descriptor; 351 size_t hub_desc_size; 352 usb_create_serialized_hub_descriptor(instance, &hub_descriptor, 353 &hub_desc_size); 354 352 355 descriptor.total_length = 353 356 sizeof (usb_standard_configuration_descriptor_t) + 354 357 sizeof (usb_standard_endpoint_descriptor_t) + 355 358 sizeof (usb_standard_interface_descriptor_t) + 356 instance->descriptor_size;359 hub_desc_size; 357 360 358 361 uint8_t * full_config_descriptor = 359 362 (uint8_t*) malloc(descriptor.total_length); 360 if(!full_config_descriptor){361 return ENOMEM;362 }363 363 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 364 364 memcpy(full_config_descriptor + sizeof (descriptor), … … 370 370 sizeof (ohci_rh_iface_descriptor) + 371 371 sizeof (ohci_rh_ep_descriptor), 372 instance->hub_descriptor, instance->descriptor_size);373 372 hub_descriptor, hub_desc_size); 373 374 374 instance->descriptors.configuration = full_config_descriptor; 375 375 instance->descriptors.configuration_size = descriptor.total_length; 376 return EOK;377 376 } 378 377 /*----------------------------------------------------------------------------*/ … … 465 464 * bit i indicates change on i`th port (i>0). For more info see 466 465 * Hub and Port status bitmap specification in USB specification 467 * (chapter 11.13.4). 468 * Uses instance`s interrupt buffer to store the interrupt information. 469 * @param instance root hub instance 470 */ 471 static void create_interrupt_mask_in_instance(rh_t * instance) { 472 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 466 * (chapter 11.13.4) 467 * @param instance root hub instance 468 * @param@out buffer pointer to created interrupt mas 469 * @param@out buffer_size size of created interrupt mask 470 */ 471 static void create_interrupt_mask(rh_t *instance, void ** buffer, 472 size_t * buffer_size) { 473 int bit_count = instance->port_count + 1; 474 (*buffer_size) = (bit_count+7 / 8); 475 476 (*buffer) = instance->interrupt_buffer;//malloc(*buffer_size); 477 uint8_t * bitmap = (uint8_t*) (*buffer); 473 478 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 474 479 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 475 bzero(bitmap, instance->interrupt_mask_size);480 bzero(bitmap, (*buffer_size)); 476 481 if (instance->registers->rh_status & mask) { 477 482 bitmap[0] = 1; … … 504 509 const uint16_t setup_request_value = setup_request->value_high; 505 510 //(setup_request->value_low << 8); 511 bool del = false; 506 512 switch (setup_request_value) { 507 513 case USB_DESCTYPE_HUB: 508 514 { 509 usb_log_debug("USB_DESCTYPE_HUB\n"); 510 result_descriptor = instance->hub_descriptor; 511 size = instance->descriptor_size; 515 uint8_t * descriptor; 516 usb_create_serialized_hub_descriptor( 517 instance, &descriptor, &size); 518 result_descriptor = descriptor; 519 if (result_descriptor) del = true; 512 520 break; 513 521 } … … 560 568 request->transfered_size = size; 561 569 memcpy(request->data_buffer, result_descriptor, size); 570 if (del) 571 free(result_descriptor); 562 572 return EOK; 563 573 } … … 885 895 * @param instance hub instance 886 896 * @param request batch request to be processed 897 * @param change_buffer chages on hub 898 * @param buffer_size size of change buffer 887 899 * 888 900 * @return 889 901 */ 890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){ 891 memcpy(request->data_buffer, instance->interrupt_buffer, 892 instance->interrupt_mask_size); 893 request->transfered_size = instance->interrupt_mask_size; 902 static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request, 903 void * change_buffer, size_t buffe_size){ 904 create_interrupt_mask(instance, &change_buffer, 905 &(request->transfered_size)); 906 memcpy(request->data_buffer, change_buffer,request->transfered_size); 894 907 instance->unfinished_interrupt_transfer = NULL; 895 908 usb_transfer_batch_finish_error(request, EOK); -
uspace/drv/ohci/root_hub.h
r890961a rb20de1d 59 59 * 60 60 * This is allocated when initializing instance, so that memory 61 * allocation is not needed when processing request. Buffer is used for 62 * interrupt bitmask. 61 * allocation is not needed when processing request. 63 62 */ 64 63 uint8_t * interrupt_buffer; 65 /** size of interrupt buffer */66 size_t interrupt_mask_size;67 /** instance`s descriptor*/68 uint8_t * hub_descriptor;69 /** size of hub descriptor */70 size_t descriptor_size;71 72 73 64 } rh_t; 74 65 -
uspace/drv/usbhub/main.c
r890961a rb20de1d 55 55 }; 56 56 57 /** 58 * usb hub driver operations 59 * 60 * The most important one is add_device, which is set to usb_hub_add_device. 61 */ 57 62 58 static usb_driver_ops_t usb_hub_driver_ops = { 63 59 .add_device = usb_hub_add_device 64 60 }; 65 61 66 /**67 * hub endpoints, excluding control endpoint68 */69 62 static usb_endpoint_description_t *usb_hub_endpoints[] = { 70 63 &hub_status_change_endpoint_description, … … 72 65 }; 73 66 74 /**75 * static usb hub driver information76 */77 67 static usb_driver_t usb_hub_driver = { 78 68 .name = NAME, -
uspace/drv/usbhub/ports.c
r890961a rb20de1d 167 167 168 168 //close address 169 //if (hub->attached_devs[port].address != 0) { 169 170 if(hub->ports[port].attached_device.address >= 0){ 170 171 /*uncomment this code to use it when DDF allows device removal … … 181 182 */ 182 183 } else { 184 // TODO: is this really reason to print a warning? 183 185 usb_log_warning("Device removed before being registered.\n"); 184 186 -
uspace/drv/usbhub/usbhub.c
r890961a rb20de1d 73 73 74 74 75 /// \TODO malloc checking 76 75 77 //********************************************* 76 78 // … … 246 248 hub_info->ports = malloc( 247 249 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 248 if(!hub_info->ports){249 return ENOMEM;250 }251 250 size_t port; 252 251 for (port = 0; port < hub_info->port_count + 1; ++port) { … … 256 255 usb_log_debug("is_power_switched\n"); 257 256 257 for (port = 1; port <= hub_info->port_count; ++port) { 258 usb_log_debug("powering port %d\n",port); 259 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 260 port, USB_HUB_FEATURE_PORT_POWER); 261 if (opResult != EOK) { 262 usb_log_error("cannot power on port %zu: %s.\n", 263 port, str_error(opResult)); 264 } 265 } 258 266 if(!has_individual_port_powering){ 259 267 usb_log_debug("!has_individual_port_powering\n"); … … 265 273 } 266 274 } 267 268 for (port = 1; port <= hub_info->port_count; ++port) {269 usb_log_debug("Powering port %zu.\n",port);270 opResult = usb_hub_set_port_feature(hub_info->control_pipe,271 port, USB_HUB_FEATURE_PORT_POWER);272 if (opResult != EOK) {273 usb_log_error("cannot power on port %zu: %s.\n",274 port, str_error(opResult));275 }276 }277 278 275 }else{ 279 usb_log_debug("!is_power_switched , not going to be powered\n");276 usb_log_debug("!is_power_switched\n"); 280 277 } 281 278 usb_log_debug2("freeing data\n"); -
uspace/drv/usbkbd/kbddev.c
r890961a rb20de1d 294 294 usb_log_debug("Creating output report.\n"); 295 295 296 //usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path,297 //USB_HID_PATH_COMPARE_END , kbd_dev->led_data,298 //kbd_dev->led_output_size);296 usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path, 297 USB_HID_PATH_COMPARE_END , kbd_dev->led_data, 298 kbd_dev->led_output_size); 299 299 int rc = usb_hid_report_output_translate(kbd_dev->parser, 0, 300 300 kbd_dev->output_buffer, kbd_dev->output_size); -
uspace/drv/vhc/Makefile
r890961a rb20de1d 39 39 40 40 SOURCES = \ 41 hub/hub.c \ 41 42 hub/virthub.c \ 42 hub/hub.c \43 43 hub/virthubops.c \ 44 44 conndev.c \ 45 45 connhost.c \ 46 dev conn.c \47 h ub.c \48 main.c \49 transfer.c46 devices.c \ 47 hc.c \ 48 hcd.c \ 49 hub.c 50 50 51 51 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/vhc/conn.h
r890961a rb20de1d 40 40 #include <usb_iface.h> 41 41 #include "vhcd.h" 42 #include "devices.h" 43 44 void connection_handler_host(sysarg_t); 42 45 43 46 extern usbhc_iface_t vhc_iface; 44 47 extern usb_iface_t vhc_usb_iface; 45 48 extern usb_iface_t rh_usb_iface; 49 50 void address_init(void); 51 46 52 47 53 void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); -
uspace/drv/vhc/conndev.c
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * Connection handling of calls from virtual device (implementation).33 * @brief Connection handling of calls from virtual device (implementation). 34 34 */ 35 35 36 36 #include <assert.h> 37 37 #include <errno.h> 38 #include <ddf/driver.h> 38 #include <usbvirt/hub.h> 39 39 40 #include "conn.h" 41 #include "hc.h" 42 #include "hub.h" 40 43 41 static fibril_local uintptr_t plugged_device_handle = 0; 44 #define DEVICE_NAME_MAXLENGTH 32 45 46 static int get_device_name(int phone, char *buffer, size_t len) 47 { 48 ipc_call_t answer_data; 49 sysarg_t answer_rc; 50 aid_t req; 51 int rc; 52 53 req = async_send_0(phone, 54 IPC_M_USBVIRT_GET_NAME, 55 &answer_data); 56 57 rc = async_data_read_start(phone, buffer, len); 58 if (rc != EOK) { 59 async_wait_for(req, NULL); 60 return EINVAL; 61 } 62 63 async_wait_for(req, &answer_rc); 64 rc = (int)answer_rc; 65 66 if (IPC_GET_ARG1(answer_data) < len) { 67 len = IPC_GET_ARG1(answer_data); 68 } else { 69 len--; 70 } 71 buffer[len] = 0; 72 73 return rc; 74 } 42 75 43 76 /** Default handler for IPC methods not handled by DDF. … … 50 83 ipc_callid_t icallid, ipc_call_t *icall) 51 84 { 52 vhc_data_t *vhc = fun->dev->driver_data;53 85 sysarg_t method = IPC_GET_IMETHOD(*icall); 54 86 55 87 if (method == IPC_M_CONNECT_TO_ME) { 56 88 int callback = IPC_GET_ARG5(*icall); 57 int rc = vhc_virtdev_plug(vhc, callback,58 &plugged_device_handle);59 if ( rc != EOK) {60 async_answer_0(icallid, rc);89 virtdev_connection_t *dev 90 = virtdev_add_device(callback, (sysarg_t)fibril_get_id()); 91 if (!dev) { 92 async_answer_0(icallid, EEXISTS); 61 93 async_hangup(callback); 62 94 return; 63 95 } 64 65 96 async_answer_0(icallid, EOK); 66 97 98 char devname[DEVICE_NAME_MAXLENGTH + 1]; 99 int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH); 100 67 101 usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n", 68 rc == EOK ? "XXX" : "<unknown>", plugged_device_handle);102 rc == EOK ? devname : "<unknown>", dev->id); 69 103 70 104 return; … … 74 108 } 75 109 76 /** Callback when client disconnects.110 /** Callback for DDF when client disconnects. 77 111 * 78 * Used to unplug virtual USB device. 79 * 80 * @param fun 112 * @param fun Device function the client was connected to. 81 113 */ 82 114 void on_client_close(ddf_fun_t *fun) 83 115 { 84 vhc_data_t *vhc = fun->dev->driver_data; 116 /* 117 * Maybe a virtual device is being unplugged. 118 */ 119 virtdev_connection_t *dev = virtdev_find((sysarg_t)fibril_get_id()); 120 if (dev == NULL) { 121 return; 122 } 85 123 86 if (plugged_device_handle != 0) { 87 usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n", 88 plugged_device_handle); 89 vhc_virtdev_unplug(vhc, plugged_device_handle); 90 } 124 usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n", 125 dev->id); 126 virtdev_destroy_device(dev); 91 127 } 92 128 -
uspace/drv/vhc/connhost.c
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * Host controller interface implementation.33 * @brief Connection handling of calls from host (implementation). 34 34 */ 35 35 #include <assert.h> … … 38 38 #include <usb/addrkeep.h> 39 39 #include <usb/ddfiface.h> 40 #include <usb/debug.h> 41 #include <usbhc_iface.h> 40 42 41 #include "vhcd.h" 43 44 #define GET_VHC_DATA(fun) \ 45 ((vhc_data_t *)fun->dev->driver_data) 46 #define VHC_DATA(vhc, fun) \ 47 vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef) 48 49 #define UNSUPPORTED(methodname) \ 50 usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \ 51 methodname, __FILE__, __LINE__) 52 53 /** Found free USB address. 54 * 55 * @param[in] fun Device function the action was invoked on. 56 * @param[in] speed Speed of the device that will get this address. 57 * @param[out] address Non-null pointer where to store the free address. 58 * @return Error code. 59 */ 60 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 61 usb_address_t *address) 62 { 63 VHC_DATA(vhc, fun); 64 65 usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper, 66 USB_SPEED_HIGH); 67 if (addr < 0) { 68 return addr; 69 } 70 71 if (address != NULL) { 72 *address = addr; 73 } 74 75 return EOK; 76 } 77 78 /** Bind USB address with device devman handle. 79 * 80 * @param[in] fun Device function the action was invoked on. 81 * @param[in] address USB address of the device. 82 * @param[in] handle Devman handle of the device. 83 * @return Error code. 84 */ 85 static int bind_address(ddf_fun_t *fun, 86 usb_address_t address, devman_handle_t handle) 87 { 88 VHC_DATA(vhc, fun); 89 usb_log_debug("Binding handle %" PRIun " to address %d.\n", 90 handle, address); 91 usb_device_keeper_bind(&vhc->dev_keeper, address, handle); 92 93 return EOK; 94 } 95 96 /** Release previously requested address. 97 * 98 * @param[in] fun Device function the action was invoked on. 99 * @param[in] address USB address to be released. 100 * @return Error code. 101 */ 102 static int release_address(ddf_fun_t *fun, usb_address_t address) 103 { 104 VHC_DATA(vhc, fun); 105 usb_log_debug("Releasing address %d...\n", address); 106 usb_device_keeper_release(&vhc->dev_keeper, address); 107 108 return ENOTSUP; 109 } 110 111 /** Register endpoint for bandwidth reservation. 112 * 113 * @param[in] fun Device function the action was invoked on. 114 * @param[in] address USB address of the device. 115 * @param[in] speed Endpoint speed (invalid means to use device one). 116 * @param[in] endpoint Endpoint number. 117 * @param[in] transfer_type USB transfer type. 118 * @param[in] direction Endpoint data direction. 119 * @param[in] max_packet_size Max packet size of the endpoint. 120 * @param[in] interval Polling interval. 121 * @return Error code. 122 */ 123 static int register_endpoint(ddf_fun_t *fun, 124 usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint, 125 usb_transfer_type_t transfer_type, usb_direction_t direction, 126 size_t max_packet_size, unsigned int interval) 127 { 128 VHC_DATA(vhc, fun); 129 130 endpoint_t *ep = malloc(sizeof(endpoint_t)); 131 if (ep == NULL) { 132 return ENOMEM; 133 } 134 135 int rc = endpoint_init(ep, address, endpoint, direction, transfer_type, 136 USB_SPEED_FULL, 1); 137 if (rc != EOK) { 138 free(ep); 139 return rc; 140 } 141 142 rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 143 if (rc != EOK) { 144 endpoint_destroy(ep); 145 return rc; 146 } 147 148 return EOK; 149 } 150 151 /** Unregister endpoint (free some bandwidth reservation). 152 * 153 * @param[in] fun Device function the action was invoked on. 154 * @param[in] address USB address of the device. 155 * @param[in] endpoint Endpoint number. 156 * @param[in] direction Endpoint data direction. 157 * @return Error code. 158 */ 159 static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address, 160 usb_endpoint_t endpoint, usb_direction_t direction) 161 { 162 VHC_DATA(vhc, fun); 163 164 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 165 address, endpoint, direction, NULL); 166 if (ep == NULL) { 167 return ENOENT; 168 } 169 170 int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager, 171 address, endpoint, direction); 172 173 return rc; 174 } 175 176 /** Schedule interrupt out transfer. 177 * 178 * The callback is supposed to be called once the transfer (on the wire) is 179 * complete regardless of the outcome. 180 * However, the callback could be called only when this function returns 181 * with success status (i.e. returns EOK). 182 * 183 * @param[in] fun Device function the action was invoked on. 184 * @param[in] target Target pipe (address and endpoint number) specification. 185 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 186 * by the caller). 187 * @param[in] size Size of the @p data buffer in bytes. 188 * @param[in] callback Callback to be issued once the transfer is complete. 189 * @param[in] arg Pass-through argument to the callback. 190 * @return Error code. 191 */ 42 #include "conn.h" 43 #include "hc.h" 44 45 46 typedef struct { 47 usb_direction_t direction; 48 usbhc_iface_transfer_out_callback_t out_callback; 49 usbhc_iface_transfer_in_callback_t in_callback; 50 ddf_fun_t *fun; 51 size_t reported_size; 52 void *arg; 53 } transfer_info_t; 54 55 typedef struct { 56 usb_direction_t direction; 57 usb_target_t target; 58 usbhc_iface_transfer_out_callback_t out_callback; 59 usbhc_iface_transfer_in_callback_t in_callback; 60 ddf_fun_t *fun; 61 void *arg; 62 void *data_buffer; 63 size_t data_buffer_size; 64 } control_transfer_info_t; 65 66 static void universal_callback(void *buffer, size_t size, 67 int outcome, void *arg) 68 { 69 transfer_info_t *transfer = (transfer_info_t *) arg; 70 71 if (transfer->reported_size != (size_t) -1) { 72 size = transfer->reported_size; 73 } 74 75 switch (transfer->direction) { 76 case USB_DIRECTION_IN: 77 transfer->in_callback(transfer->fun, 78 outcome, size, 79 transfer->arg); 80 break; 81 case USB_DIRECTION_OUT: 82 transfer->out_callback(transfer->fun, 83 outcome, 84 transfer->arg); 85 break; 86 default: 87 assert(false && "unreachable"); 88 break; 89 } 90 91 free(transfer); 92 } 93 94 static transfer_info_t *create_transfer_info(ddf_fun_t *fun, 95 usb_direction_t direction, void *arg) 96 { 97 transfer_info_t *transfer = malloc(sizeof(transfer_info_t)); 98 99 transfer->direction = direction; 100 transfer->in_callback = NULL; 101 transfer->out_callback = NULL; 102 transfer->arg = arg; 103 transfer->fun = fun; 104 transfer->reported_size = (size_t) -1; 105 106 return transfer; 107 } 108 109 static void control_abort_prematurely(control_transfer_info_t *transfer, 110 size_t size, int outcome) 111 { 112 switch (transfer->direction) { 113 case USB_DIRECTION_IN: 114 transfer->in_callback(transfer->fun, 115 outcome, size, 116 transfer->arg); 117 break; 118 case USB_DIRECTION_OUT: 119 transfer->out_callback(transfer->fun, 120 outcome, 121 transfer->arg); 122 break; 123 default: 124 assert(false && "unreachable"); 125 break; 126 } 127 } 128 129 static void control_callback_two(void *buffer, size_t size, 130 int outcome, void *arg) 131 { 132 control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg; 133 134 if (outcome != EOK) { 135 control_abort_prematurely(ctrl_transfer, outcome, size); 136 free(ctrl_transfer); 137 return; 138 } 139 140 transfer_info_t *transfer = create_transfer_info(ctrl_transfer->fun, 141 ctrl_transfer->direction, ctrl_transfer->arg); 142 transfer->out_callback = ctrl_transfer->out_callback; 143 transfer->in_callback = ctrl_transfer->in_callback; 144 transfer->reported_size = size; 145 146 switch (ctrl_transfer->direction) { 147 case USB_DIRECTION_IN: 148 hc_add_transaction_to_device(false, ctrl_transfer->target, 149 USB_TRANSFER_CONTROL, 150 NULL, 0, 151 universal_callback, transfer); 152 break; 153 case USB_DIRECTION_OUT: 154 hc_add_transaction_from_device(ctrl_transfer->target, 155 USB_TRANSFER_CONTROL, 156 NULL, 0, 157 universal_callback, transfer); 158 break; 159 default: 160 assert(false && "unreachable"); 161 break; 162 } 163 164 free(ctrl_transfer); 165 } 166 167 static void control_callback_one(void *buffer, size_t size, 168 int outcome, void *arg) 169 { 170 control_transfer_info_t *transfer = (control_transfer_info_t *) arg; 171 172 if (outcome != EOK) { 173 control_abort_prematurely(transfer, outcome, size); 174 free(transfer); 175 return; 176 } 177 178 switch (transfer->direction) { 179 case USB_DIRECTION_IN: 180 hc_add_transaction_from_device(transfer->target, 181 USB_TRANSFER_CONTROL, 182 transfer->data_buffer, transfer->data_buffer_size, 183 control_callback_two, transfer); 184 break; 185 case USB_DIRECTION_OUT: 186 hc_add_transaction_to_device(false, transfer->target, 187 USB_TRANSFER_CONTROL, 188 transfer->data_buffer, transfer->data_buffer_size, 189 control_callback_two, transfer); 190 break; 191 default: 192 assert(false && "unreachable"); 193 break; 194 } 195 } 196 197 static control_transfer_info_t *create_control_transfer_info(ddf_fun_t *fun, 198 usb_direction_t direction, usb_target_t target, 199 void *data_buffer, size_t data_buffer_size, 200 void *arg) 201 { 202 control_transfer_info_t *transfer 203 = malloc(sizeof(control_transfer_info_t)); 204 205 transfer->direction = direction; 206 transfer->target = target; 207 transfer->in_callback = NULL; 208 transfer->out_callback = NULL; 209 transfer->arg = arg; 210 transfer->fun = fun; 211 transfer->data_buffer = data_buffer; 212 transfer->data_buffer_size = data_buffer_size; 213 214 return transfer; 215 } 216 217 static int enqueue_transfer_out(ddf_fun_t *fun, 218 usb_target_t target, usb_transfer_type_t transfer_type, 219 void *buffer, size_t size, 220 usbhc_iface_transfer_out_callback_t callback, void *arg) 221 { 222 usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n", 223 target.address, target.endpoint, 224 usb_str_transfer_type(transfer_type), 225 size); 226 227 transfer_info_t *transfer 228 = create_transfer_info(fun, USB_DIRECTION_OUT, arg); 229 transfer->out_callback = callback; 230 231 hc_add_transaction_to_device(false, target, transfer_type, buffer, size, 232 universal_callback, transfer); 233 234 return EOK; 235 } 236 237 static int enqueue_transfer_in(ddf_fun_t *fun, 238 usb_target_t target, usb_transfer_type_t transfer_type, 239 void *buffer, size_t size, 240 usbhc_iface_transfer_in_callback_t callback, void *arg) 241 { 242 usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n", 243 target.address, target.endpoint, 244 usb_str_transfer_type(transfer_type), 245 size); 246 247 transfer_info_t *transfer 248 = create_transfer_info(fun, USB_DIRECTION_IN, arg); 249 transfer->in_callback = callback; 250 251 hc_add_transaction_from_device(target, transfer_type, buffer, size, 252 universal_callback, transfer); 253 254 return EOK; 255 } 256 257 192 258 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 193 259 void *data, size_t size, 194 260 usbhc_iface_transfer_out_callback_t callback, void *arg) 195 261 { 196 VHC_DATA(vhc, fun); 197 198 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 199 target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT, 200 fun, arg); 201 if (transfer == NULL) { 202 return ENOMEM; 203 } 204 205 transfer->data_buffer = data; 206 transfer->data_buffer_size = size; 207 transfer->callback_out = callback; 208 209 int rc = vhc_virtdev_add_transfer(vhc, transfer); 210 if (rc != EOK) { 211 free(transfer); 212 return rc; 213 } 214 215 return EOK; 216 } 217 218 /** Schedule interrupt in transfer. 219 * 220 * The callback is supposed to be called once the transfer (on the wire) is 221 * complete regardless of the outcome. 222 * However, the callback could be called only when this function returns 223 * with success status (i.e. returns EOK). 224 * 225 * @param[in] fun Device function the action was invoked on. 226 * @param[in] target Target pipe (address and endpoint number) specification. 227 * @param[in] data Buffer where to store the data (in USB endianess, 228 * allocated and deallocated by the caller). 229 * @param[in] size Size of the @p data buffer in bytes. 230 * @param[in] callback Callback to be issued once the transfer is complete. 231 * @param[in] arg Pass-through argument to the callback. 232 * @return Error code. 233 */ 262 return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT, 263 data, size, 264 callback, arg); 265 } 266 234 267 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 235 268 void *data, size_t size, 236 269 usbhc_iface_transfer_in_callback_t callback, void *arg) 237 270 { 238 VHC_DATA(vhc, fun); 239 240 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 241 target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT, 242 fun, arg); 243 if (transfer == NULL) { 244 return ENOMEM; 245 } 246 247 transfer->data_buffer = data; 248 transfer->data_buffer_size = size; 249 transfer->callback_in = callback; 250 251 int rc = vhc_virtdev_add_transfer(vhc, transfer); 252 if (rc != EOK) { 253 free(transfer); 254 return rc; 255 } 256 257 return EOK; 258 } 259 260 /** Schedule bulk out transfer. 261 * 262 * The callback is supposed to be called once the transfer (on the wire) is 263 * complete regardless of the outcome. 264 * However, the callback could be called only when this function returns 265 * with success status (i.e. returns EOK). 266 * 267 * @param[in] fun Device function the action was invoked on. 268 * @param[in] target Target pipe (address and endpoint number) specification. 269 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 270 * by the caller). 271 * @param[in] size Size of the @p data buffer in bytes. 272 * @param[in] callback Callback to be issued once the transfer is complete. 273 * @param[in] arg Pass-through argument to the callback. 274 * @return Error code. 275 */ 276 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 277 void *data, size_t size, 278 usbhc_iface_transfer_out_callback_t callback, void *arg) 279 { 280 UNSUPPORTED("bulk_out"); 281 282 return ENOTSUP; 283 } 284 285 /** Schedule bulk in transfer. 286 * 287 * The callback is supposed to be called once the transfer (on the wire) is 288 * complete regardless of the outcome. 289 * However, the callback could be called only when this function returns 290 * with success status (i.e. returns EOK). 291 * 292 * @param[in] fun Device function the action was invoked on. 293 * @param[in] target Target pipe (address and endpoint number) specification. 294 * @param[in] data Buffer where to store the data (in USB endianess, 295 * allocated and deallocated by the caller). 296 * @param[in] size Size of the @p data buffer in bytes. 297 * @param[in] callback Callback to be issued once the transfer is complete. 298 * @param[in] arg Pass-through argument to the callback. 299 * @return Error code. 300 */ 301 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 302 void *data, size_t size, 303 usbhc_iface_transfer_in_callback_t callback, void *arg) 304 { 305 UNSUPPORTED("bulk_in"); 306 307 return ENOTSUP; 308 } 309 310 /** Schedule control write transfer. 311 * 312 * The callback is supposed to be called once the transfer (on the wire) is 313 * complete regardless of the outcome. 314 * However, the callback could be called only when this function returns 315 * with success status (i.e. returns EOK). 316 * 317 * @param[in] fun Device function the action was invoked on. 318 * @param[in] target Target pipe (address and endpoint number) specification. 319 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 320 * and deallocated by the caller). 321 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 322 * @param[in] data_buffer Data buffer (in USB endianess, allocated and 323 * deallocated by the caller). 324 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 325 * @param[in] callback Callback to be issued once the transfer is complete. 326 * @param[in] arg Pass-through argument to the callback. 327 * @return Error code. 328 */ 271 return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT, 272 data, size, 273 callback, arg); 274 } 275 329 276 static int control_write(ddf_fun_t *fun, usb_target_t target, 330 277 void *setup_packet, size_t setup_packet_size, 331 void *data _buffer, size_t data_buffer_size,278 void *data, size_t data_size, 332 279 usbhc_iface_transfer_out_callback_t callback, void *arg) 333 280 { 334 VHC_DATA(vhc, fun); 335 336 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 337 target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL, 338 fun, arg); 339 if (transfer == NULL) { 340 return ENOMEM; 341 } 342 343 transfer->setup_buffer = setup_packet; 344 transfer->setup_buffer_size = setup_packet_size; 345 transfer->data_buffer = data_buffer; 346 transfer->data_buffer_size = data_buffer_size; 347 transfer->callback_out = callback; 348 349 int rc = vhc_virtdev_add_transfer(vhc, transfer); 350 if (rc != EOK) { 351 free(transfer); 352 return rc; 353 } 354 355 return EOK; 356 } 357 358 /** Schedule control read transfer. 359 * 360 * The callback is supposed to be called once the transfer (on the wire) is 361 * complete regardless of the outcome. 362 * However, the callback could be called only when this function returns 363 * with success status (i.e. returns EOK). 364 * 365 * @param[in] fun Device function the action was invoked on. 366 * @param[in] target Target pipe (address and endpoint number) specification. 367 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 368 * and deallocated by the caller). 369 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 370 * @param[in] data_buffer Buffer where to store the data (in USB endianess, 371 * allocated and deallocated by the caller). 372 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 373 * @param[in] callback Callback to be issued once the transfer is complete. 374 * @param[in] arg Pass-through argument to the callback. 375 * @return Error code. 376 */ 281 control_transfer_info_t *transfer 282 = create_control_transfer_info(fun, USB_DIRECTION_OUT, target, 283 data, data_size, arg); 284 transfer->out_callback = callback; 285 286 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL, 287 setup_packet, setup_packet_size, 288 control_callback_one, transfer); 289 290 return EOK; 291 } 292 377 293 static int control_read(ddf_fun_t *fun, usb_target_t target, 378 294 void *setup_packet, size_t setup_packet_size, 379 void *data _buffer, size_t data_buffer_size,295 void *data, size_t data_size, 380 296 usbhc_iface_transfer_in_callback_t callback, void *arg) 381 297 { 382 VHC_DATA(vhc, fun); 383 384 vhc_transfer_t *transfer = vhc_transfer_create(target.address, 385 target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL, 386 fun, arg); 387 if (transfer == NULL) { 388 return ENOMEM; 389 } 390 391 transfer->setup_buffer = setup_packet; 392 transfer->setup_buffer_size = setup_packet_size; 393 transfer->data_buffer = data_buffer; 394 transfer->data_buffer_size = data_buffer_size; 395 transfer->callback_in = callback; 396 397 int rc = vhc_virtdev_add_transfer(vhc, transfer); 398 if (rc != EOK) { 399 free(transfer); 400 return rc; 401 } 402 403 return EOK; 404 } 298 control_transfer_info_t *transfer 299 = create_control_transfer_info(fun, USB_DIRECTION_IN, target, 300 data, data_size, arg); 301 transfer->in_callback = callback; 302 303 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL, 304 setup_packet, setup_packet_size, 305 control_callback_one, transfer); 306 307 return EOK; 308 } 309 310 static usb_address_keeping_t addresses; 405 311 406 312 static int tell_address(ddf_fun_t *fun, devman_handle_t handle, 407 313 usb_address_t *address) 408 314 { 409 UNSUPPORTED("tell_address"); 410 411 return ENOTSUP; 315 usb_log_debug("tell_address(fun \"%s\", handle %zu)\n", 316 fun->name, (size_t) fun->handle); 317 usb_address_t addr = usb_address_keeping_find(&addresses, handle); 318 if (addr < 0) { 319 return addr; 320 } 321 322 *address = addr; 323 return EOK; 324 } 325 326 static int request_address(ddf_fun_t *fun, usb_speed_t ignored, 327 usb_address_t *address) 328 { 329 usb_address_t addr = usb_address_keeping_request(&addresses); 330 if (addr < 0) { 331 return (int)addr; 332 } 333 334 *address = addr; 335 return EOK; 336 } 337 338 static int release_address(ddf_fun_t *fun, usb_address_t address) 339 { 340 return usb_address_keeping_release(&addresses, address); 341 } 342 343 static int bind_address(ddf_fun_t *fun, usb_address_t address, 344 devman_handle_t handle) 345 { 346 usb_address_keeping_devman_bind(&addresses, address, handle); 347 return EOK; 412 348 } 413 349 … … 415 351 devman_handle_t *handle) 416 352 { 417 VHC_DATA(vhc, root_hub_fun); 418 419 *handle = vhc->hc_fun->handle; 353 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 354 assert(hc_fun != NULL); 355 356 *handle = hc_fun->handle; 357 358 usb_log_debug("usb_iface_get_hc_handle_rh_impl returns %zu\n", *handle); 420 359 421 360 return EOK; … … 425 364 usb_address_t *address) 426 365 { 427 VHC_DATA(vhc, root_hub_fun); 428 429 if (handle == 0) { 430 handle = root_hub_fun->handle; 431 } 432 433 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 434 usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle); 435 if (addr < 0) { 436 return addr; 437 } else { 438 *address = addr; 439 return EOK; 440 } 366 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 367 assert(hc_fun != NULL); 368 369 return tell_address(hc_fun, root_hub_fun->handle, address); 370 } 371 372 void address_init(void) 373 { 374 usb_address_keeping_init(&addresses, 50); 441 375 } 442 376 … … 446 380 .release_address = release_address, 447 381 448 .register_endpoint = register_endpoint,449 .unregister_endpoint = unregister_endpoint,450 451 382 .interrupt_out = interrupt_out, 452 383 .interrupt_in = interrupt_in, 453 454 .bulk_in = bulk_in,455 .bulk_out = bulk_out,456 384 457 385 .control_write = control_write, -
uspace/drv/vhc/hub.c
r890961a rb20de1d 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h> 36 37 #include <usbvirt/device.h> 37 38 #include <errno.h> … … 44 45 45 46 #include "hub.h" 46 //#include "hub/virthub.h"47 #include "hub/virthub.h" 47 48 #include "vhcd.h" 48 49 #include "conn.h" 49 50 50 usbvirt_device_t virtual_hub_device = { 51 .name = "root hub", 52 .ops = &hub_ops, 53 .address = 0 54 }; 55 51 usbvirt_device_t virtual_hub_device; 56 52 static ddf_dev_ops_t rh_ops = { 57 53 .interfaces[USB_DEV_IFACE] = &rh_usb_iface, -
uspace/drv/vhc/hub.h
r890961a rb20de1d 39 39 #include <ddf/driver.h> 40 40 41 #include "devices.h" 41 42 #include "hub/hub.h" 42 43 #include "hub/virthub.h" -
uspace/drv/vhc/hub/hub.c
r890961a rb20de1d 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h> 36 37 #include <usbvirt/device.h> 37 38 #include <errno.h> … … 40 41 #include <stdlib.h> 41 42 #include <ddf/driver.h> 42 #include <usb/debug.h>43 43 44 44 #include "hub.h" … … 96 96 * @param index Port index (one based). 97 97 */ 98 static void hub_init_port(hub_port_t *port, hub_t *hub,size_t index)98 static void hub_init_port(hub_port_t *port, size_t index) 99 99 { 100 100 port->connected_device = NULL; … … 102 102 port->state = HUB_PORT_STATE_NOT_CONFIGURED; 103 103 port->status_change = 0; 104 port->hub = hub;105 104 } 106 105 … … 113 112 size_t i; 114 113 for (i = 0; i < HUB_PORT_COUNT; i++) { 115 hub_init_port(&hub->ports[i], hub,i + 1);114 hub_init_port(&hub->ports[i], i + 1); 116 115 } 117 116 hub->custom_data = NULL; 118 hub->signal_changes = true;119 117 fibril_mutex_initialize(&hub->guard); 120 118 } … … 231 229 } 232 230 233 usb_log_debug("Setting port %zu to state %d.\n", port_index, state);234 235 231 switch (state) { 236 232 case HUB_PORT_STATE_POWERED_OFF: … … 240 236 break; 241 237 case HUB_PORT_STATE_RESUMING: 242 port->state = state;243 238 set_port_state_delayed(hub, port_index, 244 239 10, state, HUB_PORT_STATE_ENABLED); 245 240 break; 246 241 case HUB_PORT_STATE_RESETTING: 247 port->state = state;248 242 set_port_state_delayed(hub, port_index, 249 243 10, state, HUB_PORT_STATE_ENABLED); … … 421 415 { 422 416 assert(port != NULL); 423 uint16_t old_value = port->status_change;424 417 port->status_change |= change; 425 usb_log_debug("Changing status change on %zu: %04x => %04x\n",426 port->index,427 (unsigned int) old_value, (unsigned int) port->status_change);428 port->hub->signal_changes = true;429 418 } 430 419 … … 439 428 assert(port != NULL); 440 429 port->status_change &= (~change); 441 port->hub->signal_changes = true;442 430 } 443 431 -
uspace/drv/vhc/hub/hub.h
r890961a rb20de1d 72 72 } hub_status_change_t; 73 73 74 typedef struct hub hub_t;75 76 74 /** Hub port information. */ 77 75 typedef struct { … … 84 82 /** Status change bitmap. */ 85 83 uint16_t status_change; 86 /** Containing hub. */87 hub_t *hub;88 84 } hub_port_t; 89 85 90 86 /** Hub device type. */ 91 struct hub{87 typedef struct { 92 88 /** Hub ports. */ 93 89 hub_port_t ports[HUB_PORT_COUNT]; … … 96 92 /** Access guard to the whole hub. */ 97 93 fibril_mutex_t guard; 98 /** Last value of status change bitmap. */ 99 bool signal_changes; 100 }; 94 } hub_t; 101 95 102 96 void hub_init(hub_t *); -
uspace/drv/vhc/hub/virthub.c
r890961a rb20de1d 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h> 36 37 #include <usbvirt/device.h> 37 38 #include <assert.h> … … 152 153 dev->ops = &hub_ops; 153 154 dev->descriptors = &descriptors; 155 dev->lib_debug_level = 0; 156 dev->lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL; 154 157 155 158 hub_t *hub = malloc(sizeof(hub_t)); … … 161 164 dev->device_data = hub; 162 165 163 return EOK; 166 int rc; 167 #ifdef STANDALONE_HUB 168 dev->name = "hub"; 169 rc = usbvirt_connect(dev); 170 #else 171 rc = usbvirt_connect_local(dev); 172 #endif 173 174 return rc; 164 175 } 165 176 … … 170 181 * @return Port device was connected to. 171 182 */ 172 int virthub_connect_device(usbvirt_device_t *dev, v hc_virtdev_t *conn)183 int virthub_connect_device(usbvirt_device_t *dev, virtdev_connection_t *conn) 173 184 { 174 185 assert(dev != NULL); … … 190 201 * @return Error code. 191 202 */ 192 int virthub_disconnect_device(usbvirt_device_t *dev, v hc_virtdev_t *conn)203 int virthub_disconnect_device(usbvirt_device_t *dev, virtdev_connection_t *conn) 193 204 { 194 205 assert(dev != NULL); … … 201 212 hub_release(hub); 202 213 203 return E OK;214 return ENOTSUP; 204 215 } 205 216 … … 210 221 * @return Whether port is signalling to the device. 211 222 */ 212 bool virthub_is_device_enabled(usbvirt_device_t *dev, v hc_virtdev_t *conn)223 bool virthub_is_device_enabled(usbvirt_device_t *dev, virtdev_connection_t *conn) 213 224 { 214 225 assert(dev != NULL); -
uspace/drv/vhc/hub/virthub.h
r890961a rb20de1d 42 42 #define virtdev_connection_t int 43 43 #else 44 #include "../ vhcd.h"44 #include "../devices.h" 45 45 #endif 46 46 … … 80 80 81 81 int virthub_init(usbvirt_device_t *); 82 int virthub_connect_device(usbvirt_device_t *, v hc_virtdev_t *);83 int virthub_disconnect_device(usbvirt_device_t *, v hc_virtdev_t *);84 bool virthub_is_device_enabled(usbvirt_device_t *, v hc_virtdev_t *);82 int virthub_connect_device(usbvirt_device_t *, virtdev_connection_t *); 83 int virthub_disconnect_device(usbvirt_device_t *, virtdev_connection_t *); 84 bool virthub_is_device_enabled(usbvirt_device_t *, virtdev_connection_t *); 85 85 void virthub_get_status(usbvirt_device_t *, char *, size_t); 86 86 -
uspace/drv/vhc/hub/virthubops.c
r890961a rb20de1d 35 35 #include <errno.h> 36 36 #include <usb/classes/hub.h> 37 #include <usbvirt/device.h>38 37 #include "virthub.h" 39 38 #include "hub.h" 40 39 41 40 /** Callback when device changes states. */ 42 static void on_state_change( usbvirt_device_t*dev,41 static void on_state_change(struct usbvirt_device *dev, 43 42 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state) 44 43 { … … 62 61 63 62 /** Callback for data request. */ 64 static int req_on_ status_change_pipe(usbvirt_device_t*dev,65 usb_endpoint_t endpoint, usb_transfer_type_t tr_type,66 void *buffer, size_t buffer_size, size_t *actual_size)63 static int req_on_data(struct usbvirt_device *dev, 64 usb_endpoint_t endpoint, 65 void *buffer, size_t size, size_t *actual_size) 67 66 { 68 67 if (endpoint != HUB_STATUS_CHANGE_PIPE) { 69 return ESTALL; 70 } 71 if (tr_type != USB_TRANSFER_INTERRUPT) { 72 return ESTALL; 68 return EINVAL; 73 69 } 74 70 75 hub_t *hub = dev->device_data;71 hub_t *hub = (hub_t *)dev->device_data; 76 72 77 73 hub_acquire(hub); 78 74 79 if (!hub->signal_changes) {80 hub_release(hub);81 82 return ENAK;83 }84 85 86 75 uint8_t change_map = hub_get_status_change_bitmap(hub); 87 76 88 77 uint8_t *b = (uint8_t *) buffer; 89 if ( buffer_size > 0) {78 if (size > 0) { 90 79 *b = change_map; 91 80 *actual_size = 1; 92 } else {93 *actual_size = 0;94 81 } 95 82 96 hub->signal_changes = false;97 98 83 hub_release(hub); 99 84 … … 109 94 */ 110 95 static int req_clear_hub_feature(usbvirt_device_t *dev, 111 const usb_device_request_setup_packet_t *request, uint8_t *data,112 size_t *act_size)96 usb_device_request_setup_packet_t *request, 97 uint8_t *data) 113 98 { 114 99 return ENOTSUP; … … 123 108 */ 124 109 static int req_clear_port_feature(usbvirt_device_t *dev, 125 const usb_device_request_setup_packet_t *request, uint8_t *data,126 size_t *act_size)110 usb_device_request_setup_packet_t *request, 111 uint8_t *data) 127 112 { 128 113 int rc; … … 203 188 */ 204 189 static int req_get_bus_state(usbvirt_device_t *dev, 205 const usb_device_request_setup_packet_t *request, uint8_t *data,206 size_t *act_size)190 usb_device_request_setup_packet_t *request, 191 uint8_t *data) 207 192 { 208 193 return ENOTSUP; … … 217 202 */ 218 203 static int req_get_descriptor(usbvirt_device_t *dev, 219 const usb_device_request_setup_packet_t *request, uint8_t *data,220 size_t *act_size)204 usb_device_request_setup_packet_t *request, 205 uint8_t *data) 221 206 { 222 207 if (request->value_high == USB_DESCTYPE_HUB) { 223 usbvirt_control_reply_helper(request, data, act_size,208 int rc = dev->control_transfer_reply(dev, 0, 224 209 &hub_descriptor, hub_descriptor.length); 225 210 226 return EOK;211 return rc; 227 212 } 228 213 /* Let the framework handle all the rest. */ … … 238 223 */ 239 224 static int req_get_hub_status(usbvirt_device_t *dev, 240 const usb_device_request_setup_packet_t *request, uint8_t *data,241 size_t *act_size)225 usb_device_request_setup_packet_t *request, 226 uint8_t *data) 242 227 { 243 228 uint32_t hub_status = 0; 244 229 245 usbvirt_control_reply_helper(request, data, act_size,230 return dev->control_transfer_reply(dev, 0, 246 231 &hub_status, sizeof(hub_status)); 247 248 return EOK;249 232 } 250 233 … … 257 240 */ 258 241 static int req_get_port_status(usbvirt_device_t *dev, 259 const usb_device_request_setup_packet_t *request, uint8_t *data,260 size_t *act_size)242 usb_device_request_setup_packet_t *request, 243 uint8_t *data) 261 244 { 262 245 hub_t *hub = (hub_t *) dev->device_data; … … 268 251 hub_release(hub); 269 252 270 usbvirt_control_reply_helper(request, data, act_size, 271 &status, sizeof(status)); 272 273 return EOK; 253 return dev->control_transfer_reply(dev, 0, &status, 4); 274 254 } 275 255 … … 282 262 */ 283 263 static int req_set_hub_feature(usbvirt_device_t *dev, 284 const usb_device_request_setup_packet_t *request, uint8_t *data,285 size_t *act_size)264 usb_device_request_setup_packet_t *request, 265 uint8_t *data) 286 266 { 287 267 return ENOTSUP; … … 296 276 */ 297 277 static int req_set_port_feature(usbvirt_device_t *dev, 298 const usb_device_request_setup_packet_t *request, uint8_t *data,299 size_t *act_size)278 usb_device_request_setup_packet_t *request, 279 uint8_t *data) 300 280 { 301 281 int rc; … … 350 330 351 331 /** Recipient: other. */ 352 #define REC_OTHER USB _REQUEST_RECIPIENT_OTHER332 #define REC_OTHER USBVIRT_REQUEST_RECIPIENT_OTHER 353 333 /** Recipient: device. */ 354 #define REC_DEVICE USB _REQUEST_RECIPIENT_DEVICE334 #define REC_DEVICE USBVIRT_REQUEST_RECIPIENT_DEVICE 355 335 /** Direction: in. */ 356 336 #define DIR_IN USB_DIRECTION_IN … … 358 338 #define DIR_OUT USB_DIRECTION_OUT 359 339 360 361 340 /** Create a class request. 362 341 * … … 366 345 */ 367 346 #define CLASS_REQ(direction, recipient, req) \ 368 .req_direction = direction, \ 369 .req_recipient = recipient, \ 370 .req_type = USB_REQUEST_TYPE_CLASS, \ 347 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 348 USBVIRT_REQUEST_TYPE_CLASS, recipient), \ 371 349 .request = req 372 350 … … 378 356 */ 379 357 #define STD_REQ(direction, recipient, req) \ 380 .req_direction = direction, \ 381 .req_recipient = recipient, \ 382 .req_type = USB_REQUEST_TYPE_STANDARD, \ 358 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 359 USBVIRT_REQUEST_TYPE_STANDARD, recipient), \ 383 360 .request = req 384 361 385 362 /** Hub operations on control endpoint zero. */ 386 static usbvirt_control_ request_handler_t endpoint_zero_handlers[] = {363 static usbvirt_control_transfer_handler_t endpoint_zero_handlers[] = { 387 364 { 388 365 STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), … … 440 417 .callback = req_set_port_feature 441 418 }, 442 { 443 .callback = NULL 444 } 419 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 445 420 }; 446 421 … … 448 423 /** Hub operations. */ 449 424 usbvirt_device_ops_t hub_ops = { 450 .control = endpoint_zero_handlers, 451 .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe, 452 .state_changed = on_state_change, 425 .control_transfer_handlers = endpoint_zero_handlers, 426 .on_data = NULL, 427 .on_data_request = req_on_data, 428 .on_state_change = on_state_change, 453 429 }; 454 430 -
uspace/drv/vhc/vhcd.h
r890961a rb20de1d 37 37 38 38 #include <usb/debug.h> 39 #include <usbvirt/device.h>40 #include <usb/host/usb_endpoint_manager.h>41 #include <usb/host/device_keeper.h>42 #include <usbhc_iface.h>43 39 44 40 #define NAME "vhc" 41 #define NAME_DEV "hcd-virt-dev" 42 #define NAMESPACE "usb" 45 43 46 typedef struct { 47 link_t link; 48 int dev_phone; 49 usbvirt_device_t *dev_local; 50 bool plugged; 51 usb_address_t address; 52 fibril_mutex_t guard; 53 link_t transfer_queue; 54 } vhc_virtdev_t; 44 #define DEVMAP_PATH_HC NAMESPACE "/" NAME 45 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV 55 46 56 typedef struct { 57 uint32_t magic; 58 link_t devices; 59 fibril_mutex_t guard; 60 usb_endpoint_manager_t ep_manager; 61 usb_device_keeper_t dev_keeper; 62 usbvirt_device_t *hub; 63 ddf_fun_t *hc_fun; 64 } vhc_data_t; 65 66 typedef struct { 67 link_t link; 68 usb_address_t address; 69 usb_endpoint_t endpoint; 70 usb_direction_t direction; 71 usb_transfer_type_t transfer_type; 72 void *setup_buffer; 73 size_t setup_buffer_size; 74 void *data_buffer; 75 size_t data_buffer_size; 76 ddf_fun_t *ddf_fun; 77 void *callback_arg; 78 usbhc_iface_transfer_in_callback_t callback_in; 79 usbhc_iface_transfer_out_callback_t callback_out; 80 } vhc_transfer_t; 81 82 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t, 83 usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *); 84 int vhc_virtdev_plug(vhc_data_t *, int, uintptr_t *); 85 int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 86 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 87 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t); 88 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *); 89 90 int vhc_transfer_queue_processor(void *arg); 91 47 //#define dprintf(level, format, ...) 48 // usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__) 49 //void dprintf_inval_call(int, ipc_call_t, sysarg_t); 92 50 93 51 #endif -
uspace/lib/c/include/errno.h
r890961a rb20de1d 65 65 #define EEMPTY (-302) 66 66 67 /** Negative acknowledgment. */68 #define ENAK (-303)69 70 67 /** An API function is called while another blocking function is in progress. */ 71 68 #define EINPROGRESS (-10036) -
uspace/lib/usb/Makefile
r890961a rb20de1d 43 43 src/dump.c \ 44 44 src/hidiface.c \ 45 src/hidpath.c \46 45 src/hidparser.c \ 47 src/hiddescriptor.c \48 46 src/hub.c \ 49 47 src/pipepriv.c \ -
uspace/lib/usb/include/usb/classes/hid_report_items.h
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 37 37 38 38 #include <stdint.h> 39 40 /**41 * Item prefix42 */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 flags51 */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)65 39 66 40 /* MAIN ITEMS */ -
uspace/lib/usb/include/usb/classes/hidparser.h
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 39 39 #include <adt/list.h> 40 40 #include <usb/classes/hid_report_items.h> 41 #include <usb/classes/hidpath.h> 42 #include <usb/classes/hidtypes.h> 43 #include <usb/classes/hiddescriptor.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); 44 276 45 277 … … 48 280 */ 49 281 /** */ 50 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 51 size_t size, uint8_t *report_id); 282 int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id); 52 283 53 284 /** */ … … 55 286 usb_hid_report_path_t *path, int flags); 56 287 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 57 325 /* 58 326 * Output report parser functions 59 327 */ 60 328 /** Allocates output report buffer*/ 61 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 62 uint8_t report_id); 329 uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, uint8_t report_id); 63 330 64 331 /** Frees output report buffer*/ … … 69 336 usb_hid_report_path_t *path, int flags); 70 337 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); 342 71 343 /** 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); 74 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 344 int usb_hid_report_output_translate(usb_hid_report_t *report, uint8_t report_id, uint8_t *buffer, size_t size); 87 345 #endif 88 346 /** -
uspace/lib/usb/include/usb/usb.h
r890961a rb20de1d 96 96 USB_REQUEST_RECIPIENT_DEVICE = 0, 97 97 USB_REQUEST_RECIPIENT_INTERFACE = 1, 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2, 99 USB_REQUEST_RECIPIENT_OTHER = 3 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2 100 99 } usb_request_recipient_t; 101 100 -
uspace/lib/usb/src/debug.c
r890961a rb20de1d 158 158 159 159 /** Fibril local storage for the dumped buffer. */ 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; 160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN]; 163 161 164 162 /** Dump buffer into string. … … 169 167 * can not do that) and you do not have to guard it against concurrent 170 168 * calls to it. 171 * The only limitation is that each second call rewrites the buffer again 172 * (internally, two buffer are used in cyclic manner). 169 * The only limitation is that each call rewrites the buffer again. 173 170 * Thus, it is necessary to copy the buffer elsewhere (that includes printing 174 171 * to screen or writing to file). … … 176 173 * that is not a big limitation. 177 174 * 178 * @warning You cannot use this function more thantwice in the same printf175 * @warning You cannot use this function twice in the same printf 179 176 * (see detailed explanation). 180 177 * … … 188 185 { 189 186 /* 190 * Remove previous string. 187 * Remove previous string (that might also reveal double usage of 188 * this function). 191 189 */ 192 bzero(buffer_dump [buffer_dump_index], BUFFER_DUMP_LEN);190 bzero(buffer_dump, BUFFER_DUMP_LEN); 193 191 194 192 if (buffer == NULL) { … … 204 202 /* How many bytes are available in the output buffer. */ 205 203 size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN; 206 char *it = buffer_dump [buffer_dump_index];204 char *it = buffer_dump; 207 205 208 206 size_t index = 0; … … 255 253 } 256 254 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]; 255 return buffer_dump; 262 256 } 263 257 -
uspace/lib/usb/src/hidparser.c
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1 Matej Klonfar2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 41 41 #include <assert.h> 42 42 43 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); 44 78 /* 45 79 * Data translation private functions … … 51 85 int usb_pow(int a, int b); 52 86 53 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)) 54 89 // TODO: tohle ma bejt asi jinde 55 90 int usb_pow(int a, int b) … … 68 103 } 69 104 70 71 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 } 72 803 73 804 /** Parse and act upon a HID report. … … 249 980 return ret; 250 981 } 982 983 984 /** 985 * Appends one item (couple of usage_path and usage) into the usage path 986 * structure 987 * 988 * @param usage_path Usage path structure 989 * @param usage_page Usage page constant 990 * @param usage Usage constant 991 * @return Error code 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 251 1290 252 1291 /*** OUTPUT API **/ … … 504 1543 } 505 1544 1545 /** 1546 * Sets report id in usage path structure 1547 * 1548 * @param path Usage path structure 1549 * @param report_id Report id to set 1550 * @return Error code 1551 */ 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 506 1618 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 507 1619 { -
uspace/lib/usbvirt/Makefile
r890961a rb20de1d 1 1 # 2 # Copyright (c) 201 1Vojtech Horky2 # Copyright (c) 2010 Vojtech Horky 3 3 # All rights reserved. 4 4 # … … 33 33 34 34 SOURCES = \ 35 src/ipc.c \ 36 src/ctrltransfer.c \ 35 src/callback.c \ 36 src/ctrlpipe.c \ 37 src/debug.c \ 38 src/main.c \ 37 39 src/stdreq.c \ 38 src/trans fer.c40 src/transaction.c 39 41 40 42 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbvirt/include/usbvirt/device.h
r890961a rb20de1d 1 1 /* 2 * Copyright (c) 201 1Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 38 38 #include <usb/usb.h> 39 39 #include <usb/request.h> 40 41 #define USBVIRT_ENDPOINT_MAX 16 40 #include <usb/descriptor.h> 41 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; 42 73 43 74 typedef struct usbvirt_device usbvirt_device_t; 44 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 *); 51 52 typedef struct { 53 usb_direction_t req_direction; 54 usb_request_recipient_t req_recipient; 55 usb_request_type_t req_type; 75 struct usbvirt_control_transfer; 76 77 typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev, 78 usb_device_request_setup_packet_t *request, 79 uint8_t *data); 80 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 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. */ 56 99 uint8_t request; 100 /** Request name for debugging. */ 57 101 const char *name; 58 usbvirt_on_control_t callback; 59 } usbvirt_control_request_handler_t; 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; 60 156 61 157 /** Extra configuration data for GET_CONFIGURATION request. */ … … 83 179 */ 84 180 usb_standard_device_descriptor_t *device; 85 181 86 182 /** Configurations. */ 87 183 usbvirt_device_configuration_t *configuration; 88 184 /** Number of configurations. */ 89 185 size_t configuration_count; 186 /** Index of currently selected configuration. */ 187 uint8_t current_configuration; 90 188 } usbvirt_descriptors_t; 91 189 92 /** Possible states of virtual USB device. 93 * Notice that these are not 1:1 mappings to those in USB specification. 94 */ 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; 103 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; 111 190 /** Information about on-going control transfer. 191 */ 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; 204 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; 211 212 /** Virtual USB device. */ 112 213 struct usbvirt_device { 214 /** Callback device operations. */ 215 usbvirt_device_ops_t *ops; 216 217 /** Custom device data. */ 218 void *device_data; 219 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 */ 113 228 const char *name; 114 void *device_data;115 usbvirt_device_ops_t *ops;229 230 /** Standard descriptors. */ 116 231 usbvirt_descriptors_t *descriptors; 232 233 /** Current device state. */ 234 usbvirt_device_state_t state; 235 236 /** Device address. */ 117 237 usb_address_t address; 118 usbvirt_device_state_t state; 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; 119 280 }; 120 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 133 281 134 282 #endif -
uspace/lib/usbvirt/src/private.h
r890961a rb20de1d 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 */ 28 29 /** @addtogroup libusbvirt 30 * @{ 31 */ 32 /** @file 33 * @brief Virtual USB private header. 34 */ 35 #ifndef LIBUSBVIRT_PRIVATE_H_ 36 #define LIBUSBVIRT_PRIVATE_H_ 37 1 38 #include <usbvirt/device.h> 39 #include <usbvirt/hub.h> 40 #include <assert.h> 2 41 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 *);7 42 8 extern usbvirt_control_request_handler_t library_handlers[]; 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 */ -
uspace/lib/usbvirt/src/stdreq.c
r890961a rb20de1d 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 */ 28 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> 39 1 40 #include "private.h" 2 #include <usb/request.h> 3 #include <assert.h> 4 #include <errno.h> 5 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 } 14 15 memcpy(data, actual_data, actual_data_size); 16 17 if (act_size != NULL) { 18 *act_size = actual_data_size; 19 } 20 } 21 41 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 22 49 /** GET_DESCRIPTOR handler. */ 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)50 static int handle_get_descriptor(usbvirt_device_t *device, 51 usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data) 25 52 { 26 53 uint8_t type = setup_packet->value_high; 27 54 uint8_t index = setup_packet->value_low; 28 55 29 /* 56 /* 30 57 * Standard device descriptor. 31 58 */ 32 59 if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) { 33 60 if (device->descriptors && device->descriptors->device) { 34 usbvirt_control_reply_helper(setup_packet, data, act_size,61 return device->control_transfer_reply(device, 0, 35 62 device->descriptors->device, 36 63 device->descriptors->device->length); 37 return EOK;38 64 } else { 39 65 return EFORWARD; 40 66 } 41 67 } 42 68 43 69 /* 44 70 * Configuration descriptor together with interface, endpoint and … … 59 85 return ENOMEM; 60 86 } 61 87 62 88 uint8_t *ptr = all_data; 63 89 memcpy(ptr, config->descriptor, config->descriptor->length); … … 70 96 ptr += extra->length; 71 97 } 72 73 usbvirt_control_reply_helper(setup_packet, data, act_size,98 99 int rc = device->control_transfer_reply(device, 0, 74 100 all_data, config->descriptor->total_length); 75 101 76 102 free(all_data); 77 78 return EOK;79 } 80 103 104 return rc; 105 } 106 81 107 return EFORWARD; 82 108 } 83 109 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) 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) 86 113 { 87 114 uint16_t new_address = setup_packet->value; … … 92 119 return EINVAL; 93 120 } 94 121 95 122 if (new_address > 127) { 96 123 return EINVAL; 97 124 } 98 99 device-> address = new_address;100 125 126 device->new_address = new_address; 127 101 128 return EOK; 102 129 } 103 130 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) 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) 106 134 { 107 135 uint16_t configuration_value = setup_packet->value; … … 112 140 return EINVAL; 113 141 } 114 142 115 143 /* 116 144 * Configuration value is 1 byte information. … … 119 147 return EINVAL; 120 148 } 121 149 122 150 /* 123 151 * Do nothing when in default state. According to specification, … … 127 155 return EOK; 128 156 } 129 130 usbvirt_device_state_t new_state; 157 131 158 if (configuration_value == 0) { 132 new_state = USBVIRT_STATE_ADDRESS; 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; 133 164 } else { 134 // FIXME: check that this configuration exists 135 new_state = USBVIRT_STATE_CONFIGURED; 136 } 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 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 } 178 } 179 143 180 return EOK; 144 181 } 145 182 146 usbvirt_control_request_handler_t library_handlers[] = { 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[] = { 147 191 { 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 192 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN), 193 .request = USB_DEVREQ_GET_DESCRIPTOR, 194 .name = "GetDescriptor()", 195 .callback = handle_get_descriptor 154 196 }, 155 197 { 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 198 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 199 .request = USB_DEVREQ_SET_ADDRESS, 200 .name = "SetAddress()", 201 .callback = handle_set_address 162 202 }, 163 203 { 164 .req_direction = USB_DIRECTION_OUT, 165 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 166 .req_type = USB_REQUEST_TYPE_STANDARD, 204 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 167 205 .request = USB_DEVREQ_SET_CONFIGURATION, 168 .name = "SetConfiguration ",169 .callback = req_set_configuration206 .name = "SetConfiguration()", 207 .callback = handle_set_configuration 170 208 }, 171 172 { .callback = NULL } 209 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 173 210 }; 174 211 212 /** 213 * @} 214 */
Note:
See TracChangeset
for help on using the changeset viewer.
