⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbhost.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        // If an error occurred, abort this run.        if (-1 == transferred) {            char    errno_buf[USBTEST_MAX_MESSAGE];            test->result_pass  = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk OUT transfer on endpoint %d : host ioctl() system call failed\n    errno %d (%s)",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK, errno,                     strerror_r(errno, errno_buf, USBTEST_MAX_MESSAGE));            VERBOSE(2, "Bulk OUT test %d: iteration %d, error:\n    %s\n", test->id, i, test->result_message);            break;        }        if (0 != test->test_params.bulk.tx_delay) {            struct timespec delay;                        VERBOSE(2, "Bulk OUT test %d: iteration %d, sleeping for %d nanoseconds\n", test->id, \                    i, test->test_params.bulk.tx_delay);            // Note that nanosleep() can return early due to incoming signals,            // with the unelapsed time returned in a second argument. This            // allows for a retry loop. In practice this does not seem            // worthwhile, the delays are approximate anyway.            delay.tv_sec  = test->test_params.bulk.tx_delay / 1000000000;            delay.tv_nsec = test->test_params.bulk.tx_delay % 1000000000;            nanosleep(&delay, NULL);        }        // Now move on to the next transfer        USBTEST_BULK_NEXT(test->test_params.bulk);    }    // If all the packets have been transferred this test has passed.    if (i >= test->test_params.bulk.number_packets) {        test->result_pass   = 1;    }        VERBOSE(1, "Test %d bulk OUT on endpoint %d, result %d\n", test->id, test->test_params.bulk.endpoint, test->result_pass);}/*}}}*//*{{{  bulk IN                                                  */static voidrun_test_bulk_in(UsbTest* test){    unsigned char*  buf     = test->buffer;    int             i;    VERBOSE(1, "Starting test %d bulk IN on endpoint %d\n", test->id, test->test_params.bulk.endpoint);        for (i = 0; i < test->test_params.bulk.number_packets; i++) {        int transferred;        int tx_size             = test->test_params.bulk.tx_size;        int rx_size             = test->test_params.bulk.rx_size;        int size_plus_padding;                VERBOSE(2, "Bulk IN test %d: iteration %d, rx size %d, tx size %d\n", test->id, i, rx_size, tx_size);                if (rx_size < tx_size) {            rx_size = tx_size;            VERBOSE(2, "Bulk IN test %d: iteration %d, packet size reset to %d to match tx size\n",                    test->id, i, rx_size);        }        test->recovery.endpoint     = test->test_params.bulk.endpoint;        test->recovery.protocol     = USB_ENDPOINT_XFER_BULK;        test->recovery.size         = rx_size;        // Make sure there is no old data lying around        if (usbtestdata_none != test->test_params.bulk.data.format) {            memset(buf, 0, rx_size);        }        // And do the actual transfer.        size_plus_padding = rx_size;        if (size_plus_padding < (tx_size + test->test_params.bulk.rx_padding)) {            size_plus_padding += test->test_params.bulk.rx_padding;        }        do {            transferred = usb_bulk_message(test->fd, test->test_params.bulk.endpoint, buf, size_plus_padding);        } while (0 == transferred);                // Has this test run been aborted for some reason?        if (current_tests_terminated) {            VERBOSE(2, "Bulk IN test %d: iteration %d, termination detected\n", test->id, i);            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk IN transfer on endpoint %d: aborted after %d iterations\n",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK, i);            return;        }        // If an error occurred, abort this run.        if (-1 == transferred) {            char    errno_buf[USBTEST_MAX_MESSAGE];            test->result_pass  = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk IN transfer on endpoint %d : host ioctl() system call failed\n    errno %d (%s)",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK, errno,                     strerror_r(errno, errno_buf, USBTEST_MAX_MESSAGE));            VERBOSE(2, "Bulk IN test %d: iteration %d, error:\n    %s\n", test->id, i, test->result_message);            break;        }        // Did the target send the expected amount of data?        if (transferred < tx_size) {            test->result_pass   = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk IN transfer on endpoint %d : the target only sent %d bytes when %d were expected",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK, transferred, tx_size);            VERBOSE(2, "Bulk IN test %d: iteration %d, error:\n    %s\n", test->id, i, test->result_message);            break;        }                if (verbose >= 3) {            // Output the first 32 bytes of data            char msg[256];            int  index;            int  j;            index = snprintf(msg, 255, "Bulk IN test %d: iteration %d, transferred %d\n    Data %s:",                             test->id, i, transferred,                             (usbtestdata_none == test->test_params.bulk.data.format) ? "(uninitialized)" : "");            for (j = 0; ((j + 3) < transferred) && (j < 32); j+= 4) {                index += snprintf(msg+index, 255-index, " %02x%02x%02x%02x",                                  buf[j], buf[j+1], buf[j+2], buf[j+3]);            }            if (j < 32) {                index += snprintf(msg+index, 255-index, " ");                for ( ; j < transferred; j++) {                    index += snprintf(msg+index, 255-index, "%02x", buf[j]);                }                            }            VERBOSE(3, "%s\n", msg);        }                // Is the data correct?        if (!usbtest_check_buffer(&(test->test_params.bulk.data), buf, tx_size)) {            test->result_pass   = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk IN transfer on endpoint %d : mismatch between received and expected data",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK);            VERBOSE(2, "Bulk IN test %d: iteration %d, error:\n    %s\n", test->id, i, test->result_message);            break;        }                if (0 != test->test_params.bulk.rx_delay) {            struct timespec delay;                        VERBOSE(2, "Bulk IN test %d: iteration %d, sleeping for %d nanoseconds\n", test->id, \                    i, test->test_params.bulk.tx_delay);            // Note that nanosleep() can return early due to incoming signals,            // with the unelapsed time returned in a second argument. This            // allows for a retry loop. In practice this does not seem            // worthwhile, the delays are approximate anyway.            delay.tv_sec  = test->test_params.bulk.rx_delay / 1000000000;            delay.tv_nsec = test->test_params.bulk.rx_delay % 1000000000;            nanosleep(&delay, NULL);        }                USBTEST_BULK_NEXT(test->test_params.bulk);    }        // If all the packets have been transferred this test has passed.    if (i >= test->test_params.bulk.number_packets) {        test->result_pass   = 1;    }    VERBOSE(1, "Test %d bulk IN on endpoint %d, result %d\n", test->id, test->test_params.bulk.endpoint, test->result_pass);}/*}}}*//*{{{  control IN                                               */// Receive appropriate packets via the control endpoint. This is somewhat// different from bulk transfers. It is implemented using reserved control// messages.//// Note: it is not entirely clear that this test is safe. There will be// concurrent control traffic to detect test termination and the like,// and these control messages may interfere with each other. It is not// entirely clear how the Linux kernel handles concurrent control// operations.static voidrun_test_control_in(UsbTest* test){    unsigned char*  buf     = test->buffer;    int             packet_size;    int             i;    packet_size = test->test_params.control_in.packet_size_initial;    for (i = 0; i < test->test_params.control_in.number_packets; i++) {        int transferred;                test->recovery.endpoint     = 0;        test->recovery.protocol     = USB_ENDPOINT_XFER_CONTROL;        test->recovery.size         = packet_size;        // Make sure there is no old data lying around        if (usbtestdata_none != test->test_params.control_in.data.format) {            memset(buf, 0, packet_size);        }        // And do the actual transfer.        transferred = usb_control_message(test->fd, USB_TYPE_RESERVED | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_RESERVED_CONTROL_IN,                                          0, 0, packet_size, buf);        // Has this test run been aborted for some reason?        if (current_tests_terminated) {            return;        }        // If an error occurred, abort this run.        if (-1 == transferred) {            char    errno_buf[USBTEST_MAX_MESSAGE];            test->result_pass  = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, control IN transfer: host ioctl() system call failed\n    errno %d (%s)",                     errno, strerror_r(errno, errno_buf, USBTEST_MAX_MESSAGE));            break;        }        // Did the target send the expected amount of data?        if (transferred < packet_size) {            test->result_pass   = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, control IN transfer: the target only sent %d bytes when %d were expected",                     transferred, packet_size);            break;        }                // Is the data correct?        if (!usbtest_check_buffer(&(test->test_params.control_in.data), buf, packet_size)) {            test->result_pass   = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, control IN transfer: mismatch between received and expected data");            break;        }                USBTEST_CONTROL_NEXT_PACKET_SIZE(packet_size, test->test_params.control_in);    }    // If all the packets have been transferred this test has passed.    if (i >= test->test_params.control_in.number_packets) {        test->result_pass   = 1;    }}/*}}}*/// FIXME: add more tests/*{{{  run_test()                                               */// This utility is invoked from a thread in the thread pool whenever there is// work to be done. It simply dispatches to the appropriate handler.static voidrun_test(UsbTest* test){    switch (test->which_test) {      case usbtest_bulk_out:    run_test_bulk_out(test); break;      case usbtest_bulk_in:     run_test_bulk_in(test); break;      case usbtest_control_in:  run_test_control_in(test); break;      default:        fprintf(stderr, "usbhost: internal error, attempt to execute an unknown test.\n");        exit(EXIT_FAILURE);    }}/*}}}*//*}}}*//*{{{  The thread pool                                          */// ----------------------------------------------------------------------------// A pool of threads and buffers which do the real work. The number of possible// concurrent tests is defined in protocol.h. Each one requires a separate// thread, transfer buffer, semaphore, and some state information.//// Although the application is multi-threaded, in practice there is little// need for synchronization. Tests will only be started while the pool threads// are idle. When the pool threads are running the main thread will be waiting// for them all to finish, with a bit of polling to detect error conditions.// The pool threads do not share any data, apart from the file descriptor for// the USB device.typedef struct PoolEntry {    pthread_t       thread;    sem_t           wakeup;    int             running;    UsbTest         test;} PoolEntry;static PoolEntry pool[USBTEST_MAX_CONCURRENT_TESTS];// This is the entry point for every thread in the pool. It just loops forever,// waiting until it is supposed to run a test. These threads never actually// exit, instead there should be a call to exit() somewhere.static void*pool_function(void* arg){    PoolEntry*  pool_entry  = (PoolEntry*) arg;    for ( ; ; ) {        sem_wait(&(pool_entry->wakeup));        run_test(&(pool_entry->test));        pool_entry->running = 0;    }    return NULL;}// Initialize all threads in the pool.static voidpool_initialize(void)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -