Changeset b4b534ac in mainline for uspace/drv/bus/usb/vhc
- Timestamp:
- 2016-07-22T08:24:47Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f76d2c2
- Parents:
- 5b18137 (diff), 8351f9a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/drv/bus/usb/vhc
- Files:
-
- 3 deleted
- 9 edited
-
Makefile (modified) (1 diff)
-
conn.h (deleted)
-
conndev.c (modified) (3 diffs)
-
connhost.c (deleted)
-
devconn.c (modified) (5 diffs)
-
hub.c (deleted)
-
hub/virthub.c (modified) (5 diffs)
-
hub/virthub.h (modified) (1 diff)
-
hub/virthubops.c (modified) (2 diffs)
-
main.c (modified) (4 diffs)
-
transfer.c (modified) (6 diffs)
-
vhcd.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/vhc/Makefile
r5b18137 rb4b534ac 49 49 hub/virthubops.c \ 50 50 conndev.c \ 51 connhost.c \52 51 devconn.c \ 53 hub.c \54 52 main.c \ 55 53 transfer.c -
uspace/drv/bus/usb/vhc/conndev.c
r5b18137 rb4b534ac 38 38 #include <ddf/driver.h> 39 39 #include <usbvirt/ipc.h> 40 #include <usb/debug.h> 40 41 #include <async.h> 41 #include "conn.h" 42 43 #include "vhcd.h" 42 44 43 45 static fibril_local uintptr_t plugged_device_handle = 0; … … 94 96 ipc_call_t *icall) 95 97 { 96 vhc_data_t *vhc = ddf_ dev_data_get(ddf_fun_get_dev(fun));98 vhc_data_t *vhc = ddf_fun_data_get(fun); 97 99 98 100 async_sess_t *callback = … … 125 127 void on_client_close(ddf_fun_t *fun) 126 128 { 127 vhc_data_t *vhc = ddf_ dev_data_get(ddf_fun_get_dev(fun));129 vhc_data_t *vhc = ddf_fun_data_get(fun); 128 130 129 131 if (plugged_device_handle != 0) { -
uspace/drv/bus/usb/vhc/devconn.c
r5b18137 rb4b534ac 51 51 static int vhc_virtdev_plug_generic(vhc_data_t *vhc, 52 52 async_sess_t *sess, usbvirt_device_t *virtdev, 53 uintptr_t *handle, bool connect )53 uintptr_t *handle, bool connect, usb_address_t address) 54 54 { 55 55 vhc_virtdev_t *dev = vhc_virtdev_create(); … … 60 60 dev->dev_sess = sess; 61 61 dev->dev_local = virtdev; 62 dev->address = address; 62 63 63 64 fibril_mutex_lock(&vhc->guard); … … 78 79 if (connect) { 79 80 // FIXME: check status 80 (void) virthub_connect_device( vhc->hub, dev);81 (void) virthub_connect_device(&vhc->hub, dev); 81 82 } 82 83 … … 86 87 int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle) 87 88 { 88 return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true );89 return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true, 0); 89 90 } 90 91 91 92 int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle) 92 93 { 93 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true );94 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true, 0); 94 95 } 95 96 96 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle )97 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle, usb_address_t address) 97 98 { 98 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false );99 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false, address); 99 100 } 100 101 … … 104 105 105 106 // FIXME: check status 106 (void) virthub_disconnect_device( vhc->hub, dev);107 (void) virthub_disconnect_device(&vhc->hub, dev); 107 108 108 109 fibril_mutex_lock(&vhc->guard); -
uspace/drv/bus/usb/vhc/hub/virthub.c
r5b18137 rb4b534ac 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usb/classes/hub.h> 36 37 #include <usbvirt/device.h> 37 38 #include <assert.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> 41 #include <stdio.h> 40 42 #include <stdlib.h> 41 43 #include <ddf/driver.h> … … 75 77 .type = USB_DESCTYPE_HUB, 76 78 .port_count = HUB_PORT_COUNT, 77 .characteristics = 0,79 .characteristics = HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG, 78 80 .power_on_warm_up = 50, /* Huh? */ 79 81 .max_current = 100, /* Huh again. */ … … 96 98 .length = sizeof(usb_standard_configuration_descriptor_t), 97 99 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 98 .total_length = 100 .total_length = 99 101 sizeof(usb_standard_configuration_descriptor_t) 100 102 + sizeof(std_interface_descriptor) … … 144 146 * @return Error code. 145 147 */ 146 int virthub_init(usbvirt_device_t *dev )148 int virthub_init(usbvirt_device_t *dev, const char* name) 147 149 { 148 150 if (dev == NULL) { … … 151 153 dev->ops = &hub_ops; 152 154 dev->descriptors = &descriptors; 155 dev->address = 0; 156 dev->name = str_dup(name); 157 if (!dev->name) 158 return ENOMEM; 153 159 154 160 hub_t *hub = malloc(sizeof(hub_t)); 155 161 if (hub == NULL) { 162 free(dev->name); 156 163 return ENOMEM; 157 164 } -
uspace/drv/bus/usb/vhc/hub/virthub.h
r5b18137 rb4b534ac 79 79 extern hub_descriptor_t hub_descriptor; 80 80 81 int virthub_init(usbvirt_device_t * );81 int virthub_init(usbvirt_device_t *, const char *name); 82 82 int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *); 83 83 int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *); -
uspace/drv/bus/usb/vhc/hub/virthubops.c
r5b18137 rb4b534ac 340 340 341 341 342 /** IN class request. */343 #define CLASS_REQ_IN(recipient) \344 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \345 USBVIRT_REQUEST_TYPE_CLASS, recipient)346 /** OUT class request. */347 #define CLASS_REQ_OUT(recipient) \348 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \349 USBVIRT_REQUEST_TYPE_CLASS, recipient)350 342 351 343 /** Recipient: other. */ … … 353 345 /** Recipient: device. */ 354 346 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE 355 /** Direction: in. */ 356 #define DIR_IN USB_DIRECTION_IN 357 /** Direction: out. */ 358 #define DIR_OUT USB_DIRECTION_OUT 359 360 361 /** Create a class request. 362 * 363 * @param direction Request direction. 364 * @param recipient Request recipient. 365 * @param req Request code. 366 */ 367 #define CLASS_REQ(direction, recipient, req) \ 368 .req_direction = direction, \ 369 .req_recipient = recipient, \ 370 .req_type = USB_REQUEST_TYPE_CLASS, \ 371 .request = req 372 373 /** Create a standard request. 374 * 375 * @param direction Request direction. 376 * @param recipient Request recipient. 377 * @param req Request code. 378 */ 379 #define STD_REQ(direction, recipient, req) \ 380 .req_direction = direction, \ 381 .req_recipient = recipient, \ 382 .req_type = USB_REQUEST_TYPE_STANDARD, \ 383 .request = req 347 384 348 385 349 /** Hub operations on control endpoint zero. */ 386 350 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 387 351 { 388 STD_REQ (DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),389 .name = "Get Descriptor",352 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), 353 .name = "GetStdDescriptor", 390 354 .callback = req_get_descriptor 391 355 }, 392 356 { 393 CLASS_REQ (DIR_IN,REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),394 .name = "Get Descriptor",357 CLASS_REQ_IN(REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), 358 .name = "GetClassDescriptor", 395 359 .callback = req_get_descriptor 396 360 }, 397 361 { 398 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATUS),362 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS), 399 363 .name = "GetPortStatus", 400 364 .callback = req_get_port_status 401 365 }, 402 366 { 403 CLASS_REQ (DIR_OUT,REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),367 CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE), 404 368 .name = "ClearHubFeature", 405 369 .callback = req_clear_hub_feature 406 370 }, 407 371 { 408 CLASS_REQ (DIR_OUT,REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),372 CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE), 409 373 .name = "ClearPortFeature", 410 374 .callback = req_clear_port_feature 411 375 }, 412 376 { 413 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATE),377 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATE), 414 378 .name = "GetBusState", 415 379 .callback = req_get_bus_state 416 380 }, 417 381 { 418 CLASS_REQ (DIR_IN,REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),382 CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR), 419 383 .name = "GetHubDescriptor", 420 384 .callback = req_get_descriptor 421 385 }, 422 386 { 423 CLASS_REQ (DIR_IN,REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),387 CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_STATUS), 424 388 .name = "GetHubStatus", 425 389 .callback = req_get_hub_status 426 390 }, 427 391 { 428 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATUS),392 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS), 429 393 .name = "GetPortStatus", 430 394 .callback = req_get_port_status 431 395 }, 432 396 { 433 CLASS_REQ (DIR_OUT,REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),397 CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE), 434 398 .name = "SetHubFeature", 435 399 .callback = req_set_hub_feature 436 400 }, 437 401 { 438 CLASS_REQ (DIR_OUT,REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),402 CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_SET_FEATURE), 439 403 .name = "SetPortFeature", 440 404 .callback = req_set_port_feature -
uspace/drv/bus/usb/vhc/main.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <loc.h>37 #include <async.h>38 #include <unistd.h>39 #include <stdlib.h>40 #include <sysinfo.h>41 36 #include <stdio.h> 42 37 #include <errno.h> … … 44 39 #include <ddf/driver.h> 45 40 46 #include <usb/ usb.h>47 #include <usb/ddfiface.h> 48 #include <usb _iface.h>41 #include <usb/host/ddf_helpers.h> 42 43 #include <usb/debug.h> 49 44 #include "vhcd.h" 50 #include "hub.h" 51 #include "conn.h" 45 52 46 53 47 static ddf_dev_ops_t vhc_ops = { 54 .interfaces[USBHC_DEV_IFACE] = &vhc_iface,55 .interfaces[USB_DEV_IFACE] = &vhc_usb_iface,56 48 .close = on_client_close, 57 49 .default_handler = default_connection_handler 58 50 }; 59 51 52 static int vhc_control_node(ddf_dev_t *dev, ddf_fun_t **fun) 53 { 54 assert(dev); 55 assert(fun); 56 57 *fun = ddf_fun_create(dev, fun_exposed, "virtual"); 58 if (!*fun) 59 return ENOMEM; 60 61 vhc_data_t *vhc = ddf_fun_data_alloc(*fun, sizeof(vhc_data_t)); 62 if (!vhc) { 63 ddf_fun_destroy(*fun); 64 } 65 ddf_fun_set_ops(*fun, &vhc_ops); 66 const int ret = ddf_fun_bind(*fun); 67 if (ret != EOK) { 68 ddf_fun_destroy(*fun); 69 *fun = NULL; 70 return ret; 71 } 72 vhc_init(vhc); 73 return EOK; 74 } 75 76 hcd_ops_t vhc_hc_ops = { 77 .schedule = vhc_schedule, 78 }; 79 60 80 static int vhc_dev_add(ddf_dev_t *dev) 61 81 { 62 static int vhc_count = 0; 63 int rc; 82 /* Initialize virtual structure */ 83 ddf_fun_t *ctl_fun = NULL; 84 int ret = vhc_control_node(dev, &ctl_fun); 85 if (ret != EOK) { 86 usb_log_error("Failed to setup control node.\n"); 87 return ret; 88 } 89 vhc_data_t *data = ddf_fun_data_get(ctl_fun); 64 90 65 if (vhc_count > 0) { 66 return ELIMIT; 91 /* Initialize generic structures */ 92 ret = hcd_ddf_setup_hc(dev, USB_SPEED_FULL, 93 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 94 if (ret != EOK) { 95 usb_log_error("Failed to init HCD structures: %s.\n", 96 str_error(ret)); 97 ddf_fun_destroy(ctl_fun); 98 return ret; 67 99 } 68 100 69 vhc_data_t *data = ddf_dev_data_alloc(dev, 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 bandwidth_count_usb11); 77 if (rc != EOK) { 78 usb_log_fatal("Failed to initialize endpoint manager.\n"); 79 free(data); 80 return rc; 81 } 82 usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX); 101 hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops); 83 102 84 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); 85 if (hc == NULL) { 86 usb_log_fatal("Failed to create device function.\n"); 87 free(data); 88 return ENOMEM; 103 /* Add virtual hub device */ 104 ret = vhc_virtdev_plug_hub(data, &data->hub, NULL, 0); 105 if (ret != EOK) { 106 usb_log_error("Failed to plug root hub: %s.\n", str_error(ret)); 107 ddf_fun_destroy(ctl_fun); 108 return ret; 89 109 } 90 110 91 ddf_fun_set_ops(hc, &vhc_ops); 92 list_initialize(&data->devices); 93 fibril_mutex_initialize(&data->guard); 94 data->hub = &virtual_hub_device; 95 data->hc_fun = hc; 96 97 rc = ddf_fun_bind(hc); 98 if (rc != EOK) { 99 usb_log_fatal("Failed to bind HC function: %s.\n", 100 str_error(rc)); 101 free(data); 102 return rc; 111 /* 112 * Creating root hub registers a new USB device so HC 113 * needs to be ready at this time. 114 */ 115 ret = hcd_ddf_setup_root_hub(dev); 116 if (ret != EOK) { 117 usb_log_error("Failed to init VHC root hub: %s\n", 118 str_error(ret)); 119 // TODO do something here... 103 120 } 104 121 105 rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY); 106 if (rc != EOK) { 107 usb_log_fatal("Failed to add function to HC class: %s.\n", 108 str_error(rc)); 109 free(data); 110 return rc; 111 } 112 113 virtual_hub_device_init(hc); 114 115 usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n", 116 (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc)); 117 118 rc = vhc_virtdev_plug_hub(data, data->hub, NULL); 119 if (rc != EOK) { 120 usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc)); 121 free(data); 122 return rc; 123 } 124 125 return EOK; 122 return ret; 126 123 } 127 124 … … 135 132 }; 136 133 137 138 134 int main(int argc, char * argv[]) 139 { 135 { 140 136 log_init(NAME); 141 142 137 printf(NAME ": virtual USB host controller driver.\n"); 143 138 … … 145 140 } 146 141 147 148 142 /** 149 143 * @} -
uspace/drv/bus/usb/vhc/transfer.c
r5b18137 rb4b534ac 29 29 #include <errno.h> 30 30 #include <str_error.h> 31 #include <usb/debug.h> 31 32 #include <usbvirt/device.h> 32 33 #include <usbvirt/ipc.h> 33 34 #include "vhcd.h" 34 35 vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep, 36 usb_direction_t dir, usb_transfer_type_t tr_type, 37 ddf_fun_t *fun, void *callback_arg) 38 { 39 vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t)); 40 if (result == NULL) { 41 return NULL; 42 } 43 link_initialize(&result->link); 44 result->address = address; 45 result->endpoint = ep; 46 result->direction = dir; 47 result->transfer_type = tr_type; 48 result->setup_buffer = NULL; 49 result->setup_buffer_size = 0; 50 result->data_buffer = NULL; 51 result->data_buffer_size = 0; 52 result->ddf_fun = fun; 53 result->callback_arg = callback_arg; 54 result->callback_in = NULL; 55 result->callback_out = NULL; 56 57 usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result, 58 address, ep, usb_str_transfer_type_short(tr_type), 59 dir == USB_DIRECTION_IN ? "in" : "out"); 60 61 return result; 62 } 35 #include "hub/virthub.h" 63 36 64 37 static bool is_set_address_transfer(vhc_transfer_t *transfer) 65 38 { 66 if (transfer->endpoint != 0) { 67 return false; 68 } 69 if (transfer->transfer_type != USB_TRANSFER_CONTROL) { 70 return false; 71 } 72 if (transfer->direction != USB_DIRECTION_OUT) { 73 return false; 74 } 75 if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) { 76 return false; 77 } 78 usb_device_request_setup_packet_t *setup = transfer->setup_buffer; 39 if (transfer->batch->ep->endpoint != 0) { 40 return false; 41 } 42 if (transfer->batch->ep->transfer_type != USB_TRANSFER_CONTROL) { 43 return false; 44 } 45 if (usb_transfer_batch_direction(transfer->batch) != USB_DIRECTION_OUT) { 46 return false; 47 } 48 const usb_device_request_setup_packet_t *setup = 49 (void*)transfer->batch->setup_buffer; 79 50 if (setup->request_type != 0) { 80 51 return false; … … 87 58 } 88 59 89 int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer) 90 { 91 fibril_mutex_lock(&vhc->guard); 92 93 bool target_found = false; 94 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 95 fibril_mutex_lock(&dev->guard); 96 if (dev->address == transfer->address) { 97 if (target_found) { 98 usb_log_warning("Transfer would be accepted by more devices!\n"); 99 goto next; 100 } 101 target_found = true; 102 list_append(&transfer->link, &dev->transfer_queue); 103 } 104 next: 105 fibril_mutex_unlock(&dev->guard); 106 } 107 108 fibril_mutex_unlock(&vhc->guard); 109 110 if (target_found) { 111 return EOK; 60 static int process_transfer_local(usb_transfer_batch_t *batch, 61 usbvirt_device_t *dev, size_t *actual_data_size) 62 { 63 int rc; 64 65 const usb_direction_t dir = usb_transfer_batch_direction(batch); 66 67 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 68 if (dir == USB_DIRECTION_IN) { 69 rc = usbvirt_control_read(dev, 70 batch->setup_buffer, batch->setup_size, 71 batch->buffer, batch->buffer_size, 72 actual_data_size); 73 } else { 74 assert(dir == USB_DIRECTION_OUT); 75 rc = usbvirt_control_write(dev, 76 batch->setup_buffer, batch->setup_size, 77 batch->buffer, batch->buffer_size); 78 } 112 79 } else { 113 return ENOENT; 114 } 115 } 116 117 static int process_transfer_local(vhc_transfer_t *transfer, 118 usbvirt_device_t *dev, size_t *actual_data_size) 80 if (dir == USB_DIRECTION_IN) { 81 rc = usbvirt_data_in(dev, batch->ep->transfer_type, 82 batch->ep->endpoint, 83 batch->buffer, batch->buffer_size, 84 actual_data_size); 85 } else { 86 assert(dir == USB_DIRECTION_OUT); 87 rc = usbvirt_data_out(dev, batch->ep->transfer_type, 88 batch->ep->endpoint, 89 batch->buffer, batch->buffer_size); 90 } 91 } 92 93 return rc; 94 } 95 96 static int process_transfer_remote(usb_transfer_batch_t *batch, 97 async_sess_t *sess, size_t *actual_data_size) 119 98 { 120 99 int rc; 121 100 122 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 123 if (transfer->direction == USB_DIRECTION_IN) { 124 rc = usbvirt_control_read(dev, 125 transfer->setup_buffer, transfer->setup_buffer_size, 126 transfer->data_buffer, transfer->data_buffer_size, 127 actual_data_size); 128 } else { 129 assert(transfer->direction == USB_DIRECTION_OUT); 130 rc = usbvirt_control_write(dev, 131 transfer->setup_buffer, transfer->setup_buffer_size, 132 transfer->data_buffer, transfer->data_buffer_size); 101 const usb_direction_t dir = usb_transfer_batch_direction(batch); 102 103 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 104 if (dir == USB_DIRECTION_IN) { 105 rc = usbvirt_ipc_send_control_read(sess, 106 batch->setup_buffer, batch->setup_size, 107 batch->buffer, batch->buffer_size, 108 actual_data_size); 109 } else { 110 assert(dir == USB_DIRECTION_OUT); 111 rc = usbvirt_ipc_send_control_write(sess, 112 batch->setup_buffer, batch->setup_size, 113 batch->buffer, batch->buffer_size); 133 114 } 134 115 } else { 135 if (transfer->direction == USB_DIRECTION_IN) { 136 rc = usbvirt_data_in(dev, transfer->transfer_type, 137 transfer->endpoint, 138 transfer->data_buffer, transfer->data_buffer_size, 139 actual_data_size); 140 } else { 141 assert(transfer->direction == USB_DIRECTION_OUT); 142 rc = usbvirt_data_out(dev, transfer->transfer_type, 143 transfer->endpoint, 144 transfer->data_buffer, transfer->data_buffer_size); 145 } 146 } 147 148 return rc; 149 } 150 151 static int process_transfer_remote(vhc_transfer_t *transfer, 152 async_sess_t *sess, size_t *actual_data_size) 153 { 154 int rc; 155 156 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 157 if (transfer->direction == USB_DIRECTION_IN) { 158 rc = usbvirt_ipc_send_control_read(sess, 159 transfer->setup_buffer, transfer->setup_buffer_size, 160 transfer->data_buffer, transfer->data_buffer_size, 161 actual_data_size); 162 } else { 163 assert(transfer->direction == USB_DIRECTION_OUT); 164 rc = usbvirt_ipc_send_control_write(sess, 165 transfer->setup_buffer, transfer->setup_buffer_size, 166 transfer->data_buffer, transfer->data_buffer_size); 167 } 168 } else { 169 if (transfer->direction == USB_DIRECTION_IN) { 170 rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint, 171 transfer->transfer_type, 172 transfer->data_buffer, transfer->data_buffer_size, 173 actual_data_size); 174 } else { 175 assert(transfer->direction == USB_DIRECTION_OUT); 176 rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint, 177 transfer->transfer_type, 178 transfer->data_buffer, transfer->data_buffer_size); 116 if (dir == USB_DIRECTION_IN) { 117 rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint, 118 batch->ep->transfer_type, 119 batch->buffer, batch->buffer_size, 120 actual_data_size); 121 } else { 122 assert(dir == USB_DIRECTION_OUT); 123 rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint, 124 batch->ep->transfer_type, 125 batch->buffer, batch->buffer_size); 179 126 } 180 127 } … … 195 142 } 196 143 197 198 144 static void execute_transfer_callback_and_free(vhc_transfer_t *transfer, 199 145 size_t data_transfer_size, int outcome) 200 146 { 201 147 assert(outcome != ENAK); 202 203 usb_log_debug2("Transfer %p ended: %s.\n", 204 transfer, str_error(outcome)); 205 206 if (transfer->direction == USB_DIRECTION_IN) { 207 transfer->callback_in(transfer->ddf_fun, outcome, 208 data_transfer_size, transfer->callback_arg); 209 } else { 210 assert(transfer->direction == USB_DIRECTION_OUT); 211 transfer->callback_out(transfer->ddf_fun, outcome, 212 transfer->callback_arg); 213 } 214 148 assert(transfer); 149 assert(transfer->batch); 150 usb_transfer_batch_finish_error(transfer->batch, NULL, 151 data_transfer_size, outcome); 152 usb_transfer_batch_destroy(transfer->batch); 215 153 free(transfer); 154 } 155 156 int vhc_init(vhc_data_t *instance) 157 { 158 assert(instance); 159 list_initialize(&instance->devices); 160 fibril_mutex_initialize(&instance->guard); 161 instance->magic = 0xDEADBEEF; 162 return virthub_init(&instance->hub, "root hub"); 163 } 164 165 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 166 { 167 assert(hcd); 168 assert(batch); 169 vhc_data_t *vhc = hcd_get_driver_data(hcd); 170 assert(vhc); 171 172 vhc_transfer_t *transfer = malloc(sizeof(vhc_transfer_t)); 173 if (!transfer) 174 return ENOMEM; 175 link_initialize(&transfer->link); 176 transfer->batch = batch; 177 178 fibril_mutex_lock(&vhc->guard); 179 180 int targets = 0; 181 182 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 183 fibril_mutex_lock(&dev->guard); 184 if (dev->address == transfer->batch->ep->address) { 185 if (!targets) { 186 list_append(&transfer->link, &dev->transfer_queue); 187 } 188 ++targets; 189 } 190 fibril_mutex_unlock(&dev->guard); 191 } 192 193 fibril_mutex_unlock(&vhc->guard); 194 195 if (targets > 1) 196 usb_log_warning("Transfer would be accepted by more devices!\n"); 197 198 return targets ? EOK : ENOENT; 216 199 } 217 200 … … 234 217 size_t data_transfer_size = 0; 235 218 if (dev->dev_sess) { 236 rc = process_transfer_remote(transfer , dev->dev_sess,237 &data_transfer_size);219 rc = process_transfer_remote(transfer->batch, 220 dev->dev_sess, &data_transfer_size); 238 221 } else if (dev->dev_local != NULL) { 239 rc = process_transfer_local(transfer , dev->dev_local,240 &data_transfer_size);222 rc = process_transfer_local(transfer->batch, 223 dev->dev_local, &data_transfer_size); 241 224 } else { 242 225 usb_log_warning("Device has no remote phone nor local node.\n"); … … 251 234 if (is_set_address_transfer(transfer)) { 252 235 usb_device_request_setup_packet_t *setup 253 = transfer->setup_buffer;236 = (void*)transfer->batch->setup_buffer; 254 237 dev->address = setup->value; 255 238 usb_log_debug2("Address changed to %d\n", … … 284 267 return EOK; 285 268 } 286 -
uspace/drv/bus/usb/vhc/vhcd.h
r5b18137 rb4b534ac 36 36 #define VHCD_VHCD_H_ 37 37 38 #include <usb/debug.h>39 38 #include <usbvirt/device.h> 40 #include <usb/host/usb_endpoint_manager.h>41 #include <usb/host/usb_device_manager.h>42 39 #include <usbhc_iface.h> 43 40 #include <async.h> 41 42 #include <usb/host/hcd.h> 43 44 44 45 45 #define NAME "vhc" … … 59 59 list_t devices; 60 60 fibril_mutex_t guard; 61 usb_endpoint_manager_t ep_manager; 62 usb_device_manager_t dev_manager; 63 usbvirt_device_t *hub; 64 ddf_fun_t *hc_fun; 61 usbvirt_device_t hub; 65 62 } vhc_data_t; 66 63 67 64 typedef struct { 68 65 link_t link; 69 usb_address_t address; 70 usb_endpoint_t endpoint; 71 usb_direction_t direction; 72 usb_transfer_type_t transfer_type; 73 void *setup_buffer; 74 size_t setup_buffer_size; 75 void *data_buffer; 76 size_t data_buffer_size; 77 ddf_fun_t *ddf_fun; 78 void *callback_arg; 79 usbhc_iface_transfer_in_callback_t callback_in; 80 usbhc_iface_transfer_out_callback_t callback_out; 66 usb_transfer_batch_t *batch; 81 67 } vhc_transfer_t; 82 68 83 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t, 84 usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *); 69 70 void on_client_close(ddf_fun_t *fun); 71 void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid, 72 ipc_call_t *icall); 73 85 74 int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *); 86 75 int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 87 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t * );76 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *, usb_address_t address); 88 77 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t); 89 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);90 78 79 int vhc_init(vhc_data_t *instance); 80 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 91 81 int vhc_transfer_queue_processor(void *arg); 92 93 82 94 83 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
