Changes in uspace/drv/bus/usb/vhc/transfer.c [f5f0cfb:feeac0d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/vhc/transfer.c
rf5f0cfb rfeeac0d 29 29 #include <errno.h> 30 30 #include <str_error.h> 31 #include <usb/debug.h>32 31 #include <usbvirt/device.h> 33 32 #include <usbvirt/ipc.h> 34 33 #include "vhcd.h" 35 #include "hub/virthub.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 } 36 63 37 64 static bool is_set_address_transfer(vhc_transfer_t *transfer) 38 65 { 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; 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; 50 79 if (setup->request_type != 0) { 51 80 return false; … … 58 87 } 59 88 60 static int process_transfer_local(usb_transfer_batch_t *batch, 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; 112 } else { 113 return ENOENT; 114 } 115 } 116 117 static int process_transfer_local(vhc_transfer_t *transfer, 61 118 usbvirt_device_t *dev, size_t *actual_data_size) 62 119 { 63 120 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) { 121 122 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 123 if (transfer->direction == USB_DIRECTION_IN) { 69 124 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);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); 75 130 rc = usbvirt_control_write(dev, 76 batch->setup_buffer, batch->setup_size,77 batch->buffer, batch->buffer_size);78 } 79 } else { 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);131 transfer->setup_buffer, transfer->setup_buffer_size, 132 transfer->data_buffer, transfer->data_buffer_size); 133 } 134 } 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); 90 145 } 91 146 } … … 94 149 } 95 150 96 static int process_transfer_remote( usb_transfer_batch_t *batch,151 static int process_transfer_remote(vhc_transfer_t *transfer, 97 152 async_sess_t *sess, size_t *actual_data_size) 98 153 { 99 154 int rc; 100 155 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) { 156 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 157 if (transfer->direction == USB_DIRECTION_IN) { 105 158 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);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); 111 164 rc = usbvirt_ipc_send_control_write(sess, 112 batch->setup_buffer, batch->setup_size,113 batch->buffer, batch->buffer_size);114 } 115 } else { 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);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); 126 179 } 127 180 } … … 142 195 } 143 196 197 144 198 static void execute_transfer_callback_and_free(vhc_transfer_t *transfer, 145 199 size_t data_transfer_size, int outcome) 146 200 { 147 201 assert(outcome != ENAK); 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); 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 153 215 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->private_data;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, pos) {183 vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);184 fibril_mutex_lock(&dev->guard);185 if (dev->address == transfer->batch->ep->address) {186 if (!targets) {187 list_append(&transfer->link, &dev->transfer_queue);188 }189 ++targets;190 }191 fibril_mutex_unlock(&dev->guard);192 }193 194 fibril_mutex_unlock(&vhc->guard);195 196 if (targets > 1)197 usb_log_warning("Transfer would be accepted by more devices!\n");198 199 return targets ? EOK : ENOENT;200 216 } 201 217 … … 218 234 size_t data_transfer_size = 0; 219 235 if (dev->dev_sess) { 220 rc = process_transfer_remote(transfer ->batch,221 dev->dev_sess,&data_transfer_size);236 rc = process_transfer_remote(transfer, dev->dev_sess, 237 &data_transfer_size); 222 238 } else if (dev->dev_local != NULL) { 223 rc = process_transfer_local(transfer ->batch,224 dev->dev_local,&data_transfer_size);239 rc = process_transfer_local(transfer, dev->dev_local, 240 &data_transfer_size); 225 241 } else { 226 242 usb_log_warning("Device has no remote phone nor local node.\n"); … … 235 251 if (is_set_address_transfer(transfer)) { 236 252 usb_device_request_setup_packet_t *setup 237 = (void*)transfer->batch->setup_buffer;253 = transfer->setup_buffer; 238 254 dev->address = setup->value; 239 255 usb_log_debug2("Address changed to %d\n", … … 268 284 return EOK; 269 285 } 286
Note:
See TracChangeset
for help on using the changeset viewer.