Changes in uspace/drv/bus/usb/vhc/transfer.c [feeac0d:f5f0cfb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/vhc/transfer.c
rfeeac0d rf5f0cfb 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->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; 216 200 } 217 201 … … 234 218 size_t data_transfer_size = 0; 235 219 if (dev->dev_sess) { 236 rc = process_transfer_remote(transfer , dev->dev_sess,237 &data_transfer_size);220 rc = process_transfer_remote(transfer->batch, 221 dev->dev_sess, &data_transfer_size); 238 222 } else if (dev->dev_local != NULL) { 239 rc = process_transfer_local(transfer , dev->dev_local,240 &data_transfer_size);223 rc = process_transfer_local(transfer->batch, 224 dev->dev_local, &data_transfer_size); 241 225 } else { 242 226 usb_log_warning("Device has no remote phone nor local node.\n"); … … 251 235 if (is_set_address_transfer(transfer)) { 252 236 usb_device_request_setup_packet_t *setup 253 = transfer->setup_buffer;237 = (void*)transfer->batch->setup_buffer; 254 238 dev->address = setup->value; 255 239 usb_log_debug2("Address changed to %d\n", … … 284 268 return EOK; 285 269 } 286
Note:
See TracChangeset
for help on using the changeset viewer.