Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 64ce0c1 in mainline


Ignore:
Timestamp:
2018-02-02T10:13:55Z (4 years ago)
Author:
Jenda <jenda.jzqk73@…>
Branches:
lfn, master, serial
Children:
961a5ee
Parents:
e67c50a (diff), 290338b (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.
Message:

Merge commit '290338bf7224f502808b23e82d98306208962b97' into forwardport

Location:
uspace
Files:
1 added
1 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/tmon/Makefile

    re67c50a r64ce0c1  
    3030BINARY = tmon
    3131
    32 LIBS = drv
     32LIBS = drv usb
    3333
    3434SOURCES = \
     
    3636        list.c\
    3737        tf.c\
    38         burst_tests.c\
     38        tests.c\
    3939        resolve.c
    4040
  • uspace/app/tmon/commands.h

    re67c50a r64ce0c1  
    4242int tmon_list(int, char **);
    4343
    44 /* Burst tests read/write into endpoints as fast as possible. */
    45 int tmon_burst_intr_in(int, char **);
    46 int tmon_burst_intr_out(int, char **);
    47 int tmon_burst_bulk_in(int, char **);
    48 int tmon_burst_bulk_out(int, char **);
    49 int tmon_burst_isoch_in(int, char **);
    50 int tmon_burst_isoch_out(int, char **);
     44/* Tests commands differ by endpoint types. */
     45int tmon_test_intr_in(int, char **);
     46int tmon_test_intr_out(int, char **);
     47int tmon_test_bulk_in(int, char **);
     48int tmon_test_bulk_out(int, char **);
     49int tmon_test_isoch_in(int, char **);
     50int tmon_test_isoch_out(int, char **);
    5151
    5252#endif /* TMON_COMMANDS_H_ */
  • uspace/app/tmon/main.c

    re67c50a r64ce0c1  
    6464                .name = "test-intr-in",
    6565                .description = "Read from interrupt endpoint as fast as possible.",
    66                 .action = tmon_burst_intr_in,
     66                .action = tmon_test_intr_in,
    6767        },
    6868        {
    6969                .name = "test-intr-out",
    7070                .description = "Write to interrupt endpoint as fast as possible.",
    71                 .action = tmon_burst_intr_out,
     71                .action = tmon_test_intr_out,
    7272        },
    7373        {
    7474                .name = "test-bulk-in",
    7575                .description = "Read from bulk endpoint as fast as possible.",
    76                 .action = tmon_burst_bulk_in,
     76                .action = tmon_test_bulk_in,
    7777        },
    7878        {
    7979                .name = "test-bulk-out",
    8080                .description = "Write to bulk endpoint as fast as possible.",
    81                 .action = tmon_burst_bulk_out,
     81                .action = tmon_test_bulk_out,
    8282        },
    8383        {
    8484                .name = "test-isoch-in",
    8585                .description = "Read from isochronous endpoint as fast as possible.",
    86                 .action = tmon_burst_isoch_in,
     86                .action = tmon_test_isoch_in,
    8787        },
    8888        {
    8989                .name = "test-isoch-out",
    9090                .description = "Write to isochronous endpoint as fast as possible.",
    91                 .action = tmon_burst_isoch_out,
    92         }
     91                .action = tmon_test_isoch_out,
     92        },
    9393};
    9494
     
    106106static tmon_opt_t options[] = {
    107107        {
    108                 .long_name = "cycles",
    109                 .short_name = 'n',
    110                 .description = "Set the number of read/write cycles."
     108                .long_name = "duration",
     109                .short_name = 't',
     110                .description = "Set the minimum test duration (in seconds)."
    111111        },
    112112        {
    113113                .long_name = "size",
    114114                .short_name = 's',
    115                 .description = "Set the data size transferred in a single cycle."
    116         }
     115                .description = "Set the data size (in bytes) transferred in a single cycle."
     116        },
     117        {
     118                .long_name = "validate",
     119                .short_name = 'v',
     120                .description = "Validate the correctness of transferred data (impacts performance)."
     121        },
    117122};
    118123
  • uspace/app/tmon/tf.c

    re67c50a r64ce0c1  
    3636
    3737#include <stdio.h>
     38#include <macros.h>
    3839#include <devman.h>
    3940#include <str_error.h>
     
    7475        }
    7576
    76         printf("Using device: %s\n", path);
     77        printf("Device: %s\n", path);
    7778
    7879        // Read test parameters from options.
    79         tmon_test_params_t *params = NULL;
     80        void *params = NULL;
    8081        if ((rc = ops->read_params(argc, argv, &params))) {
    8182                printf(NAME ": Reading test parameters failed. %s\n", str_error(rc));
     83                return 1;
     84        }
     85
     86        if ((rc = ops->pre_run(params))) {
     87                printf(NAME ": Pre-run hook failed. %s\n", str_error(rc));
    8288                return 1;
    8389        }
     
    106112}
    107113
     114/** Unit of quantity used for pretty formatting. */
     115typedef struct tmon_unit {
     116        /** Prefix letter, which is printed before the actual unit. */
     117        const char *unit;
     118        /** Factor of the unit. */
     119        double factor;
     120} tmon_unit_t;
     121
     122/** Format a value for human reading.
     123 * @param[in] val The value to format.
     124 * @param[in] fmt Format string. Must include one double and char.
     125 *
     126 * @return Heap-allocated string if successful (caller becomes its owner), NULL otherwise.
     127 */
     128static char *format_unit(double val, const char *fmt, const tmon_unit_t *units, size_t len)
     129{
     130        // Figure out the "tightest" unit.
     131        unsigned i;
     132        for (i = 0; i < len; ++i) {
     133                if (units[i].factor <= val)
     134                        break;
     135        }
     136
     137        if (i == len) --i;
     138        const char *unit = units[i].unit;
     139        double factor = units[i].factor;
     140
     141        // Format the size.
     142        const double div_size = val / factor;
     143
     144        char *out = NULL;
     145        asprintf(&out, fmt, div_size, unit);
     146
     147        return out;
     148}
     149
     150/** Static array of size units with decreasing factors. */
     151static const tmon_unit_t size_units[] = {
     152        { .unit = "EB", .factor = 1ULL << 60 },
     153        { .unit = "PB", .factor = 1ULL << 50 },
     154        { .unit = "TB", .factor = 1ULL << 40 },
     155        { .unit = "GB", .factor = 1ULL << 30 },
     156        { .unit = "MB", .factor = 1ULL << 20 },
     157        { .unit = "kB", .factor = 1ULL << 10 },
     158        { .unit = "B",  .factor = 1ULL },
     159};
     160
     161char *tmon_format_size(double val, const char *fmt)
     162{
     163        return format_unit(val, fmt, size_units, ARRAY_SIZE(size_units));
     164}
     165
     166/** Static array of duration units with decreasing factors. */
     167static const tmon_unit_t dur_units[] = {
     168        { .unit = "d",   .factor = 60 * 60 * 24 },
     169        { .unit = "h",   .factor = 60 * 60 },
     170        { .unit = "min", .factor = 60 },
     171        { .unit = "s",   .factor = 1 },
     172        { .unit = "ms",  .factor = 1e-3 },
     173        { .unit = "us",  .factor = 1e-6 },
     174        { .unit = "ns",  .factor = 1e-9 },
     175        { .unit = "ps",  .factor = 1e-12 },
     176};
     177
     178char *tmon_format_duration(usbdiag_dur_t val, const char *fmt)
     179{
     180        return format_unit(val / 1000.0, fmt, dur_units, ARRAY_SIZE(dur_units));
     181}
     182
    108183/** @}
    109184 */
  • uspace/app/tmon/tf.h

    re67c50a r64ce0c1  
    3838
    3939#include <async.h>
    40 
    41 /** Parameters common for all tests. */
    42 typedef struct tmon_test_params {
    43         /* Nothing here. */
    44 } tmon_test_params_t;
     40#include <usbdiag_iface.h>
    4541
    4642/** Operations to implement by all tests. */
    4743typedef struct tmon_test_ops {
    48         int (*run)(async_exch_t *, const tmon_test_params_t *);
    49         int (*read_params)(int, char **, tmon_test_params_t **);
     44        int (*pre_run)(void *);
     45        int (*run)(async_exch_t *, const void *);
     46        int (*read_params)(int, char **, void **);
    5047} tmon_test_ops_t;
    5148
    5249int tmon_test_main(int, char **, const tmon_test_ops_t *);
     50
     51char *tmon_format_size(double, const char *);
     52char *tmon_format_duration(usbdiag_dur_t, const char *);
    5353
    5454#endif /* TMON_TF_H_ */
  • uspace/drv/bus/usb/usbdiag/device.c

    re67c50a r64ce0c1  
    4646
    4747static usbdiag_iface_t diag_interface = {
    48         .burst_intr_in = usbdiag_burst_test_intr_in,
    49         .burst_intr_out = usbdiag_burst_test_intr_out,
    50         .burst_bulk_in = usbdiag_burst_test_bulk_in,
    51         .burst_bulk_out = usbdiag_burst_test_bulk_out,
    52         .burst_isoch_in = usbdiag_burst_test_isoch_in,
    53         .burst_isoch_out = usbdiag_burst_test_isoch_out,
    54         .data_intr_in = usbdiag_data_test_intr_in,
    55         .data_intr_out = usbdiag_data_test_intr_out,
    56         .data_bulk_in = usbdiag_data_test_bulk_in,
    57         .data_bulk_out = usbdiag_data_test_bulk_out,
    58         .data_isoch_in = usbdiag_data_test_isoch_in,
    59         .data_isoch_out = usbdiag_data_test_isoch_out
     48        .test_in = usbdiag_dev_test_in,
     49        .test_out = usbdiag_dev_test_out,
    6050};
    6151
     
    8676        } while (0);
    8777
    88         _MAP_EP(dev->intr_in, INTR_IN);
    89         _MAP_EP(dev->intr_out, INTR_OUT);
    90         _MAP_EP(dev->bulk_in, BULK_IN);
    91         _MAP_EP(dev->bulk_out, BULK_OUT);
    92         _MAP_EP(dev->isoch_in, ISOCH_IN);
    93         _MAP_EP(dev->isoch_out, ISOCH_OUT);
     78        _MAP_EP(dev->burst_intr_in, BURST_INTR_IN);
     79        _MAP_EP(dev->burst_intr_out, BURST_INTR_OUT);
     80        _MAP_EP(dev->burst_bulk_in, BURST_BULK_IN);
     81        _MAP_EP(dev->burst_bulk_out, BURST_BULK_OUT);
     82        _MAP_EP(dev->burst_isoch_in, BURST_ISOCH_IN);
     83        _MAP_EP(dev->burst_isoch_out, BURST_ISOCH_OUT);
     84        _MAP_EP(dev->data_intr_in, DATA_INTR_IN);
     85        _MAP_EP(dev->data_intr_out, DATA_INTR_OUT);
     86        _MAP_EP(dev->data_bulk_in, DATA_BULK_IN);
     87        _MAP_EP(dev->data_bulk_out, DATA_BULK_OUT);
     88        _MAP_EP(dev->data_isoch_in, DATA_ISOCH_IN);
     89        _MAP_EP(dev->data_isoch_out, DATA_ISOCH_OUT);
    9490
    9591#undef _MAP_EP
  • uspace/drv/bus/usb/usbdiag/device.h

    re67c50a r64ce0c1  
    4040#include <usb/dev/driver.h>
    4141
    42 #define USBDIAG_EP_INTR_IN    1
    43 #define USBDIAG_EP_INTR_OUT   2
    44 #define USBDIAG_EP_BULK_IN    3
    45 #define USBDIAG_EP_BULK_OUT   4
    46 #define USBDIAG_EP_ISOCH_IN   5
    47 #define USBDIAG_EP_ISOCH_OUT  6
     42#define USBDIAG_EP_BURST_INTR_IN    1
     43#define USBDIAG_EP_BURST_INTR_OUT   2
     44#define USBDIAG_EP_BURST_BULK_IN    3
     45#define USBDIAG_EP_BURST_BULK_OUT   4
     46#define USBDIAG_EP_BURST_ISOCH_IN   5
     47#define USBDIAG_EP_BURST_ISOCH_OUT  6
     48
     49#define USBDIAG_EP_DATA_INTR_IN     7
     50#define USBDIAG_EP_DATA_INTR_OUT    8
     51#define USBDIAG_EP_DATA_BULK_IN     9
     52#define USBDIAG_EP_DATA_BULK_OUT   10
     53#define USBDIAG_EP_DATA_ISOCH_IN   11
     54#define USBDIAG_EP_DATA_ISOCH_OUT  12
    4855
    4956/**
     
    5360        usb_device_t *usb_dev;
    5461        ddf_fun_t *fun;
    55         usb_pipe_t *intr_in;
    56         usb_pipe_t *intr_out;
    57         usb_pipe_t *bulk_in;
    58         usb_pipe_t *bulk_out;
    59         usb_pipe_t *isoch_in;
    60         usb_pipe_t *isoch_out;
     62
     63        usb_pipe_t *burst_intr_in;
     64        usb_pipe_t *burst_intr_out;
     65        usb_pipe_t *burst_bulk_in;
     66        usb_pipe_t *burst_bulk_out;
     67        usb_pipe_t *burst_isoch_in;
     68        usb_pipe_t *burst_isoch_out;
     69
     70        usb_pipe_t *data_intr_in;
     71        usb_pipe_t *data_intr_out;
     72        usb_pipe_t *data_bulk_in;
     73        usb_pipe_t *data_bulk_out;
     74        usb_pipe_t *data_isoch_in;
     75        usb_pipe_t *data_isoch_out;
     76
    6177} usbdiag_dev_t;
    6278
  • uspace/drv/bus/usb/usbdiag/main.c

    re67c50a r64ce0c1  
    139139}
    140140
    141 static const usb_endpoint_description_t intr_in_ep = {
    142         .transfer_type = USB_TRANSFER_INTERRUPT,
    143         .direction = USB_DIRECTION_IN,
    144         .interface_class = USB_CLASS_DIAGNOSTIC,
    145         .interface_subclass = 0x00,
    146         .interface_protocol = 0x01,
    147         .flags = 0
    148 };
    149 static const usb_endpoint_description_t intr_out_ep = {
    150         .transfer_type = USB_TRANSFER_INTERRUPT,
    151         .direction = USB_DIRECTION_OUT,
    152         .interface_class = USB_CLASS_DIAGNOSTIC,
    153         .interface_subclass = 0x00,
    154         .interface_protocol = 0x01,
    155         .flags = 0
    156 };
    157 static const usb_endpoint_description_t bulk_in_ep = {
    158         .transfer_type = USB_TRANSFER_BULK,
    159         .direction = USB_DIRECTION_IN,
    160         .interface_class = USB_CLASS_DIAGNOSTIC,
    161         .interface_subclass = 0x00,
    162         .interface_protocol = 0x01,
    163         .flags = 0
    164 };
    165 static const usb_endpoint_description_t bulk_out_ep = {
    166         .transfer_type = USB_TRANSFER_BULK,
    167         .direction = USB_DIRECTION_OUT,
    168         .interface_class = USB_CLASS_DIAGNOSTIC,
    169         .interface_subclass = 0x00,
    170         .interface_protocol = 0x01,
    171         .flags = 0
    172 };
    173 static const usb_endpoint_description_t isoch_in_ep = {
    174         .transfer_type = USB_TRANSFER_ISOCHRONOUS,
    175         .direction = USB_DIRECTION_IN,
    176         .interface_class = USB_CLASS_DIAGNOSTIC,
    177         .interface_subclass = 0x00,
    178         .interface_protocol = 0x01,
    179         .flags = 0
    180 };
    181 static const usb_endpoint_description_t isoch_out_ep = {
     141static const usb_endpoint_description_t burst_intr_in_ep = {
     142        .transfer_type = USB_TRANSFER_INTERRUPT,
     143        .direction = USB_DIRECTION_IN,
     144        .interface_class = USB_CLASS_DIAGNOSTIC,
     145        .interface_subclass = 0x00,
     146        .interface_protocol = 0x01,
     147        .flags = 0
     148};
     149static const usb_endpoint_description_t burst_intr_out_ep = {
     150        .transfer_type = USB_TRANSFER_INTERRUPT,
     151        .direction = USB_DIRECTION_OUT,
     152        .interface_class = USB_CLASS_DIAGNOSTIC,
     153        .interface_subclass = 0x00,
     154        .interface_protocol = 0x01,
     155        .flags = 0
     156};
     157static const usb_endpoint_description_t burst_bulk_in_ep = {
     158        .transfer_type = USB_TRANSFER_BULK,
     159        .direction = USB_DIRECTION_IN,
     160        .interface_class = USB_CLASS_DIAGNOSTIC,
     161        .interface_subclass = 0x00,
     162        .interface_protocol = 0x01,
     163        .flags = 0
     164};
     165static const usb_endpoint_description_t burst_bulk_out_ep = {
     166        .transfer_type = USB_TRANSFER_BULK,
     167        .direction = USB_DIRECTION_OUT,
     168        .interface_class = USB_CLASS_DIAGNOSTIC,
     169        .interface_subclass = 0x00,
     170        .interface_protocol = 0x01,
     171        .flags = 0
     172};
     173static const usb_endpoint_description_t burst_isoch_in_ep = {
     174        .transfer_type = USB_TRANSFER_ISOCHRONOUS,
     175        .direction = USB_DIRECTION_IN,
     176        .interface_class = USB_CLASS_DIAGNOSTIC,
     177        .interface_subclass = 0x00,
     178        .interface_protocol = 0x01,
     179        .flags = 0
     180};
     181static const usb_endpoint_description_t burst_isoch_out_ep = {
     182        .transfer_type = USB_TRANSFER_ISOCHRONOUS,
     183        .direction = USB_DIRECTION_OUT,
     184        .interface_class = USB_CLASS_DIAGNOSTIC,
     185        .interface_subclass = 0x00,
     186        .interface_protocol = 0x01,
     187        .flags = 0
     188};
     189static const usb_endpoint_description_t data_intr_in_ep = {
     190        .transfer_type = USB_TRANSFER_INTERRUPT,
     191        .direction = USB_DIRECTION_IN,
     192        .interface_class = USB_CLASS_DIAGNOSTIC,
     193        .interface_subclass = 0x00,
     194        .interface_protocol = 0x01,
     195        .flags = 0
     196};
     197static const usb_endpoint_description_t data_intr_out_ep = {
     198        .transfer_type = USB_TRANSFER_INTERRUPT,
     199        .direction = USB_DIRECTION_OUT,
     200        .interface_class = USB_CLASS_DIAGNOSTIC,
     201        .interface_subclass = 0x00,
     202        .interface_protocol = 0x01,
     203        .flags = 0
     204};
     205static const usb_endpoint_description_t data_bulk_in_ep = {
     206        .transfer_type = USB_TRANSFER_BULK,
     207        .direction = USB_DIRECTION_IN,
     208        .interface_class = USB_CLASS_DIAGNOSTIC,
     209        .interface_subclass = 0x00,
     210        .interface_protocol = 0x01,
     211        .flags = 0
     212};
     213static const usb_endpoint_description_t data_bulk_out_ep = {
     214        .transfer_type = USB_TRANSFER_BULK,
     215        .direction = USB_DIRECTION_OUT,
     216        .interface_class = USB_CLASS_DIAGNOSTIC,
     217        .interface_subclass = 0x00,
     218        .interface_protocol = 0x01,
     219        .flags = 0
     220};
     221static const usb_endpoint_description_t data_isoch_in_ep = {
     222        .transfer_type = USB_TRANSFER_ISOCHRONOUS,
     223        .direction = USB_DIRECTION_IN,
     224        .interface_class = USB_CLASS_DIAGNOSTIC,
     225        .interface_subclass = 0x00,
     226        .interface_protocol = 0x01,
     227        .flags = 0
     228};
     229static const usb_endpoint_description_t data_isoch_out_ep = {
    182230        .transfer_type = USB_TRANSFER_ISOCHRONOUS,
    183231        .direction = USB_DIRECTION_OUT,
     
    189237
    190238static const usb_endpoint_description_t *diag_endpoints[] = {
    191         [USBDIAG_EP_INTR_IN] = &intr_in_ep,
    192         [USBDIAG_EP_INTR_OUT] = &intr_out_ep,
    193         [USBDIAG_EP_BULK_IN] = &bulk_in_ep,
    194         [USBDIAG_EP_BULK_OUT] = &bulk_out_ep,
    195         [USBDIAG_EP_ISOCH_IN] = &isoch_in_ep,
    196         [USBDIAG_EP_ISOCH_OUT] = &isoch_out_ep,
     239        [USBDIAG_EP_BURST_INTR_IN] = &burst_intr_in_ep,
     240        [USBDIAG_EP_BURST_INTR_OUT] = &burst_intr_out_ep,
     241        [USBDIAG_EP_BURST_BULK_IN] = &burst_bulk_in_ep,
     242        [USBDIAG_EP_BURST_BULK_OUT] = &burst_bulk_out_ep,
     243        [USBDIAG_EP_BURST_ISOCH_IN] = &burst_isoch_in_ep,
     244        [USBDIAG_EP_BURST_ISOCH_OUT] = &burst_isoch_out_ep,
     245        [USBDIAG_EP_DATA_INTR_IN] = &data_intr_in_ep,
     246        [USBDIAG_EP_DATA_INTR_OUT] = &data_intr_out_ep,
     247        [USBDIAG_EP_DATA_BULK_IN] = &data_bulk_in_ep,
     248        [USBDIAG_EP_DATA_BULK_OUT] = &data_bulk_out_ep,
     249        [USBDIAG_EP_DATA_ISOCH_IN] = &data_isoch_in_ep,
     250        [USBDIAG_EP_DATA_ISOCH_OUT] = &data_isoch_out_ep,
    197251        NULL
    198252};
  • uspace/drv/bus/usb/usbdiag/tests.c

    re67c50a r64ce0c1  
    4444#define NAME "usbdiag"
    4545
    46 static int burst_in_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
     46static const uint32_t test_data_src = 0xDEADBEEF;
     47
     48static int test_in(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    4749{
    4850        if (!pipe)
    4951                return EBADMEM;
    5052
    51         char *buffer = usb_pipe_alloc_buffer(pipe, size);
     53        bool validate = params->validate_data;
     54        size_t size = params->transfer_size;
     55        if (!size)
     56                size = pipe->desc.max_transfer_size;
     57
     58        const uint32_t test_data = uint32_host2usb(test_data_src);
     59        if (validate && size % sizeof(test_data))
     60                return EINVAL;
     61
     62        size_t test_data_size = size / sizeof(test_data);
     63        char *buffer = (char *) malloc(size);
    5264        if (!buffer)
    5365                return ENOMEM;
     
    5567        // TODO: Are we sure that no other test is running on this endpoint?
    5668
    57         usb_log_info("Performing %s IN burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
     69        usb_log_info("Performing %s IN test with duration %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), params->min_duration);
    5870
    5971        int rc = EOK;
    60         struct timeval start_time;
     72        uint32_t transfer_count = 0;
     73
     74        struct timeval start_time, final_time, stop_time;
    6175        gettimeofday(&start_time, NULL);
    62 
    63         for (int i = 0; i < cycles; ++i) {
     76        gettimeofday(&stop_time, NULL);
     77
     78        tv_add_diff(&stop_time, params->min_duration * 1000);
     79        gettimeofday(&final_time, NULL);
     80
     81        while (!tv_gt(&final_time, &stop_time)) {
     82                ++transfer_count;
     83
    6484                // Read device's response.
    6585                size_t remaining = size;
     
    83103                if (rc)
    84104                        break;
    85         }
    86 
    87         struct timeval final_time;
    88         gettimeofday(&final_time, NULL);
     105
     106                if (validate) {
     107                        uint32_t *beef_buffer = (uint32_t *) buffer;
     108
     109                        /* Check if the beef is really dead. */
     110                        for (size_t i = 0; i < test_data_size; ++i) {
     111                                if (beef_buffer[i] != test_data) {
     112                                        usb_log_error("Read of %s IN endpoint returned "
     113                                                "invalid data at address %zu. [ 0x%X != 0x%X ]",
     114                                                usb_str_transfer_type(pipe->desc.transfer_type), i * sizeof(test_data), beef_buffer[i], test_data);
     115                                        rc = EINVAL;
     116                                }
     117                        }
     118
     119                        if (rc)
     120                                break;
     121                }
     122
     123                gettimeofday(&final_time, NULL);
     124        }
     125
    89126        usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    90127            ((final_time.tv_sec - start_time.tv_sec) * 1000);
    91128
    92         usb_log_info("Burst test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
    93 
    94         usb_pipe_free_buffer(pipe, buffer);
    95         if (duration)
    96                 *duration = in_duration;
     129        usb_log_info("Test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
     130
     131        results->act_duration = in_duration;
     132        results->transfer_count = transfer_count;
     133        results->transfer_size = size;
     134
     135        free(buffer);
    97136
    98137        return rc;
    99138}
    100139
    101 static int burst_out_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
     140static int test_out(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    102141{
    103142        if (!pipe)
    104143                return EBADMEM;
     144
     145        bool validate = params->validate_data;
     146        size_t size = params->transfer_size;
     147        if (!size)
     148                size = pipe->desc.max_transfer_size;
     149
     150        const uint32_t test_data = uint32_host2usb(test_data_src);
     151
     152        if (validate && size % sizeof(test_data))
     153                return EINVAL;
    105154
    106155        char *buffer = usb_pipe_alloc_buffer(pipe, size);
     
    108157                return ENOMEM;
    109158
    110         memset(buffer, 42, size);
     159        if (validate) {
     160                for (size_t i = 0; i < size; i += sizeof(test_data)) {
     161                        memcpy(buffer + i, &test_data, sizeof(test_data));
     162                }
     163        }
    111164
    112165        // TODO: Are we sure that no other test is running on this endpoint?
    113166
    114         usb_log_info("Performing %s OUT burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
     167        usb_log_info("Performing %s OUT test.", usb_str_transfer_type(pipe->desc.transfer_type));
    115168
    116169        int rc = EOK;
    117         struct timeval start_time;
     170        uint32_t transfer_count = 0;
     171
     172        struct timeval start_time, final_time, stop_time;
    118173        gettimeofday(&start_time, NULL);
    119 
    120         for (int i = 0; i < cycles; ++i) {
     174        gettimeofday(&stop_time, NULL);
     175
     176        tv_add_diff(&stop_time, params->min_duration * 1000);
     177        gettimeofday(&final_time, NULL);
     178
     179        while (!tv_gt(&final_time, &stop_time)) {
     180                ++transfer_count;
     181
    121182                // Write buffer to device.
    122183                if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
     
    124185                        break;
    125186                }
    126         }
    127 
    128         struct timeval final_time;
    129         gettimeofday(&final_time, NULL);
     187
     188                gettimeofday(&final_time, NULL);
     189        }
     190
    130191        usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    131192            ((final_time.tv_sec - start_time.tv_sec) * 1000);
    132193
    133         usb_log_info("Burst test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
    134 
    135         usb_pipe_free_buffer(pipe, buffer);
    136         if (duration)
    137                 *duration = in_duration;
     194        usb_log_info("Test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
     195
     196        results->act_duration = in_duration;
     197        results->transfer_count = transfer_count;
     198        results->transfer_size = size;
     199
     200        free(buffer);
    138201
    139202        return rc;
    140203}
    141204
    142 static const uint32_t test_data_src = 0xDEADBEEF;
    143 
    144 static int data_in_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
    145 {
    146         if (!pipe)
    147                 return EBADMEM;
    148 
    149         const uint32_t test_data = uint32_host2usb(test_data_src);
    150 
    151         if (size % sizeof(test_data))
    152                 return EINVAL;
    153 
    154         char *buffer = usb_pipe_alloc_buffer(pipe, size);
    155         if (!buffer)
    156                 return ENOMEM;
    157 
    158         // TODO: Are we sure that no other test is running on this endpoint?
    159 
    160         usb_log_info("Performing %s IN data test.", usb_str_transfer_type(pipe->desc.transfer_type));
    161 
    162         int rc = EOK;
    163         struct timeval start_time;
    164         gettimeofday(&start_time, NULL);
    165 
    166         for (int i = 0; i < cycles; ++i) {
    167                 // Read device's response.
    168                 size_t remaining = size;
    169                 size_t transferred;
    170 
    171                 while (remaining > 0) {
    172                         if ((rc = usb_pipe_read_dma(pipe, buffer + size - remaining, remaining, &transferred))) {
    173                                 usb_log_error("Read of %s IN endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    174                                 break;
    175                         }
    176 
    177                         if (transferred > remaining) {
    178                                 usb_log_error("Read of %s IN endpoint returned more data than expected.", usb_str_transfer_type(pipe->desc.transfer_type));
    179                                 rc = EINVAL;
    180                                 break;
    181                         }
    182 
    183                         remaining -= transferred;
    184                 }
    185 
    186                 if (rc)
    187                         break;
    188 
    189                 for (size_t i = 0; i < size; i += sizeof(test_data)) {
    190                         if (*(uint32_t *)(buffer + i) != test_data) {
    191                                 usb_log_error("Read of %s IN endpoint returned "
    192                                     "invald data at address %zu.",
    193                                     usb_str_transfer_type(pipe->desc.transfer_type), i);
    194                                 rc = EINVAL;
    195                                 break;
    196                         }
    197                 }
    198 
    199                 if (rc)
    200                         break;
    201         }
    202 
    203         struct timeval final_time;
    204         gettimeofday(&final_time, NULL);
    205         usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    206             ((final_time.tv_sec - start_time.tv_sec) * 1000);
    207 
    208         usb_log_info("Data test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
    209 
    210         usb_pipe_free_buffer(pipe, buffer);
    211         if (duration)
    212                 *duration = in_duration;
    213 
    214         return rc;
    215 }
    216 
    217 static int data_out_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
    218 {
    219         if (!pipe)
    220                 return EBADMEM;
    221 
    222         const uint32_t test_data = uint32_host2usb(test_data_src);
    223 
    224         if (size % sizeof(test_data))
    225                 return EINVAL;
    226 
    227         char *buffer = usb_pipe_alloc_buffer(pipe, size);
    228         if (!buffer)
    229                 return ENOMEM;
    230 
    231         for (size_t i = 0; i < size; i += sizeof(test_data)) {
    232                 memcpy(buffer + i, &test_data, sizeof(test_data));
    233         }
    234 
    235         // TODO: Are we sure that no other test is running on this endpoint?
    236 
    237         usb_log_info("Performing %s OUT data test.", usb_str_transfer_type(pipe->desc.transfer_type));
    238 
    239         int rc = EOK;
    240         struct timeval start_time;
    241         gettimeofday(&start_time, NULL);
    242 
    243         for (int i = 0; i < cycles; ++i) {
    244                 // Write buffer to device.
    245                 if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
    246                         usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    247                         break;
    248                 }
    249         }
    250 
    251         struct timeval final_time;
    252         gettimeofday(&final_time, NULL);
    253         usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    254             ((final_time.tv_sec - start_time.tv_sec) * 1000);
    255 
    256         usb_log_info("Data test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
    257 
    258         usb_pipe_free_buffer(pipe, buffer);
    259         if (duration)
    260                 *duration = in_duration;
    261 
    262         return rc;
    263 }
    264 
    265 int usbdiag_burst_test_intr_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
     205int usbdiag_dev_test_in(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    266206{
    267207        usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
     
    269209                return EBADMEM;
    270210
    271         return burst_in_test(dev->intr_in, cycles, size, duration);
    272 }
    273 
    274 int usbdiag_burst_test_intr_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
     211        usb_pipe_t *pipe;
     212
     213        switch (params->transfer_type) {
     214        case USB_TRANSFER_INTERRUPT:
     215                pipe = params->validate_data ? dev->data_intr_in : dev->burst_intr_in;
     216                break;
     217        case USB_TRANSFER_BULK:
     218                pipe = params->validate_data ? dev->data_bulk_in : dev->burst_bulk_in;
     219                break;
     220        case USB_TRANSFER_ISOCHRONOUS:
     221                pipe = params->validate_data ? dev->data_isoch_in : dev->burst_isoch_in;
     222                break;
     223        default:
     224                return ENOTSUP;
     225        }
     226
     227        return test_in(pipe, params, results);
     228}
     229
     230int usbdiag_dev_test_out(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    275231{
    276232        usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
     
    278234                return EBADMEM;
    279235
    280         return burst_out_test(dev->intr_out, cycles, size, duration);
    281 }
    282 
    283 int usbdiag_burst_test_bulk_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    284 {
    285         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    286         if (!dev)
    287                 return EBADMEM;
    288 
    289         return burst_in_test(dev->bulk_in, cycles, size, duration);
    290 }
    291 
    292 int usbdiag_burst_test_bulk_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    293 {
    294         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    295         if (!dev)
    296                 return EBADMEM;
    297 
    298         return burst_out_test(dev->bulk_out, cycles, size, duration);
    299 }
    300 
    301 int usbdiag_burst_test_isoch_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    302 {
    303         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    304         if (!dev)
    305                 return EBADMEM;
    306 
    307         return burst_in_test(dev->isoch_in, cycles, size, duration);
    308 }
    309 
    310 int usbdiag_burst_test_isoch_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    311 {
    312         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    313         if (!dev)
    314                 return EBADMEM;
    315 
    316         return burst_out_test(dev->isoch_out, cycles, size, duration);
    317 }
    318 
    319 int usbdiag_data_test_intr_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    320 {
    321         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    322         if (!dev)
    323                 return EBADMEM;
    324 
    325         return data_in_test(dev->intr_in, cycles, size, duration);
    326 }
    327 
    328 int usbdiag_data_test_intr_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    329 {
    330         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    331         if (!dev)
    332                 return EBADMEM;
    333 
    334         return data_out_test(dev->intr_out, cycles, size, duration);
    335 }
    336 
    337 int usbdiag_data_test_bulk_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    338 {
    339         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    340         if (!dev)
    341                 return EBADMEM;
    342 
    343         return data_in_test(dev->bulk_in, cycles, size, duration);
    344 }
    345 
    346 int usbdiag_data_test_bulk_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    347 {
    348         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    349         if (!dev)
    350                 return EBADMEM;
    351 
    352         return data_out_test(dev->bulk_out, cycles, size, duration);
    353 }
    354 
    355 int usbdiag_data_test_isoch_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    356 {
    357         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    358         if (!dev)
    359                 return EBADMEM;
    360 
    361         return data_in_test(dev->isoch_in, cycles, size, duration);
    362 }
    363 
    364 int usbdiag_data_test_isoch_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
    365 {
    366         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    367         if (!dev)
    368                 return EBADMEM;
    369 
    370         return data_out_test(dev->isoch_out, cycles, size, duration);
     236        usb_pipe_t *pipe;
     237
     238        switch (params->transfer_type) {
     239        case USB_TRANSFER_INTERRUPT:
     240                pipe = params->validate_data ? dev->data_intr_out : dev->burst_intr_out;
     241                break;
     242        case USB_TRANSFER_BULK:
     243                pipe = params->validate_data ? dev->data_bulk_out : dev->burst_bulk_out;
     244                break;
     245        case USB_TRANSFER_ISOCHRONOUS:
     246                pipe = params->validate_data ? dev->data_isoch_out : dev->burst_isoch_out;
     247                break;
     248        default:
     249                return ENOTSUP;
     250        }
     251
     252        return test_out(pipe, params, results);
    371253}
    372254
  • uspace/drv/bus/usb/usbdiag/tests.h

    re67c50a r64ce0c1  
    3939#include <ddf/driver.h>
    4040
    41 int usbdiag_burst_test_intr_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    42 int usbdiag_burst_test_intr_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    43 int usbdiag_burst_test_bulk_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    44 int usbdiag_burst_test_bulk_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    45 int usbdiag_burst_test_isoch_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    46 int usbdiag_burst_test_isoch_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    47 
    48 int usbdiag_data_test_intr_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    49 int usbdiag_data_test_intr_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    50 int usbdiag_data_test_bulk_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    51 int usbdiag_data_test_bulk_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    52 int usbdiag_data_test_isoch_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
    53 int usbdiag_data_test_isoch_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
     41int usbdiag_dev_test_in(ddf_fun_t *, const usbdiag_test_params_t *, usbdiag_test_results_t *);
     42int usbdiag_dev_test_out(ddf_fun_t *, const usbdiag_test_params_t *, usbdiag_test_results_t *);
    5443
    5544#endif /* USBDIAG_TESTS_H_ */
  • uspace/drv/bus/usb/xhci/endpoint.c

    re67c50a r64ce0c1  
    8888        if (dev->speed >= USB_SPEED_SUPER) {
    8989                ep->packets_per_uframe = xhci_ep->max_burst * xhci_ep->mult;
    90                 ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     90                if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS
     91                        || ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     92                        ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     93                }
     94                else {
     95                        ep->max_transfer_size = 200 * PAGE_SIZE;
     96                }
    9197        }
    9298
  • uspace/drv/bus/usb/xhci/transfers.c

    re67c50a r64ce0c1  
    126126}
    127127
     128static int calculate_trb_count(xhci_transfer_t *transfer)
     129{
     130        const size_t size = transfer->batch.buffer_size;
     131        return (size + PAGE_SIZE - 1 )/ PAGE_SIZE;
     132}
     133
     134static void trb_set_buffer(xhci_transfer_t *transfer, xhci_trb_t *trb,
     135        size_t i, size_t total, size_t *remaining)
     136{
     137        const uintptr_t ptr = dma_buffer_phys(&transfer->hc_buffer,
     138                transfer->hc_buffer.virt + i * PAGE_SIZE);
     139
     140        trb->parameter = host2xhci(64, ptr);
     141        TRB_CTRL_SET_TD_SIZE(*trb, max(31, total - i - 1));
     142        if (*remaining > PAGE_SIZE) {
     143                TRB_CTRL_SET_XFER_LEN(*trb, PAGE_SIZE);
     144                *remaining -= PAGE_SIZE;
     145        }
     146        else {
     147                TRB_CTRL_SET_XFER_LEN(*trb, *remaining);
     148                *remaining = 0;
     149        }
     150}
     151
    128152static int schedule_control(xhci_hc_t* hc, xhci_transfer_t* transfer)
    129153{
     
    133157        usb_device_request_setup_packet_t* setup = &batch->setup.packet;
    134158
    135         xhci_trb_t trbs[3];
    136         int trbs_used = 0;
    137 
    138         xhci_trb_t *trb_setup = trbs + trbs_used++;
     159        size_t buffer_count = 0;
     160        if (setup->length > 0) {
     161                buffer_count = calculate_trb_count(transfer);
     162        }
     163
     164        xhci_trb_t trbs[buffer_count + 2];
     165
     166        xhci_trb_t *trb_setup = trbs;
    139167        xhci_trb_clean(trb_setup);
    140168
     
    155183
    156184        /* Data stage */
    157         xhci_trb_t *trb_data = NULL;
    158185        if (setup->length > 0) {
    159                 trb_data = trbs + trbs_used++;
    160                 xhci_trb_clean(trb_data);
    161 
    162                 trb_data->parameter = host2xhci(64, transfer->hc_buffer.phys);
    163 
    164                 // data size (sent for OUT, or buffer size)
    165                 TRB_CTRL_SET_XFER_LEN(*trb_data, batch->buffer_size);
    166                 // FIXME: TD size 4.11.2.4
    167                 TRB_CTRL_SET_TD_SIZE(*trb_data, 1);
    168 
    169                 // Some more fields here, no idea what they mean
    170                 TRB_CTRL_SET_TRB_TYPE(*trb_data, XHCI_TRB_TYPE_DATA_STAGE);
    171 
    172186                int stage_dir = REQUEST_TYPE_IS_DEVICE_TO_HOST(setup->request_type)
    173187                                        ? STAGE_IN : STAGE_OUT;
    174                 TRB_CTRL_SET_DIR(*trb_data, stage_dir);
     188                size_t remaining = transfer->batch.buffer_size;
     189
     190                for (size_t i = 0; i < buffer_count; ++i) {
     191                        xhci_trb_clean(&trbs[i + 1]);
     192                        trb_set_buffer(transfer, &trbs[i + 1], i, buffer_count, &remaining);
     193
     194                        TRB_CTRL_SET_DIR(trbs[i + 1], stage_dir);
     195                        TRB_CTRL_SET_TRB_TYPE(trbs[i + 1], XHCI_TRB_TYPE_DATA_STAGE);
     196
     197                        if (i == buffer_count - 1) break;
     198
     199                        /* Set the chain bit as this is not the last TRB */
     200                        TRB_CTRL_SET_CHAIN(trbs[i], 1);
     201                }
    175202        }
    176203
    177204        /* Status stage */
    178         xhci_trb_t *trb_status = trbs + trbs_used++;
     205        xhci_trb_t *trb_status = trbs + buffer_count + 1;
    179206        xhci_trb_clean(trb_status);
    180207
     
    192219
    193220        return xhci_trb_ring_enqueue_multiple(get_ring(transfer), trbs,
    194             trbs_used, &transfer->interrupt_trb_phys);
     221            buffer_count + 2, &transfer->interrupt_trb_phys);
    195222}
    196223
    197224static int schedule_bulk(xhci_hc_t* hc, xhci_transfer_t *transfer)
    198225{
    199         xhci_trb_t trb;
    200         xhci_trb_clean(&trb);
    201         trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
    202 
    203         // data size (sent for OUT, or buffer size)
    204         TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
    205 
    206226        /* The stream-enabled endpoints need to chain ED trb */
    207227        xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep);
    208228        if (!ep->primary_stream_data_size) {
    209                 // FIXME: TD size 4.11.2.4
    210                 TRB_CTRL_SET_TD_SIZE(trb, 1);
    211 
    212                 // we want an interrupt after this td is done
    213                 TRB_CTRL_SET_IOC(trb, 1);
    214                 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
     229                const size_t buffer_count = calculate_trb_count(transfer);
     230                xhci_trb_t trbs[buffer_count];
     231                size_t remaining = transfer->batch.buffer_size;
     232
     233                for (size_t i = 0; i < buffer_count; ++i) {
     234                        xhci_trb_clean(&trbs[i]);
     235                        trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
     236                        TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
     237
     238                        if (i == buffer_count - 1) break;
     239
     240                        /* Set the chain bit as this is not the last TRB */
     241                        TRB_CTRL_SET_CHAIN(trbs[i], 1);
     242                }
     243                /* Set the interrupt bit for last TRB */
     244                TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
    215245
    216246                xhci_trb_ring_t* ring = get_ring(transfer);
    217                 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     247                return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
     248                        &transfer->interrupt_trb_phys);
    218249        }
    219250        else {
    220                 TRB_CTRL_SET_TD_SIZE(trb, 2);
    221                 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    222                 TRB_CTRL_SET_CHAIN(trb, 1);
    223                 TRB_CTRL_SET_ENT(trb, 1);
    224 
    225251                xhci_trb_ring_t* ring = get_ring(transfer);
    226252                if (!ring) {
     
    228254                }
    229255
    230                 int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
    231 
    232                 if (err) {
    233                         return err;
    234                 }
    235 
    236                 xhci_trb_clean(&trb);
    237                 trb.parameter = host2xhci(64, (uintptr_t) transfer);
    238                 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA);
    239                 TRB_CTRL_SET_IOC(trb, 1);
    240 
    241                 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     256                const size_t buffer_count = calculate_trb_count(transfer);
     257                xhci_trb_t trbs[buffer_count + 1];
     258                size_t remaining = transfer->batch.buffer_size;
     259
     260                for (size_t i = 0; i < buffer_count; ++i) {
     261                        xhci_trb_clean(&trbs[i]);
     262                        trb_set_buffer(transfer, &trbs[i], i, buffer_count + 1, &remaining);
     263                        TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
     264                        TRB_CTRL_SET_CHAIN(trbs[i], 1);
     265                }
     266                TRB_CTRL_SET_ENT(trbs[buffer_count - 1], 1);
     267
     268                xhci_trb_clean(&trbs[buffer_count]);
     269                trbs[buffer_count].parameter = host2xhci(64, (uintptr_t) transfer);
     270                TRB_CTRL_SET_TRB_TYPE(trbs[buffer_count], XHCI_TRB_TYPE_EVENT_DATA);
     271                TRB_CTRL_SET_IOC(trbs[buffer_count], 1);
     272
     273                return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count + 1,
     274                        &transfer->interrupt_trb_phys);
    242275        }
    243276}
     
    245278static int schedule_interrupt(xhci_hc_t* hc, xhci_transfer_t* transfer)
    246279{
    247         xhci_trb_t trb;
    248         xhci_trb_clean(&trb);
    249         trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
    250 
    251         // data size (sent for OUT, or buffer size)
    252         TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
    253         // FIXME: TD size 4.11.2.4
    254         TRB_CTRL_SET_TD_SIZE(trb, 1);
    255 
    256         // we want an interrupt after this td is done
    257         TRB_CTRL_SET_IOC(trb, 1);
    258 
    259         TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
     280        const size_t buffer_count = calculate_trb_count(transfer);
     281        xhci_trb_t trbs[buffer_count];
     282        size_t remaining = transfer->batch.buffer_size;
     283
     284        for (size_t i = 0; i < buffer_count; ++i) {
     285                xhci_trb_clean(&trbs[i]);
     286                trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
     287                TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
     288
     289                if (i == buffer_count - 1) break;
     290
     291                /* Set the chain bit as this is not the last TRB */
     292                TRB_CTRL_SET_CHAIN(trbs[i], 1);
     293        }
     294        /* Set the interrupt bit for last TRB */
     295        TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
    260296
    261297        xhci_trb_ring_t* ring = get_ring(transfer);
    262 
    263         return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     298        return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
     299                &transfer->interrupt_trb_phys);
    264300}
    265301
  • uspace/lib/drv/generic/remote_usbdiag.c

    re67c50a r64ce0c1  
    4343
    4444typedef enum {
    45         IPC_M_USBDIAG_BURST_INTR_IN,
    46         IPC_M_USBDIAG_BURST_INTR_OUT,
    47         IPC_M_USBDIAG_BURST_BULK_IN,
    48         IPC_M_USBDIAG_BURST_BULK_OUT,
    49         IPC_M_USBDIAG_BURST_ISOCH_IN,
    50         IPC_M_USBDIAG_BURST_ISOCH_OUT,
    51         IPC_M_USBDIAG_DATA_INTR_IN,
    52         IPC_M_USBDIAG_DATA_INTR_OUT,
    53         IPC_M_USBDIAG_DATA_BULK_IN,
    54         IPC_M_USBDIAG_DATA_BULK_OUT,
    55         IPC_M_USBDIAG_DATA_ISOCH_IN,
    56         IPC_M_USBDIAG_DATA_ISOCH_OUT
     45        IPC_M_USBDIAG_TEST_IN,
     46        IPC_M_USBDIAG_TEST_OUT,
    5747} usb_iface_funcs_t;
    5848
     
    6858}
    6959
    70 int usbdiag_burst_intr_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
     60int usbdiag_test_in(async_exch_t *exch, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    7161{
    7262        if (!exch)
    7363                return EBADMEM;
    7464
    75         sysarg_t duration_;
    76         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_INTR_IN, cycles, size, &duration_);
    77 
    78         if (rc == EOK && duration)
    79                 *duration = duration_;
    80 
    81         return rc;
    82 }
    83 
    84 int usbdiag_burst_intr_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
     65        ipc_call_t answer;
     66        aid_t req = async_send_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_TEST_IN, &answer);
     67
     68        int rc = async_data_write_start(exch, params, sizeof(usbdiag_test_params_t));
     69        if (rc != EOK) {
     70                async_exchange_end(exch);
     71                async_forget(req);
     72                return rc;
     73        }
     74
     75        rc = async_data_read_start(exch, results, sizeof(usbdiag_test_results_t));
     76        if (rc != EOK) {
     77                async_exchange_end(exch);
     78                async_forget(req);
     79                return rc;
     80        }
     81
     82        async_exchange_end(exch);
     83
     84        errno_t retval;
     85        async_wait_for(req, &retval);
     86
     87        return (int) retval;
     88}
     89
     90int usbdiag_test_out(async_exch_t *exch, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    8591{
    8692        if (!exch)
    8793                return EBADMEM;
    8894
    89         sysarg_t duration_;
    90         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_INTR_OUT, cycles, size, &duration_);
    91 
    92         if (rc == EOK && duration)
    93                 *duration = duration_;
    94 
    95         return rc;
    96 }
    97 
    98 int usbdiag_burst_bulk_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    99 {
    100         if (!exch)
    101                 return EBADMEM;
    102 
    103         sysarg_t duration_;
    104         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_BULK_IN, cycles, size, &duration_);
    105 
    106         if (rc == EOK && duration)
    107                 *duration = duration_;
    108 
    109         return rc;
    110 }
    111 
    112 int usbdiag_burst_bulk_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    113 {
    114         if (!exch)
    115                 return EBADMEM;
    116 
    117         sysarg_t duration_;
    118         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_BULK_OUT, cycles, size, &duration_);
    119 
    120         if (rc == EOK && duration)
    121                 *duration = duration_;
    122 
    123         return rc;
    124 }
    125 
    126 int usbdiag_burst_isoch_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    127 {
    128         if (!exch)
    129                 return EBADMEM;
    130 
    131         sysarg_t duration_;
    132         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_ISOCH_IN, cycles, size, &duration_);
    133 
    134         if (rc == EOK && duration)
    135                 *duration = duration_;
    136 
    137         return rc;
    138 }
    139 
    140 int usbdiag_burst_isoch_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    141 {
    142         if (!exch)
    143                 return EBADMEM;
    144 
    145         sysarg_t duration_;
    146         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_ISOCH_OUT, cycles, size, &duration_);
    147 
    148         if (rc == EOK && duration)
    149                 *duration = duration_;
    150 
    151         return rc;
    152 }
    153 
    154 int usbdiag_data_intr_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    155 {
    156         if (!exch)
    157                 return EBADMEM;
    158 
    159         sysarg_t duration_;
    160         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_INTR_IN, cycles, size, &duration_);
    161 
    162         if (rc == EOK && duration)
    163                 *duration = duration_;
    164 
    165         return rc;
    166 }
    167 
    168 int usbdiag_data_intr_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    169 {
    170         if (!exch)
    171                 return EBADMEM;
    172 
    173         sysarg_t duration_;
    174         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_INTR_OUT, cycles, size, &duration_);
    175 
    176         if (rc == EOK && duration)
    177                 *duration = duration_;
    178 
    179         return rc;
    180 }
    181 
    182 int usbdiag_data_bulk_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    183 {
    184         if (!exch)
    185                 return EBADMEM;
    186 
    187         sysarg_t duration_;
    188         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_BULK_IN, cycles, size, &duration_);
    189 
    190         if (rc == EOK && duration)
    191                 *duration = duration_;
    192 
    193         return rc;
    194 }
    195 
    196 int usbdiag_data_bulk_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    197 {
    198         if (!exch)
    199                 return EBADMEM;
    200 
    201         sysarg_t duration_;
    202         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_BULK_OUT, cycles, size, &duration_);
    203 
    204         if (rc == EOK && duration)
    205                 *duration = duration_;
    206 
    207         return rc;
    208 }
    209 
    210 int usbdiag_data_isoch_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    211 {
    212         if (!exch)
    213                 return EBADMEM;
    214 
    215         sysarg_t duration_;
    216         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_ISOCH_IN, cycles, size, &duration_);
    217 
    218         if (rc == EOK && duration)
    219                 *duration = duration_;
    220 
    221         return rc;
    222 }
    223 
    224 int usbdiag_data_isoch_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
    225 {
    226         if (!exch)
    227                 return EBADMEM;
    228 
    229         sysarg_t duration_;
    230         const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_ISOCH_OUT, cycles, size, &duration_);
    231 
    232         if (rc == EOK && duration)
    233                 *duration = duration_;
    234 
    235         return rc;
    236 }
    237 
    238 static void remote_usbdiag_burst_intr_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    239 static void remote_usbdiag_burst_intr_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    240 static void remote_usbdiag_burst_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    241 static void remote_usbdiag_burst_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    242 static void remote_usbdiag_burst_isoch_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    243 static void remote_usbdiag_burst_isoch_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    244 
    245 static void remote_usbdiag_data_intr_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    246 static void remote_usbdiag_data_intr_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    247 static void remote_usbdiag_data_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    248 static void remote_usbdiag_data_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    249 static void remote_usbdiag_data_isoch_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    250 static void remote_usbdiag_data_isoch_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     95        ipc_call_t answer;
     96        aid_t req = async_send_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_TEST_OUT, &answer);
     97
     98        int rc = async_data_write_start(exch, params, sizeof(usbdiag_test_params_t));
     99        if (rc != EOK) {
     100                async_exchange_end(exch);
     101                async_forget(req);
     102                return rc;
     103        }
     104
     105        rc = async_data_read_start(exch, results, sizeof(usbdiag_test_results_t));
     106        if (rc != EOK) {
     107                async_exchange_end(exch);
     108                async_forget(req);
     109                return rc;
     110        }
     111
     112        async_exchange_end(exch);
     113
     114        errno_t retval;
     115        async_wait_for(req, &retval);
     116
     117        return (int) retval;
     118}
     119
     120static void remote_usbdiag_test_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     121static void remote_usbdiag_test_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    251122
    252123/** Remote USB diagnostic interface operations. */
    253124static const remote_iface_func_ptr_t remote_usbdiag_iface_ops [] = {
    254         [IPC_M_USBDIAG_BURST_INTR_IN] = remote_usbdiag_burst_intr_in,
    255         [IPC_M_USBDIAG_BURST_INTR_OUT] = remote_usbdiag_burst_intr_out,
    256         [IPC_M_USBDIAG_BURST_BULK_IN] = remote_usbdiag_burst_bulk_in,
    257         [IPC_M_USBDIAG_BURST_BULK_OUT] = remote_usbdiag_burst_bulk_out,
    258         [IPC_M_USBDIAG_BURST_ISOCH_IN] = remote_usbdiag_burst_isoch_in,
    259         [IPC_M_USBDIAG_BURST_ISOCH_OUT] = remote_usbdiag_burst_isoch_out,
    260         [IPC_M_USBDIAG_DATA_INTR_IN] = remote_usbdiag_data_intr_in,
    261         [IPC_M_USBDIAG_DATA_INTR_OUT] = remote_usbdiag_data_intr_out,
    262         [IPC_M_USBDIAG_DATA_BULK_IN] = remote_usbdiag_data_bulk_in,
    263         [IPC_M_USBDIAG_DATA_BULK_OUT] = remote_usbdiag_data_bulk_out,
    264         [IPC_M_USBDIAG_DATA_ISOCH_IN] = remote_usbdiag_data_isoch_in,
    265         [IPC_M_USBDIAG_DATA_ISOCH_OUT] = remote_usbdiag_data_isoch_out
     125        [IPC_M_USBDIAG_TEST_IN] = remote_usbdiag_test_in,
     126        [IPC_M_USBDIAG_TEST_OUT] = remote_usbdiag_test_out
    266127};
    267128
     
    272133};
    273134
    274 void remote_usbdiag_burst_intr_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     135void remote_usbdiag_test_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    275136{
    276137        const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    277138
    278         if (diag_iface->burst_bulk_in == NULL) {
    279                 async_answer_0(callid, ENOTSUP);
    280                 return;
    281         }
    282 
    283         int cycles = DEV_IPC_GET_ARG1(*call);
    284         size_t size = DEV_IPC_GET_ARG2(*call);
    285         usbdiag_dur_t duration;
    286         const int ret = diag_iface->burst_intr_in(fun, cycles, size, &duration);
     139        size_t size;
     140        ipc_callid_t data_callid;
     141        if (!async_data_write_receive(&data_callid, &size)) {
     142                async_answer_0(data_callid, EINVAL);
     143                async_answer_0(callid, EINVAL);
     144                return;
     145        }
     146
     147        if (size != sizeof(usbdiag_test_params_t)) {
     148                async_answer_0(data_callid, EINVAL);
     149                async_answer_0(callid, EINVAL);
     150                return;
     151        }
     152
     153        usbdiag_test_params_t params;
     154        if (async_data_write_finalize(data_callid, &params, size) != EOK) {
     155                async_answer_0(callid, EINVAL);
     156                return;
     157        }
     158
     159        usbdiag_test_results_t results;
     160        const int ret = !diag_iface->test_in ? ENOTSUP : diag_iface->test_in(fun, &params, &results);
    287161
    288162        if (ret != EOK) {
    289163                async_answer_0(callid, ret);
    290         } else {
    291                 async_answer_1(callid, EOK, duration);
    292         }
    293 }
    294 
    295 void remote_usbdiag_burst_intr_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     164                return;
     165        }
     166
     167        if (!async_data_read_receive(&data_callid, &size)) {
     168                async_answer_0(data_callid, EINVAL);
     169                async_answer_0(callid, EINVAL);
     170                return;
     171        }
     172
     173        if (size != sizeof(usbdiag_test_results_t)) {
     174                async_answer_0(data_callid, EINVAL);
     175                async_answer_0(callid, EINVAL);
     176                return;
     177        }
     178       
     179        if (async_data_read_finalize(data_callid, &results, size) != EOK) {
     180                async_answer_0(callid, EINVAL);
     181                return;
     182        }
     183
     184        async_answer_0(callid, ret);
     185}
     186
     187void remote_usbdiag_test_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    296188{
    297189        const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    298190
    299         if (diag_iface->burst_bulk_out == NULL) {
    300                 async_answer_0(callid, ENOTSUP);
    301                 return;
    302         }
    303 
    304         int cycles = DEV_IPC_GET_ARG1(*call);
    305         size_t size = DEV_IPC_GET_ARG2(*call);
    306         usbdiag_dur_t duration;
    307         const int ret = diag_iface->burst_intr_out(fun, cycles, size, &duration);
     191        size_t size;
     192        ipc_callid_t data_callid;
     193        if (!async_data_write_receive(&data_callid, &size)) {
     194                async_answer_0(data_callid, EINVAL);
     195                async_answer_0(callid, EINVAL);
     196                return;
     197        }
     198
     199        if (size != sizeof(usbdiag_test_params_t)) {
     200                async_answer_0(data_callid, EINVAL);
     201                async_answer_0(callid, EINVAL);
     202                return;
     203        }
     204
     205        usbdiag_test_params_t params;
     206        if (async_data_write_finalize(data_callid, &params, size) != EOK) {
     207                async_answer_0(callid, EINVAL);
     208                return;
     209        }
     210
     211        usbdiag_test_results_t results;
     212        const int ret = !diag_iface->test_out ? ENOTSUP : diag_iface->test_out(fun, &params, &results);
    308213
    309214        if (ret != EOK) {
    310215                async_answer_0(callid, ret);
    311         } else {
    312                 async_answer_1(callid, EOK, duration);
    313         }
    314 }
    315 
    316 void remote_usbdiag_burst_bulk_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    317 {
    318         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    319 
    320         if (diag_iface->burst_bulk_in == NULL) {
    321                 async_answer_0(callid, ENOTSUP);
    322                 return;
    323         }
    324 
    325         int cycles = DEV_IPC_GET_ARG1(*call);
    326         size_t size = DEV_IPC_GET_ARG2(*call);
    327         usbdiag_dur_t duration;
    328         const int ret = diag_iface->burst_bulk_in(fun, cycles, size, &duration);
    329 
    330         if (ret != EOK) {
    331                 async_answer_0(callid, ret);
    332         } else {
    333                 async_answer_1(callid, EOK, duration);
    334         }
    335 }
    336 
    337 void remote_usbdiag_burst_bulk_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    338 {
    339         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    340 
    341         if (diag_iface->burst_bulk_out == NULL) {
    342                 async_answer_0(callid, ENOTSUP);
    343                 return;
    344         }
    345 
    346         int cycles = DEV_IPC_GET_ARG1(*call);
    347         size_t size = DEV_IPC_GET_ARG2(*call);
    348         usbdiag_dur_t duration;
    349         const int ret = diag_iface->burst_bulk_out(fun, cycles, size, &duration);
    350 
    351         if (ret != EOK) {
    352                 async_answer_0(callid, ret);
    353         } else {
    354                 async_answer_1(callid, EOK, duration);
    355         }
    356 }
    357 
    358 void remote_usbdiag_burst_isoch_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    359 {
    360         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    361 
    362         if (diag_iface->burst_isoch_in == NULL) {
    363                 async_answer_0(callid, ENOTSUP);
    364                 return;
    365         }
    366 
    367         int cycles = DEV_IPC_GET_ARG1(*call);
    368         size_t size = DEV_IPC_GET_ARG2(*call);
    369         usbdiag_dur_t duration;
    370         const int ret = diag_iface->burst_isoch_in(fun, cycles, size, &duration);
    371 
    372         if (ret != EOK) {
    373                 async_answer_0(callid, ret);
    374         } else {
    375                 async_answer_1(callid, EOK, duration);
    376         }
    377 }
    378 
    379 void remote_usbdiag_burst_isoch_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    380 {
    381         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    382 
    383         if (diag_iface->burst_isoch_out == NULL) {
    384                 async_answer_0(callid, ENOTSUP);
    385                 return;
    386         }
    387 
    388         int cycles = DEV_IPC_GET_ARG1(*call);
    389         size_t size = DEV_IPC_GET_ARG2(*call);
    390         usbdiag_dur_t duration;
    391         const int ret = diag_iface->burst_isoch_out(fun, cycles, size, &duration);
    392 
    393         if (ret != EOK) {
    394                 async_answer_0(callid, ret);
    395         } else {
    396                 async_answer_1(callid, EOK, duration);
    397         }
    398 }
    399 
    400 void remote_usbdiag_data_intr_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    401 {
    402         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    403 
    404         if (diag_iface->data_bulk_in == NULL) {
    405                 async_answer_0(callid, ENOTSUP);
    406                 return;
    407         }
    408 
    409         int cycles = DEV_IPC_GET_ARG1(*call);
    410         size_t size = DEV_IPC_GET_ARG2(*call);
    411         usbdiag_dur_t duration;
    412         const int ret = diag_iface->data_intr_in(fun, cycles, size, &duration);
    413 
    414         if (ret != EOK) {
    415                 async_answer_0(callid, ret);
    416         } else {
    417                 async_answer_1(callid, EOK, duration);
    418         }
    419 }
    420 
    421 void remote_usbdiag_data_intr_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    422 {
    423         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    424 
    425         if (diag_iface->data_bulk_out == NULL) {
    426                 async_answer_0(callid, ENOTSUP);
    427                 return;
    428         }
    429 
    430         int cycles = DEV_IPC_GET_ARG1(*call);
    431         size_t size = DEV_IPC_GET_ARG2(*call);
    432         usbdiag_dur_t duration;
    433         const int ret = diag_iface->data_intr_out(fun, cycles, size, &duration);
    434 
    435         if (ret != EOK) {
    436                 async_answer_0(callid, ret);
    437         } else {
    438                 async_answer_1(callid, EOK, duration);
    439         }
    440 }
    441 
    442 void remote_usbdiag_data_bulk_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    443 {
    444         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    445 
    446         if (diag_iface->data_bulk_in == NULL) {
    447                 async_answer_0(callid, ENOTSUP);
    448                 return;
    449         }
    450 
    451         int cycles = DEV_IPC_GET_ARG1(*call);
    452         size_t size = DEV_IPC_GET_ARG2(*call);
    453         usbdiag_dur_t duration;
    454         const int ret = diag_iface->data_bulk_in(fun, cycles, size, &duration);
    455 
    456         if (ret != EOK) {
    457                 async_answer_0(callid, ret);
    458         } else {
    459                 async_answer_1(callid, EOK, duration);
    460         }
    461 }
    462 
    463 void remote_usbdiag_data_bulk_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    464 {
    465         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    466 
    467         if (diag_iface->data_bulk_out == NULL) {
    468                 async_answer_0(callid, ENOTSUP);
    469                 return;
    470         }
    471 
    472         int cycles = DEV_IPC_GET_ARG1(*call);
    473         size_t size = DEV_IPC_GET_ARG2(*call);
    474         usbdiag_dur_t duration;
    475         const int ret = diag_iface->data_bulk_out(fun, cycles, size, &duration);
    476 
    477         if (ret != EOK) {
    478                 async_answer_0(callid, ret);
    479         } else {
    480                 async_answer_1(callid, EOK, duration);
    481         }
    482 }
    483 
    484 void remote_usbdiag_data_isoch_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    485 {
    486         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    487 
    488         if (diag_iface->data_isoch_in == NULL) {
    489                 async_answer_0(callid, ENOTSUP);
    490                 return;
    491         }
    492 
    493         int cycles = DEV_IPC_GET_ARG1(*call);
    494         size_t size = DEV_IPC_GET_ARG2(*call);
    495         usbdiag_dur_t duration;
    496         const int ret = diag_iface->data_isoch_in(fun, cycles, size, &duration);
    497 
    498         if (ret != EOK) {
    499                 async_answer_0(callid, ret);
    500         } else {
    501                 async_answer_1(callid, EOK, duration);
    502         }
    503 }
    504 
    505 void remote_usbdiag_data_isoch_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
    506 {
    507         const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
    508 
    509         if (diag_iface->data_isoch_out == NULL) {
    510                 async_answer_0(callid, ENOTSUP);
    511                 return;
    512         }
    513 
    514         int cycles = DEV_IPC_GET_ARG1(*call);
    515         size_t size = DEV_IPC_GET_ARG2(*call);
    516         usbdiag_dur_t duration;
    517         const int ret = diag_iface->data_isoch_out(fun, cycles, size, &duration);
    518 
    519         if (ret != EOK) {
    520                 async_answer_0(callid, ret);
    521         } else {
    522                 async_answer_1(callid, EOK, duration);
    523         }
     216                return;
     217        }
     218
     219        if (!async_data_read_receive(&data_callid, &size)) {
     220                async_answer_0(data_callid, EINVAL);
     221                async_answer_0(callid, EINVAL);
     222                return;
     223        }
     224
     225        if (size != sizeof(usbdiag_test_results_t)) {
     226                async_answer_0(data_callid, EINVAL);
     227                async_answer_0(callid, EINVAL);
     228                return;
     229        }
     230       
     231        if (async_data_read_finalize(data_callid, &results, size) != EOK) {
     232                async_answer_0(callid, EINVAL);
     233                return;
     234        }
     235
     236        async_answer_0(callid, ret);
    524237}
    525238
  • uspace/lib/drv/include/usbdiag_iface.h

    re67c50a r64ce0c1  
    3939
    4040#include <async.h>
     41#include <usbhc_iface.h>
    4142#include "ddf/driver.h"
    4243
     
    4647typedef unsigned long usbdiag_dur_t;
    4748
     49/** Test parameters. */
     50typedef struct usbdiag_test_params {
     51        usb_transfer_type_t transfer_type;
     52        size_t transfer_size;
     53        usbdiag_dur_t min_duration;
     54        bool validate_data;
     55} usbdiag_test_params_t;
     56
     57/** Test results. */
     58typedef struct usbdiag_test_results {
     59        usbdiag_dur_t act_duration;
     60        uint32_t transfer_count;
     61        size_t transfer_size;
     62} usbdiag_test_results_t;
     63
    4864async_sess_t *usbdiag_connect(devman_handle_t);
    4965void usbdiag_disconnect(async_sess_t*);
    5066
    51 int usbdiag_burst_intr_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    52 int usbdiag_burst_intr_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
    53 int usbdiag_burst_bulk_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    54 int usbdiag_burst_bulk_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
    55 int usbdiag_burst_isoch_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    56 int usbdiag_burst_isoch_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
    57 
    58 int usbdiag_data_intr_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    59 int usbdiag_data_intr_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
    60 int usbdiag_data_bulk_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    61 int usbdiag_data_bulk_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
    62 int usbdiag_data_isoch_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
    63 int usbdiag_data_isoch_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
     67int usbdiag_test_in(async_exch_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
     68int usbdiag_test_out(async_exch_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
    6469
    6570/** USB diagnostic device communication interface. */
    6671typedef struct {
    67         int (*burst_intr_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    68         int (*burst_intr_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    69         int (*burst_bulk_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    70         int (*burst_bulk_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    71         int (*burst_isoch_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    72         int (*burst_isoch_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    73         int (*data_intr_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    74         int (*data_intr_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    75         int (*data_bulk_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    76         int (*data_bulk_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    77         int (*data_isoch_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
    78         int (*data_isoch_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
     72        int (*test_in)(ddf_fun_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
     73        int (*test_out)(ddf_fun_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
    7974} usbdiag_iface_t;
    8075
  • uspace/lib/usbdev/src/pipesinit.c

    re67c50a r64ce0c1  
    146146                if (interface_number_fits
    147147                    && interface_setting_fits
    148                     && endpoint_descriptions_fits) {
     148                    && endpoint_descriptions_fits
     149                    && !mapping->present) {
    149150                        return mapping;
    150151                }
     
    153154                mapping_count--;
    154155        }
     156
    155157        return NULL;
    156158}
  • uspace/lib/usbhost/src/endpoint.c

    re67c50a r64ce0c1  
    244244
    245245        /** Limit transfers with reserved bandwidth to the amount reserved */
    246         if ((ep->transfer_type == USB_TRANSFER_INTERRUPT
    247             || ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    248             && size > ep->max_transfer_size)
     246        if (ep->direction == USB_DIRECTION_OUT && size > ep->max_transfer_size)
    249247                return ENOSPC;
    250248
Note: See TracChangeset for help on using the changeset viewer.