Ignore:
File:
1 edited

Legend:

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

    r290338b rda9d6ca  
    4444#define NAME "usbdiag"
    4545
    46 static const uint32_t test_data_src = 0xDEADBEEF;
    47 
    48 static int test_in(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
     46static int burst_in_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
    4947{
    5048        if (!pipe)
    5149                return EBADMEM;
    5250
    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);
     51        char *buffer = usb_pipe_alloc_buffer(pipe, size);
    6452        if (!buffer)
    6553                return ENOMEM;
     
    6755        // TODO: Are we sure that no other test is running on this endpoint?
    6856
    69         usb_log_info("Performing %s IN test with duration %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), params->min_duration);
     57        usb_log_info("Performing %s IN burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
    7058
    7159        int rc = EOK;
    72         uint32_t transfer_count = 0;
    73 
    74         struct timeval start_time, final_time, stop_time;
     60        struct timeval start_time;
    7561        gettimeofday(&start_time, NULL);
    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 
     62
     63        for (int i = 0; i < cycles; ++i) {
    8464                // Read device's response.
    8565                size_t remaining = size;
     
    8767
    8868                while (remaining > 0) {
    89                         if ((rc = usb_pipe_read(pipe, buffer + size - remaining, remaining, &transferred))) {
     69                        if ((rc = usb_pipe_read_dma(pipe, buffer + size - remaining, remaining, &transferred))) {
    9070                                usb_log_error("Read of %s IN endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    9171                                break;
     
    10383                if (rc)
    10484                        break;
    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 
     85        }
     86
     87        struct timeval final_time;
     88        gettimeofday(&final_time, NULL);
    12689        usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    12790            ((final_time.tv_sec - start_time.tv_sec) * 1000);
    12891
    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);
     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;
    13697
    13798        return rc;
    13899}
    139100
    140 static int test_out(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
     101static int burst_out_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
    141102{
    142103        if (!pipe)
    143104                return EBADMEM;
    144105
    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);
     106        char *buffer = usb_pipe_alloc_buffer(pipe, size);
    156107        if (!buffer)
    157108                return ENOMEM;
    158109
    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         }
     110        memset(buffer, 42, size);
    164111
    165112        // TODO: Are we sure that no other test is running on this endpoint?
    166113
    167         usb_log_info("Performing %s OUT test.", usb_str_transfer_type(pipe->desc.transfer_type));
     114        usb_log_info("Performing %s OUT burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
    168115
    169116        int rc = EOK;
    170         uint32_t transfer_count = 0;
    171 
    172         struct timeval start_time, final_time, stop_time;
     117        struct timeval start_time;
    173118        gettimeofday(&start_time, NULL);
    174         gettimeofday(&stop_time, NULL);
    175 
    176         tv_add_diff(&stop_time, params->min_duration * 1000);
     119
     120        for (int i = 0; i < cycles; ++i) {
     121                // Write buffer to device.
     122                if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
     123                        usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
     124                        break;
     125                }
     126        }
     127
     128        struct timeval final_time;
    177129        gettimeofday(&final_time, NULL);
    178 
    179         while (!tv_gt(&final_time, &stop_time)) {
    180                 ++transfer_count;
    181 
    182                 // Write buffer to device.
    183                 if ((rc = usb_pipe_write(pipe, buffer, size))) {
    184                         usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
    185                         break;
    186                 }
    187 
    188                 gettimeofday(&final_time, NULL);
    189         }
    190 
    191130        usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
    192131            ((final_time.tv_sec - start_time.tv_sec) * 1000);
    193132
    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);
     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;
    201138
    202139        return rc;
    203140}
    204141
    205 int usbdiag_dev_test_in(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    206 {
    207         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    208         if (!dev)
    209                 return EBADMEM;
    210 
    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 
    230 int usbdiag_dev_test_out(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
    231 {
    232         usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
    233         if (!dev)
    234                 return EBADMEM;
    235 
    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);
     142static const uint32_t test_data_src = 0xDEADBEEF;
     143
     144static 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
     217static 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
     265int usbdiag_burst_test_intr_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
     266{
     267        usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
     268        if (!dev)
     269                return EBADMEM;
     270
     271        return burst_in_test(dev->intr_in, cycles, size, duration);
     272}
     273
     274int usbdiag_burst_test_intr_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
     275{
     276        usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
     277        if (!dev)
     278                return EBADMEM;
     279
     280        return burst_out_test(dev->intr_out, cycles, size, duration);
     281}
     282
     283int 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
     292int 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
     301int 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
     310int 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
     319int 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
     328int 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
     337int 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
     346int 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
     355int 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
     364int 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);
    253371}
    254372
Note: See TracChangeset for help on using the changeset viewer.