Changeset 54d71e1 in mainline
- Timestamp:
- 2011-04-29T07:05:30Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 361fcec
- Parents:
- 9014dcd (diff), cd4ae1e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 10 added
- 7 deleted
- 32 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
r9014dcd r54d71e1 70 70 ./uspace/app/virtusbkbd/vuk 71 71 ./uspace/app/virtusbhub/vuh 72 ./uspace/app/vuhid/vuh 72 73 ./uspace/app/virtusbhub/vhc_hub/* 73 74 ./uspace/app/websrv/websrv -
boot/Makefile.common
r9014dcd r54d71e1 144 144 $(USPACE_PATH)/app/usbinfo/usbinfo \ 145 145 $(USPACE_PATH)/app/virtusbkbd/vuk \ 146 $(USPACE_PATH)/app/v irtusbhub/vuh \146 $(USPACE_PATH)/app/vuhid/vuh \ 147 147 $(USPACE_PATH)/app/websrv/websrv 148 148 -
uspace/Makefile
r9014dcd r54d71e1 52 52 app/usbinfo \ 53 53 app/virtusbkbd \ 54 app/v irtusbhub\54 app/vuhid \ 55 55 app/netecho \ 56 56 app/nettest1 \ -
uspace/app/usbinfo/main.c
r9014dcd r54d71e1 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"; 57 62 } 58 63 -
uspace/app/virtusbkbd/Makefile
r9014dcd r54d71e1 32 32 BINARY = vuk 33 33 34 LIBS = $(LIBUSB _PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a34 LIBS = $(LIBUSBVIRT_PREFIX)/libusbvirt.a $(LIBUSB_PREFIX)/libusb.a 35 35 EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include 36 36 -
uspace/app/virtusbkbd/stdreq.c
r9014dcd r54d71e1 39 39 #include "kbdconfig.h" 40 40 41 int stdreq_on_get_descriptor(struct usbvirt_device *dev, 42 usb_device_request_setup_packet_t *request, uint8_t *data) 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) 43 44 { 44 if ( request->value_high == USB_DESCTYPE_HID_REPORT) {45 if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) { 45 46 /* 46 47 * For simplicity, always return the same 47 48 * report descriptor. 48 49 */ 49 int rc = dev->control_transfer_reply(dev, 0, 50 usbvirt_control_reply_helper(setup_packet, 51 data, act_size, 50 52 report_descriptor, report_descriptor_size); 51 52 return rc;53 54 return EOK; 53 55 } 54 56 -
uspace/app/virtusbkbd/stdreq.h
r9014dcd r54d71e1 38 38 #include <usbvirt/device.h> 39 39 40 int stdreq_on_get_descriptor(usbvirt_device_t *, 41 usb_device_request_setup_packet_t *, uint8_t *); 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); 42 43 43 44 #endif -
uspace/app/virtusbkbd/virtusbkbd.c
r9014dcd r54d71e1 48 48 #include <usb/descriptor.h> 49 49 #include <usb/classes/hid.h> 50 #include <usb/debug.h> 50 51 #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 78 69 79 70 /** Compares current and last status of pressed keys. … … 100 91 } 101 92 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) 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) 104 96 { 105 97 static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE]; … … 122 114 if (keypress_check_with_last_request(data, last_data, 123 115 2 + KB_MAX_KEYS_AT_ONCE)) { 124 *actual_size = 0; 125 return EOK; 116 return ENAK; 126 117 } 127 118 … … 131 122 } 132 123 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), 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, 139 129 .request = USB_DEVREQ_GET_DESCRIPTOR, 140 130 .name = "GetDescriptor", 141 .callback = stdreq_on_get_descriptor131 .callback = req_get_descriptor 142 132 }, 143 133 { 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 134 .callback = NULL 135 } 153 136 }; 154 137 … … 157 140 */ 158 141 static usbvirt_device_ops_t keyboard_ops = { 159 .control_transfer_handlers = endpoint_zero_handlers, 160 .on_data = on_incoming_data, 161 .on_data_request = on_request_for_data 142 .control = endpoint_zero_handlers, 143 .data_in[1] = on_request_for_data 162 144 }; 163 145 … … 197 179 .ops = &keyboard_ops, 198 180 .descriptors = &descriptors, 199 .lib_debug_level = 3,200 .lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL,201 181 .name = "keyboard" 202 182 }; … … 262 242 263 243 264 int rc = usbvirt_ connect(&keyboard_dev);244 int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc"); 265 245 if (rc != EOK) { 266 246 printf("%s: Unable to start communication with VHCD (%s).\n", … … 278 258 printf("%s: Terminating...\n", NAME); 279 259 280 usbvirt_disconnect(&keyboard_dev);260 //usbvirt_disconnect(&keyboard_dev); 281 261 282 262 return 0; -
uspace/app/vuhid/Makefile
r9014dcd r54d71e1 28 28 29 29 USPACE_PREFIX = ../.. 30 # acronym for virtual USB hu b30 # acronym for virtual USB human input device 31 31 # (it is really annoying to write long names) 32 32 BINARY = vuh 33 33 34 LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBUSBVIRT_PREFIX)/libusbvirt.a 35 EXTRA_CFLAGS = -DSTANDALONE_HUB \ 36 -DHUB_PORT_COUNT=10 \ 37 -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include 34 LIBS = \ 35 $(LIBUSBVIRT_PREFIX)/libusbvirt.a \ 36 $(LIBUSB_PREFIX)/libusb.a 37 EXTRA_CFLAGS = \ 38 -I$(LIBUSB_PREFIX)/include \ 39 -I$(LIBUSBVIRT_PREFIX)/include \ 40 -I$(LIBDRV_PREFIX)/include 41 42 43 SOURCES_INTERFACES = \ 44 hids/bootkbd.c 38 45 39 46 SOURCES = \ 40 47 main.c \ 41 $(STOLEN_VHC_SOURCES) 42 43 STOLEN_VHC_SOURCES = \ 44 vhc_hub/hub.c \ 45 vhc_hub/virthub.c \ 46 vhc_hub/virthubops.c 47 STOLEN_VHC_HEADERS = \ 48 vhc_hub/hub.h \ 49 vhc_hub/virthub.h 50 51 PRE_DEPEND = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS) 52 53 EXTRA_CLEAN = $(STOLEN_VHC_SOURCES) $(STOLEN_VHC_HEADERS) 54 55 HUB_IN_VHC = $(USPACE_PREFIX)/drv/vhc/hub 48 device.c \ 49 ifaces.c \ 50 stdreq.c \ 51 $(SOURCES_INTERFACES) 52 56 53 57 54 include $(USPACE_PREFIX)/Makefile.common 58 59 vhc_hub/%.h: $(HUB_IN_VHC)/%.h60 ln -sfn ../$(HUB_IN_VHC)/$*.h $@61 vhc_hub/%.c: $(HUB_IN_VHC)/%.c62 ln -sfn ../$(HUB_IN_VHC)/$*.c $@ -
uspace/app/vuhid/ifaces.h
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup libusbvirt29 /** @addtogroup usbvirthid 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief Debugging support.33 * 34 34 */ 35 #i nclude <stdio.h>36 # include <bool.h>35 #ifndef VUHID_IFACES_H_ 36 #define VUHID_IFACES_H_ 37 37 38 #include " private.h"38 #include "virthid.h" 39 39 40 extern vuhid_interface_t *available_hid_interfaces[]; 40 41 41 static void debug_print(int level, uint8_t tag, 42 int current_level, uint8_t enabled_tags, 43 const char *format, va_list args) 44 { 45 if (level > current_level) { 46 return; 47 } 48 49 if ((tag & enabled_tags) == 0) { 50 return; 51 } 52 53 bool print_prefix = true; 54 55 if ((format[0] == '%') && (format[1] == 'M')) { 56 format += 2; 57 print_prefix = false; 58 } 59 60 if (print_prefix) { 61 printf("[vusb]: "); 62 while (--level > 0) { 63 printf(" "); 64 } 65 } 66 67 vprintf(format, args); 68 69 if (print_prefix) { 70 printf("\n"); 71 } 72 } 73 74 75 void user_debug(usbvirt_device_t *device, int level, uint8_t tag, 76 const char *format, ...) 77 { 78 va_list args; 79 va_start(args, format); 80 81 debug_print(level, tag, 82 device->debug_level, device->debug_enabled_tags, 83 format, args); 84 85 va_end(args); 86 } 87 88 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag, 89 const char *format, ...) 90 { 91 va_list args; 92 va_start(args, format); 93 94 debug_print(level, tag, 95 device->lib_debug_level, device->lib_debug_enabled_tags, 96 format, args); 97 98 va_end(args); 99 } 100 42 #endif 101 43 /** 102 44 * @} -
uspace/app/vuhid/stdreq.h
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup drvusbvhc29 /** @addtogroup usbvirthid 30 30 * @{ 31 */ 31 */ 32 32 /** @file 33 * @brief Virtual device management.33 * Device request handlers. 34 34 */ 35 #ifndef V HCD_DEVICES_H_36 #define V HCD_DEVICES_H_35 #ifndef VUHID_STDREQ_H_ 36 #define VUHID_STDREQ_H_ 37 37 38 #include <adt/list.h> 39 #include <usb/usb.h> 38 #include <usbvirt/device.h> 40 39 41 #include "hc.h" 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); 42 43 43 /** Connected virtual device. */ 44 typedef struct { 45 /** Phone used when sending data to device. */ 46 int phone; 47 /** Unique identification. */ 48 sysarg_t id; 49 /** Linked-list handle. */ 50 link_t link; 51 } virtdev_connection_t; 44 int req_set_protocol(usbvirt_device_t *device, 45 const usb_device_request_setup_packet_t *setup_packet, 46 uint8_t *data, size_t *act_size); 52 47 53 virtdev_connection_t *virtdev_add_device(int, sysarg_t); 54 virtdev_connection_t *virtdev_find(sysarg_t); 55 void virtdev_destroy_device(virtdev_connection_t *); 56 int virtdev_send_to_all(transaction_t *); 48 int req_set_report(usbvirt_device_t *device, 49 const usb_device_request_setup_packet_t *setup_packet, 50 uint8_t *data, size_t *act_size); 57 51 58 52 #endif -
uspace/app/vuhid/virthid.h
r9014dcd r54d71e1 27 27 */ 28 28 29 /** @addtogroup usbvirth ub29 /** @addtogroup usbvirthid 30 30 * @{ 31 31 */ 32 /** 33 * @file 34 * @brief Virtual USB hub. 32 /** @file 33 * 35 34 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <errno.h> 40 #include <str_error.h> 41 #include <bool.h> 35 #ifndef VUHID_VIRTHID_H_ 36 #define VUHID_VIRTHID_H_ 42 37 43 38 #include <usb/usb.h> 44 #include <usb/descriptor.h>45 #include <usb/classes/hub.h>46 39 #include <usbvirt/device.h> 47 #include <usbvirt/hub.h>48 40 49 #include "vhc_hub/virthub.h" 41 #define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX 42 #define VUHID_INTERFACE_MAX 8 50 43 51 #define NAME "vuh" 44 typedef struct vuhid_interface vuhid_interface_t; 52 45 53 static usbvirt_device_t hub_device; 46 struct vuhid_interface { 47 const char *name; 48 const char *id; 49 int usb_subclass; 50 int usb_protocol; 54 51 55 #define VERBOSE_SLEEP(sec, msg, ...) \ 56 do { \ 57 char _status[HUB_PORT_COUNT + 2]; \ 58 printf(NAME ": doing nothing for %zu seconds...\n", \ 59 (size_t) (sec)); \ 60 fibril_sleep((sec)); \ 61 virthub_get_status(&hub_device, _status, HUB_PORT_COUNT + 1); \ 62 printf(NAME ": " msg " [%s]\n" #__VA_ARGS__, _status); \ 63 } while (0) 52 uint8_t *report_descriptor; 53 size_t report_descriptor_size; 64 54 65 static void fibril_sleep(size_t sec) 66 { 67 while (sec-- > 0) { 68 async_usleep(1000*1000); 69 } 70 } 55 size_t in_data_size; 56 size_t out_data_size; 71 57 72 static int dev1 = 1; 58 int (*on_data_in)(vuhid_interface_t *, void *, size_t, size_t *); 59 int (*on_data_out)(vuhid_interface_t *, void *, size_t); 60 void (*live)(vuhid_interface_t *); 73 61 74 int main(int argc, char * argv[]) 75 { 76 int rc; 62 int set_protocol; 77 63 78 printf(NAME ": virtual USB hub.\n"); 64 void *interface_data; 65 }; 79 66 80 rc = virthub_init(&hub_device); 81 if (rc != EOK) { 82 printf(NAME ": Unable to start communication with VHCD (%s).\n", 83 str_error(rc)); 84 return rc; 85 } 86 87 while (true) { 88 VERBOSE_SLEEP(8, "will pretend device plug-in..."); 89 virthub_connect_device(&hub_device, &dev1); 67 typedef struct { 68 vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX]; 69 size_t in_endpoint_first_free; 70 vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX]; 71 size_t out_endpoint_first_free; 72 vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX]; 73 } vuhid_data_t; 90 74 91 VERBOSE_SLEEP(8, "will pretend device un-plug..."); 92 virthub_disconnect_device(&hub_device, &dev1); 93 } 75 typedef struct { 76 uint8_t length; 77 uint8_t type; 78 uint16_t hid_spec_release; 79 uint8_t country_code; 80 uint8_t descriptor_count; 81 uint8_t descriptor1_type; 82 uint16_t descriptor1_length; 83 } __attribute__ ((packed)) hid_descriptor_t; 94 84 95 usbvirt_disconnect(&hub_device); 96 97 return 0; 98 } 85 int add_interface_by_id(vuhid_interface_t **, const char *, usbvirt_device_t *); 99 86 100 101 /** @} 87 #endif 88 /** 89 * @} 102 90 */ -
uspace/drv/uhci-hcd/hc.c
r9014dcd r54d71e1 44 44 #include "hc.h" 45 45 46 static irq_cmd_t uhci_cmds[] = { 47 { 48 .cmd = CMD_PIO_READ_16, 49 .addr = NULL, /* patched for every instance */ 50 .dstarg = 1 51 }, 52 { 53 .cmd = CMD_PIO_WRITE_16, 54 .addr = NULL, /* pathed for every instance */ 55 .value = 0x1f 56 }, 57 { 58 .cmd = CMD_ACCEPT 59 } 60 }; 61 /*----------------------------------------------------------------------------*/ 46 #define UHCI_INTR_ALLOW_INTERRUPTS \ 47 (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET) 48 #define UHCI_STATUS_USED_INTERRUPTS \ 49 (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT) 50 51 62 52 static int hc_init_transfer_lists(hc_t *instance); 63 53 static int hc_init_mem_structures(hc_t *instance); … … 151 141 /* Enable all interrupts, but resume interrupt */ 152 142 pio_write_16(&instance->registers->usbintr, 153 UHCI_INTR_ CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);143 UHCI_INTR_ALLOW_INTERRUPTS); 154 144 } 155 145 … … 177 167 { 178 168 assert(instance); 179 #define CHECK_RET_ DEST_CMDS_RETURN(ret, message...) \169 #define CHECK_RET_RETURN(ret, message...) \ 180 170 if (ret != EOK) { \ 181 171 usb_log_error(message); \ 182 if (instance->interrupt_code.cmds != NULL) \183 free(instance->interrupt_code.cmds); \184 172 return ret; \ 185 173 } else (void) 0 186 174 187 175 /* Init interrupt code */ 188 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 189 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 190 CHECK_RET_DEST_CMDS_RETURN(ret, 191 "Failed to allocate interrupt cmds space.\n"); 192 176 instance->interrupt_code.cmds = instance->interrupt_commands; 193 177 { 194 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 195 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 196 interrupt_commands[0].addr = 197 (void*)&instance->registers->usbsts; 198 interrupt_commands[1].addr = 199 (void*)&instance->registers->usbsts; 200 instance->interrupt_code.cmdcount = 201 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 178 /* Read status register */ 179 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16; 180 instance->interrupt_commands[0].dstarg = 1; 181 instance->interrupt_commands[0].addr = 182 &instance->registers->usbsts; 183 184 /* Test whether we are the interrupt cause */ 185 instance->interrupt_commands[1].cmd = CMD_BTEST; 186 instance->interrupt_commands[1].value = 187 UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS; 188 instance->interrupt_commands[1].srcarg = 1; 189 instance->interrupt_commands[1].dstarg = 2; 190 191 /* Predicate cleaning and accepting */ 192 instance->interrupt_commands[2].cmd = CMD_PREDICATE; 193 instance->interrupt_commands[2].value = 2; 194 instance->interrupt_commands[2].srcarg = 2; 195 196 /* Write clean status register */ 197 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16; 198 instance->interrupt_commands[3].srcarg = 1; 199 instance->interrupt_commands[3].addr = 200 &instance->registers->usbsts; 201 202 /* Accept interrupt */ 203 instance->interrupt_commands[4].cmd = CMD_ACCEPT; 204 205 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS; 202 206 } 203 207 204 208 /* Init transfer lists */ 205 ret = hc_init_transfer_lists(instance);206 CHECK_RET_ DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");209 int ret = hc_init_transfer_lists(instance); 210 CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n"); 207 211 usb_log_debug("Initialized transfer lists.\n"); 208 212 … … 210 214 instance->frame_list = get_page(); 211 215 ret = instance ? EOK : ENOMEM; 212 CHECK_RET_ DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");216 CHECK_RET_RETURN(ret, "Failed to get frame list page.\n"); 213 217 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list); 214 218 215 219 /* Set all frames to point to the first queue head */ 216 const uint32_t queue = 217 LINK_POINTER_QH(addr_to_phys( 218 instance->transfers_interrupt.queue_head)); 220 const uint32_t queue = LINK_POINTER_QH( 221 addr_to_phys(instance->transfers_interrupt.queue_head)); 219 222 220 223 unsigned i = 0; … … 229 232 ret = usb_endpoint_manager_init(&instance->ep_manager, 230 233 BANDWIDTH_AVAILABLE_USB11); 231 assert(ret == EOK); 232 233 return EOK; 234 #undef CHECK_RET_DEST_CMDS_RETURN 234 CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n", 235 str_error(ret)); 236 237 return EOK; 238 #undef CHECK_RET_RETURN 235 239 } 236 240 /*----------------------------------------------------------------------------*/ … … 277 281 #ifdef FSBR 278 282 transfer_list_set_next(&instance->transfers_bulk_full, 279 283 &instance->transfers_control_full); 280 284 #endif 281 285 … … 330 334 { 331 335 assert(instance); 332 // status |= 1; //Uncomment to work around qemu hang333 336 /* Lower 2 bits are transaction error and transaction complete */ 334 337 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { … … 352 355 } 353 356 /* Resume interrupts are not supported */ 357 if (status & UHCI_STATUS_RESUME) { 358 usb_log_error("Resume interrupt!\n"); 359 } 354 360 355 361 /* Bits 4 and 5 indicate hc error */ … … 380 386 { 381 387 usb_log_debug("Started interrupt emulator.\n"); 382 hc_t *instance = (hc_t*)arg;388 hc_t *instance = arg; 383 389 assert(instance); 384 390 385 391 while (1) { 386 /* Read dand clear status register */392 /* Read and clear status register */ 387 393 uint16_t status = pio_read_16(&instance->registers->usbsts); 388 394 pio_write_16(&instance->registers->usbsts, status); 389 395 if (status != 0) 390 396 usb_log_debug2("UHCI status: %x.\n", status); 397 // Qemu fails to report stalled communication 398 // see https://bugs.launchpad.net/qemu/+bug/757654 399 // This is a simple workaround to force queue processing every time 400 // status |= 1; 391 401 hc_interrupt(instance, status); 392 402 async_usleep(UHCI_INT_EMULATOR_TIMEOUT); … … 402 412 int hc_debug_checker(void *arg) 403 413 { 404 hc_t *instance = (hc_t*)arg;414 hc_t *instance = arg; 405 415 assert(instance); 406 416 -
uspace/drv/uhci-hcd/hc.h
r9014dcd r54d71e1 69 69 #define UHCI_STATUS_ERROR_INTERRUPT (1 << 1) 70 70 #define UHCI_STATUS_INTERRUPT (1 << 0) 71 #define UHCI_STATUS_NM_INTERRUPTS \ 72 (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR) 71 73 72 74 /** Interrupt enabled registers */ … … 91 93 #define UHCI_DEBUGER_TIMEOUT 5000000 92 94 #define UHCI_ALLOWED_HW_FAIL 5 95 #define UHCI_NEEDED_IRQ_COMMANDS 5 93 96 94 97 /* Main HC driver structure */ … … 119 122 /** Code to be executed in kernel interrupt handler */ 120 123 irq_code_t interrupt_code; 124 125 /** Commands that form interrupt code */ 126 irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS]; 121 127 122 128 /** Fibril periodically checking status register*/ -
uspace/drv/uhci-hcd/pci.c
r9014dcd r54d71e1 146 146 * write all WC bits in USB legacy register */ 147 147 sysarg_t address = 0xc0; 148 sysarg_t value = 0x 8f00;148 sysarg_t value = 0xaf00; 149 149 150 150 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), -
uspace/drv/uhci-hcd/uhci-hcd.ma
r9014dcd r54d71e1 20 20 10 pci/ven=8086&dev=2938 21 21 10 pci/ven=8086&dev=2939 22 23 10 pci/ven=8086&dev=24c2 24 10 pci/ven=8086&dev=24c4 25 10 pci/ven=8086&dev=24c7 -
uspace/drv/usbhub/usbhub.c
r9014dcd r54d71e1 256 256 257 257 for (port = 1; port <= hub_info->port_count; ++port) { 258 usb_log_debug(" powering port %d\n",port);258 usb_log_debug("Powering port %zu.\n",port); 259 259 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 260 260 port, USB_HUB_FEATURE_PORT_POWER); -
uspace/drv/vhc/Makefile
r9014dcd r54d71e1 39 39 40 40 SOURCES = \ 41 hub/virthub.c \ 41 42 hub/hub.c \ 42 hub/virthub.c \43 43 hub/virthubops.c \ 44 44 conndev.c \ 45 45 connhost.c \ 46 dev ices.c \47 h c.c \48 hcd.c \49 hub.c46 devconn.c \ 47 hub.c \ 48 main.c \ 49 transfer.c 50 50 51 51 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/vhc/conn.h
r9014dcd r54d71e1 40 40 #include <usb_iface.h> 41 41 #include "vhcd.h" 42 #include "devices.h"43 44 void connection_handler_host(sysarg_t);45 42 46 43 extern usbhc_iface_t vhc_iface; 47 44 extern usb_iface_t vhc_usb_iface; 48 45 extern usb_iface_t rh_usb_iface; 49 50 void address_init(void);51 52 46 53 47 void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); -
uspace/drv/vhc/conndev.c
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @briefConnection handling of calls from virtual device (implementation).33 * Connection handling of calls from virtual device (implementation). 34 34 */ 35 35 36 36 #include <assert.h> 37 37 #include <errno.h> 38 #include <usbvirt/hub.h> 38 #include <ddf/driver.h> 39 #include "conn.h" 39 40 40 #include "conn.h" 41 #include "hc.h" 42 #include "hub.h" 43 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 } 41 static fibril_local uintptr_t plugged_device_handle = 0; 75 42 76 43 /** Default handler for IPC methods not handled by DDF. … … 83 50 ipc_callid_t icallid, ipc_call_t *icall) 84 51 { 52 vhc_data_t *vhc = fun->dev->driver_data; 85 53 sysarg_t method = IPC_GET_IMETHOD(*icall); 86 54 87 55 if (method == IPC_M_CONNECT_TO_ME) { 88 56 int callback = IPC_GET_ARG5(*icall); 89 virtdev_connection_t *dev90 = virtdev_add_device(callback, (sysarg_t)fibril_get_id());91 if ( !dev) {92 async_answer_0(icallid, EEXISTS);57 int rc = vhc_virtdev_plug(vhc, callback, 58 &plugged_device_handle); 59 if (rc != EOK) { 60 async_answer_0(icallid, rc); 93 61 async_hangup(callback); 94 62 return; 95 63 } 64 96 65 async_answer_0(icallid, EOK); 97 66 98 char devname[DEVICE_NAME_MAXLENGTH + 1];99 int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);100 101 67 usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n", 102 rc == EOK ? devname : "<unknown>", dev->id);68 rc == EOK ? "XXX" : "<unknown>", plugged_device_handle); 103 69 104 70 return; … … 108 74 } 109 75 110 /** Callback for DDFwhen client disconnects.76 /** Callback when client disconnects. 111 77 * 112 * @param fun Device function the client was connected to. 78 * Used to unplug virtual USB device. 79 * 80 * @param fun 113 81 */ 114 82 void on_client_close(ddf_fun_t *fun) 115 83 { 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;84 vhc_data_t *vhc = fun->dev->driver_data; 85 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); 122 90 } 123 124 usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",125 dev->id);126 virtdev_destroy_device(dev);127 91 } 128 92 -
uspace/drv/vhc/connhost.c
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief Connection handling of calls from host (implementation).33 * Host controller interface implementation. 34 34 */ 35 35 #include <assert.h> … … 38 38 #include <usb/addrkeep.h> 39 39 #include <usb/ddfiface.h> 40 40 #include <usb/debug.h> 41 #include <usbhc_iface.h> 41 42 #include "vhcd.h" 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 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 */ 258 192 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 259 193 void *data, size_t size, 260 194 usbhc_iface_transfer_out_callback_t callback, void *arg) 261 195 { 262 return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT, 263 data, size, 264 callback, arg); 265 } 266 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 */ 267 234 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 268 235 void *data, size_t size, 269 236 usbhc_iface_transfer_in_callback_t callback, void *arg) 270 237 { 271 return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT, 272 data, size, 273 callback, arg); 274 } 275 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 */ 276 329 static int control_write(ddf_fun_t *fun, usb_target_t target, 277 330 void *setup_packet, size_t setup_packet_size, 278 void *data , size_t data_size,331 void *data_buffer, size_t data_buffer_size, 279 332 usbhc_iface_transfer_out_callback_t callback, void *arg) 280 333 { 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 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 */ 293 377 static int control_read(ddf_fun_t *fun, usb_target_t target, 294 378 void *setup_packet, size_t setup_packet_size, 295 void *data , size_t data_size,379 void *data_buffer, size_t data_buffer_size, 296 380 usbhc_iface_transfer_in_callback_t callback, void *arg) 297 381 { 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; 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 } 311 405 312 406 static int tell_address(ddf_fun_t *fun, devman_handle_t handle, 313 407 usb_address_t *address) 314 408 { 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); 409 UNSUPPORTED("tell_address"); 410 411 return ENOTSUP; 412 } 413 414 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 415 devman_handle_t *handle) 416 { 417 VHC_DATA(vhc, root_hub_fun); 418 419 *handle = vhc->hc_fun->handle; 420 421 return EOK; 422 } 423 424 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle, 425 usb_address_t *address) 426 { 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); 318 435 if (addr < 0) { 319 436 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; 348 } 349 350 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 351 devman_handle_t *handle) 352 { 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); 359 360 return EOK; 361 } 362 363 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle, 364 usb_address_t *address) 365 { 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); 437 } else { 438 *address = addr; 439 return EOK; 440 } 375 441 } 376 442 … … 380 446 .release_address = release_address, 381 447 448 .register_endpoint = register_endpoint, 449 .unregister_endpoint = unregister_endpoint, 450 382 451 .interrupt_out = interrupt_out, 383 452 .interrupt_in = interrupt_in, 453 454 .bulk_in = bulk_in, 455 .bulk_out = bulk_out, 384 456 385 457 .control_write = control_write, -
uspace/drv/vhc/hub.c
r9014dcd r54d71e1 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <errno.h> … … 45 44 46 45 #include "hub.h" 47 #include "hub/virthub.h"46 //#include "hub/virthub.h" 48 47 #include "vhcd.h" 49 48 #include "conn.h" 50 49 51 usbvirt_device_t virtual_hub_device; 50 usbvirt_device_t virtual_hub_device = { 51 .name = "root hub", 52 .ops = &hub_ops, 53 .address = 0 54 }; 55 52 56 static ddf_dev_ops_t rh_ops = { 53 57 .interfaces[USB_DEV_IFACE] = &rh_usb_iface, -
uspace/drv/vhc/hub.h
r9014dcd r54d71e1 39 39 #include <ddf/driver.h> 40 40 41 #include "devices.h"42 41 #include "hub/hub.h" 43 42 #include "hub/virthub.h" -
uspace/drv/vhc/hub/hub.c
r9014dcd r54d71e1 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <errno.h> … … 41 40 #include <stdlib.h> 42 41 #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, size_t index)98 static void hub_init_port(hub_port_t *port, hub_t *hub, 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; 104 105 } 105 106 … … 112 113 size_t i; 113 114 for (i = 0; i < HUB_PORT_COUNT; i++) { 114 hub_init_port(&hub->ports[i], i + 1);115 hub_init_port(&hub->ports[i], hub, i + 1); 115 116 } 116 117 hub->custom_data = NULL; 118 hub->signal_changes = true; 117 119 fibril_mutex_initialize(&hub->guard); 118 120 } … … 229 231 } 230 232 233 usb_log_debug("Setting port %zu to state %d.\n", port_index, state); 234 231 235 switch (state) { 232 236 case HUB_PORT_STATE_POWERED_OFF: … … 236 240 break; 237 241 case HUB_PORT_STATE_RESUMING: 242 port->state = state; 238 243 set_port_state_delayed(hub, port_index, 239 244 10, state, HUB_PORT_STATE_ENABLED); 240 245 break; 241 246 case HUB_PORT_STATE_RESETTING: 247 port->state = state; 242 248 set_port_state_delayed(hub, port_index, 243 249 10, state, HUB_PORT_STATE_ENABLED); … … 415 421 { 416 422 assert(port != NULL); 423 uint16_t old_value = port->status_change; 417 424 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; 418 429 } 419 430 … … 428 439 assert(port != NULL); 429 440 port->status_change &= (~change); 441 port->hub->signal_changes = true; 430 442 } 431 443 -
uspace/drv/vhc/hub/hub.h
r9014dcd r54d71e1 72 72 } hub_status_change_t; 73 73 74 typedef struct hub hub_t; 75 74 76 /** Hub port information. */ 75 77 typedef struct { … … 82 84 /** Status change bitmap. */ 83 85 uint16_t status_change; 86 /** Containing hub. */ 87 hub_t *hub; 84 88 } hub_port_t; 85 89 86 90 /** Hub device type. */ 87 typedef struct{91 struct hub { 88 92 /** Hub ports. */ 89 93 hub_port_t ports[HUB_PORT_COUNT]; … … 92 96 /** Access guard to the whole hub. */ 93 97 fibril_mutex_t guard; 94 } hub_t; 98 /** Last value of status change bitmap. */ 99 bool signal_changes; 100 }; 95 101 96 102 void hub_init(hub_t *); -
uspace/drv/vhc/hub/virthub.c
r9014dcd r54d71e1 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usbvirt/hub.h>37 36 #include <usbvirt/device.h> 38 37 #include <assert.h> … … 153 152 dev->ops = &hub_ops; 154 153 dev->descriptors = &descriptors; 155 dev->lib_debug_level = 0;156 dev->lib_debug_enabled_tags = USBVIRT_DEBUGTAG_ALL;157 154 158 155 hub_t *hub = malloc(sizeof(hub_t)); … … 164 161 dev->device_data = hub; 165 162 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; 163 return EOK; 175 164 } 176 165 … … 181 170 * @return Port device was connected to. 182 171 */ 183 int virthub_connect_device(usbvirt_device_t *dev, v irtdev_connection_t *conn)172 int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn) 184 173 { 185 174 assert(dev != NULL); … … 201 190 * @return Error code. 202 191 */ 203 int virthub_disconnect_device(usbvirt_device_t *dev, v irtdev_connection_t *conn)192 int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn) 204 193 { 205 194 assert(dev != NULL); … … 212 201 hub_release(hub); 213 202 214 return E NOTSUP;203 return EOK; 215 204 } 216 205 … … 221 210 * @return Whether port is signalling to the device. 222 211 */ 223 bool virthub_is_device_enabled(usbvirt_device_t *dev, v irtdev_connection_t *conn)212 bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn) 224 213 { 225 214 assert(dev != NULL); -
uspace/drv/vhc/hub/virthub.h
r9014dcd r54d71e1 42 42 #define virtdev_connection_t int 43 43 #else 44 #include "../ devices.h"44 #include "../vhcd.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 irtdev_connection_t *);83 int virthub_disconnect_device(usbvirt_device_t *, v irtdev_connection_t *);84 bool virthub_is_device_enabled(usbvirt_device_t *, v irtdev_connection_t *);82 int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *); 83 int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *); 84 bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *); 85 85 void virthub_get_status(usbvirt_device_t *, char *, size_t); 86 86 -
uspace/drv/vhc/hub/virthubops.c
r9014dcd r54d71e1 35 35 #include <errno.h> 36 36 #include <usb/classes/hub.h> 37 #include <usbvirt/device.h> 37 38 #include "virthub.h" 38 39 #include "hub.h" 39 40 40 41 /** Callback when device changes states. */ 41 static void on_state_change( struct usbvirt_device*dev,42 static void on_state_change(usbvirt_device_t *dev, 42 43 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state) 43 44 { … … 61 62 62 63 /** Callback for data request. */ 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)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) 66 67 { 67 68 if (endpoint != HUB_STATUS_CHANGE_PIPE) { 68 return EINVAL; 69 return ESTALL; 70 } 71 if (tr_type != USB_TRANSFER_INTERRUPT) { 72 return ESTALL; 69 73 } 70 74 71 hub_t *hub = (hub_t *)dev->device_data;75 hub_t *hub = dev->device_data; 72 76 73 77 hub_acquire(hub); 74 78 79 if (!hub->signal_changes) { 80 hub_release(hub); 81 82 return ENAK; 83 } 84 85 75 86 uint8_t change_map = hub_get_status_change_bitmap(hub); 76 87 77 88 uint8_t *b = (uint8_t *) buffer; 78 if ( size > 0) {89 if (buffer_size > 0) { 79 90 *b = change_map; 80 91 *actual_size = 1; 92 } else { 93 *actual_size = 0; 81 94 } 82 95 96 hub->signal_changes = false; 97 83 98 hub_release(hub); 84 99 … … 94 109 */ 95 110 static int req_clear_hub_feature(usbvirt_device_t *dev, 96 usb_device_request_setup_packet_t *request,97 uint8_t *data)111 const usb_device_request_setup_packet_t *request, uint8_t *data, 112 size_t *act_size) 98 113 { 99 114 return ENOTSUP; … … 108 123 */ 109 124 static int req_clear_port_feature(usbvirt_device_t *dev, 110 usb_device_request_setup_packet_t *request,111 uint8_t *data)125 const usb_device_request_setup_packet_t *request, uint8_t *data, 126 size_t *act_size) 112 127 { 113 128 int rc; … … 188 203 */ 189 204 static int req_get_bus_state(usbvirt_device_t *dev, 190 usb_device_request_setup_packet_t *request,191 uint8_t *data)205 const usb_device_request_setup_packet_t *request, uint8_t *data, 206 size_t *act_size) 192 207 { 193 208 return ENOTSUP; … … 202 217 */ 203 218 static int req_get_descriptor(usbvirt_device_t *dev, 204 usb_device_request_setup_packet_t *request,205 uint8_t *data)219 const usb_device_request_setup_packet_t *request, uint8_t *data, 220 size_t *act_size) 206 221 { 207 222 if (request->value_high == USB_DESCTYPE_HUB) { 208 int rc = dev->control_transfer_reply(dev, 0,223 usbvirt_control_reply_helper(request, data, act_size, 209 224 &hub_descriptor, hub_descriptor.length); 210 225 211 return rc;226 return EOK; 212 227 } 213 228 /* Let the framework handle all the rest. */ … … 223 238 */ 224 239 static int req_get_hub_status(usbvirt_device_t *dev, 225 usb_device_request_setup_packet_t *request,226 uint8_t *data)240 const usb_device_request_setup_packet_t *request, uint8_t *data, 241 size_t *act_size) 227 242 { 228 243 uint32_t hub_status = 0; 229 244 230 return dev->control_transfer_reply(dev, 0,245 usbvirt_control_reply_helper(request, data, act_size, 231 246 &hub_status, sizeof(hub_status)); 247 248 return EOK; 232 249 } 233 250 … … 240 257 */ 241 258 static int req_get_port_status(usbvirt_device_t *dev, 242 usb_device_request_setup_packet_t *request,243 uint8_t *data)259 const usb_device_request_setup_packet_t *request, uint8_t *data, 260 size_t *act_size) 244 261 { 245 262 hub_t *hub = (hub_t *) dev->device_data; … … 251 268 hub_release(hub); 252 269 253 return dev->control_transfer_reply(dev, 0, &status, 4); 270 usbvirt_control_reply_helper(request, data, act_size, 271 &status, sizeof(status)); 272 273 return EOK; 254 274 } 255 275 … … 262 282 */ 263 283 static int req_set_hub_feature(usbvirt_device_t *dev, 264 usb_device_request_setup_packet_t *request,265 uint8_t *data)284 const usb_device_request_setup_packet_t *request, uint8_t *data, 285 size_t *act_size) 266 286 { 267 287 return ENOTSUP; … … 276 296 */ 277 297 static int req_set_port_feature(usbvirt_device_t *dev, 278 usb_device_request_setup_packet_t *request,279 uint8_t *data)298 const usb_device_request_setup_packet_t *request, uint8_t *data, 299 size_t *act_size) 280 300 { 281 301 int rc; … … 330 350 331 351 /** Recipient: other. */ 332 #define REC_OTHER USB VIRT_REQUEST_RECIPIENT_OTHER352 #define REC_OTHER USB_REQUEST_RECIPIENT_OTHER 333 353 /** Recipient: device. */ 334 #define REC_DEVICE USB VIRT_REQUEST_RECIPIENT_DEVICE354 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE 335 355 /** Direction: in. */ 336 356 #define DIR_IN USB_DIRECTION_IN … … 338 358 #define DIR_OUT USB_DIRECTION_OUT 339 359 360 340 361 /** Create a class request. 341 362 * … … 345 366 */ 346 367 #define CLASS_REQ(direction, recipient, req) \ 347 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 348 USBVIRT_REQUEST_TYPE_CLASS, recipient), \ 368 .req_direction = direction, \ 369 .req_recipient = recipient, \ 370 .req_type = USB_REQUEST_TYPE_CLASS, \ 349 371 .request = req 350 372 … … 356 378 */ 357 379 #define STD_REQ(direction, recipient, req) \ 358 .request_type = USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 359 USBVIRT_REQUEST_TYPE_STANDARD, recipient), \ 380 .req_direction = direction, \ 381 .req_recipient = recipient, \ 382 .req_type = USB_REQUEST_TYPE_STANDARD, \ 360 383 .request = req 361 384 362 385 /** Hub operations on control endpoint zero. */ 363 static usbvirt_control_ transfer_handler_t endpoint_zero_handlers[] = {386 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 364 387 { 365 388 STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), … … 417 440 .callback = req_set_port_feature 418 441 }, 419 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 442 { 443 .callback = NULL 444 } 420 445 }; 421 446 … … 423 448 /** Hub operations. */ 424 449 usbvirt_device_ops_t hub_ops = { 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, 450 .control = endpoint_zero_handlers, 451 .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe, 452 .state_changed = on_state_change, 429 453 }; 430 454 -
uspace/drv/vhc/main.c
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief Virtual host controller driver.33 * Virtual host controller. 34 34 */ 35 35 … … 48 48 #include <usb_iface.h> 49 49 #include "vhcd.h" 50 #include "hc.h"51 #include "devices.h"52 50 #include "hub.h" 53 51 #include "conn.h" … … 65 63 int rc; 66 64 67 /*68 * Currently, we know how to simulate only single HC.69 */70 65 if (vhc_count > 0) { 71 66 return ELIMIT; 72 67 } 73 68 74 /* 75 * Create exposed function representing the host controller 76 * itself. 77 */ 69 vhc_data_t *data = malloc(sizeof(vhc_data_t)); 70 if (data == NULL) { 71 usb_log_fatal("Failed to allocate memory.\n"); 72 return ENOMEM; 73 } 74 data->magic = 0xDEADBEEF; 75 rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1); 76 if (rc != EOK) { 77 usb_log_fatal("Failed to initialize endpoint manager.\n"); 78 free(data); 79 return rc; 80 } 81 usb_device_keeper_init(&data->dev_keeper); 82 78 83 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); 79 84 if (hc == NULL) { 80 85 usb_log_fatal("Failed to create device function.\n"); 86 free(data); 81 87 return ENOMEM; 82 88 } 83 89 84 90 hc->ops = &vhc_ops; 91 list_initialize(&data->devices); 92 fibril_mutex_initialize(&data->guard); 93 data->hub = &virtual_hub_device; 94 data->hc_fun = hc; 95 96 dev->driver_data = data; 85 97 86 98 rc = ddf_fun_bind(hc); … … 88 100 usb_log_fatal("Failed to bind HC function: %s.\n", 89 101 str_error(rc)); 102 free(data); 90 103 return rc; 91 104 } … … 93 106 ddf_fun_add_to_class(hc, "usbhc"); 94 107 95 /*96 * Initialize our hub and announce its presence.97 */98 108 virtual_hub_device_init(hc); 99 109 100 110 usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n", 101 111 (size_t) dev->handle, (size_t) hc->handle); 112 113 114 115 rc = vhc_virtdev_plug_hub(data, data->hub, NULL); 116 if (rc != EOK) { 117 usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc)); 118 free(data); 119 return rc; 120 } 102 121 103 122 return EOK; … … 116 135 int main(int argc, char * argv[]) 117 136 { 118 /*119 * Temporary workaround. Wait a little bit to be the last driver120 * in devman output.121 */122 //sleep(5);123 124 137 usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME); 125 138 126 139 printf(NAME ": virtual USB host controller driver.\n"); 127 140 128 /*129 * Initialize address management.130 */131 address_init();132 133 /*134 * Run the transfer scheduler.135 */136 hc_manager();137 138 /*139 * We are also a driver within devman framework.140 */141 141 return ddf_driver_main(&vhc_driver); 142 142 } -
uspace/drv/vhc/vhcd.h
r9014dcd r54d71e1 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> 39 43 40 44 #define NAME "vhc" 41 #define NAME_DEV "hcd-virt-dev"42 #define NAMESPACE "usb"43 45 44 #define DEVMAP_PATH_HC NAMESPACE "/" NAME 45 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV 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; 46 55 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); 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 50 92 51 93 #endif -
uspace/lib/c/include/errno.h
r9014dcd r54d71e1 65 65 #define EEMPTY (-302) 66 66 67 /** Negative acknowledgment. */ 68 #define ENAK (-303) 69 67 70 /** An API function is called while another blocking function is in progress. */ 68 71 #define EINPROGRESS (-10036) -
uspace/lib/usb/include/usb/usb.h
r9014dcd r54d71e1 96 96 USB_REQUEST_RECIPIENT_DEVICE = 0, 97 97 USB_REQUEST_RECIPIENT_INTERFACE = 1, 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2 98 USB_REQUEST_RECIPIENT_ENDPOINT = 2, 99 USB_REQUEST_RECIPIENT_OTHER = 3 99 100 } usb_request_recipient_t; 100 101 -
uspace/lib/usb/src/debug.c
r9014dcd r54d71e1 158 158 159 159 /** Fibril local storage for the dumped buffer. */ 160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN]; 160 static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN]; 161 /** Fibril local storage for buffer switching. */ 162 static fibril_local int buffer_dump_index = 0; 161 163 162 164 /** Dump buffer into string. … … 167 169 * can not do that) and you do not have to guard it against concurrent 168 170 * calls to it. 169 * The only limitation is that each call rewrites the buffer again. 171 * The only limitation is that each second call rewrites the buffer again 172 * (internally, two buffer are used in cyclic manner). 170 173 * Thus, it is necessary to copy the buffer elsewhere (that includes printing 171 174 * to screen or writing to file). … … 173 176 * that is not a big limitation. 174 177 * 175 * @warning You cannot use this function twice in the same printf178 * @warning You cannot use this function more than twice in the same printf 176 179 * (see detailed explanation). 177 180 * … … 185 188 { 186 189 /* 187 * Remove previous string (that might also reveal double usage of 188 * this function). 190 * Remove previous string. 189 191 */ 190 bzero(buffer_dump , BUFFER_DUMP_LEN);192 bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN); 191 193 192 194 if (buffer == NULL) { … … 202 204 /* How many bytes are available in the output buffer. */ 203 205 size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN; 204 char *it = buffer_dump ;206 char *it = buffer_dump[buffer_dump_index]; 205 207 206 208 size_t index = 0; … … 253 255 } 254 256 255 return buffer_dump; 257 /* Next time, use the other buffer. */ 258 buffer_dump_index = 1 - buffer_dump_index; 259 260 /* Need to take the old one due to previous line. */ 261 return buffer_dump[1 - buffer_dump_index]; 256 262 } 257 263 -
uspace/lib/usbvirt/Makefile
r9014dcd r54d71e1 1 1 # 2 # Copyright (c) 201 0Vojtech Horky2 # Copyright (c) 2011 Vojtech Horky 3 3 # All rights reserved. 4 4 # … … 33 33 34 34 SOURCES = \ 35 src/callback.c \ 36 src/ctrlpipe.c \ 37 src/debug.c \ 38 src/main.c \ 35 src/ipc.c \ 36 src/ctrltransfer.c \ 39 37 src/stdreq.c \ 40 src/trans action.c38 src/transfer.c 41 39 42 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbvirt/include/usbvirt/device.h
r9014dcd r54d71e1 1 1 /* 2 * Copyright (c) 201 0Vojtech Horky2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 38 38 #include <usb/usb.h> 39 39 #include <usb/request.h> 40 #include <usb/descriptor.h>41 40 42 /** Request type of a control transfer. */ 43 typedef enum { 44 /** Standard USB request. */ 45 USBVIRT_REQUEST_TYPE_STANDARD = 0, 46 /** Standard class USB request. */ 47 USBVIRT_REQUEST_TYPE_CLASS = 1 48 } usbvirt_request_type_t; 49 50 /** Recipient of control request. */ 51 typedef enum { 52 /** Device is the recipient of the control request. */ 53 USBVIRT_REQUEST_RECIPIENT_DEVICE = 0, 54 /** Interface is the recipient of the control request. */ 55 USBVIRT_REQUEST_RECIPIENT_INTERFACE = 1, 56 /** Endpoint is the recipient of the control request. */ 57 USBVIRT_REQUEST_RECIPIENT_ENDPOINT = 2, 58 /** Other part of the device is the recipient of the control request. */ 59 USBVIRT_REQUEST_RECIPIENT_OTHER = 3 60 } usbvirt_request_recipient_t; 61 62 /** Possible states of virtual USB device. 63 * Notice that these are not 1:1 mappings to those in USB specification. 64 */ 65 typedef enum { 66 /** Default state, device listens at default address. */ 67 USBVIRT_STATE_DEFAULT, 68 /** Device has non-default address assigned. */ 69 USBVIRT_STATE_ADDRESS, 70 /** Device is configured. */ 71 USBVIRT_STATE_CONFIGURED 72 } usbvirt_device_state_t; 41 #define USBVIRT_ENDPOINT_MAX 16 73 42 74 43 typedef struct usbvirt_device usbvirt_device_t; 75 struct usbvirt_control_transfer;76 44 77 typedef int (*usbvirt_on_device_request_t)(usbvirt_device_t *dev, 78 usb_device_request_setup_packet_t *request, 79 uint8_t *data); 45 typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t, 46 usb_transfer_type_t, void *, size_t); 47 typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t, 48 usb_transfer_type_t, void *, size_t, size_t *); 49 typedef int (*usbvirt_on_control_t)(usbvirt_device_t *, 50 const usb_device_request_setup_packet_t *, uint8_t *, size_t *); 80 51 81 /** Callback for control request over pipe zero.82 *83 * @param dev Virtual device answering the call.84 * @param request Request setup packet.85 * @param data Data when DATA stage is present.86 * @return Error code.87 */88 typedef int (*usbvirt_control_request_callback_t)(usbvirt_device_t *dev,89 usb_device_request_setup_packet_t *request,90 uint8_t *data);91 92 /** Handler for control transfer on endpoint zero. */93 52 typedef struct { 94 /** Request type bitmap. 95 * Use USBVIRT_MAKE_CONTROL_REQUEST_TYPE for creating the bitmap. 96 */ 97 uint8_t request_type; 98 /** Request code. */ 53 usb_direction_t req_direction; 54 usb_request_recipient_t req_recipient; 55 usb_request_type_t req_type; 99 56 uint8_t request; 100 /** Request name for debugging. */101 57 const char *name; 102 /** Callback for the request. 103 * NULL value here announces end of a list. 104 */ 105 usbvirt_control_request_callback_t callback; 106 } usbvirt_control_transfer_handler_t; 107 108 /** Create control request type bitmap. 109 * 110 * @param direction Transfer direction (use usb_direction_t). 111 * @param type Request type (use usbvirt_request_type_t). 112 * @param recipient Recipient of the request (use usbvirt_request_recipient_t). 113 * @return Request type bitmap. 114 */ 115 #define USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, type, recipient) \ 116 ((((direction) == USB_DIRECTION_IN) ? 1 : 0) << 7) \ 117 | (((type) & 3) << 5) \ 118 | (((recipient) & 31)) 119 120 /** Create last item in an array of control request handlers. */ 121 #define USBVIRT_CONTROL_TRANSFER_HANDLER_LAST { 0, 0, NULL, NULL } 122 123 /** Device operations. */ 124 typedef struct { 125 /** Callbacks for transfers over control pipe zero. */ 126 usbvirt_control_transfer_handler_t *control_transfer_handlers; 127 128 int (*on_control_transfer)(usbvirt_device_t *dev, 129 usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer); 130 131 /** Callback for all other incoming data. */ 132 int (*on_data)(usbvirt_device_t *dev, 133 usb_endpoint_t endpoint, void *buffer, size_t size); 134 135 /** Callback for host request for data. */ 136 int (*on_data_request)(usbvirt_device_t *dev, 137 usb_endpoint_t endpoint, void *buffer, size_t size, size_t *actual_size); 138 139 /** Decides direction of control transfer. */ 140 usb_direction_t (*decide_control_transfer_direction)( 141 usb_endpoint_t endpoint, void *buffer, size_t size); 142 143 /** Callback when device changes its state. 144 * 145 * It is correct that this function is called when both states 146 * are equal (e.g. this function is called during SET_CONFIGURATION 147 * request done on already configured device). 148 * 149 * @warning The value of <code>dev->state</code> before calling 150 * this function is not specified (i.e. can be @p old_state or 151 * @p new_state). 152 */ 153 void (*on_state_change)(usbvirt_device_t *dev, 154 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state); 155 } usbvirt_device_ops_t; 58 usbvirt_on_control_t callback; 59 } usbvirt_control_request_handler_t; 156 60 157 61 /** Extra configuration data for GET_CONFIGURATION request. */ … … 179 83 */ 180 84 usb_standard_device_descriptor_t *device; 181 85 182 86 /** Configurations. */ 183 87 usbvirt_device_configuration_t *configuration; 184 88 /** Number of configurations. */ 185 89 size_t configuration_count; 186 /** Index of currently selected configuration. */187 uint8_t current_configuration;188 90 } usbvirt_descriptors_t; 189 91 190 /** Information about on-going control transfer. 92 /** Possible states of virtual USB device. 93 * Notice that these are not 1:1 mappings to those in USB specification. 191 94 */ 192 typedef struct usbvirt_control_transfer { 193 /** Transfer direction (read/write control transfer). */ 194 usb_direction_t direction; 195 /** Request data. */ 196 void *request; 197 /** Size of request data. */ 198 size_t request_size; 199 /** Payload. */ 200 void *data; 201 /** Size of payload. */ 202 size_t data_size; 203 } usbvirt_control_transfer_t; 95 typedef enum { 96 /** Default state, device listens at default address. */ 97 USBVIRT_STATE_DEFAULT, 98 /** Device has non-default address assigned. */ 99 USBVIRT_STATE_ADDRESS, 100 /** Device is configured. */ 101 USBVIRT_STATE_CONFIGURED 102 } usbvirt_device_state_t; 204 103 205 typedef enum { 206 USBVIRT_DEBUGTAG_BASE = 1, 207 USBVIRT_DEBUGTAG_TRANSACTION = 2, 208 USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO = 4, 209 USBVIRT_DEBUGTAG_ALL = 255 210 } usbvirt_debug_tags_t; 104 typedef struct { 105 usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX]; 106 usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX]; 107 usbvirt_control_request_handler_t *control; 108 void (*state_changed)(usbvirt_device_t *dev, 109 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state); 110 } usbvirt_device_ops_t; 211 111 212 /** Virtual USB device. */213 112 struct usbvirt_device { 214 /** Callback device operations. */ 113 const char *name; 114 void *device_data; 215 115 usbvirt_device_ops_t *ops; 216 217 /** Custom device data. */ 218 void *device_data; 116 usbvirt_descriptors_t *descriptors; 117 usb_address_t address; 118 usbvirt_device_state_t state; 119 }; 219 120 220 /** Reply onto control transfer. 221 */ 222 int (*control_transfer_reply)(usbvirt_device_t *dev, 223 usb_endpoint_t endpoint, void *buffer, size_t size); 224 225 /** Device name. 226 * Used in debug prints and sent to virtual host controller. 227 */ 228 const char *name; 229 230 /** Standard descriptors. */ 231 usbvirt_descriptors_t *descriptors; 232 233 /** Current device state. */ 234 usbvirt_device_state_t state; 235 236 /** Device address. */ 237 usb_address_t address; 238 /** New device address. 239 * This field is used during SET_ADDRESS request. 240 * On all other occasions, it holds invalid address (e.g. -1). 241 */ 242 usb_address_t new_address; 243 244 /** Process OUT transaction. */ 245 int (*transaction_out)(usbvirt_device_t *dev, 246 usb_endpoint_t endpoint, void *buffer, size_t size); 247 /** Process SETUP transaction. */ 248 int (*transaction_setup)(usbvirt_device_t *dev, 249 usb_endpoint_t endpoint, void *buffer, size_t size); 250 /** Process IN transaction. */ 251 int (*transaction_in)(usbvirt_device_t *dev, 252 usb_endpoint_t endpoint, void *buffer, size_t size, size_t *data_size); 253 254 /** State information on control-transfer endpoints. */ 255 usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX]; 256 257 /* User debugging. */ 258 259 /** Debug print. */ 260 void (*debug)(usbvirt_device_t *dev, int level, uint8_t tag, 261 const char *format, ...); 262 263 /** Current debug level. */ 264 int debug_level; 265 266 /** Bitmap of currently enabled tags. */ 267 uint8_t debug_enabled_tags; 268 269 /* Library debugging. */ 270 271 /** Debug print. */ 272 void (*lib_debug)(usbvirt_device_t *dev, int level, uint8_t tag, 273 const char *format, ...); 274 275 /** Current debug level. */ 276 int lib_debug_level; 277 278 /** Bitmap of currently enabled tags. */ 279 uint8_t lib_debug_enabled_tags; 280 }; 121 int usbvirt_device_plug(usbvirt_device_t *, const char *); 122 123 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *, 124 uint8_t *, size_t *, void *, size_t); 125 126 int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t); 127 int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *); 128 int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 129 void *, size_t); 130 int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 131 void *, size_t, size_t *); 132 281 133 282 134 #endif -
uspace/lib/usbvirt/include/usbvirt/ipc.h
r9014dcd r54d71e1 33 33 * @brief Virtual USB device. 34 34 */ 35 #ifndef LIBUSBVIRT_ HUB_H_36 #define LIBUSBVIRT_ HUB_H_35 #ifndef LIBUSBVIRT_IPC_H_ 36 #define LIBUSBVIRT_IPC_H_ 37 37 38 #include "device.h" 38 #include <ipc/common.h> 39 #include <usb/usb.h> 40 #include <bool.h> 39 41 40 /** USB transaction type.41 * This types does not correspond directly to types in USB specification,42 * as actually DATA transactions are marked with these types to identify43 * their direction (and tag).44 */45 42 typedef enum { 46 USBVIRT_TRANSACTION_SETUP, 47 USBVIRT_TRANSACTION_IN, 48 USBVIRT_TRANSACTION_OUT 49 } usbvirt_transaction_type_t; 43 IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80, 44 IPC_M_USBVIRT_CONTROL_READ, 45 IPC_M_USBVIRT_CONTROL_WRITE, 46 IPC_M_USBVIRT_INTERRUPT_IN, 47 IPC_M_USBVIRT_INTERRUPT_OUT 48 } usbvirt_ipc_t; 50 49 51 const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type); 50 int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t, 51 void *, size_t, size_t *); 52 int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t, 53 void *, size_t); 54 int usbvirt_ipc_send_data_in(int, usb_endpoint_t, usb_transfer_type_t, 55 void *, size_t, size_t *); 56 int usbvirt_ipc_send_data_out(int, usb_endpoint_t, usb_transfer_type_t, 57 void *, size_t); 52 58 53 /** Telephony methods of virtual devices. */ 54 typedef enum { 55 IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD, 56 IPC_M_USBVIRT_TRANSACTION_SETUP, 57 IPC_M_USBVIRT_TRANSACTION_OUT, 58 IPC_M_USBVIRT_TRANSACTION_IN, 59 } usbvirt_device_method_t; 60 61 int usbvirt_connect(usbvirt_device_t *); 62 int usbvirt_connect_local(usbvirt_device_t *); 63 int usbvirt_disconnect(usbvirt_device_t *dev); 59 bool usbvirt_is_usbvirt_method(sysarg_t); 60 bool usbvirt_ipc_handle_call(usbvirt_device_t *, ipc_callid_t, ipc_call_t *); 64 61 65 62 #endif -
uspace/lib/usbvirt/src/private.h
r9014dcd r54d71e1 1 /* 2 * Copyright (c) 2010 Vojtech Horky 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 1 #include <usbvirt/device.h> 28 2 29 /** @addtogroup libusbvirt 30 * @{ 31 */ 32 /** @file 33 * @brief Virtual USB private header. 34 */ 35 #ifndef LIBUSBVIRT_PRIVATE_H_ 36 #define LIBUSBVIRT_PRIVATE_H_ 3 int process_control_transfer(usbvirt_device_t *, 4 usbvirt_control_request_handler_t *, 5 usb_device_request_setup_packet_t *, 6 uint8_t *, size_t *); 37 7 38 #include <usbvirt/device.h> 39 #include <usbvirt/hub.h> 40 #include <assert.h> 41 42 43 #define DEVICE_HAS_OP(dev, op) \ 44 ( \ 45 ( ((dev)->ops) != NULL ) \ 46 && \ 47 ( ((dev)->ops->op) != NULL ) \ 48 ) 49 50 int usbvirt_data_to_host(struct usbvirt_device *dev, 51 usb_endpoint_t endpoint, void *buffer, size_t size); 52 53 int handle_incoming_data(struct usbvirt_device *dev, 54 usb_endpoint_t endpoint, void *buffer, size_t size); 55 56 int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer); 57 58 int handle_std_request(usbvirt_device_t *device, usb_device_request_setup_packet_t *request, uint8_t *data); 59 60 void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall); 61 62 int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint, 63 void *buffer, size_t size); 64 int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint, 65 void *buffer, size_t size); 66 int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint, 67 void *buffer, size_t size, size_t *data_size); 68 69 70 void user_debug(usbvirt_device_t *device, int level, uint8_t tag, 71 const char *format, ...); 72 void lib_debug(usbvirt_device_t *device, int level, uint8_t tag, 73 const char *format, ...); 74 75 static inline const char *str_device_state(usbvirt_device_state_t state) 76 { 77 switch (state) { 78 case USBVIRT_STATE_DEFAULT: 79 return "default"; 80 case USBVIRT_STATE_ADDRESS: 81 return "address"; 82 case USBVIRT_STATE_CONFIGURED: 83 return "configured"; 84 default: 85 return "unknown"; 86 } 87 } 88 89 extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[]; 90 91 #endif 92 /** 93 * @} 94 */ 8 extern usbvirt_control_request_handler_t library_handlers[]; -
uspace/lib/usbvirt/src/stdreq.c
r9014dcd r54d71e1 1 /* 2 * Copyright (c) 2010 Vojtech Horky 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 1 #include "private.h" 2 #include <usb/request.h> 3 #include <assert.h> 4 #include <errno.h> 28 5 29 /** @addtogroup libusbvirt 30 * @{ 31 */ 32 /** @file 33 * @brief Preprocessing of standard device requests. 34 */ 35 #include <errno.h> 36 #include <stdlib.h> 37 #include <mem.h> 38 #include <usb/request.h> 6 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet, 7 uint8_t *data, size_t *act_size, 8 void *actual_data, size_t actual_data_size) 9 { 10 size_t expected_size = setup_packet->length; 11 if (expected_size < actual_data_size) { 12 actual_data_size = expected_size; 13 } 39 14 40 #include "private.h" 15 memcpy(data, actual_data, actual_data_size); 41 16 42 /* 43 * All sub handlers must return EFORWARD to inform the caller that 44 * they were not able to process the request (yes, it is abuse of 45 * this error code but such error code shall not collide with anything 46 * else in this context). 47 */ 48 17 if (act_size != NULL) { 18 *act_size = actual_data_size; 19 } 20 } 21 49 22 /** GET_DESCRIPTOR handler. */ 50 static int handle_get_descriptor(usbvirt_device_t *device,51 usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data)23 static int req_get_descriptor(usbvirt_device_t *device, 24 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size) 52 25 { 53 26 uint8_t type = setup_packet->value_high; 54 27 uint8_t index = setup_packet->value_low; 55 28 56 /* 29 /* 57 30 * Standard device descriptor. 58 31 */ 59 32 if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) { 60 33 if (device->descriptors && device->descriptors->device) { 61 return device->control_transfer_reply(device, 0,34 usbvirt_control_reply_helper(setup_packet, data, act_size, 62 35 device->descriptors->device, 63 36 device->descriptors->device->length); 37 return EOK; 64 38 } else { 65 39 return EFORWARD; 66 40 } 67 41 } 68 42 69 43 /* 70 44 * Configuration descriptor together with interface, endpoint and … … 85 59 return ENOMEM; 86 60 } 87 61 88 62 uint8_t *ptr = all_data; 89 63 memcpy(ptr, config->descriptor, config->descriptor->length); … … 96 70 ptr += extra->length; 97 71 } 98 99 int rc = device->control_transfer_reply(device, 0,72 73 usbvirt_control_reply_helper(setup_packet, data, act_size, 100 74 all_data, config->descriptor->total_length); 101 75 102 76 free(all_data); 103 104 return rc;77 78 return EOK; 105 79 } 106 80 107 81 return EFORWARD; 108 82 } 109 83 110 /** SET_ADDRESS handler. */ 111 static int handle_set_address(usbvirt_device_t *device, 112 usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data) 84 static int req_set_address(usbvirt_device_t *device, 85 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size) 113 86 { 114 87 uint16_t new_address = setup_packet->value; … … 119 92 return EINVAL; 120 93 } 121 94 122 95 if (new_address > 127) { 123 96 return EINVAL; 124 97 } 125 126 device-> new_address = new_address;127 98 99 device->address = new_address; 100 128 101 return EOK; 129 102 } 130 103 131 /** SET_CONFIGURATION handler. */ 132 static int handle_set_configuration(usbvirt_device_t *device, 133 usb_device_request_setup_packet_t *setup_packet, uint8_t *extra_data) 104 static int req_set_configuration(usbvirt_device_t *device, 105 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size) 134 106 { 135 107 uint16_t configuration_value = setup_packet->value; … … 140 112 return EINVAL; 141 113 } 142 114 143 115 /* 144 116 * Configuration value is 1 byte information. … … 147 119 return EINVAL; 148 120 } 149 121 150 122 /* 151 123 * Do nothing when in default state. According to specification, … … 155 127 return EOK; 156 128 } 157 129 130 usbvirt_device_state_t new_state; 158 131 if (configuration_value == 0) { 159 if (DEVICE_HAS_OP(device, on_state_change)) { 160 device->ops->on_state_change(device, device->state, 161 USBVIRT_STATE_ADDRESS); 162 } 163 device->state = USBVIRT_STATE_ADDRESS; 132 new_state = USBVIRT_STATE_ADDRESS; 164 133 } else { 165 /* 166 * TODO: browse provided configurations and verify that 167 * user selected existing configuration. 168 */ 169 if (DEVICE_HAS_OP(device, on_state_change)) { 170 device->ops->on_state_change(device, device->state, 171 USBVIRT_STATE_CONFIGURED); 172 } 173 device->state = USBVIRT_STATE_CONFIGURED; 174 if (device->descriptors) { 175 device->descriptors->current_configuration 176 = configuration_value; 177 } 134 // FIXME: check that this configuration exists 135 new_state = USBVIRT_STATE_CONFIGURED; 178 136 } 179 137 138 if (device->ops && device->ops->state_changed) { 139 device->ops->state_changed(device, device->state, new_state); 140 } 141 device->state = new_state; 142 180 143 return EOK; 181 144 } 182 145 183 184 #define MAKE_BM_REQUEST(direction, recipient) \ 185 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 186 USBVIRT_REQUEST_TYPE_STANDARD, recipient) 187 #define MAKE_BM_REQUEST_DEV(direction) \ 188 MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE) 189 190 usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = { 146 usbvirt_control_request_handler_t library_handlers[] = { 191 147 { 192 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN), 193 .request = USB_DEVREQ_GET_DESCRIPTOR, 194 .name = "GetDescriptor()", 195 .callback = handle_get_descriptor 148 .req_direction = USB_DIRECTION_OUT, 149 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 150 .req_type = USB_REQUEST_TYPE_STANDARD, 151 .request = USB_DEVREQ_SET_ADDRESS, 152 .name = "SetAddress", 153 .callback = req_set_address 196 154 }, 197 155 { 198 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 199 .request = USB_DEVREQ_SET_ADDRESS, 200 .name = "SetAddress()", 201 .callback = handle_set_address 156 .req_direction = USB_DIRECTION_IN, 157 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 158 .req_type = USB_REQUEST_TYPE_STANDARD, 159 .request = USB_DEVREQ_GET_DESCRIPTOR, 160 .name = "GetDescriptor", 161 .callback = req_get_descriptor 202 162 }, 203 163 { 204 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 164 .req_direction = USB_DIRECTION_OUT, 165 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 166 .req_type = USB_REQUEST_TYPE_STANDARD, 205 167 .request = USB_DEVREQ_SET_CONFIGURATION, 206 .name = "SetConfiguration ()",207 .callback = handle_set_configuration168 .name = "SetConfiguration", 169 .callback = req_set_configuration 208 170 }, 209 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 171 172 { .callback = NULL } 210 173 }; 211 174 212 /**213 * @}214 */
Note:
See TracChangeset
for help on using the changeset viewer.