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

📄 usbhost.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
            switch (this_len) {              case 1: transfer.request  = USBTEST_CONTROL_DATA1; break;              case 2: transfer.request  = USBTEST_CONTROL_DATA2; break;              case 3: transfer.request  = USBTEST_CONTROL_DATA3; break;              case 4: transfer.request  = USBTEST_CONTROL_DATA4; break;              default:                fprintf(stderr, "usbhost: internal error, confusion about transfer length.\n");                exit(EXIT_FAILURE);            }            transfer.value      = (buf[i]   << 8) | buf[i+1];   // Possible read beyond end of buffer,            transfer.index      = (buf[i+2] << 8) | buf[i+3];   // but not worth worrying about.            transfer.length     = 0;            transfer.timeout    = 10 * 1000; // ten seconds, the target should always accept data faster than this.            transfer.data       = NULL;            // This is too strict, deciding what to do about errors should be            // handled by higher-level code. However it will do for now.            ioctl_result = ioctl(fd, USBDEVFS_CONTROL, &transfer);            if (0 != ioctl_result) {                fprintf(stderr, "usbhost: error, failed to send control message (data) to target.\n");                exit(EXIT_FAILURE);            }        }        // There is no more data to be transferred.        length = 0;    }#endif        transfer.requesttype        = request_type;    transfer.request            = request;    transfer.value              = value;    transfer.index              = index;    transfer.length             = length;    transfer.timeout            = 10000;    transfer.data               = data;    result = ioctl(fd, USBDEVFS_CONTROL, &transfer);    return result;}// A variant of the above which can be called when the target should always respond// correctly. This can be used for class control messages.static intusb_reliable_control_message(int fd, int request_type, int request, int value, int index, int length, void* data){    int result = usb_control_message(fd, request_type, request, value, index, length, data);    if (-1 == result) {        fprintf(stderr, "usbhost: error, failed to send control message %02x to target.\n", request);        fprintf(stderr, "       : errno %d (%s)\n", errno, strerror(errno));        exit(EXIT_FAILURE);    }    return result;}    // Either send or receive a single bulk message. The top bit of the endpoint// number indicates the direction.static intusb_bulk_message(int fd, int endpoint, unsigned char* buffer, int length){    struct  usbdevfs_bulktransfer    transfer;    int     result;        transfer.ep         = endpoint;    transfer.len        = length;    transfer.timeout    = 60 * 60 * 1000;    // An hour. These operations should not time out because that    // leaves the system in a confused state. Instead there is    // higher-level recovery code that should ensure the operation    // really does complete, and the return value here is used    // by the calling code to determine whether the operation    // was successful or whether there was an error and the recovery    // code was invoked.    transfer.data       = buffer;    errno               = 0;    result = ioctl(fd, USBDEVFS_BULK, &transfer);    return result;}// Synchronise with the target. This can be used after the host has sent a request that// may take a bit of time, e.g. it may involve waking up a thread. The host will send// synch requests at regular intervals, until the target is ready.//// The limit argument can be used to avoid locking up. -1 means loop forever, otherwise// it means that many iterations of 100ms apiece.static intusb_sync(int fd, int limit){    unsigned char   buf[1];    struct timespec delay;    int             loops   = 0;    int             result  = 0;    VERBOSE(2, "Synchronizing with target\n");        while (1) {        buf[0]  = 0;        usb_reliable_control_message(fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_SYNCH, 0, 0, 1, buf);        if (buf[0]) {            result = 1;            break;        } else {            if ((-1 != limit) && (++loops > limit)) {                break;            } else {                VERBOSE(3, "Not yet synchronized, sleeping\n");                delay.tv_sec    = 0;                delay.tv_nsec   = 100000000;    // 100 ms                nanosleep(&delay, NULL);            }        }    }    VERBOSE(2, "%s\n", result ? "Synchronized" : "Not synchronized");    return result;}// Abort the target. Things seem to be completely messed up and there is no easy// way to restore sanity to both target and host.static voidusb_abort(int fd){    VERBOSE(2, "Target-side abort operation invoked\n");    usb_reliable_control_message(fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_ABORT, 0, 0, 0, (void*)0);}/*}}}*//*{{{  Initialise endpoints                                     */// ----------------------------------------------------------------------------// On power-up some endpoints may not be in a sensible state. For example,// with the SA11x0 the hardware may start accepting bulk OUT transfers// before the target-side software has started a receive operation,// so if the host sends a bulk packet before the target is ready then// things get messy. This is especially troublesome if the target-side// attempts any diagnostic output because of verbosity.//// This code loops through the various endpoints and makes sure that// they are all in a reasonable state, before any real tests get run// That means known hardware flaws do not show up as test failures,// but of course they are still documented and application software// will have to do the right thing.static voidusb_initialise_control_endpoint(int min_size, int max_size){    // At this time there are no known problems on any hardware    // that would need to be addressed}static voidusb_initialise_isochronous_in_endpoint(int number, int min_size, int max_size){    // At this time there are no known problems on any hardware    // that would need to be addressed}static voidusb_initialise_isochronous_out_endpoint(int number, int min_size, int max_size){    // At this time there are no known problems on any hardware    // that would need to be addressed}static voidusb_initialise_bulk_in_endpoint(int number, int min_size, int max_size, int padding){    // At this time there are no known problems on any hardware    // that would need to be addressed}static voidusb_initialise_bulk_out_endpoint(int number, int min_size, int max_size){    char buf[1];        // On the SA1110 the hardware comes up with a bogus default value,    // causing the hardware to accept packets before the software has    // set up DMA or in any way prepared for incoming data. This is    // a problem. It is worked around by making the target receive    // a single packet, sending that packet, and then performing a    // sync.    VERBOSE(2, "Performing bulk OUT initialization on endpoint %d\n", number);        usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN,                                 USBTEST_INIT_BULK_OUT, number, 0, 0, (void*) 0);    usb_bulk_message(usb_master_fd, number, buf, 1);    usb_sync(usb_master_fd, 10);}static voidusb_initialise_interrupt_in_endpoint(int number, int min_size, int max_size){    // At this time there are no known problems on any hardware    // that would need to be addressed}static voidusb_initialise_interrupt_out_endpoint(int number, int min_size, int max_size){    // At this time there are no known problems on any hardware    // that would need to be addressed}/*}}}*//*{{{  Host/target common code                                  */#define HOST#include "../tests/common.c"/*}}}*//*{{{  The test cases themselves                                *//*{{{  UsbTest definition                                       */// ----------------------------------------------------------------------------// All the data associated with a single test.typedef struct UsbTest {    // A "unique" identifier to make verbose output easier to understand.    int                 id;              // Which file descriptor should be used to access USB.    int                 fd;        // Which test should be run.    usbtest             which_test;    // Test-specific details.    union {        UsbTest_Bulk        bulk;        UsbTest_ControlIn   control_in;    } test_params;    // How to recover from any problems. Specifically, what kind of message    // could the target send or receive that would unlock the thread on this    // side.    UsbTest_Recovery    recovery;    int                 result_pass;    char                result_message[USBTEST_MAX_MESSAGE];    unsigned char       buffer[USBTEST_MAX_BULK_DATA + USBTEST_MAX_BULK_DATA_EXTRA];} UsbTest;// Reset the information in a given test. This is used by the pool allocation// code. The data union is left alone, filling in the appropriate union// member is left to other code.static voidreset_usbtest(UsbTest* test){    static int next_id = 1;    test->id                    = next_id++;    test->which_test            = usbtest_invalid;    usbtest_recovery_reset(&(test->recovery));    test->result_pass           = 0;    test->result_message[0]     = '\0';}/*}}}*//*{{{  bulk OUT                                                 */static voidrun_test_bulk_out(UsbTest* test){    unsigned char*  buf     = test->buffer;    int             i;    VERBOSE(1, "Starting test %d, bulk OUT 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 packet_size = test->test_params.bulk.tx_size;        test->recovery.endpoint     = test->test_params.bulk.endpoint;        test->recovery.protocol     = USB_ENDPOINT_XFER_BULK;        test->recovery.size         = packet_size;                usbtest_fill_buffer(&(test->test_params.bulk.data), buf, packet_size);        if (verbose < 3) {            VERBOSE(2, "Bulk OUT test %d: iteration %d, packet size %d\n", test->id, i, packet_size);        } else {            // Output the first 32 bytes of data as well.            char msg[256];            int  index;            int  j;            index = snprintf(msg, 255, "Bulk OUT test %d: iteration %d, packet size %d\n    Data %s:",                             test->id, i, packet_size,                             (usbtestdata_none == test->test_params.bulk.data.format) ? "(uninitialized)" : "");            for (j = 0; ((j + 3) < packet_size) && (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 < packet_size; j++) {                    index += snprintf(msg+index, 255-index, "%02x", buf[j]);                }                            }            VERBOSE(3, "%s\n", msg);        }        transferred = usb_bulk_message(test->fd, test->test_params.bulk.endpoint, buf, packet_size);                // Has this test run been aborted for some reason?        if (current_tests_terminated) {            VERBOSE(2, "Bulk OUT test %d: iteration %d, termination detected\n", test->id, i);            test->result_pass = 0;            snprintf(test->result_message, USBTEST_MAX_MESSAGE,                     "Host, bulk OUT transfer on endpoint %d: aborted after %d iterations\n",                     test->test_params.bulk.endpoint & USB_ENDPOINT_NUMBER_MASK, i);            return;        }

⌨️ 快捷键说明

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