Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/vhc/transfer.c

    r58563585 r9d58539  
    2929#include <errno.h>
    3030#include <str_error.h>
    31 #include <usb/debug.h>
    3231#include <usbvirt/device.h>
    3332#include <usbvirt/ipc.h>
    3433#include "vhcd.h"
    35 #include "hub/virthub.h"
     34
     35vhc_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}
    3663
    3764static bool is_set_address_transfer(vhc_transfer_t *transfer)
    3865{
    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;
    5079        if (setup->request_type != 0) {
    5180                return false;
     
    5887}
    5988
    60 static int process_transfer_local(usb_transfer_batch_t *batch,
     89int 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, pos) {
     95                vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);
     96                fibril_mutex_lock(&dev->guard);
     97                if (dev->address == transfer->address) {
     98                        if (target_found) {
     99                                usb_log_warning("Transfer would be accepted by more devices!\n");
     100                                goto next;
     101                        }
     102                        target_found = true;
     103                        list_append(&transfer->link, &dev->transfer_queue);
     104                }
     105next:
     106                fibril_mutex_unlock(&dev->guard);
     107        }
     108
     109        fibril_mutex_unlock(&vhc->guard);
     110
     111        if (target_found) {
     112                return EOK;
     113        } else {
     114                return ENOENT;
     115        }
     116}
     117
     118static int process_transfer_local(vhc_transfer_t *transfer,
    61119    usbvirt_device_t *dev, size_t *actual_data_size)
    62120{
    63121        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) {
     122
     123        if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
     124                if (transfer->direction == USB_DIRECTION_IN) {
    69125                        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);
     126                            transfer->setup_buffer, transfer->setup_buffer_size,
     127                            transfer->data_buffer, transfer->data_buffer_size,
     128                            actual_data_size);
     129                } else {
     130                        assert(transfer->direction == USB_DIRECTION_OUT);
    75131                        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);
     132                            transfer->setup_buffer, transfer->setup_buffer_size,
     133                            transfer->data_buffer, transfer->data_buffer_size);
     134                }
     135        } else {
     136                if (transfer->direction == USB_DIRECTION_IN) {
     137                        rc = usbvirt_data_in(dev, transfer->transfer_type,
     138                            transfer->endpoint,
     139                            transfer->data_buffer, transfer->data_buffer_size,
     140                            actual_data_size);
     141                } else {
     142                        assert(transfer->direction == USB_DIRECTION_OUT);
     143                        rc = usbvirt_data_out(dev, transfer->transfer_type,
     144                            transfer->endpoint,
     145                            transfer->data_buffer, transfer->data_buffer_size);
    90146                }
    91147        }
     
    94150}
    95151
    96 static int process_transfer_remote(usb_transfer_batch_t *batch,
     152static int process_transfer_remote(vhc_transfer_t *transfer,
    97153    async_sess_t *sess, size_t *actual_data_size)
    98154{
    99155        int rc;
    100156
    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) {
     157        if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
     158                if (transfer->direction == USB_DIRECTION_IN) {
    105159                        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);
     160                            transfer->setup_buffer, transfer->setup_buffer_size,
     161                            transfer->data_buffer, transfer->data_buffer_size,
     162                            actual_data_size);
     163                } else {
     164                        assert(transfer->direction == USB_DIRECTION_OUT);
    111165                        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);
     166                            transfer->setup_buffer, transfer->setup_buffer_size,
     167                            transfer->data_buffer, transfer->data_buffer_size);
     168                }
     169        } else {
     170                if (transfer->direction == USB_DIRECTION_IN) {
     171                        rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint,
     172                            transfer->transfer_type,
     173                            transfer->data_buffer, transfer->data_buffer_size,
     174                            actual_data_size);
     175                } else {
     176                        assert(transfer->direction == USB_DIRECTION_OUT);
     177                        rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint,
     178                            transfer->transfer_type,
     179                            transfer->data_buffer, transfer->data_buffer_size);
    126180                }
    127181        }
     
    142196}
    143197
     198
    144199static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
    145200    size_t data_transfer_size, int outcome)
    146201{
    147202        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);
     203
     204        usb_log_debug2("Transfer %p ended: %s.\n",
     205            transfer, str_error(outcome));
     206
     207        if (transfer->direction == USB_DIRECTION_IN) {
     208                transfer->callback_in(transfer->ddf_fun, outcome,
     209                    data_transfer_size, transfer->callback_arg);
     210        } else {
     211                assert(transfer->direction == USB_DIRECTION_OUT);
     212                transfer->callback_out(transfer->ddf_fun, outcome,
     213                    transfer->callback_arg);
     214        }
     215
    153216        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;
    199217}
    200218
     
    217235                size_t data_transfer_size = 0;
    218236                if (dev->dev_sess) {
    219                         rc = process_transfer_remote(transfer->batch,
    220                             dev->dev_sess, &data_transfer_size);
     237                        rc = process_transfer_remote(transfer, dev->dev_sess,
     238                            &data_transfer_size);
    221239                } else if (dev->dev_local != NULL) {
    222                         rc = process_transfer_local(transfer->batch,
    223                             dev->dev_local, &data_transfer_size);
     240                        rc = process_transfer_local(transfer, dev->dev_local,
     241                            &data_transfer_size);
    224242                } else {
    225243                        usb_log_warning("Device has no remote phone nor local node.\n");
     
    233251                if (rc == EOK) {
    234252                        if (is_set_address_transfer(transfer)) {
    235                                 usb_device_request_setup_packet_t *setup =
    236                                     (void*) transfer->batch->setup_buffer;
     253                                usb_device_request_setup_packet_t *setup
     254                                    = transfer->setup_buffer;
    237255                                dev->address = setup->value;
    238256                                usb_log_debug2("Address changed to %d\n",
     
    267285        return EOK;
    268286}
     287
Note: See TracChangeset for help on using the changeset viewer.