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

📄 usbtarget.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*{{{  Banner                                                   *//*=================================================================////        target.c////        USB testing - target-side////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// This program performs appropriate USB initialization and initializes// itself as a specific type of USB peripheral, Red Hat eCos testing.// There is no actual host-side device driver for this, instead there is// a test application which performs ioctl's on /proc/bus/usb/... and// makes appropriate functionality available to a Tcl script.//// Author(s):     bartv// Date:          2001-07-04//####DESCRIPTIONEND####//==========================================================================*//*}}}*//*{{{  #include's                                               */#include <stdio.h>#include <cyg/infra/cyg_ass.h>#include <cyg/infra/diag.h>#include <cyg/kernel/kapi.h>#include <cyg/hal/hal_arch.h>#include <cyg/io/io.h>#include <cyg/io/usb/usbs.h>#include <cyg/infra/testcase.h>#include "protocol.h"/*}}}*//*{{{  Statics                                                  */// ----------------------------------------------------------------------------// Statics.// The number of endpoints supported by the device driver.static int number_endpoints     = 0;// The control endpointstatic usbs_control_endpoint* control_endpoint = (usbs_control_endpoint*) 0;// Buffers for incoming and outgoing data, and a length field.static unsigned char class_request[USBTEST_MAX_CONTROL_DATA + 1];static unsigned char class_reply[USBTEST_MAX_CONTROL_DATA + 1];static int           class_request_size  = 0;// This semaphore is used by DSRs to wake up the main thread when work has to// be done at thread level.static cyg_sem_t    main_wakeup;// And this function pointer identifies the work that has to be done.static void         (*main_thread_action)(void)  = (void (*)(void)) 0;// Is the system still busy processing a previous request? This variable is// checked in response to the synch request. It may get updated in// DSRs as well as at thread level, hence volatile.static volatile int idle    = 1;// Are any tests currently running?static int          running = 0;// Has the current batch of tests been terminated by the host? This// flag is checked by the various test handlers at appropriate// intervals, and helps to handle the case where one of the side has// terminated early because an error has been detected.static int          current_tests_terminated = 0;// A counter for the number of threads involved in the current batch of tests.static int          thread_counter    = 0;// An extra buffer for recovery operations, for example to accept and discard// data which the host is still trying to send.static unsigned char recovery_buffer[USBTEST_MAX_BULK_DATA + USBTEST_MAX_BULK_DATA_EXTRA];/*}}}*//*{{{  Logging                                                  */// ----------------------------------------------------------------------------// The target-side code can provide various levels of run-time logging.// Obviously the verbose flag cannot be controlled by a command-line// argument, but it can be set from inside gdb or alternatively by// a request from the host.//// NOTE: is printf() the best I/O routine to use here?static int verbose = 0;#define VERBOSE(_level_, _format_, _args_...)   \    do {                                        \        if (verbose >= _level_) {               \            diag_printf(_format_, ## _args_);        \        }                                       \    } while (0);/*}}}*//*{{{  Utilities                                                */// ----------------------------------------------------------------------------// A reimplementation of nanosleep, to avoid having to pull in the// POSIX compatibility testing for USB testing.static voidusbs_nanosleep(int delay){    cyg_tick_count_t ticks;    cyg_resolution_t resolution = cyg_clock_get_resolution(cyg_real_time_clock());    // (resolution.dividend/resolution.divisor) == nanoseconds/tick    //   e.g. 1000000000/100, i.e. 10000000 ns or 10 ms per tick    // So ticks = (delay * divisor) / dividend    //   e.g. (10000000 * 100) / 1000000000    // with a likely value of 0 for delays of less than the clock resolution,    // so round those up to one tick.    cyg_uint64 tmp = (cyg_uint64) delay;    tmp *= (cyg_uint64) resolution.divisor;    tmp /= (cyg_uint64) resolution.dividend;    ticks = (int) tmp;    if (0 != ticks) {        cyg_thread_delay(ticks);    }}// ----------------------------------------------------------------------------// Fix any problems in the driver-supplied endpoint data//// Maximum transfer sizes are limited not just by the capabilities// of the driver but also by the testing code itself, since e.g.// buffers for transfers are statically allocated.static voidfix_driver_endpoint_data(void){    int i;        for (i = 0; !USBS_TESTING_ENDPOINTS_IS_TERMINATOR(usbs_testing_endpoints[i]); i++) {        if (USB_ENDPOINT_DESCRIPTOR_ATTR_BULK == usbs_testing_endpoints[i].endpoint_type) {            if ((-1 == usbs_testing_endpoints[i].max_size) ||                (usbs_testing_endpoints[i].max_size > USBTEST_MAX_BULK_DATA)) {                usbs_testing_endpoints[i].max_size = USBTEST_MAX_BULK_DATA;            }        }    }}// ----------------------------------------------------------------------------// A heartbeat thread.//// USB tests can run for a long time with no traffic on the debug channel,// which can cause problems. To avoid problems it is possible to have a// heartbeat thread running in the background, sending output at one// second intervals.//// Depending on the configuration the output may still be line-buffered,// but that is still sufficient to keep things happy.static cyg_bool     heartbeat = false;static cyg_thread   heartbeat_data;static cyg_handle_t heartbeat_handle;static char         heartbeat_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];static voidheartbeat_function(cyg_addrword_t arg __attribute((unused))){    char* message = "alive\n";    int i;        for ( i = 0; ; i = (i + 1) % 6) {        usbs_nanosleep(1000000000);        if (heartbeat) {            diag_write_char(message[i]);        }    }}static voidstart_heartbeat(void){    cyg_thread_create( 0, &heartbeat_function, 0,                       "heartbeat", heartbeat_stack, CYGNUM_HAL_STACK_SIZE_TYPICAL,                       &heartbeat_handle, &heartbeat_data);    cyg_thread_resume(heartbeat_handle);}/*}}}*//*{{{  Endpoint usage                                           */// ----------------------------------------------------------------------------// It is important to keep track of which endpoints are currently in use,// because the behaviour of the USB I/O routines is undefined if there are// concurrent attempts to communicate on the same endpoint. Normally this is// not a problem because the host will ensure that a given endpoint is used// for only one endpoint at a time, but when performing recovery action it// is important that the system is sure that a given endpoint can be accessed// safely.static cyg_bool in_endpoint_in_use[16];static cyg_bool out_endpoint_in_use[16];// Lock the given endpoint. In theory this is only ever accessed from a single// test thread at a time, but just in case...static voidlock_endpoint(int endpoint, int direction){    CYG_ASSERTC((endpoint >=0) && (endpoint < 16));    CYG_ASSERTC((USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN == direction) || (USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT == direction));        cyg_scheduler_lock();    if (0 == endpoint) {        // Comms traffic on endpoint 0 is implemented using reserved control messages.        // It is not really possible to have concurrent IN and OUT operations because        // the two would interfere with each other.        CYG_ASSERTC(!in_endpoint_in_use[0] && !out_endpoint_in_use[0]);        in_endpoint_in_use[0]  = true;        out_endpoint_in_use[0] = true;    } else if (USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN == direction) {        CYG_ASSERTC(!in_endpoint_in_use[endpoint]);        in_endpoint_in_use[endpoint] = true;    } else {        CYG_ASSERTC(!out_endpoint_in_use[endpoint]);        out_endpoint_in_use[endpoint] = true;    }    cyg_scheduler_unlock();}static voidunlock_endpoint(int endpoint, int direction){    CYG_ASSERTC((endpoint >= 0) && (endpoint < 16));    CYG_ASSERTC((USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN == direction) || (USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT == direction));        if (0 == endpoint) {        CYG_ASSERTC(in_endpoint_in_use[0] && out_endpoint_in_use[0]);        in_endpoint_in_use[0]   = false;        out_endpoint_in_use[0]  = false;    } else if (USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN == direction) {        CYG_ASSERTC(in_endpoint_in_use[endpoint]);        in_endpoint_in_use[endpoint] = false;    } else {        CYG_ASSERTC(out_endpoint_in_use[endpoint]);        out_endpoint_in_use[endpoint] = false;    }}static cyg_boolis_endpoint_locked(int endpoint, int direction){    cyg_bool    result = false;        if (0 == endpoint) {        result = in_endpoint_in_use[0];    } else if (USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN == direction) {        result = in_endpoint_in_use[endpoint];    } else {        result = out_endpoint_in_use[endpoint];    }    return result;}// For a given endpoint number, direction and protocol, search through the table // supplied by the device driver of all available endpoints. This can be used// to e.g. get hold of the name of the devtab entry or a pointer to the endpoint// data structure itself.static intlookup_endpoint(int endpoint_number, int direction, int protocol){    int result = -1;    int i;    for (i = 0; !USBS_TESTING_ENDPOINTS_IS_TERMINATOR(usbs_testing_endpoints[i]); i++) {        if ((usbs_testing_endpoints[i].endpoint_type        == protocol)        &&            (usbs_testing_endpoints[i].endpoint_number      == endpoint_number) &&            (usbs_testing_endpoints[i].endpoint_direction   == direction)) {            result = i;            break;        }

⌨️ 快捷键说明

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