Ignore:
File:
1 edited

Legend:

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

    r58563585 rfeeac0d  
    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, 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                }
     104next:
     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
     117static int process_transfer_local(vhc_transfer_t *transfer,
    61118    usbvirt_device_t *dev, size_t *actual_data_size)
    62119{
    63120        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) {
    69124                        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);
    75130                        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);
    90145                }
    91146        }
     
    94149}
    95150
    96 static int process_transfer_remote(usb_transfer_batch_t *batch,
     151static int process_transfer_remote(vhc_transfer_t *transfer,
    97152    async_sess_t *sess, size_t *actual_data_size)
    98153{
    99154        int rc;
    100155
    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) {
    105158                        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);
    111164                        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);
    126179                }
    127180        }
     
    142195}
    143196
     197
    144198static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
    145199    size_t data_transfer_size, int outcome)
    146200{
    147201        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
    153215        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;
    199216}
    200217
     
    217234                size_t data_transfer_size = 0;
    218235                if (dev->dev_sess) {
    219                         rc = process_transfer_remote(transfer->batch,
    220                             dev->dev_sess, &data_transfer_size);
     236                        rc = process_transfer_remote(transfer, dev->dev_sess,
     237                            &data_transfer_size);
    221238                } else if (dev->dev_local != NULL) {
    222                         rc = process_transfer_local(transfer->batch,
    223                             dev->dev_local, &data_transfer_size);
     239                        rc = process_transfer_local(transfer, dev->dev_local,
     240                            &data_transfer_size);
    224241                } else {
    225242                        usb_log_warning("Device has no remote phone nor local node.\n");
     
    233250                if (rc == EOK) {
    234251                        if (is_set_address_transfer(transfer)) {
    235                                 usb_device_request_setup_packet_t *setup =
    236                                     (void*) transfer->batch->setup_buffer;
     252                                usb_device_request_setup_packet_t *setup
     253                                    = transfer->setup_buffer;
    237254                                dev->address = setup->value;
    238255                                usb_log_debug2("Address changed to %d\n",
     
    267284        return EOK;
    268285}
     286
Note: See TracChangeset for help on using the changeset viewer.