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

📄 usbtarget.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
// stuff. This information is held in a static.static usbs_control_returnhandle_sync(usb_devreq* req){    CYG_ASSERTC((1 == req->length_lo) && (0 == req->length_hi) && \                ((req->type & USB_DEVREQ_DIRECTION_MASK) == USB_DEVREQ_DIRECTION_IN));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A sync operation should not involve any data");        class_reply[0]                  = (unsigned char) idle;    control_endpoint->buffer        = class_reply;    control_endpoint->buffer_size   = 1;    return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  pass/fail                                                */// Allow the host to generate some pass or fail messages, and// optionally terminate the test. These are synchronous requests// so the data can be left in class_request.static int passfail_request   = 0;// Invoked from thread contextstatic voidhandle_passfail_action(void){    switch (passfail_request) {      case USBTEST_PASS:        CYG_TEST_PASS(class_request);        break;      case USBTEST_PASS_EXIT:        CYG_TEST_PASS(class_request);        CYG_TEST_EXIT("Exiting normally as requested by the host");        break;      case USBTEST_FAIL:        CYG_TEST_FAIL(class_request);        break;      case USBTEST_FAIL_EXIT:        CYG_TEST_FAIL(class_request);        CYG_TEST_EXIT("Exiting normally as requested by the host");        break;      default:        CYG_FAIL("Bogus invocation of usbtest_main_passfail");        break;    }}// Invoked from DSR contextstatic usbs_control_returnhandle_passfail(usb_devreq* req){    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(class_request_size > 0, "A pass/fail message should be supplied");    CYG_ASSERT(idle, "Pass/fail messages are only allowed when idle");    CYG_ASSERT((void (*)(void))0 == main_thread_action, "No thread operation should be pending.");        passfail_request    = req->request;    idle                = false;    main_thread_action  = &handle_passfail_action;    cyg_semaphore_post(&main_wakeup);    return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  abort                                                    */// The host has concluded that there is no easy way to get both target and// host back to a sensible state. For example there may be a thread that// is blocked waiting for some I/O that is not going to complete. The abort// should be handled at thread level, not DSR level, so that the host// still sees the low-level USB handshake.static voidhandle_abort_action(void){    CYG_TEST_FAIL_EXIT("Test abort requested by host application");}static usbs_control_returnhandle_abort(usb_devreq* req){    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(idle, "Abort messages are only allowed when idle");    CYG_ASSERT((void (*)(void))0 == main_thread_action, "No thread operation should be pending.");        idle                = false;    main_thread_action  = &handle_abort_action;    cyg_semaphore_post(&main_wakeup);        return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  cancel                                                   */// Invoked from thread context// Cancelling pending test cases simply involves iterating over the allocated// entries in the pool, invoking any cancellation functions that have been// defined, and then resetting the tread count. The actual tests have not// yet started so none of the threads will be active.static voidhandle_cancel_action(void){    int i;    for (i = 0; i < thread_counter; i++) {        if ((void (*)(UsbTest*))0 != pool[i].test.cancel_fn) {            (*(pool[i].test.cancel_fn))(&(pool[i].test));            pool[i].test.cancel_fn  = (void (*)(UsbTest*)) 0;        }    }    thread_counter    = 0;}// Invoked from DSR contextstatic usbs_control_returnhandle_cancel(usb_devreq* req){    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A cancel operation should not involve any data");    CYG_ASSERT(idle, "Cancel requests are only allowed when idle");    CYG_ASSERT(!running, "Cancel requests cannot be sent once the system is running");    CYG_ASSERT((void (*)(void))0 == main_thread_action, "No thread operation should be pending.");        idle                = false;    main_thread_action = &handle_cancel_action;    cyg_semaphore_post(&main_wakeup);    return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  start                                                    */// Start the tests running. This just involves waking up the pool threads// and setting the running flag, with the latter serving primarily for// assertions. static usbs_control_returnhandle_start(usb_devreq* req){    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A start operation should not involve any data");    CYG_ASSERT(!running, "Start requests cannot be sent if the system is already running");    current_tests_terminated = false;    running = true;    pool_start();        return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  finished                                                 */// Have all the tests finished? This involves checking all the threads// involved in the current batch of tests and seeing whether or not// their running flag is still set.static usbs_control_returnhandle_finished(usb_devreq* req){    int i;    int result = 1;        CYG_ASSERTC((1 == req->length_lo) && (0 == req->length_hi) && \                ((req->type & USB_DEVREQ_DIRECTION_MASK) == USB_DEVREQ_DIRECTION_IN));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A finished operation should not involve any data");    CYG_ASSERT(running, "Finished requests can only be sent if the system is already running");        for (i = 0; i < thread_counter; i++) {        if (pool[i].running) {            result = 0;            break;        }    }    class_reply[0]                  = (unsigned char) result;    control_endpoint->buffer        = class_reply;    control_endpoint->buffer_size   = 1;    return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  set terminated                                           */// A timeout has occurred, or there is some other failure. The first step// in recovery is to set the terminated flag so that as recovery action// takes place and the threads wake up they make no attempt to continue// doing more transfers.static usbs_control_returnhandle_set_terminated(usb_devreq* req){    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A set-terminated operation should not involve any data");    CYG_ASSERT(running, "The terminated flag can only be set when there are running tests");    current_tests_terminated = 1;        return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  get recovery                                             */// Return the recovery information for one of the threads involved in the// current batch of tests, so that the host can perform a USB operation// that will sort out that thread.static usbs_control_returnhandle_get_recovery(usb_devreq* req){    int buffer_index;        CYG_ASSERT(current_tests_terminated, "Recovery should only be attempted when the terminated flag is set");    CYG_ASSERT(running, "If there are no tests running then recovery is impossible");    CYG_ASSERTC((12 == req->length_lo) && (0 == req->length_hi) && \                ((req->type & USB_DEVREQ_DIRECTION_MASK) == USB_DEVREQ_DIRECTION_IN));    CYG_ASSERTC(req->index_lo <= thread_counter);    CYG_ASSERTC((0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(0 == class_request_size, "A get-recovery operation should not involve any data");    control_endpoint->buffer        = class_reply;    if (!pool[req->index_lo].running) {        // Actually, this particular thread has terminated so no recovery is needed.        control_endpoint->buffer_size   = 0;    } else {        buffer_index    = 0;        pack_usbtest_recovery(&(pool[req->index_lo].test.recovery), class_reply, &buffer_index);        control_endpoint->buffer_size   = buffer_index;    }        return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  perform recovery                                         */// The host has identified a course of action that could unlock a thread// on the host-side that is currently blocked performing a USB operation.// Typically this involves either sending or accepting some data. If the// endpoint is still locked, in other words if there is a still a local// thread attempting to communicate on the specified endpoint, then// things are messed up: both sides are trying to communicate, but nothing// is happening. The eCos USB API is such that attempting multiple// concurrent operations on a single endpoint is disallowed, so// the recovery request has to be ignored. If things do not sort themselves// out then the whole test run will have to be aborted.// A dummy completion function for when a recovery operation has completed.static voidrecovery_callback(void* callback_arg, int transferred){    CYG_UNUSED_PARAM(void*, callback_arg);    CYG_UNUSED_PARAM(int, transferred);}    static usbs_control_returnhandle_perform_recovery(usb_devreq* req){    int                 buffer_index;    int                 endpoint_number;    int                 endpoint_direction;    UsbTest_Recovery    recovery;        CYG_ASSERT(current_tests_terminated, "Recovery should only be attempted when the terminated flag is set");    CYG_ASSERT(running, "If there are no tests running then recovery is impossible");    CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));    CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));    CYG_ASSERT(12 == class_request_size, "A perform-recovery operation requires recovery data");    buffer_index = 0;    unpack_usbtest_recovery(&recovery, class_request, &buffer_index);    endpoint_number     = recovery.endpoint & ~USB_DEVREQ_DIRECTION_MASK;    endpoint_direction  = recovery.endpoint & USB_DEVREQ_DIRECTION_MASK;    if (!is_endpoint_locked(endpoint_number, endpoint_direction)) {        // Locking the endpoint here would be good, but the endpoint would then        // have to be unlocked again - probably in the recovery callback.        // This complication is ignored for now.        if (USB_ENDPOINT_DESCRIPTOR_ATTR_BULK == recovery.protocol) {            int ep_index = lookup_endpoint(endpoint_number, endpoint_direction, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK);            CYG_ASSERTC(-1 != ep_index);            if (USB_DEVREQ_DIRECTION_IN == endpoint_direction) {                // The host wants some data. Supply it. A single byte will do fine to                // complete the transfer.                usbs_start_tx_buffer((usbs_tx_endpoint*) usbs_testing_endpoints[ep_index].endpoint,                                     recovery_buffer, 1, &recovery_callback, (void*) 0);            } else {                // The host is trying to send some data. Accept all of it.                usbs_start_rx_buffer((usbs_rx_endpoint*) usbs_testing_endpoints[ep_index].endpoint,                                     recovery_buffer, recovery.size, &recovery_callback, (void*) 0);            }        }        // No support for isochronous or interrupt transfers yet.        // handle_reserved_control_messages() should generate stalls which        // have the desired effect.    }        return USBS_CONTROL_RETURN_HANDLED;}/*}}}*//*{{{  get result                                               */// Return the result of one the tests. This can be a single

⌨️ 快捷键说明

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