Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbdiag/tests.c

    rda9d6ca r290338b  
    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;
     
    6787
    6888                while (remaining > 0) {
    69                         if ((rc = usb_pipe_read_dma(pipe, buffer + size - remaining, remaining, &transferred))) {
     89                        if ((rc = usb_pipe_read(pipe, buffer + size - remaining, remaining, &transferred))) {
    7090                                usb_log_error("Read of %s IN endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    7191                                break;
     
    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;
    105144
    106         char *buffer = usb_pipe_alloc_buffer(pipe, size);
     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;
     154
     155        char *buffer = (char *) malloc(size);
    107156        if (!buffer)
    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.
    122                 if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
     183                if ((rc = usb_pipe_write(pipe, buffer, size))) {
    123184                        usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    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
Note: See TracChangeset for help on using the changeset viewer.