Network Device -- USB-ethernet support for the eCos TCP/IP Stack
Description
If the USB peripheral involves running the eCos TCP/IP stack and that
-stack needs to use USB-ethernet as a transport layer (or as one of the
-transports), then the USB-ethernet package can provide a suitable
-network device driver. It is still necessary for higher-level code to
-perform appropriate initialization by calling usbs_eth_init, but
-after that it will be the TCP/IP stack rather than application code
-that transmits or receives ethernet frames.
Not all peripherals involving the USB-ethernet package will require a
-TCP/IP stack. Hence the provision of the network device is controlled
-by a configuration option CYGPKG_USBS_ETHDRV. By
-default this will be enabled if the TCP/IP package
-CYGPKG_NET is loaded, and disabled otherwise.
There are a number of other configuration options related to the
-network device. CYGFUN_USBS_ETHDRV_STATISTICS
-determines whether or not the package will maintain statistics, mainly
-intended for SNMP: by default this will be enabled if the SNMP support
-package CYGPKG_SNMPAGENT is loaded, and disabled
-otherwise. The name of the ethernet device is controlled by
-CYGDATA_USBS_ETHDRV_NAME, and has a default value
-of either eth0 or eth1
-depending on whether or not there is another network device driver
-present in the configuration.
Usually eCos network device drivers default to using DHCP for
-obtaining necessary information such as IP addresses. This is not
-appropriate for USB-ethernet devices. On the host-side the
-USB-ethernet network device will not exist until the USB peripheral
-has been plugged in and communication has been established. Therefore
-any DHCP daemon on the host would not be listening on that network
-device at the point that eCos requests its IP and other information. A
-related issue is that the use of DHCP would imply the presence of a
-DHCP daemon on every affected host machine, as opposed to a single
-daemon (plus backups) for the network as a whole. For these reasons
-the USB-ethernet package precludes the use of DHCP as a way of setting
-the IP address, instead requiring alternatives such as manual
-configuration.
The USB-ethernet package provides two main modes of operation. In the
-first mode it provides a network device
-driver for use by a TCP/IP stack running inside the USB
-peripheral. All incoming ethernet packages should be passed up the
-TCP/IP stack, and only the stack will generate outgoing packets. Apart
-from initialization and possibly
-certain control operations,
-higher-level code will not interact with the USB-ethernet package
-directly.
In the second mode there is no TCP/IP stack running inside the USB
-peripheral. For example, a simple USB-ethernet converter has an
-ethernet chip and a USB port: ethernet packets received by the
-ethernet chip need to be forwarded to the USB host, and ethernet
-packets sent by the USB host need to be sent out of the ethernet chip.
-usbs_eth_start_rx and
-usbs_eth_start_tx allow for this lower-level
-access to the USB-ethernet package.
The two modes of operation are mutually exclusive. If the network
-device driver mode is enabled then application code should communicate
-at the TCP/IP level, and not by using the lower-level functions.
-Instead, it is the network device driver that will make use of these
-functions, and it assumes that it has exclusive access. The package
-does not perform any locking.
The transmit and receive functions work in much the same way. The
-first argument identifies the usbs_eth
-structure that should be used. For the majority of applications this
-will be usbs_eth0. The second argument specifies
-the location of the ethernet packet; outgoing for
-usbs_eth_start_tx and incoming for
-usbs_eth_start_rx. This buffer should correspond
-to the protocol:
Outgoing packets can consist of up to 1516 bytes, consisting of a
-two-byte header specific to USB-ethernet followed by a standard
-ethernet frame (a header with 6-byte destination address, 6-byte
-source address and a further two bytes, followed by a payload of
-up to 1500 bytes). The two-byte USB-ethernet header consists simply of
-the size of the ethernet frame, i.e. the size of the rest of the
-packet not including the USB-ethernet header, with the least
-significant byte first.
For incoming packets the supplied buffer should usually be at least
-1516 bytes. There may be special circumstances in which a smaller
-buffer might be safe; for example, if the host-side device driver is
-modified to support only smaller packets. Once the packet has been
-received the buffer will contain a two-byte header specific to
-USB-ethernet, followed by a normal ethernet frame. The header
-gives the size of the ethernet frame, excluding the header, with the
-least significant byte first.
Both usbs_eth_start_tx and
-usbs_eth_start_rx are asynchronous: the transfer
-is started and, some time later, a completion function will be invoked.
-The third and fourth arguments to both
-usbs_eth_start_tx and
-usbs_eth_start_rx supply the completion function
-and an argument to that function respectively. The completion function
-will be invoked with three arguments: a pointer to the
-usbs_eth data structure, usually
-usbs_eth0; the supplied completion data ; and a
-return code field. A negative value indicates that an error occurred,
-for example -EPIPE if the connection between USB
-host and peripheral has been broken, or -EAGAIN if
-an endpoint has been halted. A positive value indicates the total size
-of the transfer, which should correspond to the size in the
-USB-ethernet header plus an additional two bytes for the header
-itself.
If the data transfer is succesful then the completion function will
-typically be invoked in DSR context rather than in thread context,
-although this depends on the implementation of the underlying USB
-device driver. Therefore the completion function is restricted in what
-it can do; in particular, it must not make any calls that will or may
-block such as locking a mutex or allocating memory. The kernel
-documentation should be consulted for more details of DSR's and
-interrupt handling generally. Note that if the transfer finishes
-quickly then the completion function may be invoked before
-usbs_eth_start_rx or
-usbs_eth_start_tx returns. This is especially
-likely to happen if the current thread is descheduled after starting
-the data transfer but before returning from these functions.
For transmit operations, it is possible for
-usbs_eth_start_tx to invoke the completion
-function immediately. If there is no current connection between host
-and target then the transmit will fail immediately with
--EPIPE. In addition the USB-ethernet package will
-check the destination MAC address and make sure that the ethernet
-frame really is intended for the host: either it must be for the
-address specified in the initialization call usbs_eth_init, or
-it must be a broadcast packet, or the host must have enabled
-promiscuous mode.
Introduction -- eCos support for developing USB ethernet peripherals
Introduction
The eCos USB-ethernet package provides additional support for USB
-peripherals that involve some sort of ethernet-style network. This can
-be a traditional ethernet, or it can involve some other networking
-technology that uses ethernet frames as a unit of transfer. It
-provides functions to transfer ethernet frames over the USB bus,
-handles certain control messages from the host, and optionally it can
-provide a network device driver for use by the eCos TCP/IP stack.
-The package comes with an example host-side device driver.
The USB-ethernet package is not tied to any specific hardware. It
-requires the presence of USB hardware and a suitable device driver,
-but not all USB peripherals involve ethernet communications. Hence the
-configuration system cannot load the package automatically for
-specific targets, in the way that a USB device driver or an ethernet
-driver can be loaded automatically. Instead, the package has to be
-added explicitly. When using the command line tools this will involve
-an operation like the following:
$ ecosconfig add usbs_eth
Typically, this will automatically cause the USB device driver to
-become active. Loading the USB-ethernet package automatically provides
-functionality for initialization,
-data transfer, and the handling of
-control messages and state
-changes. If the current configuration includes the eCos TCP/IP stack
-then the network device driver
-support will be enabled as well by default, allowing the stack to
-exchange ethernet frames over the USB bus.
There is a USB standard for a class of communication devices including
-ethernet. The package does not implement this standard, due to
-limitations in the hardware for which the package was first developed.
-Instead, the package uses its own protocol between USB
-host device driver and the
-peripheral.
Usage Scenarios
The USB-ethernet package can be used several different scenarios. In
-a simple scenario, the peripheral serves only to connect the USB host
-to a suitable network:
After initialization, and once the USB connection between host and
-peripheral has been established, higher-level code needs to detect
-packets that are intended for the host, and to forward these. This can
-be achieved by the low-level usbs_eth_start_tx
-function. Similarly, higher-level code needs to detect packets coming
-from the host, using usbs_eth_start_rx, and to
-forward these using the real network. As far as the host is concerned
-it is connected directly to the network. In this scenario there is no
-confusion about addresses: there is a single MAC address for the
-host/peripheral combination, corresponding to the connection to the
-real network, and it is this address which should be supplied during
-initialization.
In a more complicated scenario, there is a TCP/IP stack running inside
-the peripheral.
This involves the USB-ethernet package providing a service both to the
-host and to the eCos TCP/IP stack. It achieves the latter by acting as
-an eCos network device. Typically, the TCP/IP stack will be configured
-to act as a network bridge. The USB peripheral needs to examine the
-packets arriving over the real network. Some of these packets will be
-intended for the host, while others will be intended for the
-peripheral itself. To distinguish between these two scenarios, two
-distinct MAC addresses are needed: one for the host, and one for the
-peripheral. Similarly, packets sent by the host may have to be
-forwarded via the real network, or they may be intended for the TCP/IP
-stack inside the peripheral. Packets generated inside the peripheral's
-TCP/IP stack may need to be sent via the real network or over the USB
-bus. The network bridge software will have to take care of all these
-possibilities. Unusually for a network bridge, one of the network
-segments being bridged will only ever have one machine attached.
There are other possible usage scenarios. For example, the peripheral
-might not be attached to a real network at all. Instead it could be
-the USB host that acts as a network bridge, allowing a TCP/IP stack
-inside the peripheral to communicate with the outside world. The
-various details will depend on the exact type of peripheral being
-developed.
Example Host-side Device Driver -- Provide host-side support for the eCos USB-ethernet package
Description
The USB-ethernet package is supplied with a single host-side device
-driver. This driver has been developed against the Linux kernel
-2.2.16-22, as shipped with Red Hat 7. The driver is provided as is and
-should not be considered production quality: for example it only
-checks for a bogus vendor id 0x4242 rather than an
-official vendor id supplied by the USB Implementers Forum. Also, if the
-peripheral involves multiple configurations or multiple interfaces, it
-will fail to detect this. However, the driver can be used for simple
-testing and as the basis of a full device driver. Details of the
-protocol used between host and peripheral can be found in the Communication Protocol section.
The host-side device driver can be found in the host subdirectory of the USB-ethernet
-package, specifically the file ecos_usbeth.c, and
-comes with a Makefile. Both files may need
-to be modified for specific applications. For example, the vendor id
-table ecos_usbeth_implementations may need to be
-updated for the specific USB peripheral being built. The
-Makefile assumes that the Linux kernel sources
-reside in /usr/src/linux, and
-that the kernel has already been configured and built. Assuming this
-is the case, the device driver can be built simply by invoking
-make with no additional arguments. This will result
-in a dynamically loadable kernel module,
-ecos_usbeth.o, in the current directory.
Note: As normal for Linux kernel builds, the generated files such as
-ecos_usbeth.o live in the same directory as the
-source tree. This is very different from eCos where the source tree
-(or component repository) is kept separate from any builds. There may
-be problems if the component repository is kept read-only or if it is
-put under source code control. Any such problems can be avoided by
-making a copy of the host
-subdirectory and building that copy.
Loading the kernel module into the current system requires root
-privileges. If the generic USB support is also a loadable module and
-has not been loaded already, this must happen first:
Depending on the host hardware, the uhci or
-usb-ohci modules may be more appropriate. Loading
-the generic USB module will typically result in a number of messages
-to the logfile /var/log/messages, giving details
-of the specific host-side hardware that has been detected plus any
-hubs. The next step is to load the USB-ethernet module:
# insmod ecos_usbeth.o
This should result in a number of additional diagnostics in the
-logfile:
If a suitable USB peripheral is now connected the host will detect
-this, assign an address in the local USB network, obtain enumeration
-data, and find a suitable device driver. Assuming the peripheral and
-device driver agree on the supported vendor ids, the
-ecos_usbeth.o module will be selected and this
-will be reported in the system log:
Apr 1 18:04:12 grumpy kernel: usb.c: USB new device connect, assigned device number 3
-Apr 1 18:04:12 grumpy kernel: eCos-based USB ethernet peripheral active at eth1
What can happen next depends very much on the software that is running
-on top of the USB-ethernet package inside the peripheral. For example,
-if there is a TCP/IP stack then it should be possible to bring up a
-network connection between host and peripheral using
-ifconfig.
\ No newline at end of file
Index: eth/slave/v2_0/doc/simple.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: eth/slave/v2_0/doc/simple.png
===================================================================
--- eth/slave/v2_0/doc/simple.png (revision 174)
+++ eth/slave/v2_0/doc/simple.png (nonexistent)
eth/slave/v2_0/doc/simple.png
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: eth/slave/v2_0/doc/makefile
===================================================================
--- eth/slave/v2_0/doc/makefile (revision 174)
+++ eth/slave/v2_0/doc/makefile (nonexistent)
@@ -1,55 +0,0 @@
-#=============================================================================
-#
-# makefile
-#
-# For building the USB-ethernet package documentation
-#
-#=============================================================================
-#####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####
-#
-# Author(s): bartv
-# Date: 2001-01-11
-#####DESCRIPTIONEND####
-#=============================================================================
-
-TOPLEVEL := ../../../../../..
-MAIN_SGML := usbseth.sgml
-MAIN_HTML := io-usb-slave-eth.html
-MAIN_PDF := io-usb-slave-eth.pdf
-OTHER_SGML :=
-PICTURES := simple tcpip
-
-include $(TOPLEVEL)/pkgconf/rules.doc
Index: eth/slave/v2_0/doc/simple.fig
===================================================================
--- eth/slave/v2_0/doc/simple.fig (revision 174)
+++ eth/slave/v2_0/doc/simple.fig (nonexistent)
@@ -1,23 +0,0 @@
-#FIG 3.2
-Portrait
-Center
-Inches
-Letter
-100.00
-Single
--2
-1200 2
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 600 600 2400 600 2400 2400 600 2400 600 600
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 2400 1500 4200 1500
-2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
- 4200 600 6000 600 6000 2400 4200 2400 4200 600
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 6000 1500 6600 1500
-2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
- 6600 300 6600 2700
-4 0 0 50 0 0 12 0.0000 4 135 675 3000 1425 USB bus\001
-4 0 0 50 0 0 12 0.0000 4 135 735 1200 1425 USB host\001
-4 0 0 50 0 0 12 0.0000 4 180 1155 4500 1425 USB peripheral\001
-4 0 0 50 0 0 12 0.0000 4 135 945 6150 2925 real network\001
Index: eth/slave/v2_0/doc/usbseth-control.html
===================================================================
--- eth/slave/v2_0/doc/usbseth-control.html (revision 174)
+++ eth/slave/v2_0/doc/usbseth-control.html (nonexistent)
@@ -1,309 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-USB-ethernet State Handling
eCos Support for Developing USB-ethernet Peripherals
void usbs_eth_state_change_handler(usbs_control_endpoint* ep0, void* callback_data, usbs_state_change change, int old_state);
void usbs_eth_disable(usbs_eth* usbseth>);
void usbs_eth_enable(usbs_eth* usbseth>);
Description
When the USB-ethernet package is initialized by a call to usbs_eth_init it
-installs usbs_eth_state_change_handler to handle
-USB state changes. This allows the package to detect when the
-connection between the host and the peripheral is established or
-broken, resulting in internal calls to
-usbs_eth_enable and
-usbs_eth_disable respectively. This is
-appropriate if no other code needs to access the USB device. However,
-if there is other code, either other USB-related packages or the
-application itself, that needs to perform I/O over the USB bus, then
-typically the USB-ethernet package should not have exclusive access to
-state change events. Instead, the assumption is that higher-level
-code, typically provided by the application, will install an
-alternative state change handler in the control endpoint data
-structure after the call to usbs_eth_init. This
-alternative handler will either chain into
-usbs_eth_state_change_handler when appropriate,
-or else it will invoke usbs_eth_enable and
-usbs_eth_disable directly. For further details of
-state change handlers and control endpoints generally, see the
-documentation for the common USB-slave package.
Similarly, usbs_eth_init will install
-usbs_eth_class_control_handler in the control
-endpoint data structure as the appropriate handler for class-specific
-USB control messages. This code will handle the ethernet-specific
-control messages , for example
-requests by the host to enable or disable promiscuous mode or to
-obtain the MAC address. If the USB device is not shared with any other
-code then this is both necessary and sufficient. However, if other code
-is involved and if that code also needs to process certain control
-messages, higher-level code should install its own handler and chain
-to the USB-ethernet one when appropriate. It should be noted that the
-request code is encoded in just a single byte, so there is a real
-possibility that exactly the same number will be used by different
-protocols for different requests. Any such problems will have to be
-identified and resolved by application developers, and may involve
-modifying the source code for the USB-ethernet package.
As an alternative to chaining the state change handler, higher-level
-code can instead call usbs_eth_disable and
-usbs_eth_enable directly. These functions may
-also be called if the USB-ethernet package should become inactive for
-reasons not related directly to events on the USB bus. The main effect
-of usbs_eth_enable is to restart receive
-operations and to allow transmits. The main effect of
-usbs_eth_disable is to block further transmits:
-any current receive operations need to be aborted at the USB level,
-for example by halting the appropriate endpoint.
\ No newline at end of file
Index: eth/slave/v2_0/doc/usbseth.sgml
===================================================================
--- eth/slave/v2_0/doc/usbseth.sgml (revision 174)
+++ eth/slave/v2_0/doc/usbseth.sgml (nonexistent)
@@ -1,810 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- eCos Support for Developing USB-ethernet Peripherals
-
-
-
-
-
-Introduction
-
-
-Introduction
-eCos support for developing USB ethernet peripherals
-
-
-Introduction
-
-The eCos USB-ethernet package provides additional support for USB
-peripherals that involve some sort of ethernet-style network. This can
-be a traditional ethernet, or it can involve some other networking
-technology that uses ethernet frames as a unit of transfer. It
-provides functions to transfer ethernet frames over the USB bus,
-handles certain control messages from the host, and optionally it can
-provide a network device driver for use by the eCos TCP/IP stack.
-The package comes with an example host-side device driver.
-
-
-The USB-ethernet package is not tied to any specific hardware. It
-requires the presence of USB hardware and a suitable device driver,
-but not all USB peripherals involve ethernet communications. Hence the
-configuration system cannot load the package automatically for
-specific targets, in the way that a USB device driver or an ethernet
-driver can be loaded automatically. Instead, the package has to be
-added explicitly. When using the command line tools this will involve
-an operation like the following:
-
-
-$ ecosconfig add usbs_eth
-
-
-Typically, this will automatically cause the USB device driver to
-become active. Loading the USB-ethernet package automatically provides
-functionality for initialization,
-data transfer, and the handling of
-control messages and state
-changes. If the current configuration includes the eCos TCP/IP stack
-then the network device driver
-support will be enabled as well by default, allowing the stack to
-exchange ethernet frames over the USB bus.
-
-
-There is a USB standard for a class of communication devices including
-ethernet. The package does not implement this standard, due to
-limitations in the hardware for which the package was first developed.
-Instead, the package uses its own protocol between USB
-host device driver and the
-peripheral.
-
-
-
-Usage Scenarios
-
-The USB-ethernet package can be used several different scenarios. In
-a simple scenario, the peripheral serves only to connect the USB host
-to a suitable network:
-
-
-
-
-
-
-
-
-
-After initialization, and once the USB connection between host and
-peripheral has been established, higher-level code needs to detect
-packets that are intended for the host, and to forward these. This can
-be achieved by the low-level usbs_eth_start_tx
-function. Similarly, higher-level code needs to detect packets coming
-from the host, using usbs_eth_start_rx, and to
-forward these using the real network. As far as the host is concerned
-it is connected directly to the network. In this scenario there is no
-confusion about addresses: there is a single MAC address for the
-host/peripheral combination, corresponding to the connection to the
-real network, and it is this address which should be supplied during
-initialization.
-
-
-In a more complicated scenario, there is a TCP/IP stack running inside
-the peripheral.
-
-
-
-
-
-
-
-
-
-This involves the USB-ethernet package providing a service both to the
-host and to the eCos TCP/IP stack. It achieves the latter by acting as
-an eCos network device. Typically, the TCP/IP stack will be configured
-to act as a network bridge. The USB peripheral needs to examine the
-packets arriving over the real network. Some of these packets will be
-intended for the host, while others will be intended for the
-peripheral itself. To distinguish between these two scenarios, two
-distinct MAC addresses are needed: one for the host, and one for the
-peripheral. Similarly, packets sent by the host may have to be
-forwarded via the real network, or they may be intended for the TCP/IP
-stack inside the peripheral. Packets generated inside the peripheral's
-TCP/IP stack may need to be sent via the real network or over the USB
-bus. The network bridge software will have to take care of all these
-possibilities. Unusually for a network bridge, one of the network
-segments being bridged will only ever have one machine attached.
-
-
-There are other possible usage scenarios. For example, the peripheral
-might not be attached to a real network at all. Instead it could be
-the USB host that acts as a network bridge, allowing a TCP/IP stack
-inside the peripheral to communicate with the outside world. The
-various details will depend on the exact type of peripheral being
-developed.
-
-
-
-
-
-
-
-
-
-Initializing the USB-ethernet Package
-
-
-usbs_eth_init
-Initializing the USB-ethernet Package
-
-
-
-
-
-#include <cyg/io/usb/usbs_eth.h>
-
-
-void usbs_eth_init
-usbs_eth* usbeth
-usbs_control_endpoint* ep0
-usbs_rx_endpoint* ep1
-usbs_tx_endpoint* ep2
-unsigned char* mac_address
-
-
-
-
-Description
-
-The USB-ethernet package is not tied to any specific hardware. It
-requires certain functionality: there must be USB-slave hardware
-supported by a device driver; there must also be two endpoints for
-bulk transfers between host and peripheral, one for each direction;
-there must also be a control endpoint, although of course that is
-implicit with any USB hardware.
-
-
-However, USB-slave hardware may well provide more endpoints than the
-minimum required for ethernet support. Some of those endpoints might
-be used by other packages, while other endpoints might be used
-directly by the application, or might not be needed for the peripheral
-being built. There is also the possibility of a USB peripheral that
-supports multiple configurations, with the ethernet support active in
-only some of those configurations. The USB-ethernet package has no
-knowledge about any of this, so it relies on higher-level code to tell
-it which endpoints should be used and other information. This is the
-purpose of the usbs_eth_init function.
-
-
-The first argument identifies the specific
-usbs_eth data structure that is affected. It
-is expected that the vast majority of affected applications will only
-provide a single USB-ethernet device to a single host, and the package
-automatically provides a suitable data structure
-usbs_eth0 to support this. If multiple
-usbs_eth structures are needed for some
-reason then these need to be instantiated by other code, and each one
-needs to be initialised by a call to
-usbs_eth_init().
-
-
-The next three arguments identify the endpoints that should be used
-for USB communications: a control endpoint, a receive endpoint for
-ethernet packets coming from the host to the peripheral, and a
-transmit endpoint for ethernet packets going in the other direction.
-Obviously all three endpoints should be provided by the same USB
-hardware. The USB-ethernet package assumes that it has sole access to
-the receive and transmit endpoints, subject to the use of
-usbs_eth_disable and
-usbs_eth_enable control functions. The package
-also assumes that no other code is interested in USB state changes or
-class control messages: it installs handlers
-usbs_eth_state_change_handler
-and
-usbs_eth_class_control_handler
-in the control endpoint. If any other code does need to handle USB
-state changes or class control messages then replacement handlers
-should be installed after the call to
-usbs_eth_init, and those replacements should
-invoke the USB-ethernet ones when appropriate.
-
-
-The final argument to usbs_eth_init specifies
-the MAC address (or Ethernet Station Address) that should be provided
-to the host-side device driver. Since the USB-ethernet package does not
-interact directly with a real ethernet device it cannot obtain the MAC
-address from any hardware. Instead, it must be supplied by higher-level
-code. The details depend on the scenario in which the
-USB-ethernet package is being used.
-
-
-The call to usbs_eth_init should normally happen
-after the enumeration data has been provided but before the underlying
-USB device driver has been started. If the USB device were to be
-started first then a connection between host and peripheral could be
-established immediately, and the host-side device driver would attempt
-to contact the USB-ethernet package for information such as the MAC
-address.
-
-
-int
-main(int argc, char** argv)
-{
- unsigned char host_MAC[6] = { 0x40, 0x5d, 0x90, 0xa9, 0xbc, 0x02 };
-
- usbs_sa11x0_ep0.enumeration_data = &usb_enum_data;
- …
- usbs_eth_init(&usbs_eth0, &usbs_sa11x0_ep0, &usbs_sa11x0_ep1, &usbs_sa11x0_ep2, host_MAC);
- …
- usbs_start(&usbs_sa11x0_ep0);
- …
-}
-
-
-
-
-
-
-
-
-
-
-USB-ethernet Data Transfers
-
-
-USB-ethernet Data Transfers
-Exchanging ethernet packets with the USB host
-
-
-
-
-
-#include <cyg/io/usb/usbs_eth.h>
-
-
-
-void usbs_eth_start_rx
-usbs_eth* usbseth
-unsigned char* buffer
-void (*)(usbs_eth*, void*, int) complete_fn
-void* complete_data
-
-
-
-void usbs_eth_start_tx
-usbs_eth* usbseth
-unsigned char* buffer
-void (*)(usbs_eth*, void*, int) complete_fn
-void* complete_data
-
-
-
-
-
-Description
-
-The USB-ethernet package provides two main modes of operation. In the
-first mode it provides a network device
-driver for use by a TCP/IP stack running inside the USB
-peripheral. All incoming ethernet packages should be passed up the
-TCP/IP stack, and only the stack will generate outgoing packets. Apart
-from initialization and possibly
-certain control operations,
-higher-level code will not interact with the USB-ethernet package
-directly.
-
-
-In the second mode there is no TCP/IP stack running inside the USB
-peripheral. For example, a simple USB-ethernet converter has an
-ethernet chip and a USB port: ethernet packets received by the
-ethernet chip need to be forwarded to the USB host, and ethernet
-packets sent by the USB host need to be sent out of the ethernet chip.
-usbs_eth_start_rx and
-usbs_eth_start_tx allow for this lower-level
-access to the USB-ethernet package.
-
-
-The two modes of operation are mutually exclusive. If the network
-device driver mode is enabled then application code should communicate
-at the TCP/IP level, and not by using the lower-level functions.
-Instead, it is the network device driver that will make use of these
-functions, and it assumes that it has exclusive access. The package
-does not perform any locking.
-
-
-The transmit and receive functions work in much the same way. The
-first argument identifies the usbs_eth
-structure that should be used. For the majority of applications this
-will be usbs_eth0. The second argument specifies
-the location of the ethernet packet; outgoing for
-usbs_eth_start_tx and incoming for
-usbs_eth_start_rx. This buffer should correspond
-to the protocol:
-
-
-
-
-Outgoing packets can consist of up to 1516 bytes, consisting of a
-two-byte header specific to USB-ethernet followed by a standard
-ethernet frame (a header with 6-byte destination address, 6-byte
-source address and a further two bytes, followed by a payload of
-up to 1500 bytes). The two-byte USB-ethernet header consists simply of
-the size of the ethernet frame, i.e. the size of the rest of the
-packet not including the USB-ethernet header, with the least
-significant byte first.
-
-
-
-
-For incoming packets the supplied buffer should usually be at least
-1516 bytes. There may be special circumstances in which a smaller
-buffer might be safe; for example, if the host-side device driver is
-modified to support only smaller packets. Once the packet has been
-received the buffer will contain a two-byte header specific to
-USB-ethernet, followed by a normal ethernet frame. The header
-gives the size of the ethernet frame, excluding the header, with the
-least significant byte first.
-
-
-
-
-Both usbs_eth_start_tx and
-usbs_eth_start_rx are asynchronous: the transfer
-is started and, some time later, a completion function will be invoked.
-The third and fourth arguments to both
-usbs_eth_start_tx and
-usbs_eth_start_rx supply the completion function
-and an argument to that function respectively. The completion function
-will be invoked with three arguments: a pointer to the
-usbs_eth data structure, usually
-usbs_eth0; the supplied completion data ; and a
-return code field. A negative value indicates that an error occurred,
-for example -EPIPE if the connection between USB
-host and peripheral has been broken, or -EAGAIN if
-an endpoint has been halted. A positive value indicates the total size
-of the transfer, which should correspond to the size in the
-USB-ethernet header plus an additional two bytes for the header
-itself.
-
-
-If the data transfer is succesful then the completion function will
-typically be invoked in DSR context rather than in thread context,
-although this depends on the implementation of the underlying USB
-device driver. Therefore the completion function is restricted in what
-it can do; in particular, it must not make any calls that will or may
-block such as locking a mutex or allocating memory. The kernel
-documentation should be consulted for more details of DSR's and
-interrupt handling generally. Note that if the transfer finishes
-quickly then the completion function may be invoked before
-usbs_eth_start_rx or
-usbs_eth_start_tx returns. This is especially
-likely to happen if the current thread is descheduled after starting
-the data transfer but before returning from these functions.
-
-
-For transmit operations, it is possible for
-usbs_eth_start_tx to invoke the completion
-function immediately. If there is no current connection between host
-and target then the transmit will fail immediately with
--EPIPE. In addition the USB-ethernet package will
-check the destination MAC address and make sure that the ethernet
-frame really is intended for the host: either it must be for the
-address specified in the initialization call usbs_eth_init, or
-it must be a broadcast packet, or the host must have enabled
-promiscuous mode.
-
-
-
-
-
-
-
-
-
-
-USB-ethernet State Handling
-
-
-USB-ethernet State Handling
-Maintaining the USB-ethernet connection with the host
-
-
-
-
-
-#include <cyg/io/usb/usbs_eth.h>
-
-
-
-usbs_control_return usbs_eth_class_control_handler
-usbs_control_endpoint* ep0
-void* callback_data
-
-
-
-void usbs_eth_state_change_handler
-usbs_control_endpoint* ep0
-void* callback_data
-usbs_state_change change
-int old_state
-
-
-
-void usbs_eth_disable
-usbs_eth* usbseth>
-
-
-void usbs_eth_enable
-usbs_eth* usbseth>
-
-
-
-
-
-Description
-
-When the USB-ethernet package is initialized by a call to usbs_eth_init it
-installs usbs_eth_state_change_handler to handle
-USB state changes. This allows the package to detect when the
-connection between the host and the peripheral is established or
-broken, resulting in internal calls to
-usbs_eth_enable and
-usbs_eth_disable respectively. This is
-appropriate if no other code needs to access the USB device. However,
-if there is other code, either other USB-related packages or the
-application itself, that needs to perform I/O over the USB bus, then
-typically the USB-ethernet package should not have exclusive access to
-state change events. Instead, the assumption is that higher-level
-code, typically provided by the application, will install an
-alternative state change handler in the control endpoint data
-structure after the call to usbs_eth_init. This
-alternative handler will either chain into
-usbs_eth_state_change_handler when appropriate,
-or else it will invoke usbs_eth_enable and
-usbs_eth_disable directly. For further details of
-state change handlers and control endpoints generally, see the
-documentation for the common USB-slave package.
-
-
-Similarly, usbs_eth_init will install
-usbs_eth_class_control_handler in the control
-endpoint data structure as the appropriate handler for class-specific
-USB control messages. This code will handle the ethernet-specific
-control messages , for example
-requests by the host to enable or disable promiscuous mode or to
-obtain the MAC address. If the USB device is not shared with any other
-code then this is both necessary and sufficient. However, if other code
-is involved and if that code also needs to process certain control
-messages, higher-level code should install its own handler and chain
-to the USB-ethernet one when appropriate. It should be noted that the
-request code is encoded in just a single byte, so there is a real
-possibility that exactly the same number will be used by different
-protocols for different requests. Any such problems will have to be
-identified and resolved by application developers, and may involve
-modifying the source code for the USB-ethernet package.
-
-
-As an alternative to chaining the state change handler, higher-level
-code can instead call usbs_eth_disable and
-usbs_eth_enable directly. These functions may
-also be called if the USB-ethernet package should become inactive for
-reasons not related directly to events on the USB bus. The main effect
-of usbs_eth_enable is to restart receive
-operations and to allow transmits. The main effect of
-usbs_eth_disable is to block further transmits:
-any current receive operations need to be aborted at the USB level,
-for example by halting the appropriate endpoint.
-
-
-
-
-
-
-
-
-
-
-Network Device for the eCos TCP/IP Stack
-
-
-Network Device
-USB-ethernet support for the eCos TCP/IP Stack
-
-
-Description
-
-If the USB peripheral involves running the eCos TCP/IP stack and that
-stack needs to use USB-ethernet as a transport layer (or as one of the
-transports), then the USB-ethernet package can provide a suitable
-network device driver. It is still necessary for higher-level code to
-perform appropriate initialization by calling usbs_eth_init, but
-after that it will be the TCP/IP stack rather than application code
-that transmits or receives ethernet frames.
-
-
-Not all peripherals involving the USB-ethernet package will require a
-TCP/IP stack. Hence the provision of the network device is controlled
-by a configuration option CYGPKG_USBS_ETHDRV. By
-default this will be enabled if the TCP/IP package
-CYGPKG_NET is loaded, and disabled otherwise.
-
-
-There are a number of other configuration options related to the
-network device. CYGFUN_USBS_ETHDRV_STATISTICS
-determines whether or not the package will maintain statistics, mainly
-intended for SNMP: by default this will be enabled if the SNMP support
-package CYGPKG_SNMPAGENT is loaded, and disabled
-otherwise. The name of the ethernet device is controlled by
-CYGDATA_USBS_ETHDRV_NAME, and has a default value
-of either eth0 or eth1
-depending on whether or not there is another network device driver
-present in the configuration.
-
-
-Usually eCos network device drivers default to using DHCP for
-obtaining necessary information such as IP addresses. This is not
-appropriate for USB-ethernet devices. On the host-side the
-USB-ethernet network device will not exist until the USB peripheral
-has been plugged in and communication has been established. Therefore
-any DHCP daemon on the host would not be listening on that network
-device at the point that eCos requests its IP and other information. A
-related issue is that the use of DHCP would imply the presence of a
-DHCP daemon on every affected host machine, as opposed to a single
-daemon (plus backups) for the network as a whole. For these reasons
-the USB-ethernet package precludes the use of DHCP as a way of setting
-the IP address, instead requiring alternatives such as manual
-configuration.
-
-
-
-
-
-
-
-
-
-
-Example Host-side Device Driver
-
-
-Example Host-side Device Driver
-Provide host-side support for the eCos USB-ethernet package
-
-
-Description
-
-The USB-ethernet package is supplied with a single host-side device
-driver. This driver has been developed against the Linux kernel
-2.2.16-22, as shipped with Red Hat 7. The driver is provided as is and
-should not be considered production quality: for example it only
-checks for a bogus vendor id 0x4242 rather than an
-official vendor id supplied by the USB Implementers Forum. Also, if the
-peripheral involves multiple configurations or multiple interfaces, it
-will fail to detect this. However, the driver can be used for simple
-testing and as the basis of a full device driver. Details of the
-protocol used between host and peripheral can be found in the Communication Protocol section.
-
-
-The host-side device driver can be found in the host subdirectory of the USB-ethernet
-package, specifically the file ecos_usbeth.c, and
-comes with a Makefile. Both files may need
-to be modified for specific applications. For example, the vendor id
-table ecos_usbeth_implementations may need to be
-updated for the specific USB peripheral being built. The
-Makefile assumes that the Linux kernel sources
-reside in /usr/src/linux, and
-that the kernel has already been configured and built. Assuming this
-is the case, the device driver can be built simply by invoking
-make with no additional arguments. This will result
-in a dynamically loadable kernel module,
-ecos_usbeth.o, in the current directory.
-
-
-
-As normal for Linux kernel builds, the generated files such as
-ecos_usbeth.o live in the same directory as the
-source tree. This is very different from eCos where the source tree
-(or component repository) is kept separate from any builds. There may
-be problems if the component repository is kept read-only or if it is
-put under source code control. Any such problems can be avoided by
-making a copy of the host
-subdirectory and building that copy.
-
-
-
-Loading the kernel module into the current system requires root
-privileges. If the generic USB support is also a loadable module and
-has not been loaded already, this must happen first:
-
-
-# insmod usb-uhci
-Using /lib/modules/2.2.16-22/usb/usb-uhci.o
-
-
-Depending on the host hardware, the uhci or
-usb-ohci modules may be more appropriate. Loading
-the generic USB module will typically result in a number of messages
-to the logfile /var/log/messages, giving details
-of the specific host-side hardware that has been detected plus any
-hubs. The next step is to load the USB-ethernet module:
-
-
-# insmod ecos_usbeth.o
-
-
-This should result in a number of additional diagnostics in the
-logfile:
-
-
-Apr 1 18:01:08 grumpy kernel: eCos USB-ethernet device driver
-Apr 1 18:01:08 grumpy kernel: usb.c: registered new driver ecos_usbeth
-
-
-If a suitable USB peripheral is now connected the host will detect
-this, assign an address in the local USB network, obtain enumeration
-data, and find a suitable device driver. Assuming the peripheral and
-device driver agree on the supported vendor ids, the
-ecos_usbeth.o module will be selected and this
-will be reported in the system log:
-
-
-Apr 1 18:04:12 grumpy kernel: usb.c: USB new device connect, assigned device number 3
-Apr 1 18:04:12 grumpy kernel: eCos-based USB ethernet peripheral active at eth1
-
-
-What can happen next depends very much on the software that is running
-on top of the USB-ethernet package inside the peripheral. For example,
-if there is a TCP/IP stack then it should be possible to bring up a
-network connection between host and peripheral using
-ifconfig.
-
-
-
-
-
-
-
-
-
-
-Communication Protocol
-
-
-Communication Protocol
-Protocol used between the host-side device driver and the eCos
-USB-ethernet package
-
-
-Description
-
-There is a USB standard for the protocol to be used between the host
-and a class of communication devices, including ethernet. However, the
-eCos USB-ethernet package does not implement this protocol: the target
-hardware for which the package was first developed had certain
-limitations, and could not implement the standard. Instead, the package
-implements a simple new protocol.
-
-
-A USB-ethernet peripheral involves bulk transfers on two endpoints:
-one endpoint will be used for packets from host to peripheral and the
-other will be used for the opposite direction. Transfers in both
-directions are variable length, with a lower limit of 16 bytes and an
-upper limit of 1516 bytes. The first two bytes of each transfer
-constitute a header specific to USB-ethernet. The next 14 bytes form
-the normal header for an ethernet frame: destination MAC address,
-source MAC address, and a protocol field. The remaining data, up to
-1500 bytes, are the payload. The first two bytes give the size of the
-ethernet frame, least significant byte first, with a value between 14
-and 1514.
-
-
-For example an ARP request from host to peripheral involves an
-ethernet frame of 42 bytes (0x002A), with the usual 14-byte header and
-a 28-byte payload. The destination is the broadcast address
-0xFFFFFFFFFFFF. The source depends on the MAC address specified for
-the host in the call to usbs_eth_init, e.g.
-0x405D90A9BC02. The remaining data is as specified by the appropriate
-IETF RFC's. The actual bulk
-USB transfer involves the following sequence of 44 bytes:
-
-
-2a 00 ff ff ff ff ff ff 40 5d 90 a9 bc 02 08 06
-00 01 08 00 06 04 00 01 40 5d 90 a9 bc 02 0a 00
-00 01 00 00 00 00 00 00 0a 00 00 02
-
-
-In addition there are two control messages. These will be sent by the
-host to endpoint 0, the control endpoint, and by default they will
-be handled by
-usbs_eth_class_control_handler. If class-specific
-control messages are intercepted by other code then it is the
-responsibility of that code to invoke the USB-ethernet handler when
-appropriate.
-
-
-The first control message can be used by the host to obtain a MAC
-address:
-
-
-#define ECOS_USBETH_CONTROL_GET_MAC_ADDRESS 0x01
-
-
-The control message's type field should specify IN as the direction.
-The request field should be 0x01. The length fields
-should specify a size of 6 bytes. The remaining fields of the control
-message will be ignored by the USB-ethernet package. The response
-consists of the 6-byte MAC address supplied by the initialization call
-usbs_eth_init.
-
-
-The second control message can be used by the host to enable or
-disable promiscuous mode.
-
-
-#define ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE 0x02
-
-
-This control message involves no further data so the length field
-should be set to 0. The value field should be non-zero to enable
-promiscuous mode, zero to disable it. The request field should be
-0x02. The remaining fields in the control message
-will be ignored. It is the responsibility of the host-side device
-driver to keep track of whether or not promiscuous mode is currently
-enabled. It will be disabled when the peripheral changes to
-Configured state, typically at the point where the host-side device
-driver has been activated.
-
-
-
-
-
-
-
-
-
Index: eth/slave/v2_0/ChangeLog
===================================================================
--- eth/slave/v2_0/ChangeLog (revision 174)
+++ eth/slave/v2_0/ChangeLog (nonexistent)
@@ -1,150 +0,0 @@
-2003-03-23 Iztok Zupet
-
- * doc/usbseth.sgml: Remove .eps and .gif and introduce .png for
- for PDF output.
- * doc/simple.gif, doc/tcpip.gif: Delete.
- * doc/simple.png, doc/tcpip.png: New files to replace GIFs.
-
-2003-02-25 Jonathan Larmour
-
- * doc/usbseth.sgml: Declare as not to get
- correct TOC numbering.
-
-2003-02-24 Jonathan Larmour
-
- * cdl/usbs_eth.cdl: Fix doc link.
-
- * doc/usbseth.sgml: Comment out DOCTYPE for now to allow building
- with standard doc build.
-
-2002-07-26 David Smith
-
- * host/ecos_usbeth.c (ecos_usbeth_probe):
- Two changes to the code that checks to see if this is the correct
- driver for the USB peripheral that was just loaded. Fixed a bug
- that was comparing the product id of the peripheral to the vendor
- id. Supports multiple implementations (vendor id/product id sets)
- so that the same driver could be used for several devices.
-
-2001-07-10 Bart Veer
-
- * doc/usbseth.sgml, doc/*.html:
- Document the below changes.
-
- * cdl/usbs_eth.cdl:
- The USB-ethernet device now registers itself as either eth0 or
- eth1 by default, depending on what else is present in the system.
- Also bootp/dhcp support is prohibited for this network device on
- the ground that it is rather unlikely that a host will provide
- a dhcp service for a network device that does not exist until the
- host-target connection has been fully established.
-
-
-2001-07-02 Bart Veer
-
- * host/ecos_usbeth.c (ecos_usbeth_probe):
- Determine the endpoints to use for transmits and receives
- from the descriptors supplied by the device.
-
-2001-06-28 Bart Veer
-
- * include/usbs_eth.h, src/usbsethdrv.c, src/usbseth.c:
- Align receive boundaries to cacheline boundaries, and
- always transfer a multiple of the cacheline size. This
- avoids problems with some USB device drivers.
-
-2001-05-21 Bart Veer
-
- * host/ecos_usbeth.c (ecos_usbeth_start_tx):
- Cope with targets that have problems receiving zero-byte
- packets.
-
-2001-02-02 Bart Veer
-
- * cdl/usbs_eth.cdl:
- Add doc property to point at the HTML
-
- * doc/usbseth.sgml, doc/*.html:
- Incorporate changes from docs department, regenerate HTML
-
-2001-01-26 Bart Veer
-
- * src/usbsethdrv.c (usbs_ethdrv_ioctl):
- Change chipset specification to null, since there is no real
- hardware involved, plus SNMP cleanup.
-
-2001-01-22 Bart Veer
-
- * doc/usbseth.sgml, doc/makefile, doc/simple.fig, doc/tcpip.fig:
- Added documentation.
-
-2000-12-15 Bart Veer
-
- * src/usbsethdrv.c:
- Enable poll functions.
-
-2000-11-29 Bart Veer
-
- * host/ecos_usbeth.c:
- Remove debugging and fix the MTU
-
-2000-11-28 Bart Veer
-
- * cdl/usbs_eth.cdl
- * include/usbs_eth.h
- * src/usbseth.c
- * src/usbsethdrv
- Clean-up, adding missing functionality such as SNMP support,
- update to current USB API.
-
-2000-11-24 Bart Veer
-
- * host/ecos_usbeth.c:
- Ignore runt packets, cope with the confusion between
- CRC errors and timeouts.
-
- * include/usbs_eth.h, src/usbseth.c
- Clean up alignments.
-
-2000-11-22 Bart Veer
-
- * include/usbs_eth.h: Fix nested #include protection
-
-2000-11-21 Bart Veer
-
- * First check-in of eCos USB support.
-
-//===========================================================================
-//####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####
-//===========================================================================
Index: eth/slave/v2_0/src/usbsethdrv.c
===================================================================
--- eth/slave/v2_0/src/usbsethdrv.c (revision 174)
+++ eth/slave/v2_0/src/usbsethdrv.c (nonexistent)
@@ -1,616 +0,0 @@
-//==========================================================================
-//
-// usbethdrv.c
-//
-// Network device driver for USB-ethernet devices.
-//
-//==========================================================================
-//####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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-10-04
-//
-//####DESCRIPTIONEND####
-//==========================================================================
-
-#include
-#include
-#include
-#include
-
-#define __ECOS 1
-#include
-#include
-#include
-
-#include
-#include
-
-// ----------------------------------------------------------------------------
-// The network driver data structure.
-ETH_DRV_SC(usbs_eth_sc0,
- (void*) &usbs_eth0,
- CYGDAT_USBS_ETHDRV_NAME,
- usbs_ethdrv_start,
- usbs_ethdrv_stop,
- usbs_ethdrv_ioctl,
- usbs_ethdrv_can_send,
- usbs_ethdrv_send,
- usbs_ethdrv_recv,
- usbs_ethdrv_deliver,
- usbs_ethdrv_poll,
- usbs_ethdrv_intvector);
-
-NETDEVTAB_ENTRY(usbs_eth_netdev0,
- "usbs_eth0",
- usbs_ethdrv_init,
- &usbs_eth_sc0);
-
-// ----------------------------------------------------------------------------
-// Statics gathering. The following macro can be used to increment a
-// statistic without having to use a #ifdef for the statistics
-// configuration option everywhere.
-#ifdef CYGFUN_USBS_ETHDRV_STATISTICS
-# define INCR_STAT(a) \
- CYG_MACRO_START \
- (a) += 1; \
- CYG_MACRO_END
-#else
-# define INCR_STAT(a) CYG_EMPTY_STATEMENT
-#endif
-
-// Various constants related to SNMP statistics. It is not clear
-// what these are all for.
-#ifdef CYGFUN_USBS_ETHDRV_STATISTICS
-# define CYGDAT_USBS_ETHDRV_DESCRIPTION "eCos USB ethernet device"
-#endif
-// ----------------------------------------------------------------------------
-// Utility functions.
-//
-// The TCP/IP stack works in terms of scatter/gather buffers. USB tends to
-// involve DMA operations so it is more convenient to work in terms of
-// 1514 byte flat buffers. Actually, the first two bytes of the buffer
-// are used to hold the ethernet frame size to work around restrictions
-// with certain hardware implementations of USB that may be unable to
-// transfer certain packet sizes.
-
-static bool
-scatter(unsigned char* buf, struct eth_drv_sg* sg, int sg_len)
-{
- unsigned int size;
-
- size = buf[0] | (buf[1] << 8);
- buf++; buf++;
-
- CYG_ASSERT((size >= CYGNUM_USBS_ETH_MIN_FRAME_SIZE) && (size <= CYGNUM_USBS_ETH_MAX_FRAME_SIZE),\
- "ethernet frame size limits must be observed");
-
- while ((size > 0) && (sg_len > 0)) {
- if (size > sg->len) {
- memcpy((void*) sg->buf, buf, sg->len);
- buf += sg->len;
- size -= sg->len;
- sg++;
- sg_len--;
- } else {
- memcpy((void*) sg->buf, buf, size);
- size = 0;
- }
- }
-
- return 0 == size;
-}
-
-static bool
-gather(unsigned char* buf, unsigned int size, struct eth_drv_sg* sg, int sg_len)
-{
- unsigned int left = size;
- unsigned char* base = buf;
-
- buf++; buf++;
- while ((left > 0) && (sg_len > 0)) {
- if (left > sg->len) {
- memcpy(buf, (void*) sg->buf, sg->len);
- buf += sg->len;
- left -= sg->len;
- sg++;
- sg_len--;
- } else {
- memcpy(buf, (void*) sg->buf, left);
- left = 0;
- }
- }
- size = size - left;
- base[0] = size & 0x00FF;
- base[1] = (size >> 8) & 0x00FF;
-
- return 0 == left;
-}
-
-
-// ----------------------------------------------------------------------------
-// usbs_ethdrv_init()
-//
-// This function is called during system initialization to decide
-// whether or not this particular network device is usable. For
-// USB-ethernet this is problematical, the device is only really
-// usable once both sides have come up. The typical sequence
-// of events is something like:
-//
-// 1) the eCos peripheral is powered up. Static constructors are
-// run resulting in basic initialization.
-//
-// 2) the eCos TCP/IP stack initialization happens. Roughly in
-// parallel the eCos USB slave side is initialized as well,
-// i.e. enumeration data is supplied to control endpoints,
-// endpoints are associated with application classes, and so
-// on. The relative order of TCP/IP and USB initialization is
-// not particularly important.
-//
-// It is the TCP/IP stack's initialization code that will
-// invoke usbs_eth_init().
-//
-// 3) host-side USB detects that the eCos peripheral has been
-// connected or powered up. It goes through the enumeration
-// process and will end up loading a host-side network driver.
-// This connects to the eCos-side USB ethernet code to
-// e.g. obtain the MAC address.
-//
-// 4) when the host-side is ready, the eCos side can be brought up.
-// The required call is (sc->funs->eth_drv->init)(sc, enaddr)
-//
-// In practice it is easier for now to invoke the init() function
-// immediately. There are not going to be any incoming packets
-// until the host is ready, and can_send() can just return false
-// for the time being.
-//
-// Invoked in: thread context only
-// ----------------------------------------------------------------------------
-
-static bool
-usbs_ethdrv_init(struct cyg_netdevtab_entry* ndp)
-{
- struct eth_drv_sc* sc = (struct eth_drv_sc*)(ndp->device_instance);
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
-
- (*sc->funs->eth_drv->init)(sc, eth->ecos_MAC);
- return true;
-}
-
-// ----------------------------------------------------------------------------
-// The receive process that is used to transfer a received ethernet
-// packet into the stack. The calling sequence is somewhat convoluted.
-// It started off as:
-//
-// 1) Ethernet hw ISR invoked by hardware, schedules its own
-// hw_dsr(), and blocks further interrupts in the ethernet chip
-// 2) hw_dsr() calls generic eth_drv_dsr() from io/eth common package
-// 3) eth_drv_dsr() interacts with the TCP/IP stack and allocates mbufs
-// (typically, the TCP/IP stack might not be in use)
-// 4) eth_drv_dsr() calls usbs_eth_recv() to transfer the data to mbufs
-// 5) eth_drv_dsr() returns to hw_dsr() which reenables interrupts
-// 6) hw_dsr() completes and everything can proceed.
-//
-// The problem with this is that the whole ethernet packet gets copied
-// inside a DSR, affecting dispatch latency (but not interrupt latency).
-// This is bad. Hence there is an alternative route involving a separate
-// thread in the TCP/IP stack.
-//
-// 1) Ethernet hw ISR runs as before, scheduling hw_dsr()
-// 2) hw_dsr() calls up into eth_drv_dsr()
-// 3) eth_drv_dsr() wakes up a thread inside the TCP/IP stack
-// 4) eth_drv_dsr() returns to hw_dsr(), which performs no further
-// processing. Ethernet chip interrupts remain disabled.
-// 5) The TCP/IP thread ends up calling hw_deliver(). This should take
-// care of any pending activity. For every buffered packet there should
-// be a call to a generic recv() function which then goes back into
-// the driver-specific recv() function.
-//
-// The advantage is that ethernet packet copying now happens at thread
-// level rather than DSR level so thread priorities can be used to
-// schedule things.
-//
-// USB-ethernet does not interact directly with any hardware, instead
-// it just passes information to lower levels of USB code. The reception
-// process is started by usbs_ethdrv_start() when the TCP/IP stack brings
-// up the interface.
-//
-// When the USB transfer has completed a callback will be invoked, at
-// DSR level. Assuming the transfer went ok, the callback will invoke
-// eth_drv_dsr() to inform the higher level code.
-//
-// The deliver function can check the state of the buffer
-// and go through the sc->funs->eth_drv->recv()/recv() sequence
-// to transfer the data into the stack.
-//
-// usbs_ethdrv_recv() does a scatter from the internal buffer into the
-// mbuf, thus freeing up the buffer. This allows it to start another
-// receive,
-//
-// Synchronisation involves the scheduler lock because the recv
-// callback is invoked inside a DSR.
-
-static void usbs_ethdrv_halted_callback(void*, int);
-
-static void
-usbs_ethdrv_recv_callback(usbs_eth* eth, void* callback_data, int size)
-{
- cyg_bool resubmit = true;
-
- struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
- CYG_ASSERT( eth == (usbs_eth*)(sc->driver_private), "USB and TCP/IP worlds need to be consistent");
-
- INCR_STAT(eth->interrupts);
- if (!eth->ecos_up) {
- // This message should just be discarded since the eCos TCP/IP
- // stack is not expecting anything from this interface.
- // Reception will resume when the interface comes back up.
- eth->rx_active = false;
- resubmit = false;
- } else if (size < 0) {
- // An error has occurred. The likely possibilities are:
- // -EPIPE: connection to the host has been broken
- // -EAGAIN: the endpoint is haltedn
- // -EMSGSIZE: bogus message from host
- // -EIO: other
-
- if (-EAGAIN == size) {
- // EAGAIN should be handled by waiting for the endpoint to be reset.
- resubmit = false;
- usbs_start_rx_endpoint_wait(eth->rx_endpoint, &usbs_ethdrv_halted_callback, (void*) sc);
- } else if (-EMSGSIZE == size) {
- // Do nothing for now
- } else {
- // EPIPE should be resubmitted, the usbseth.c will use the
- // pending rx support. EIO could mean anything.
- }
- } else if (0 == size) {
- // The endpoint is no longer halted. Just do the resubmit at
- // the end.
- } else {
- // A packet has been received. Now do a size sanity check
- // based on the first two bytes.
- int real_size = eth->rx_bufptr[0] + (eth->rx_bufptr[1] << 8);
- if (real_size < CYGNUM_USBS_ETH_MIN_FRAME_SIZE) {
- INCR_STAT(eth->rx_short_frames);
- } else if (real_size > CYGNUM_USBS_ETH_MAX_FRAME_SIZE) {
- INCR_STAT(eth->rx_too_long_frames);
- } else {
- // The packet appears to be valid. Inform higher level
- // code and mark the buffer as in use.
- resubmit = false;
- eth->rx_buffer_full = true;
- eth->rx_active = false;
- eth_drv_dsr(0, 0, (cyg_addrword_t) sc);
- }
- }
-
- if (resubmit) {
- eth->rx_active = true;
- usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, callback_data);
- }
-}
-
-// Another callback, used to wait while an endpoint is halted.
-static void
-usbs_ethdrv_halted_callback(void* callback_data, int size)
-{
- struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
- usbs_ethdrv_recv_callback((usbs_eth*) sc->driver_private, callback_data, 0);
-}
-
-// Start a receive operation. It is not possible to abort an existing
-// rx operation, so a valid sequence of events is: start, rx ongoing,
-// stop, restart. The rx_active field is used to keep track of whether
-// or not there is still a receive in progress. The receive callback
-// will just discard incoming data if the eCos stack is not currently
-// running.
-static void
-usbs_ethdrv_start_recv(struct eth_drv_sc* sc, usbs_eth* eth)
-{
- cyg_drv_dsr_lock();
- if (!eth->rx_active) {
- eth->rx_active = true;
- usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, (void*) sc);
- }
- cyg_drv_dsr_unlock();
-}
-
-// This is invoked from the delivery thread when a valid buffer
-// has been received. The buffer should be scattered into the
-// supplied list, then another receive should be started.
-
-static void
-usbs_ethdrv_recv(struct eth_drv_sc* sc,
- struct eth_drv_sg* sg_list, int sg_len)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
-
- CYG_ASSERT( eth->rx_buffer_full, "This function should only be called when there is a buffer available");
- (void) scatter(eth->rx_bufptr, sg_list, sg_len);
- eth->rx_buffer_full = false;
- eth->rx_active = true;
- usbs_eth_start_rx(eth, eth->rx_bufptr, &usbs_ethdrv_recv_callback, (void*) sc);
-}
-
-// ----------------------------------------------------------------------------
-// Now for the transmit process.
-//
-// When an application thread writes down a socket the data gets moved
-// into mbufs, and then passed to the appropriate device driver - which
-// may or may not be able to process it immediately. There is also a
-// timeout thread within the TCP/IP to handle retransmits etc.
-//
-// The stack will start by calling usbs_ethdrv_can_send() to determine
-// whether or not the driver can accept the packet. For the purposes
-// of the USB-ethernet driver this is true provided both host
-// and target are up and there is a spare buffer available.
-//
-// If the usbs_eth_can_send() returns true then there will be a call
-// to usbs_ethdrv_send(). This gathers the data into a single
-// buffer. If there is no transmit in progress yet then one is started.
-//
-// At some point the packet will have been transmitted and a callback
-// gets invoked. This needs to call eth_drv_dsr(), waking up the
-// delivery thread. The deliver() function can then check which
-// transmissions have completed and inform the higher level code
-// via sc->funs->eth_drv->tx_done(). The buffer can be re-used at
-// that point.
-
-static void
-usbs_ethdrv_send_callback(usbs_eth* eth, void* callback_data, int size)
-{
- struct eth_drv_sc* sc = (struct eth_drv_sc*) callback_data;
- CYG_ASSERT( eth == (usbs_eth*)(sc->driver_private), "USB and TCP/IP worlds need to be consistent");
-
- INCR_STAT(eth->interrupts);
-
- // There are a variety of possible error codes. -EAGAIN indicates
- // that the endpoint is stalled. -EPIPE indicates that the
- // connection to the host has been lost. These are not really
- // particularly interesting. Whatever happens the buffer
- // must be cleared and higher-level code informed so that
- // the mbufs can be released.
- if (size > 0) {
- INCR_STAT(eth->tx_count);
- }
- eth->tx_done = true;
- eth_drv_dsr(0, 0, (cyg_addrword_t) sc);
-}
-
-// Is it possible to send an ethernet frame? This requires
-// an empty buffer, i.e. there should be no existing
-// transmit in progress. It also requires that the host
-// is connected and that the endpoint is not currently halted.
-static int
-usbs_ethdrv_can_send(struct eth_drv_sc* sc)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- return eth->host_up && !eth->tx_buffer_full && !eth->tx_endpoint->halted;
-}
-
-// Actually start a packet transmission. This means collecting
-// all the data into a single buffer and then invoking the
-// lower-level code. The latter may discard the packet immediately
-// if the MAC is not appropriate: it would be more efficient to
-// catch that here, especially for large packets, but the check
-// has to happen inside the lower-level code anyway in case
-// that is being invoked directly rather than via the driver.
-//
-// There is a possible recursion problem,
-// send->start_tx->tx_done->can_send->send, which is guarded
-// against using the tx_in_send flag.
-
-static void
-usbs_ethdrv_send(struct eth_drv_sc* sc,
- struct eth_drv_sg* sgl_list, int sg_len, int total_len,
- unsigned long key)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
-
- CYG_ASSERT( 0 == eth->tx_in_send, "send() should not be invoked recursively");
- CYG_ASSERT( total_len <= CYGNUM_USBS_ETH_MAX_FRAME_SIZE, "ethernet maximum frame size should be observed");
- CYG_ASSERT( CYGNUM_USBS_ETH_MIN_FRAME_SIZE <= total_len, "ethernet minimum frame size should be observed");
-
- eth->tx_in_send = true;
- CYG_ASSERT( !eth->tx_buffer_full, "the transmit buffer should be empty");
- gather(eth->tx_buffer, CYGNUM_USBS_ETH_MAX_FRAME_SIZE, sgl_list, sg_len);
- eth->tx_buffer_full = true;
- eth->tx_done = false;
- eth->tx_key = key;
- usbs_eth_start_tx(eth, eth->tx_buffer, &usbs_ethdrv_send_callback, (void*) sc);
- eth->tx_in_send = false;
-}
-
-// ----------------------------------------------------------------------------
-// Deliver needs to take into account both receive and transmit buffers.
-
-static void
-usbs_ethdrv_deliver(struct eth_drv_sc* sc)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
-
- if (eth->rx_buffer_full) {
- int size = eth->rx_bufptr[0] + (eth->rx_bufptr[1] << 8);
- (*sc->funs->eth_drv->recv)(sc, size);
- }
- if (eth->tx_done) {
- unsigned long key = eth->tx_key;
- eth->tx_buffer_full = false;
- eth->tx_done = false;
- (*sc->funs->eth_drv->tx_done)(sc, key, 1);
- }
-}
-
-// ----------------------------------------------------------------------------
-// usbs_ethdrv_start()
-//
-// This gets called by the TCP/IP stack later on during
-// initialization, when the stack is ready to send and receive
-// packets. It may get called multiple times while the stack
-// is running, with different flags values.
-//
-// As far as transmits are concerned, nothing needs to be done. If no
-// transmit is in progress then everything is fine anyway. If a
-// transmit is already in progress then it must be allowed to complete
-// via the usual route. Receives should however be restarted, the
-// start function has appropriate safeguards.
-//
-// Invoked in: thread context only
-// ----------------------------------------------------------------------------
-
-static void
-usbs_ethdrv_start(struct eth_drv_sc* sc, unsigned char* enaddr, int flags)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- if (!eth->ecos_up) {
- eth->ecos_up = true;
- usbs_ethdrv_start_recv(sc, eth);
- }
-}
-
-// ----------------------------------------------------------------------------
-// usbs_ethdrv_stop()
-//
-// Similarly this gets called by the TCP/IP stack to bring the network
-// interface down. Nothing should happen for any packets currently
-// being transmitted or received, that would cause confusion everywhere.
-// The receive callback checks the ecos_up flag and does the right
-// thing. The TCP/IP stack should not call can_send() after taking
-// the interface down so no new transmits will be initiated.
-//
-// Invoked in: thread context only
-// ----------------------------------------------------------------------------
-
-static void
-usbs_ethdrv_stop(struct eth_drv_sc* sc)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- eth->ecos_up = false;
-}
-
-// ----------------------------------------------------------------------------
-// usbs_eth_ioctl()
-//
-// The operations to worry about here are:
-//
-// SET_MAC_ADDRESS,via the SIOCSIFHWADDR ioctl
-//
-// GET_IF_STATS and GET_IF_STATS_UD, to report gathered statistics.
-//
-// Invoked in: thread context only
-// ----------------------------------------------------------------------------
-
-static int
-usbs_ethdrv_ioctl(struct eth_drv_sc* sc, unsigned long key, void* data, int data_length)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- int result = EINVAL;
-
- switch(key) {
- case ETH_DRV_SET_MAC_ADDRESS:
- {
- if (6 == data_length) {
- memcpy(eth->ecos_MAC, data, 6);
- result = 0;
- }
- }
- break;
-#if defined(CYGFUN_USBS_ETHDRV_STATISTICS) && defined(ETH_DRV_GET_IF_STATS_UD)
- case ETH_DRV_GET_IF_STATS_UD:
- case ETH_DRV_GET_IF_STATS:
- {
- static unsigned char my_chipset[] = { 0, 0 };
- struct ether_drv_stats *p = (struct ether_drv_stats*) data;
- int i;
- strcpy(p->description, CYGDAT_USBS_ETHDRV_DESCRIPTION);
- for ( i = 0; i < SNMP_CHIPSET_LEN; i++ ) {
- if ( 0 == (p->snmp_chipset[i] = my_chipset[i]) ) {
- break;
- }
- }
- p->duplex = 3; // 3 == duplex
- p->operational = (eth->host_up && eth->ecos_up) ? 3 : 2; // 3 == up, 2 == down
- p->speed = 10 * 1000000;
- p->supports_dot3 = 1;
- p->rx_too_long_frames = eth->rx_too_long_frames;
- p->rx_short_frames = eth->rx_short_frames;
- p->interrupts = eth->interrupts;
- p->rx_count = eth->rx_count;
- p->tx_count = eth->tx_count;
- p->tx_queue_len = 1;
- }
- break;
-#endif
-
- default:
- break;
- }
-
- return result;
-}
-
-
-// ----------------------------------------------------------------------------
-// usbs_ethdrv_poll()
-//
-// On real ethernet hardware this is used by RedBoot once the
-// application has started running, so that the network device can be
-// used for debugging purposes as well as for the application's own
-// needs. The lower-level USB device may supply a poll function as well.
-// ----------------------------------------------------------------------------
-static void
-usbs_ethdrv_poll(struct eth_drv_sc* sc)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- (*eth->control_endpoint->poll_fn)(eth->control_endpoint);
-}
-
-// ----------------------------------------------------------------------------
-// usbs_ethdrv_intvector()
-//
-// See usbs_eth_poll().
-// ----------------------------------------------------------------------------
-
-static int
-usbs_ethdrv_intvector(struct eth_drv_sc* sc)
-{
- usbs_eth* eth = (usbs_eth*)(sc->driver_private);
- return eth->control_endpoint->interrupt_vector;
-}
-
-
Index: eth/slave/v2_0/src/usbseth.c
===================================================================
--- eth/slave/v2_0/src/usbseth.c (revision 174)
+++ eth/slave/v2_0/src/usbseth.c (nonexistent)
@@ -1,321 +0,0 @@
-//==========================================================================
-//
-// usbseth.c
-//
-// Support for USB-ethernet devices, slave-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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-10-04
-//
-//####DESCRIPTIONEND####
-//
-//==========================================================================
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#define __ECOS 1
-#include
-
-#ifdef CYGPKG_USBS_ETHDRV
-#include
-#include
-#endif
-
-// ----------------------------------------------------------------------------
-// Static data.
-//
-// usbs_eth0 contains the per-device data, both the low-level data
-// such as which endpoints to use and the network-driver data such as
-// SNMP statistics. If this package is loaded then the assumption
-// is that there should be at least one USB-ethernet device. Additional
-// ones can be instantiated in application code if necessary. A call
-// to usbs_eth_init() is required for initialization.
-usbs_eth usbs_eth0;
-
-// ----------------------------------------------------------------------------
-// Initialization. This should be called explicitly by application code
-// at an appropriate point in the system startup.
-void
-usbs_eth_init(usbs_eth* eth, usbs_control_endpoint* ctrl, usbs_rx_endpoint* rx, usbs_tx_endpoint* tx, unsigned char* mac)
-{
- eth->control_endpoint = ctrl;
- eth->rx_endpoint = rx;
- eth->tx_endpoint = tx;
- eth->host_up = false;
- eth->host_promiscuous = false;
- memcpy(eth->host_MAC, mac, 6);
- eth->rx_pending_buf = (unsigned char*) 0;
-
- // Install default handlers for some messages. Higher level code
- // may override this.
- ctrl->state_change_fn = &usbs_eth_state_change_handler;
- ctrl->state_change_data = (void*) eth;
- ctrl->class_control_fn = &usbs_eth_class_control_handler;
- ctrl->class_control_data = (void*) eth;
-
-#ifdef CYGPKG_USBS_ETHDRV
- eth->ecos_up = false;
- eth->rx_active = false;
-# ifdef CYGFUN_USBS_ETHDRV_STATISTICS
- eth->interrupts = 0;
- eth->tx_count = 0;
- eth->rx_count = 0;
-# endif
-# ifndef HAL_DCACHE_LINE_SIZE
- eth->rx_bufptr = eth->rx_buffer;
-# else
-# endif
- eth->rx_bufptr = (unsigned char*) ((((cyg_uint32)eth->rx_buffer) + HAL_DCACHE_LINE_SIZE - 1)
- & ~(HAL_DCACHE_LINE_SIZE - 1));
- eth->rx_buffer_full = false;
- eth->tx_in_send = false;
- eth->tx_buffer_full = false;
- eth->tx_done = false;
-#endif
-}
-
-
-// ----------------------------------------------------------------------------
-// Generic transmit and receive operations. These can be called
-// explicitly by application code, or implicitly via the eCos ethernet
-// device driver code in usbsethdrv.c. These two modes of operation
-// should not be mixed since the routines do not perform any
-// synchronization themselves, instead they rely on higher level code.
-
-// Packet transmission. The exported function is usbs_eth_start_tx(),
-// which can be invoked from thread context or DSR context. The
-// supplied buffer must already be in a form that can be transmitted
-// directly out of the USB endpoint with no further processing
-// (although it is necessary to extract the size information from the
-// buffer).
-//
-// When the underlying USB transfer has completed the USB code will invoke
-// usbs_eth_tx_callback(), usually in DSR context although possibly in
-// thread context depending on the specific USB implementation. The
-// underlying USB driver may have had to do some padding so the amount
-// transferred may be slightly greater than requested.
-
-static void
-usbs_eth_tx_callback(void* usbs_callback_arg, int size)
-{
- usbs_eth* eth = (usbs_eth*) usbs_callback_arg;
- CYG_ASSERT( (size < 0) || (size >= CYGNUM_USBS_ETH_MINTU), "returned size must be valid.");
- (*eth->tx_callback_fn)(eth, eth->tx_callback_arg, size);
-}
-
-void
-usbs_eth_start_tx(usbs_eth* eth, unsigned char* buf, void (*callback_fn)(usbs_eth*, void*, int), void* callback_arg)
-{
- int size;
- cyg_bool address_ok = false;
- static const unsigned char broadcast_mac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
- size = buf[0] + (buf[1] << 8);
- CYG_ASSERT( (size < 0) || ((size >= CYGNUM_USBS_ETH_MIN_FRAME_SIZE) && (size <= CYGNUM_USBS_ETH_MAX_FRAME_SIZE)), \
- "ethernet frame size constraints must be observed");
-
- if ((0 == memcmp(buf + 2, eth->host_MAC, 6)) ||
- (0 == memcmp(buf + 2, broadcast_mac, 6))) {
- address_ok = true;
- }
-
- // The following checks involve data that can change as a result
- // of control operations, so it is necessary to synchronize with
- // those. The control operations will typically run at DSR level
- // so a DSR lock has to be used.
-
- cyg_drv_dsr_lock();
- if (eth->host_up && (address_ok || eth->host_promiscuous)) {
-
- eth->tx_callback_fn = callback_fn;
- eth->tx_callback_arg = callback_arg;
- eth->tx_endpoint->buffer = buf;
- eth->tx_endpoint->buffer_size = size + 2;
- eth->tx_endpoint->complete_fn = &usbs_eth_tx_callback;
- eth->tx_endpoint->complete_data = (void*) eth;
- (*(eth->tx_endpoint->start_tx_fn))(eth->tx_endpoint);
-
- } else {
- // Packets not intended for the host can be discarded quietly.
- // A broken connection needs to be reported.
- (*callback_fn)(eth, callback_arg, eth->host_up ? size : -EPIPE);
- }
- cyg_drv_dsr_unlock();
-}
-
-// Packet reception. This simply involves starting a transfer for
-// up to the maximum ethernet frame size. The lower-level USB code
-// will detect the end of the transfer. The exported function is
-// usbs_eth_start_rx().
-static void
-usbs_eth_rx_callback(void* usbs_callback_arg, int size)
-{
- usbs_eth* eth = (usbs_eth*) usbs_callback_arg;
-
- CYG_ASSERT( (size <= 0) || ((size >= CYGNUM_USBS_ETH_MINTU) && (size <= CYGNUM_USBS_ETH_MAXTU)), \
- "ethernet frame size constraints must be observed");
-
- (*eth->rx_callback_fn)(eth, eth->rx_callback_arg, size);
-}
-
-void
-usbs_eth_start_rx(usbs_eth* eth, unsigned char* buf, void (*callback_fn)(usbs_eth*, void*, int), void* callback_arg)
-{
- eth->rx_callback_fn = callback_fn;
- eth->rx_callback_arg = callback_arg;
-
- cyg_drv_dsr_lock();
- if (eth->host_up) {
- eth->rx_endpoint->buffer = buf;
- eth->rx_endpoint->buffer_size = CYGNUM_USBS_ETH_RXSIZE;
- eth->rx_endpoint->complete_fn = &usbs_eth_rx_callback;
- eth->rx_endpoint->complete_data = (void*) eth;
- (*(eth->rx_endpoint->start_rx_fn))(eth->rx_endpoint);
- } else {
- CYG_ASSERT( (void*) 0 == eth->rx_pending_buf, "No RX operation should be in progress");
- eth->rx_pending_buf = buf;
- }
- cyg_drv_dsr_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// Control operations. The host may send two types of application-specific
-// control messages, one to get the MAC address and one to enable/disable
-// promiscuous mode on the host side. This callback will typically be invoked
-// in DSR context.
-
-// These constants need to be shared somehow with the driver in ../host/,
-// but if some variant of that driver becomes part of the Linux kernel
-// then its sources must be self-contained with no dependencies on
-// eCos sources or headers. Hence a duplicate definition for now.
-#define USBS_ETH_CONTROL_GET_MAC_ADDRESS 0x01
-#define USBS_ETH_CONTROL_SET_PROMISCUOUS_MODE 0x02
-
-usbs_control_return
-usbs_eth_class_control_handler(usbs_control_endpoint* endpoint, void* callback_data)
-{
- usbs_control_return result = USBS_CONTROL_RETURN_STALL;
-
- usbs_eth* eth = (usbs_eth*) callback_data;
- usb_devreq* devreq = (usb_devreq*) endpoint->control_buffer;
- int size = (devreq->length_hi << 8) + devreq->length_lo;
-
- CYG_ASSERT(endpoint == eth->control_endpoint, "USB ethernet control messages correctly routed");
-
- if (USBS_ETH_CONTROL_GET_MAC_ADDRESS == devreq->request) {
- // This should be an IN operation for at least six bytes.
- if ((size >= 6) &&
- (USB_DEVREQ_DIRECTION_IN == (devreq->type & USB_DEVREQ_DIRECTION_MASK))) {
-
- endpoint->buffer = eth->host_MAC;
- endpoint->buffer_size = 6;
- result = USBS_CONTROL_RETURN_HANDLED;
- }
- // Otherwise drop through with a return value of STALL
-
- } else if (USBS_ETH_CONTROL_SET_PROMISCUOUS_MODE == devreq->request) {
- // The length should be 0, no more data is expected by either side.
- if (0 == size) {
- // The new promiscuity mode is encoded in value_lo;
- eth->host_promiscuous = devreq->value_lo;
- result = USBS_CONTROL_RETURN_HANDLED;
- }
- }
-
- return result;
-}
-
-// State changes. As far as the ethernet code is concerned, if there
-// is a change to CONFIGURED state then the device has come up,
-// otherwise if there is a change from CONFIGURED state it has gone
-// down. All other state changes are irrelevant.
-void
-usbs_eth_state_change_handler(usbs_control_endpoint* endpoint, void* callback_data, usbs_state_change change, int old_state)
-{
- usbs_eth* eth = (usbs_eth*) callback_data;
- CYG_ASSERT(endpoint == eth->control_endpoint, "USB ethernet state changes correctly routed");
-
- if (USBS_STATE_CHANGE_CONFIGURED == change) {
- if (USBS_STATE_CONFIGURED != old_state) {
- usbs_eth_enable(eth);
- }
- } else if ((USBS_STATE_CHANGE_RESUMED == change) && (USBS_STATE_CONFIGURED == (USBS_STATE_MASK & old_state))) {
- usbs_eth_enable(eth);
- } else if (eth->host_up) {
- usbs_eth_disable(eth);
- }
-}
-
-// Disabling the ethernet device means clearing the host_up flag.
-// This will block future transmits and receives but not any
-// that are currently underway.
-void
-usbs_eth_disable(usbs_eth* eth)
-{
- eth->host_up = false;
-}
-
-// Enabling the ethernet device means setting the host_up flag and
-// possibly activating a pending rx operation.
-void
-usbs_eth_enable(usbs_eth* eth)
-{
- if (!eth->host_up) {
- eth->host_up = true;
- eth->host_promiscuous = false;
- if ((void*) 0 != eth->rx_pending_buf) {
- eth->rx_endpoint->buffer = eth->rx_pending_buf;
- eth->rx_endpoint->buffer_size = CYGNUM_USBS_ETH_RXSIZE;
- eth->rx_endpoint->complete_fn = &usbs_eth_rx_callback;
- eth->rx_endpoint->complete_data = (void*) eth;
- eth->rx_pending_buf = (void*) 0;
- (*(eth->rx_endpoint->start_rx_fn))(eth->rx_endpoint);
- }
- }
-}
-
Index: eth/slave/v2_0/host/ecos_usbeth.c
===================================================================
--- eth/slave/v2_0/host/ecos_usbeth.c (revision 174)
+++ eth/slave/v2_0/host/ecos_usbeth.c (nonexistent)
@@ -1,572 +0,0 @@
-//==========================================================================
-//
-// ecos_usbeth.c
-//
-// Linux device driver for eCos-based USB ethernet peripherals.
-//
-//==========================================================================
-//####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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-11-12
-//
-//####DESCRIPTIONEND####
-//==========================================================================
-
-#include
-#include
-#include
-#include
-#include
-
-#ifdef MODULE
-MODULE_AUTHOR("Bart Veer ");
-MODULE_DESCRIPTION("USB ethernet driver for eCos-based peripherals");
-#endif
-
-// This array identifies specific implementations of eCos USB-ethernet
-// devices. All implementations should add their vendor and device
-// details.
-
-typedef struct ecos_usbeth_impl {
- const char* name;
- __u16 vendor;
- __u16 id;
-} ecos_usbeth_impl;
-
-const static ecos_usbeth_impl ecos_usbeth_implementations[] = {
- { "eCos ether", 0x4242, 0x4242 },
- { (const char*) 0, 0, 0 }
-};
-
-
-// Constants. These have to be kept in sync with the target-side
-// code.
-#define ECOS_USBETH_MAXTU 1516
-#define ECOS_USBETH_MAX_CONTROL_TU 8
-#define ECOS_USBETH_CONTROL_GET_MAC_ADDRESS 0x01
-#define ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE 0x02
-
-// The main data structure. It keeps track of both the USB
-// and network side of things, and provides buffers for
-// the various operations.
-//
-// NOTE: currently this driver only supports a single
-// plugged-in device. Theoretically multiple eCos-based
-// USB ethernet devices could be plugged in to a single
-// host and each one would require an ecos_usbeth
-// structure.
-typedef struct ecos_usbeth {
- spinlock_t usb_lock;
- int target_promiscuous;
- struct usb_device* usb_dev;
- struct net_device* net_dev;
- struct net_device_stats stats;
- struct urb rx_urb;
- struct urb tx_urb;
- unsigned char rx_buffer[ECOS_USBETH_MAXTU];
- unsigned char tx_buffer[ECOS_USBETH_MAXTU];
-} ecos_usbeth;
-
-
-// open()
-// Invoked by the TCP/IP stack when the interface is brought up.
-// This just starts a receive operation.
-static int
-ecos_usbeth_open(struct net_device* net)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;
- int res;
-
- netif_start_queue(net);
- res = usb_submit_urb(&(usbeth->rx_urb));
- if (0 != res) {
- printk("ecos_usbeth: failed to start USB receives, %d\n", res);
- }
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-// close()
-// Invoked by the TCP/IP stack when the interface is taken down.
-// Any active USB operations need to be cancelled. During
-// a disconnect this may get called twice, once for the
-// disconnect and once for the network interface being
-// brought down.
-static int
-ecos_usbeth_close(struct net_device* net)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;
-
- if (0 != netif_running(net)) {
- netif_stop_queue(net);
- net->start = 0;
-
- if (-EINPROGRESS == usbeth->rx_urb.status) {
- usb_unlink_urb(&(usbeth->rx_urb));
- }
- if (-EINPROGRESS == usbeth->tx_urb.status) {
- usb_unlink_urb(&(usbeth->tx_urb));
- }
- MOD_DEC_USE_COUNT;
- }
-
- return 0;
-}
-
-// Reception.
-// probe() fills in an rx_urb. When the net device is brought up
-// the urb is activated, and this callback gets run for incoming
-// data.
-static void
-ecos_usbeth_rx_callback(struct urb* urb)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) urb->context;
- struct net_device* net = usbeth->net_dev;
- struct sk_buff* skb;
- int len;
- int res;
-
- if (0 != urb->status) {
- // This happens numerous times during a disconnect. Do not
- // issue a warning, but do clear the status field or things
- // get confused when resubmitting.
- //
- // Some host hardware does not distinguish between CRC errors
- // (very rare) and timeouts (perfectly normal). Do not
- // increment the error count if it might have been a timeout.
- if (USB_ST_CRC != urb->status) {
- usbeth->stats.rx_errors++;
- }
- urb->status = 0;
- } else if (2 > urb->actual_length) {
- // With some hardware the target may have to send a bogus
- // first packet. Just ignore those.
-
- } else {
- len = usbeth->rx_buffer[0] + (usbeth->rx_buffer[1] << 8);
- if (len > (urb->actual_length - 2)) {
- usbeth->stats.rx_errors++;
- usbeth->stats.rx_length_errors++;
- printk("ecos_usbeth: warning, packet size mismatch, got %d bytes, expected %d\n",
- urb->actual_length, len);
- } else {
- skb = dev_alloc_skb(len + 2);
- if ((struct sk_buff*)0 == skb) {
- printk("ecos_usbeth: failed to alloc skb, dropping packet\n");
- usbeth->stats.rx_dropped++;
- } else {
-#if 0
- {
- int i;
- printk("--------------------------------------------------------------\n");
- printk("ecos_usbeth RX: total size %d\n", len);
- for (i = 0; (i < len) && (i < 128); i+= 8) {
- printk("rx %x %x %x %x %x %x %x %x\n",
- usbeth->rx_buffer[i+0], usbeth->rx_buffer[i+1], usbeth->rx_buffer[i+2], usbeth->rx_buffer[i+3],
- usbeth->rx_buffer[i+4], usbeth->rx_buffer[i+5], usbeth->rx_buffer[i+6], usbeth->rx_buffer[i+7]);
- }
- printk("--------------------------------------------------------------\n");
- }
-#endif
- skb->dev = net;
- eth_copy_and_sum(skb, &(usbeth->rx_buffer[2]), len, 0);
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, net);
- netif_rx(skb);
- usbeth->stats.rx_packets++;
- usbeth->stats.rx_bytes += len;
- }
- }
- }
-
- if (0 != netif_running(net)) {
- res = usb_submit_urb(&(usbeth->rx_urb));
- if (0 != res) {
- printk("ecos_usbeth: failed to restart USB receives after packet, %d\n", res);
- }
- }
-}
-
-// start_tx().
-// Transmit a single packet. The relevant USB protocol requires a
-// 2-byte length field at the start, the incoming buffer has no space
-// for this, and the URB API does not support any form of
-// scatter/gather. Therefore unfortunately the whole packet has to be
-// copied. The callback function is specified when the URB is filled
-// in by probe().
-static void
-ecos_usbeth_tx_callback(struct urb* urb)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) urb->context;
- spin_lock(&usbeth->usb_lock);
- if (0 != netif_running(usbeth->net_dev)) {
- netif_wake_queue(usbeth->net_dev);
- }
- spin_unlock(&usbeth->usb_lock);
-}
-
-static int
-ecos_usbeth_start_tx(struct sk_buff* skb, struct net_device* net)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;
- int res;
-
- if ((skb->len + 2) > ECOS_USBETH_MAXTU) {
- printk("ecos_usbeth: oversized packet of %d bytes\n", skb->len);
- return 0;
- }
-
- if (netif_queue_stopped(net)) {
- // Another transmission already in progress.
- // USB bulk operations should complete within 5s.
- int current_delay = jiffies - net->trans_start;
- if (current_delay < (5 * HZ)) {
- return 1;
- } else {
- // There has been a timeout. Discard this message.
- //printk("transmission timed out\n");
- usbeth->stats.tx_errors++;
- dev_kfree_skb(skb);
- return 0;
- }
- }
-
- spin_lock(&usbeth->usb_lock);
- usbeth->tx_buffer[0] = skb->len & 0x00FF;
- usbeth->tx_buffer[1] = (skb->len >> 8) & 0x00FF;
- memcpy(&(usbeth->tx_buffer[2]), skb->data, skb->len);
- usbeth->tx_urb.transfer_buffer_length = skb->len + 2;
-
- // Some targets are unhappy about receiving 0-length packets, not
- // just sending them.
- if (0 == (usbeth->tx_urb.transfer_buffer_length % 64)) {
- usbeth->tx_urb.transfer_buffer_length++;
- }
-#if 0
- {
- int i;
- printk("--------------------------------------------------------------\n");
- printk("ecos_usbeth start_tx: len %d\n", skb->len + 2);
- for (i = 0; (i < (skb->len + 2)) && (i < 128); i+= 8) {
- printk("tx %x %x %x %x %x %x %x %x\n",
- usbeth->tx_buffer[i], usbeth->tx_buffer[i+1], usbeth->tx_buffer[i+2], usbeth->tx_buffer[i+3],
- usbeth->tx_buffer[i+4], usbeth->tx_buffer[i+5], usbeth->tx_buffer[i+6], usbeth->tx_buffer[i+7]);
- }
- printk("--------------------------------------------------------------\n");
- }
-#endif
- res = usb_submit_urb(&(usbeth->tx_urb));
- if (0 == res) {
- netif_stop_queue(net);
- net->trans_start = jiffies;
- usbeth->stats.tx_packets++;
- usbeth->stats.tx_bytes += skb->len;
- } else {
- printk("ecos_usbeth: failed to start USB packet transmission, %d\n", res);
- usbeth->stats.tx_errors++;
- }
-
- spin_unlock(&usbeth->usb_lock);
- dev_kfree_skb(skb);
- return 0;
-}
-
-
-// set_rx_mode()
-// Invoked by the network stack to enable/disable promiscuous mode or
-// for multicasting. The latter is not yet supported on the target
-// side. The former involves a USB control message. The main call
-// is not allowed to block.
-static void
-ecos_usbeth_set_rx_mode_callback(struct urb* urb)
-{
- kfree(urb->setup_packet);
- usb_free_urb(urb);
-}
-
-static void
-ecos_usbeth_set_rx_mode(struct net_device* net)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;
- __u16 promiscuous = net->flags & IFF_PROMISC;
- int res;
-
- if (promiscuous != usbeth->target_promiscuous) {
- devrequest* req;
- urb_t* urb;
-
- urb = usb_alloc_urb(0);
- if ((urb_t*)0 == urb) {
- return;
- }
- req = kmalloc(sizeof(devrequest), GFP_KERNEL);
- if ((devrequest*)0 == req) {
- usb_free_urb(urb);
- return;
- }
- req->requesttype = USB_TYPE_CLASS | USB_RECIP_DEVICE;
- req->request = ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE;
- req->value = cpu_to_le16p(&promiscuous);
- req->index = 0;
- req->length = 0;
-
- FILL_CONTROL_URB(urb,
- usbeth->usb_dev,
- usb_sndctrlpipe(usbeth->usb_dev, 0),
- (unsigned char*) req,
- (void*) 0,
- 0,
- &ecos_usbeth_set_rx_mode_callback,
- (void*) usbeth);
- res = usb_submit_urb(urb);
- if (0 != res) {
- kfree(req);
- usb_free_urb(urb);
- } else {
- usbeth->target_promiscuous = promiscuous;
- }
- }
-}
-
-// netdev_stats()
-// Supply the current network statistics. These are held in
-// the stats field of the ecos_usbeth structure
-static struct net_device_stats*
-ecos_usbeth_netdev_stats(struct net_device* net)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;
- return &(usbeth->stats);
-}
-
-// ioctl()
-// Currently none of the network ioctl()'s are supported
-static int
-ecos_usbeth_ioctl(struct net_device* net, struct ifreq* request, int command)
-{
- return -EINVAL;
-}
-
-// probe().
-// This is invoked by the generic USB code when a new device has
-// been detected and its configuration details have been extracted
-// and stored in the usbdev structure. The interface_id specifies
-// a specific USB interface, to cope with multifunction peripherals.
-//
-// FIXME; right now this code only copes with simple enumeration data.
-// OK, to be really honest it just looks for the vendor and device ids
-// in the simple test cases and ignores everything else.
-//
-// On success it should return a non-NULL pointer, which happens to be
-// a newly allocated ecos_usbeth structure. This will get passed to
-// the disconnect function. Filling in the ecos_usbeth structure will,
-// amongst other things, register this as a network device driver.
-// The MAC address is obtained from the peripheral via a control
-// request.
-
-static void*
-ecos_usbeth_probe(struct usb_device* usbdev, unsigned int interface_id)
-{
- struct net_device* net;
- ecos_usbeth* usbeth;
- int res;
- unsigned char MAC[6];
- unsigned char dummy[1];
- int tx_endpoint = -1;
- int rx_endpoint = -1;
- const ecos_usbeth_impl* impl;
- int found_impl = 0;
-
- // See if this is the correct driver for this USB peripheral.
- impl = ecos_usbeth_implementations;
- while (impl->name != NULL) {
- if ((usbdev->descriptor.idVendor != impl->vendor) ||
- (usbdev->descriptor.idProduct != impl->id)) {
- found_impl = 1;
- break;
- }
- impl++;
- }
- if (! found_impl) {
- return (void*) 0;
- }
-
- // For now only support USB-ethernet peripherals consisting of a single
- // configuration, with a single interface, with two bulk endpoints.
- if ((1 != usbdev->descriptor.bNumConfigurations) ||
- (1 != usbdev->config[0].bNumInterfaces) ||
- (2 != usbdev->config[0].interface[0].altsetting->bNumEndpoints)) {
- return (void*) 0;
- }
- if ((0 == (usbdev->config[0].interface[0].altsetting->endpoint[0].bEndpointAddress & USB_DIR_IN)) &&
- (0 != (usbdev->config[0].interface[0].altsetting->endpoint[1].bEndpointAddress & USB_DIR_IN))) {
- tx_endpoint = usbdev->config[0].interface[0].altsetting->endpoint[0].bEndpointAddress;
- rx_endpoint = usbdev->config[0].interface[0].altsetting->endpoint[1].bEndpointAddress & ~USB_DIR_IN;
- }
- if ((0 != (usbdev->config[0].interface[0].altsetting->endpoint[0].bEndpointAddress & USB_DIR_IN)) &&
- (0 == (usbdev->config[0].interface[0].altsetting->endpoint[1].bEndpointAddress & USB_DIR_IN))) {
- tx_endpoint = usbdev->config[0].interface[0].altsetting->endpoint[1].bEndpointAddress;
- rx_endpoint = usbdev->config[0].interface[0].altsetting->endpoint[0].bEndpointAddress & ~USB_DIR_IN;
- }
- if (-1 == tx_endpoint) {
- return (void*) 0;
- }
-
- res = usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue);
- if (0 != res) {
- printk("ecos_usbeth: failed to set configuration, %d\n", res);
- return (void*) 0;
- }
- res = usb_control_msg(usbdev,
- usb_rcvctrlpipe(usbdev, 0),
- ECOS_USBETH_CONTROL_GET_MAC_ADDRESS,
- USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN,
- 0,
- 0,
- (void*) MAC,
- 6,
- 5 * HZ);
- if (6 != res) {
- printk("ecos_usbeth: failed to get MAC address, %d\n", res);
- return (void*) 0;
- }
-
- res = usb_control_msg(usbdev,
- usb_sndctrlpipe(usbdev, 0), // pipe
- ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE, // request
- USB_TYPE_CLASS | USB_RECIP_DEVICE, // requesttype
- 0, // value
- 0, // index
- (void*) dummy, // data
- 0, // size
- 5 * HZ); // timeout
- if (0 != res) {
- printk("ecos_usbeth: failed to disable promiscous mode, %d\n", res);
- }
-
- usbeth = (ecos_usbeth*) kmalloc(sizeof(ecos_usbeth), GFP_KERNEL);
- if ((ecos_usbeth*)0 == usbeth) {
- printk("ecos_usbeth: failed to allocate memory for usbeth data structure\n");
- return (void*) 0;
- }
- memset(usbeth, 0, sizeof(ecos_usbeth));
-
- net = init_etherdev(0, 0);
- if ((struct net_device*) 0 == net) {
- kfree(usbeth);
- printk("ecos_usbeth: failed to allocate memory for net data structure\n");
- return (void*) 0;
- }
-
- usbeth->usb_lock = SPIN_LOCK_UNLOCKED;
- usbeth->usb_dev = usbdev;
- FILL_BULK_URB(&(usbeth->tx_urb), usbdev, usb_sndbulkpipe(usbdev, tx_endpoint),
- usbeth->tx_buffer, ECOS_USBETH_MAXTU, &ecos_usbeth_tx_callback, (void*) usbeth);
- FILL_BULK_URB(&(usbeth->rx_urb), usbdev, usb_rcvbulkpipe(usbdev, rx_endpoint),
- usbeth->rx_buffer, ECOS_USBETH_MAXTU, &ecos_usbeth_rx_callback, (void*) usbeth);
-
- usbeth->net_dev = net;
- usbeth->target_promiscuous = 0;
-
- net->priv = (void*) usbeth;
- net->open = &ecos_usbeth_open;
- net->stop = &ecos_usbeth_close;
- net->do_ioctl = &ecos_usbeth_ioctl;
- net->hard_start_xmit = &ecos_usbeth_start_tx;
- net->set_multicast_list = &ecos_usbeth_set_rx_mode;
- net->get_stats = &ecos_usbeth_netdev_stats;
- net->mtu = 1500; // ECOS_USBETH_MAXTU - 2;
- memcpy(net->dev_addr, MAC, 6);
-
- printk("eCos-based USB ethernet peripheral active at %s\n", net->name);
- MOD_INC_USE_COUNT;
- return (void*) usbeth;
-}
-
-// disconnect().
-// Invoked after probe() has recognized a device but that device
-// has gone away.
-static void
-ecos_usbeth_disconnect(struct usb_device* usbdev, void* data)
-{
- ecos_usbeth* usbeth = (ecos_usbeth*) data;
- if (!usbeth) {
- printk("ecos_usbeth: warning, disconnecting unconnected device\n");
- return;
- }
- if (0 != netif_running(usbeth->net_dev)) {
- ecos_usbeth_close(usbeth->net_dev);
- }
- unregister_netdev(usbeth->net_dev);
- if (-EINPROGRESS == usbeth->rx_urb.status) {
- usb_unlink_urb(&(usbeth->rx_urb));
- }
- if (-EINPROGRESS == usbeth->tx_urb.status) {
- usb_unlink_urb(&(usbeth->tx_urb));
- }
- kfree(usbeth);
- MOD_DEC_USE_COUNT;
-}
-
-static struct usb_driver ecos_usbeth_driver = {
- name: "ecos_usbeth",
- probe: ecos_usbeth_probe,
- disconnect: ecos_usbeth_disconnect,
-};
-
-// init()
-// Called when the module is loaded. It just registers the device with
-// the generic USB code. Nothing else can really be done until
-// the USB code detects that a device has been attached.
-int __init
-ecos_usbeth_init(void)
-{
- printk("eCos USB-ethernet device driver\n");
- return usb_register(&ecos_usbeth_driver);
-}
-
-// exit()
-// Called when the module is unloaded. disconnect() will be
-// invoked if appropriate.
-void __exit
-ecos_usbeth_exit(void)
-{
- usb_deregister(&ecos_usbeth_driver);
-}
-
-module_init(ecos_usbeth_init);
-module_exit(ecos_usbeth_exit);
Index: eth/slave/v2_0/host/COPYING
===================================================================
--- eth/slave/v2_0/host/COPYING (revision 174)
+++ eth/slave/v2_0/host/COPYING (nonexistent)
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C) 19yy
-
- This program 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 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19yy name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- , 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
Index: eth/slave/v2_0/host/Makefile
===================================================================
--- eth/slave/v2_0/host/Makefile (revision 174)
+++ eth/slave/v2_0/host/Makefile (nonexistent)
@@ -1,95 +0,0 @@
-#
-# Makefile for the Linux device driver for eCos USB-ethernet
-# devices. This makefile has been cloned from the one in
-# /usr/src/linux-2.2.16/drivers/usb
-#
-
-# This makefile will chain to the Linux makefile if appropriate.
-# The toplevel Linux makefile sets the variable KERNELRELEASE
-ifeq (,$(KERNELRELEASE))
-
-default:
- make -C /usr/src/linux SUBDIRS=$(shell pwd) modules
-
-modules: default
-
-modules_install:
- @echo Support for installing this module not yet implemented.
-
-else
-
-# A recursive invocation of this makefile from the Linux one.
-
-# Build this driver as a module.
-CONFIG_USB_ECOS_USBETH = m
-
-# Subdirs.
-
-SUB_DIRS :=
-MOD_SUB_DIRS := $(SUB_DIRS)
-MOD_IN_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS)
-
-# The target object and module list name.
-
-O_TARGET :=
-M_OBJS :=
-O_OBJS :=
-MOD_LIST_NAME := ECOS_USBETH_MODULE
-
-# Objects that export symbols.
-
-export-objs :=
-
-# Multipart objects.
-
-list-multi :=
-
-# Optional parts of multipart objects.
-
-# Object file lists.
-
-obj-y :=
-obj-m :=
-obj-n :=
-obj- :=
-
-# Object files in subdirectories
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_USB_ECOS_USBETH) += ecos_usbeth.o
-
-# Extract lists of the multi-part drivers.
-# The 'int-*' lists are the intermediate files used to build the multi's.
-
-multi-y := $(filter $(list-multi), $(obj-y))
-multi-m := $(filter $(list-multi), $(obj-m))
-int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-
-# Files that are both resident and modular: remove from modular.
-
-obj-m := $(filter-out $(obj-y), $(obj-m))
-int-m := $(filter-out $(int-y), $(int-m))
-
-# Take multi-part drivers out of obj-y and put components in.
-
-obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
-
-# Translate to Rules.make lists.
-
-O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y)))
-OX_OBJS := $(sort $(filter $(export-objs), $(obj-y)))
-M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
-MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
-
-# The global Rules.make.
-
-include $(TOPDIR)/Rules.make
-
-# Link rules for multi-part drivers.
-
-endif
Index: common/v2_0/cdl/usb.cdl
===================================================================
--- common/v2_0/cdl/usb.cdl (revision 174)
+++ common/v2_0/cdl/usb.cdl (nonexistent)
@@ -1,63 +0,0 @@
-# ====================================================================
-#
-# usb.cdl
-#
-# USB support
-#
-# ====================================================================
-#####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####
-#
-# Author(s): bartv
-# Original data: bartv
-# Contributors:
-# Date: 2000-10-04
-#
-#####DESCRIPTIONEND####
-#
-# ====================================================================
-
-cdl_package CYGPKG_IO_USB {
- display "USB Support"
- include_dir "cyg/io/usb"
- parent CYGPKG_IO
-
- cdl_interface CYGHWR_IO_USB_HOST {
- display "Availability of USB host-side hardware"
- }
- cdl_interface CYGHWR_IO_USB_SLAVE {
- display "Availability of USB slave-side hardware"
- }
-}
Index: common/v2_0/include/usb.h
===================================================================
--- common/v2_0/include/usb.h (revision 174)
+++ common/v2_0/include/usb.h (nonexistent)
@@ -1,249 +0,0 @@
-#ifndef CYGONCE_USB_H
-# define CYGONCE_USB_H
-//==========================================================================
-//
-// include/usb.h
-//
-// Data common to USB host and USB slave
-//
-//==========================================================================
-//####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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-10-04
-//
-//####DESCRIPTIONEND####
-//==========================================================================
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// USB device requests, the setup packet.
-//
-// The structure is defined entirely in terms of bytes, eliminating
-// any confusion about who is supposed to swap what when. This avoids
-// endianness-related portability problems, and eliminates any need
-// to worry about alignment. Also for some requests the value field
-// is split into separate bytes anyway.
-typedef struct usb_devreq {
- unsigned char type;
- unsigned char request;
- unsigned char value_lo;
- unsigned char value_hi;
- unsigned char index_lo;
- unsigned char index_hi;
- unsigned char length_lo;
- unsigned char length_hi;
-} usb_devreq __attribute__((packed));
-
-// Encoding of the request_type
-#define USB_DEVREQ_DIRECTION_OUT 0
-#define USB_DEVREQ_DIRECTION_IN (1 << 7)
-#define USB_DEVREQ_DIRECTION_MASK (1 << 7)
-
-#define USB_DEVREQ_TYPE_STANDARD 0
-#define USB_DEVREQ_TYPE_CLASS (0x1 << 5)
-#define USB_DEVREQ_TYPE_VENDOR (0x2 << 5)
-#define USB_DEVREQ_TYPE_RESERVED (0x3 << 5)
-#define USB_DEVREQ_TYPE_MASK (0x3 << 5)
-
-#define USB_DEVREQ_RECIPIENT_DEVICE 0x00
-#define USB_DEVREQ_RECIPIENT_INTERFACE 0x01
-#define USB_DEVREQ_RECIPIENT_ENDPOINT 0x02
-#define USB_DEVREQ_RECIPIENT_OTHER 0x03
-#define USB_DEVREQ_RECIPIENT_MASK 0x1F
-
-// The standard request codes.
-#define USB_DEVREQ_GET_STATUS 0
-#define USB_DEVREQ_CLEAR_FEATURE 1
-#define USB_DEVREQ_SET_FEATURE 3
-#define USB_DEVREQ_SET_ADDRESS 5
-#define USB_DEVREQ_GET_DESCRIPTOR 6
-#define USB_DEVREQ_SET_DESCRIPTOR 7
-#define USB_DEVREQ_GET_CONFIGURATION 8
-#define USB_DEVREQ_SET_CONFIGURATION 9
-#define USB_DEVREQ_GET_INTERFACE 10
-#define USB_DEVREQ_SET_INTERFACE 11
-#define USB_DEVREQ_SYNCH_FRAME 12
-
-// Descriptor types. These are placed in value_hi for the
-// GET_DESCRIPTOR and SET_DESCRIPTOR requests, with an index
-// in value_lo. They also go into the type fields of the
-// various descriptor structures.
-#define USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE 1
-#define USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION 2
-#define USB_DEVREQ_DESCRIPTOR_TYPE_STRING 3
-#define USB_DEVREQ_DESCRIPTOR_TYPE_INTERFACE 4
-#define USB_DEVREQ_DESCRIPTOR_TYPE_ENDPOINT 5
-
-// Feature selectors. These go into value_lo for the CLEAR_FEATURE and
-// SET_FEATURE requests, and in the first response byte for
-// GET_STATUS.
-#define USB_DEVREQ_FEATURE_DEVICE_REMOTE_WAKEUP 1
-#define USB_DEVREQ_FEATURE_ENDPOINT_HALT 0
-
-// Index decoding. When the CLEAR_FEATURE, SET_FEATURE and GET_STATUS
-// requests is applied to an endpoint (as per the recipient field in
-// the type field) index_lo identifies the endpoint.
-#define USB_DEVREQ_INDEX_DIRECTION_OUT 0
-#define USB_DEVREQ_INDEX_DIRECTION_IN (1 << 7)
-#define USB_DEVREQ_INDEX_DIRECTION_MASK (1 << 7)
-#define USB_DEVREQ_INDEX_ENDPOINT_MASK 0x0F
-
-// Descriptors for the GET_DESCRIPTOR and SET_DESCRIPTOR requests.
-typedef struct usb_device_descriptor {
- unsigned char length; // USB_DEVICE_DESCRIPTOR_LENGTH == 18
- unsigned char type; // USB_DEVREQ_DESCRIPTOR_TYPE
- unsigned char usb_spec_lo;
- unsigned char usb_spec_hi;
- unsigned char device_class;
- unsigned char device_subclass;
- unsigned char device_protocol;
- unsigned char max_packet_size;
- unsigned char vendor_lo;
- unsigned char vendor_hi;
- unsigned char product_lo;
- unsigned char product_hi;
- unsigned char device_lo;
- unsigned char device_hi;
- unsigned char manufacturer_str;
- unsigned char product_str;
- unsigned char serial_number_str;
- unsigned char number_configurations;
-} usb_device_descriptor __attribute__((packed));
-
-#define USB_DEVICE_DESCRIPTOR_LENGTH 18
-#define USB_DEVICE_DESCRIPTOR_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE
-#define USB_DEVICE_DESCRIPTOR_USB11_LO 0x10
-#define USB_DEVICE_DESCRIPTOR_USB11_HI 0x01
-
-#define USB_DEVICE_DESCRIPTOR_CLASS_INTERFACE 0x00
-#define USB_DEVICE_DESCRIPTOR_CLASS_VENDOR 0x00FF
-#define USB_DEVICE_DESCRIPTOR_SUBCLASS_INTERFACE 0x00
-#define USB_DEVICE_DESCRIPTOR_SUBCLASS_VENDOR 0x00FF
-#define USB_DEVICE_DESCRIPTOR_PROTOCOL_INTERFACE 0x00
-#define USB_DEVICE_DESCRIPTOR_PROTOCOL_VENDOR 0x00FF
-
-typedef struct usb_configuration_descriptor {
- unsigned char length;
- unsigned char type;
- unsigned char total_length_lo;
- unsigned char total_length_hi;
- unsigned char number_interfaces;
- unsigned char configuration_id;
- unsigned char configuration_str;
- unsigned char attributes;
- unsigned char max_power;
-} usb_configuration_descriptor __attribute__((packed));
-
-#define USB_CONFIGURATION_DESCRIPTOR_LENGTH 9
-#define USB_CONFIGURATION_DESCRIPTOR_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION
-#define USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED (1 << 7)
-#define USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED (1 << 6)
-#define USB_CONFIGURATION_DESCRIPTOR_ATTR_REMOTE_WAKEUP (1 << 5)
-
-typedef struct usb_interface_descriptor {
- unsigned char length;
- unsigned char type;
- unsigned char interface_id;
- unsigned char alternate_setting;
- unsigned char number_endpoints;
- unsigned char interface_class;
- unsigned char interface_subclass;
- unsigned char interface_protocol;
- unsigned char interface_str;
-} usb_interface_descriptor __attribute__((packed));
-
-#define USB_INTERFACE_DESCRIPTOR_LENGTH 9
-#define USB_INTERFACE_DESCRIPTOR_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_INTERFACE
-#define USB_INTERFACE_DESCRIPTOR_CLASS_VENDOR 0x00FF
-#define USB_INTERFACE_DESCRIPTOR_SUBCLASS_VENDOR 0x00FF
-#define USB_INTERFACE_DESCRIPTOR_PROTOCOL_VENDOR 0x00FF
-
-typedef struct usb_endpoint_descriptor {
- unsigned char length;
- unsigned char type;
- unsigned char endpoint;
- unsigned char attributes;
- unsigned char max_packet_lo;
- unsigned char max_packet_hi;
- unsigned char interval;
-} usb_endpoint_descriptor;
-
-#define USB_ENDPOINT_DESCRIPTOR_LENGTH 7
-#define USB_ENDPOINT_DESCRIPTOR_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_ENDPOINT
-#define USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT 0
-#define USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN (1 << 7)
-#define USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL 0x00
-#define USB_ENDPOINT_DESCRIPTOR_ATTR_ISOCHRONOUS 0x01
-#define USB_ENDPOINT_DESCRIPTOR_ATTR_BULK 0x02
-#define USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT 0x03
-
-// String descriptors. If these are used at all then string 0
-// must be a table of supported LANGID codes. For a simple device
-// which only supports US English, the following sequence of
-// four bytes should suffice for string 0. In practice string
-// constants tend to be used which makes the use of these
-// #define's difficult.
-#define USB_STRING_DESCRIPTOR_STRING0_LENGTH 4
-#define USB_STRING_DESCRIPTOR_STRING0_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_STRING
-#define USB_STRING_DESCRIPTOR_STRING0_LANGID_LO 0x09
-#define USB_STRING_DESCRIPTOR_STRING0_LANGID_HI 0x04
-
-// For subsequent strings the length and data will have to be
-// determined by the application developer or by a suitable tool.
-#define USB_STRING_DESCRIPTOR_TYPE USB_DEVREQ_DESCRIPTOR_TYPE_STRING
-
-// Utility macros to calculate the total_length fields in a
-// configuration descriptor.
-#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(interfaces, endpoints) \
- (USB_CONFIGURATION_DESCRIPTOR_LENGTH + \
- (interfaces * USB_INTERFACE_DESCRIPTOR_LENGTH) + \
- (endpoints * USB_ENDPOINT_DESCRIPTOR_LENGTH)) % 256
-
-#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(interfaces, endpoints) \
- (USB_CONFIGURATION_DESCRIPTOR_LENGTH + \
- (interfaces * USB_INTERFACE_DESCRIPTOR_LENGTH) + \
- (endpoints * USB_ENDPOINT_DESCRIPTOR_LENGTH)) / 256
-
-#ifdef __cplusplus
-} // extern "C" {
-#endif
-
-#endif // CYGONCE_USB_H
-
Index: common/v2_0/ChangeLog
===================================================================
--- common/v2_0/ChangeLog (revision 174)
+++ common/v2_0/ChangeLog (nonexistent)
@@ -1,47 +0,0 @@
-2001-01-25 Bart Veer
-
- * cdl/usb.cdl:
- Correctly parent below CYGPKG_IO
-
-2000-11-22 Bart Veer
-
- * include/usb.h: Fix nested #include protection.
-
-2000-11-21 Bart Veer
-
- * First check-in of eCos USB support.
-
-//===========================================================================
-//####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####
-//===========================================================================
Index: slave/v2_0/cdl/usbs.cdl
===================================================================
--- slave/v2_0/cdl/usbs.cdl (revision 174)
+++ slave/v2_0/cdl/usbs.cdl (nonexistent)
@@ -1,134 +0,0 @@
-# ====================================================================
-#
-# usbs.cdl
-#
-# USB slave-side support
-#
-# ====================================================================
-#####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####
-#
-# Author(s): bartv
-# Original data: bartv
-# Contributors:
-# Date: 2000-10-04
-#
-#####DESCRIPTIONEND####
-#
-# ====================================================================
-
-cdl_package CYGPKG_IO_USB_SLAVE {
- display "USB slave-side support"
- parent CYGPKG_IO_USB
- include_dir "cyg/io/usb"
- active_if CYGHWR_IO_USB_SLAVE
- doc ref/io-usb-slave.html
-
- compile usbs.c
-
- cdl_interface CYGINT_IO_USB_SLAVE_CLIENTS {
- display "Number of clients of USB devices"
- description "
- This counter keeps track of the number of clients of
- USB devices, especially application-class packages such
- as the USB-ethernet support. It can be used by USB
- device drivers for default settings.
- "
- }
-
- cdl_option CYGGLO_IO_USB_SLAVE_APPLICATION {
- display "Application code uses USB devices"
- default_value 0
- implements CYGINT_IO_USB_SLAVE_CLIENTS
- description "
- If the USB devices are accessed by application code
- rather than by other packages then enabling this
- option will cause the USB device drivers to be enabled.
- "
- }
-
- cdl_option CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES {
- display "Provide devtab entries by default"
- default_value CYGPKG_IO
- requires CYGPKG_IO
- description "
- The USB slave-side endpoints can typically be accessed in two
- different ways. There is support for the traditional way of
- doing I/O with open/read/write calls, which involves the
- use of devtab entries. It is also possible to use a
- USB-specific API, defined largely in terms of asynchronous
- operations and callbacks (the read/write implementation uses
- these lower-level calls). If neither the application nor
- any other USB-related packages require the higher-level
- read/write calls then it is possible to save some memory
- by eliminating the devtab entries.
- "
- }
-
- cdl_interface CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS {
- display "Number of available host->slave endpoints"
- }
- cdl_interface CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS {
- display "Number of available slave->host endpoints"
- }
-
- cdl_option CYGBLD_IO_USB_SLAVE_USBTEST {
- display "Build the main USB test program"
- doc ref/usbs-testing.html
- description "
- The USB slave-side software is supplied with host-side
- and target-side software that allows a variety of testing
- to be performed. The slave-side software is not built
- by default since it can only operate in specific environments
- and in conjunction with the host-side software. Enabling
- this option causes the slave-side software to be added
- to the list of test cases for the current configuration."
- default_value 0
- implements CYGINT_IO_USB_SLAVE_CLIENTS
- requires { is_substr(CYGPKG_IO_USB_SLAVE_TESTS, " tests/usbtarget") }
-
- requires CYGFUN_KERNEL_API_C CYGFUN_KERNEL_THREADS_TIMER !CYGINT_KNEREL_SCHEDULER_UNIQUE_PRIORITIES
- requires CYGPKG_LIBC_STDIO CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
- }
-
- cdl_option CYGPKG_IO_USB_SLAVE_TESTS {
- display "Kernel tests"
- flavor data
- no_define
- default_value { "" }
- description "This option specifies the set of tests to be
- built for the USB slave package"
- }
-}
Index: slave/v2_0/tests/usbtarget.c
===================================================================
--- slave/v2_0/tests/usbtarget.c (revision 174)
+++ slave/v2_0/tests/usbtarget.c (nonexistent)
@@ -1,1848 +0,0 @@
-/*{{{ 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "protocol.h"
-
-/*}}}*/
-
-/*{{{ Statics */
-
-// ----------------------------------------------------------------------------
-// Statics.
-
-// The number of endpoints supported by the device driver.
-static int number_endpoints = 0;
-
-// The control endpoint
-static 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 void
-usbs_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 void
-fix_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 void
-heartbeat_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 void
-start_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 void
-lock_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 void
-unlock_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_bool
-is_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 int
-lookup_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;
- }
- }
- return result;
-}
-
-/*}}}*/
-/*{{{ Enumeration data */
-
-// ----------------------------------------------------------------------------
-// The enumeration data.
-//
-// For simplicity this configuration involves just a single interface.
-// The target has to list all the endpoints, or the Linux kernel will
-// not allow application code to access them. Hence the information
-// provided by the device drivers has to be turned into endpoint descriptors.
-
-usb_configuration_descriptor usb_configuration = {
- length: USB_CONFIGURATION_DESCRIPTOR_LENGTH,
- type: USB_CONFIGURATION_DESCRIPTOR_TYPE,
- total_length_lo: USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(1, 0),
- total_length_hi: USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(1, 0),
- number_interfaces: 1,
- configuration_id: 1, // id 0 is special according to the spec
- configuration_str: 0,
- attributes: USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED |
- USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED,
- max_power: 50
-};
-
-usb_interface_descriptor usb_interface = {
- length: USB_INTERFACE_DESCRIPTOR_LENGTH,
- type: USB_INTERFACE_DESCRIPTOR_TYPE,
- interface_id: 0,
- alternate_setting: 0,
- number_endpoints: 0,
- interface_class: USB_INTERFACE_DESCRIPTOR_CLASS_VENDOR,
- interface_subclass: USB_INTERFACE_DESCRIPTOR_SUBCLASS_VENDOR,
- interface_protocol: USB_INTERFACE_DESCRIPTOR_PROTOCOL_VENDOR,
- interface_str: 0
-};
-
-usb_endpoint_descriptor usb_endpoints[USBTEST_MAX_ENDPOINTS];
-
-const unsigned char* usb_strings[] = {
- "\004\003\011\004",
- "\020\003R\000e\000d\000 \000H\000a\000t\000",
- "\054\003R\000e\000d\000 \000H\000a\000t\000 \000e\000C\000o\000s\000 \000"
- "U\000S\000B\000 \000t\000e\000s\000t\000"
-};
-
-usbs_enumeration_data usb_enum_data = {
- {
- length: USB_DEVICE_DESCRIPTOR_LENGTH,
- type: USB_DEVICE_DESCRIPTOR_TYPE,
- usb_spec_lo: USB_DEVICE_DESCRIPTOR_USB11_LO,
- usb_spec_hi: USB_DEVICE_DESCRIPTOR_USB11_HI,
- device_class: USB_DEVICE_DESCRIPTOR_CLASS_VENDOR,
- device_subclass: USB_DEVICE_DESCRIPTOR_SUBCLASS_VENDOR,
- device_protocol: USB_DEVICE_DESCRIPTOR_PROTOCOL_VENDOR,
- max_packet_size: 8,
- vendor_lo: 0x42, // Note: this is not an allocated vendor id
- vendor_hi: 0x42,
- product_lo: 0x00,
- product_hi: 0x01,
- device_lo: 0x00,
- device_hi: 0x01,
- manufacturer_str: 1,
- product_str: 2,
- serial_number_str: 0,
- number_configurations: 1
- },
- total_number_interfaces: 1,
- total_number_endpoints: 0,
- total_number_strings: 3,
- configurations: &usb_configuration,
- interfaces: &usb_interface,
- endpoints: usb_endpoints,
- strings: usb_strings
-};
-
-static void
-provide_endpoint_enumeration_data(void)
-{
- int enum_endpoint_count = 0;
- int i;
-
- for (i = 0; !USBS_TESTING_ENDPOINTS_IS_TERMINATOR(usbs_testing_endpoints[i]); i++) {
-
- // The control endpoint need not appear in the enumeration data.
- if (USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL == usbs_testing_endpoints[i].endpoint_type) {
- continue;
- }
-
- usb_endpoints[enum_endpoint_count].length = USB_ENDPOINT_DESCRIPTOR_LENGTH;
- usb_endpoints[enum_endpoint_count].type = USB_ENDPOINT_DESCRIPTOR_TYPE;
- usb_endpoints[enum_endpoint_count].endpoint = usbs_testing_endpoints[i].endpoint_number |
- usbs_testing_endpoints[i].endpoint_direction;
-
- switch (usbs_testing_endpoints[i].endpoint_type) {
- case USB_ENDPOINT_DESCRIPTOR_ATTR_BULK:
- usb_endpoints[enum_endpoint_count].attributes = USB_ENDPOINT_DESCRIPTOR_ATTR_BULK;
- usb_endpoints[enum_endpoint_count].max_packet_lo = 64;
- usb_endpoints[enum_endpoint_count].max_packet_hi = 0;
- usb_endpoints[enum_endpoint_count].interval = 0;
- break;
-
- case USB_ENDPOINT_DESCRIPTOR_ATTR_ISOCHRONOUS:
- usb_endpoints[enum_endpoint_count].attributes = USB_ENDPOINT_DESCRIPTOR_ATTR_ISOCHRONOUS;
- usb_endpoints[enum_endpoint_count].max_packet_lo = usbs_testing_endpoints[i].max_size & 0x0FF;
- usb_endpoints[enum_endpoint_count].max_packet_hi = (usbs_testing_endpoints[i].max_size >> 8) & 0x0FF;
- usb_endpoints[enum_endpoint_count].interval = 1;
- break;
-
- case USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT:
- usb_endpoints[enum_endpoint_count].attributes = USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT;
- usb_endpoints[enum_endpoint_count].max_packet_lo = (unsigned char) usbs_testing_endpoints[i].max_size;
- usb_endpoints[enum_endpoint_count].max_packet_hi = 0;
- usb_endpoints[enum_endpoint_count].interval = 1; // NOTE: possibly incorrect
- break;
- }
-
- enum_endpoint_count++;
- }
-
- usb_interface.number_endpoints = enum_endpoint_count;
- usb_enum_data.total_number_endpoints = enum_endpoint_count;
- usb_configuration.total_length_lo = USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(1, enum_endpoint_count);
- usb_configuration.total_length_hi = USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(1, enum_endpoint_count);
-}
-
-/*}}}*/
-/*{{{ Host/target common code */
-
-#define TARGET
-#include "common.c"
-
-/*}}}*/
-/*{{{ The tests */
-
-/*{{{ UsbTest structure */
-
-// ----------------------------------------------------------------------------
-// All the information associated with a particular testcase. Much of this
-// is identical to the equivalent host-side structure, but some additional
-// information is needed so the structure and associated routines are not
-// shared.
-typedef struct UsbTest {
-
- // A unique identifier to make verbose output easier to understand
- int id;
-
- // 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;
-
- // The test result, to be collected and passed back to the host.
- int result_pass;
- char result_message[USBTEST_MAX_MESSAGE];
-
- // Support for synchronization. This allows the UsbTest structure to be
- // used as the callback data for low-level USB calls.
- cyg_sem_t sem;
- int transferred;
-
- // Some tests may need extra cancellation support
- void (*cancel_fn)(struct UsbTest*);
- 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 void
-reset_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';
- cyg_semaphore_init(&(test->sem), 0);
- test->transferred = 0;
- test->cancel_fn = (void (*)(UsbTest*)) 0;
-}
-
-// Forward declaration. The pool code depends on run_test(), setting up a test requires the pool.
-static UsbTest* pool_allocate(void);
-
-/*}}}*/
-/*{{{ Bulk transfers */
-
-/*{{{ handle_test_bulk() */
-
-// Prepare for a bulk transfer test. This means allocating a thread to do
-// the work, and extracting the test parameters from the current buffer.
-// The thread allocation code does not require any locking since all worker
-// threads should be idle when starting a new thread, so the work can be
-// done entirely at DSR level and no synch is required.
-static usbs_control_return
-handle_test_bulk(usb_devreq* req)
-{
- UsbTest* test;
- int index = 0;
-
- test = pool_allocate();
- unpack_usbtest_bulk(&(test->test_params.bulk), class_request, &index);
- test->which_test = (USB_DEVREQ_DIRECTION_IN == (test->test_params.bulk.endpoint & USB_DEVREQ_DIRECTION_MASK)) ?
- usbtest_bulk_in : usbtest_bulk_out;
-
- VERBOSE(3, "Preparing USB bulk test on endpoint %d, direction %s, for %d packets\n", \
- test->test_params.bulk.endpoint & ~USB_DEVREQ_DIRECTION_MASK, \
- (usbtest_bulk_in == test->which_test) ? "IN" : "OUT", \
- test->test_params.bulk.number_packets);
- VERBOSE(3, " I/O mechanism is %s\n", \
- (usb_io_mechanism_usb == test->test_params.bulk.io_mechanism) ? "low-level USB" : \
- (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism) ? "devtab" : "");
- VERBOSE(3, " Data format %s, data1 %d, data* %d, data+ %d, data1* %d, data1+ %d, data** %d, data*+ %d, data+* %d, data++ %d\n",\
- (usbtestdata_none == test->test_params.bulk.data.format) ? "none" : \
- (usbtestdata_bytefill == test->test_params.bulk.data.format) ? "bytefill" : \
- (usbtestdata_wordfill == test->test_params.bulk.data.format) ? "wordfill" : \
- (usbtestdata_byteseq == test->test_params.bulk.data.format) ? "byteseq" : \
- (usbtestdata_wordseq == test->test_params.bulk.data.format) ? "wordseq" : "", \
- test->test_params.bulk.data.seed, \
- test->test_params.bulk.data.multiplier, \
- test->test_params.bulk.data.increment, \
- test->test_params.bulk.data.transfer_seed_multiplier, \
- test->test_params.bulk.data.transfer_seed_increment, \
- test->test_params.bulk.data.transfer_multiplier_multiplier, \
- test->test_params.bulk.data.transfer_multiplier_increment, \
- test->test_params.bulk.data.transfer_increment_multiplier, \
- test->test_params.bulk.data.transfer_increment_increment);
- VERBOSE(3, " txsize1 %d, txsize>= %d, txsize<= %d, txsize* %d, txsize/ %d, txsize+ %d\n", \
- test->test_params.bulk.tx_size, test->test_params.bulk.tx_size_min, \
- test->test_params.bulk.tx_size_max, test->test_params.bulk.tx_size_multiplier, \
- test->test_params.bulk.tx_size_divisor, test->test_params.bulk.tx_size_increment);
- VERBOSE(3, " rxsize1 %d, rxsize>= %d, rxsize<= %d, rxsize* %d, rxsize/ %d, rxsize+ %d\n", \
- test->test_params.bulk.rx_size, test->test_params.bulk.rx_size_min, \
- test->test_params.bulk.rx_size_max, test->test_params.bulk.rx_size_multiplier, \
- test->test_params.bulk.rx_size_divisor, test->test_params.bulk.rx_size_increment);
- VERBOSE(3, " txdelay1 %d, txdelay>= %d, txdelay<= %d, txdelay* %d, txdelay/ %d, txdelay+ %d\n", \
- test->test_params.bulk.tx_delay, test->test_params.bulk.tx_delay_min, \
- test->test_params.bulk.tx_delay_max, test->test_params.bulk.tx_delay_multiplier, \
- test->test_params.bulk.tx_delay_divisor, test->test_params.bulk.tx_delay_increment);
- VERBOSE(3, " rxdelay1 %d, rxdelay>= %d, rxdelay<= %d, rxdelay* %d, rxdelay/ %d, rxdelay+ %d\n", \
- test->test_params.bulk.rx_delay, test->test_params.bulk.rx_delay_min, \
- test->test_params.bulk.rx_delay_max, test->test_params.bulk.rx_delay_multiplier, \
- test->test_params.bulk.rx_delay_divisor, test->test_params.bulk.rx_delay_increment);
-
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ run_test_bulk_out() */
-
-// The same callback can be used for IN and OUT transfers. Note that
-// starting the next transfer is left to the thread, it is not done
-// at DSR level.
-static void
-run_test_bulk_in_out_callback(void* callback_arg, int transferred)
-{
- UsbTest* test = (UsbTest*) callback_arg;
- test->transferred = transferred;
- cyg_semaphore_post(&(test->sem));
-}
-
-// OUT transfers, i.e. the host will be sending some number of
-// packets. The I/O can happen in a number of different ways, e.g. via
-// the low-level USB API or via devtab routines.
-static void
-run_test_bulk_out(UsbTest* test)
-{
- unsigned char* buf;
- int endpoint_number = test->test_params.bulk.endpoint & ~USB_DEVREQ_DIRECTION_MASK;
- int ep_index;
- usbs_rx_endpoint* endpoint = 0;
- cyg_io_handle_t io_handle = (cyg_io_handle_t)0;
- int alignment;
- int transferred;
- int i;
-
- VERBOSE(1, "Starting test %d, bulk out on endpoint %d\n", test->id, endpoint_number);
-
- ep_index = lookup_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK);
- if (ep_index == -1) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk OUT transfer on endpoint %d: no such bulk endpoint", endpoint_number);
- return;
- }
- endpoint = (usbs_rx_endpoint*) usbs_testing_endpoints[ep_index].endpoint;
- alignment = usbs_testing_endpoints[ep_index].alignment;
- if (0 != alignment) {
- buf = (unsigned char*) ((((cyg_uint32)test->buffer) + alignment - 1) & ~(alignment - 1));
- } else {
- buf = test->buffer;
- }
-
- CYG_ASSERTC((usb_io_mechanism_usb == test->test_params.bulk.io_mechanism) || \
- (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism));
- if (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism) {
- if (((const char*)0 == usbs_testing_endpoints[ep_index].devtab_entry) ||
- (0 != cyg_io_lookup(usbs_testing_endpoints[ep_index].devtab_entry, &io_handle))) {
-
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk OUT transfer on endpoint %d: no devtab entry", endpoint_number);
- return;
- }
- }
-
- // Make sure nobody else is using this endpoint
- lock_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT);
-
- for (i = 0; i < test->test_params.bulk.number_packets; i++) {
- int rx_size = test->test_params.bulk.rx_size;
- int tx_size = test->test_params.bulk.tx_size;
-
- VERBOSE(2, "Bulk OUT 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 OUT test %d: iteration %d, packet size reset to %d to match tx size\n",
- test->id, i, rx_size);
- }
-
- test->recovery.endpoint = endpoint_number | USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT;
- test->recovery.protocol = USB_ENDPOINT_DESCRIPTOR_ATTR_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);
- }
-
- // Do the actual transfer, using the I/O mechanism specified for this test.
- switch (test->test_params.bulk.io_mechanism)
- {
- case usb_io_mechanism_usb :
- {
- test->transferred = 0;
- usbs_start_rx_buffer(endpoint, buf, rx_size, &run_test_bulk_in_out_callback, (void*) test);
- cyg_semaphore_wait(&(test->sem));
- transferred = test->transferred;
- break;
- }
-
- case usb_io_mechanism_dev :
- {
- int result;
- transferred = rx_size;
- result = cyg_io_read(io_handle, (void*) buf, &transferred);
- if (result < 0) {
- transferred = result;
- }
- break;
- }
-
- default:
- CYG_FAIL("Invalid test mechanism specified");
- break;
- }
-
- // Has this test 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,
- "Target, bulk OUT transfer on endpoint %d: transfer aborted after iteration %d", endpoint_number, i);
- break;
- }
-
- // If an error occurred, abort this run
- if (transferred < 0) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk OUT transfer on endpoint %d: transfer failed with %d", endpoint_number, transferred);
- VERBOSE(2, "Bulk OUT test %d: iteration %d, error:\n %s\n", test->id, i, test->result_message);
- break;
- }
-
- // Did the host send the expected amount of data?
- if (transferred < test->test_params.bulk.tx_size) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk OUT transfer on endpoint %d : the host only sent %d bytes when %d were expected",
- endpoint_number, transferred, tx_size);
- VERBOSE(2, "Bulk OUT 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 OUT 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, transferred)) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk OUT transfer on endpoint %d : mismatch between received and expected data", endpoint_number);
- 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.rx_delay) {
- VERBOSE(2, "Bulk OUT test %d: iteration %d, sleeping for %d nanoseconds\n", test->id, \
- i, test->test_params.bulk.rx_delay);
- usbs_nanosleep(test->test_params.bulk.rx_delay);
- }
-
- // Move on to the next transfer
- USBTEST_BULK_NEXT(test->test_params.bulk);
- }
-
- // Always unlock the endpoint on completion
- unlock_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT);
-
- // 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, endpoint_number, test->result_pass);
-}
-
-/*}}}*/
-/*{{{ run_test_bulk_in() */
-
-// IN transfers, i.e. the host is expected to receive some data. These are slightly
-// easier than OUT transfers because it is the host that will do the checking.
-static void
-run_test_bulk_in(UsbTest* test)
-{
- unsigned char* buf;
- int endpoint_number = test->test_params.bulk.endpoint & ~USB_DEVREQ_DIRECTION_MASK;
- int ep_index;
- usbs_tx_endpoint* endpoint = 0;
- cyg_io_handle_t io_handle = (cyg_io_handle_t)0;
- int alignment;
- int transferred;
- int i;
-
- VERBOSE(1, "Starting test %d, bulk IN on endpoint %d\n", test->id, endpoint_number);
-
- ep_index = lookup_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK);
- if (ep_index == -1) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk IN transfer on endpoint %d: no such bulk endpoint", endpoint_number);
- return;
- }
- endpoint = (usbs_tx_endpoint*) usbs_testing_endpoints[ep_index].endpoint;
- alignment = usbs_testing_endpoints[ep_index].alignment;
- if (0 != alignment) {
- buf = (unsigned char*) ((((cyg_uint32)test->buffer) + alignment - 1) & ~(alignment - 1));
- } else {
- buf = test->buffer;
- }
-
- CYG_ASSERTC((usb_io_mechanism_usb == test->test_params.bulk.io_mechanism) || \
- (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism));
- if (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism) {
- if (((const char*)0 == usbs_testing_endpoints[ep_index].devtab_entry) ||
- (0 != cyg_io_lookup(usbs_testing_endpoints[ep_index].devtab_entry, &io_handle))) {
-
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk IN transfer on endpoint %d: no devtab entry", endpoint_number);
- return;
- }
- }
-
- // Make sure nobody else is using this endpoint
- lock_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN);
-
- for (i = 0; i < test->test_params.bulk.number_packets; i++) {
- int packet_size = test->test_params.bulk.tx_size;
-
- test->recovery.endpoint = endpoint_number | USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN;
- test->recovery.protocol = USB_ENDPOINT_DESCRIPTOR_ATTR_BULK;
- test->recovery.size = packet_size + usbs_testing_endpoints[ep_index].max_in_padding;
-
- // Make sure the buffer contains the data expected by the host
- 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 IN 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);
- }
-
- // Do the actual transfer, using the I/O mechanism specified for this test.
- switch (test->test_params.bulk.io_mechanism)
- {
- case usb_io_mechanism_usb :
- {
- test->transferred = 0;
- usbs_start_tx_buffer(endpoint, buf, packet_size, &run_test_bulk_in_out_callback, (void*) test);
- cyg_semaphore_wait(&(test->sem));
- transferred = test->transferred;
- break;
- }
-
- case usb_io_mechanism_dev :
- {
- int result;
- transferred = packet_size;
- result = cyg_io_write(io_handle, (void*) buf, &transferred);
- if (result < 0) {
- transferred = result;
- }
- break;
- }
-
- default:
- CYG_FAIL("Invalid test mechanism specified");
- break;
- }
-
- // Has this test been aborted for some reason?
- if (current_tests_terminated) {
- VERBOSE(2, "Bulk IN test %d: iteration %d, termination detected\n", test->id, i);
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk IN transfer on endpoint %d : terminated on iteration %d, packet_size %d\n",
- endpoint_number, i, packet_size);
- break;
- }
-
- // If an error occurred, abort this run
- if (transferred < 0) {
- test->result_pass = 0;
- snprintf(test->result_message, USBTEST_MAX_MESSAGE,
- "Target, bulk IN transfer on endpoint %d: transfer failed with %d", endpoint_number, transferred);
- VERBOSE(2, "Bulk IN test %d: iteration %d, error:\n %s\n", test->id, i, test->result_message);
- break;
- }
-
- // No need to check the transfer size, the USB code is only
- // allowed to send the exact amount of data requested.
-
- if (0 != test->test_params.bulk.tx_delay) {
- VERBOSE(2, "Bulk IN test %d: iteration %d, sleeping for %d nanoseconds\n", test->id, i, \
- test->test_params.bulk.tx_delay);
- usbs_nanosleep(test->test_params.bulk.tx_delay);
- }
-
- // Move on to the next transfer
- USBTEST_BULK_NEXT(test->test_params.bulk);
- }
-
- // Always unlock the endpoint on completion
- unlock_endpoint(endpoint_number, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN);
-
- // 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, endpoint_number, test->result_pass);
-}
-
-/*}}}*/
-
-/*}}}*/
-/*{{{ Control IN transfers */
-
-// Control-IN transfers. These have to be handled a little bit differently
-// from bulk transfers. The target never actually initiates anything. Instead
-// the host will send reserved control messages which are handled at DSR
-// level and passed to handle_reserved_control_messages() below. Assuming
-// a control-IN test is in progress, that will take appropriate action. The
-// thread will be woken up only once all packets have been transferred, or
-// on abnormal termination.
-
-// Is a control-IN test currently in progress?
-static UsbTest* control_in_test = 0;
-
-// What is the expected packet size?
-static int control_in_test_packet_size = 0;
-
-// How many packets have been transferred so far?
-static int control_in_packets_transferred = 0;
-
-// Cancel a control-in test. handle_test_control_in() will have updated the static
-// control_in_test so that handle_reserved_control_messages() knows what to do.
-// If the test is not actually going to be run then system consistency demands
-// that this update be undone. Also, the endpoint will have been locked to
-// detect concurrent tests on the control endpoint.
-static void
-cancel_test_control_in(UsbTest* test)
-{
- CYG_ASSERTC(test == control_in_test);
- control_in_test = (UsbTest*) 0;
- control_in_test_packet_size = 0;
- control_in_packets_transferred = 0;
- unlock_endpoint(0, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN);
- test->cancel_fn = (void (*)(UsbTest*)) 0;
-}
-
-// Prepare for a control-IN transfer test.
-static usbs_control_return
-handle_test_control_in(usb_devreq* req)
-{
- UsbTest* test;
- int index = 0;
-
- CYG_ASSERTC((UsbTest*)0 == control_in_test);
-
- test = pool_allocate();
- unpack_usbtest_control_in(&(test->test_params.control_in), class_request, &index);
-
- lock_endpoint(0, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN);
- test->which_test = usbtest_control_in;
- test->recovery.endpoint = 0;
- test->recovery.protocol = USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL;
- test->recovery.size = 0; // Does not actually matter
- test->cancel_fn = &cancel_test_control_in;
-
- // Assume a pass. Failures are easy to detect.
- test->result_pass = 1;
-
- control_in_test = test;
- control_in_test_packet_size = test->test_params.control_in.packet_size_initial;
- control_in_packets_transferred = 0;
-
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-// The thread for a control-in test. Actually all the hard work is done at DSR
-// level, so this thread serves simply to detect when the test has completed
-// and to perform some clean-ups.
-static void
-run_test_control_in(UsbTest* test)
-{
- CYG_ASSERTC(test == control_in_test);
-
- cyg_semaphore_wait(&(test->sem));
-
- // The DSR has detected that the test is complete.
- control_in_test = (UsbTest*) 0;
- control_in_test_packet_size = 0;
- control_in_packets_transferred = 0;
- test->cancel_fn = (void (*)(UsbTest*)) 0;
- unlock_endpoint(0, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN);
-}
-
-// ----------------------------------------------------------------------------
-// This is installed from inside main() as the handler for reserved
-// control messages.
-static usbs_control_return
-handle_reserved_control_messages(usbs_control_endpoint* endpoint, void* data)
-{
- usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
- usbs_control_return result;
-
- CYG_ASSERT(endpoint == control_endpoint, "control endpoint mismatch");
- switch(req->request) {
- case USBTEST_RESERVED_CONTROL_IN:
- {
- unsigned char* buf;
- int len;
-
- if ((UsbTest*)0 == control_in_test) {
- result = USBS_CONTROL_RETURN_STALL;
- break;
- }
-
- // Is this test over? If so indicate a failure because we
- // cannot have received all the control packets.
- if (current_tests_terminated) {
- control_in_test->result_pass = 0;
- snprintf(control_in_test->result_message, USBTEST_MAX_MESSAGE,
- "Target, control IN transfer: not all packets received.");
- cyg_semaphore_post(&(control_in_test->sem));
- control_in_test = (UsbTest*) 0;
- result = USBS_CONTROL_RETURN_STALL;
- break;
- }
-
- // A control-IN test is indeed in progress, and the current state is
- // held in control_in_test and control_in_test_packet_size. Check that
- // the packet size matches up, i.e. that host and target are in sync.
- len = (req->length_hi << 8) || req->length_lo;
- if (control_in_test_packet_size != len) {
- control_in_test->result_pass = 0;
- snprintf(control_in_test->result_message, USBTEST_MAX_MESSAGE,
- "Target, control IN transfer on endpoint %d : the host only requested %d bytes instead of %d",
- len, control_in_test_packet_size);
- cyg_semaphore_post(&(control_in_test->sem));
- control_in_test = (UsbTest*) 0;
- result = USBS_CONTROL_RETURN_STALL;
- break;
- }
-
- // Prepare a suitable reply buffer. This is happening at
- // DSR level so runtime is important, but with an upper
- // bound of 255 bytes the buffer should be small enough.
- buf = control_in_test->buffer;
- usbtest_fill_buffer(&(control_in_test->test_params.control_in.data), buf, control_in_test_packet_size);
- control_endpoint->buffer_size = control_in_test_packet_size;
- control_endpoint->buffer = buf;
- USBTEST_CONTROL_NEXT_PACKET_SIZE(control_in_test_packet_size, control_in_test->test_params.control_in);
-
- // Have all the packets been transferred?
- control_in_packets_transferred++;
- if (control_in_packets_transferred == control_in_test->test_params.control_in.number_packets) {
- cyg_semaphore_post(&(control_in_test->sem));
- control_in_test = (UsbTest*) 0;
- }
- result = USBS_CONTROL_RETURN_HANDLED;
- break;
- }
- default:
- CYG_FAIL("Unexpected reserved control message");
- break;
- }
-
- return result;
-}
-
-/*}}}*/
-
-// FIXME: add more tests.
-
-// 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 void
-run_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:
- CYG_TEST_FAIL_EXIT("Internal error, attempt to run unknown test.\n");
- break;
- }
-}
-
-/*}}}*/
-/*{{{ The thread pool */
-
-// ----------------------------------------------------------------------------
-// Just like on the host side, it is desirable to have a pool of
-// threads available to perform test operations. Strictly speaking
-// some tests will run without needing a separate thread, since many
-// operations can be performed at DSR level. However typical
-// application code will involve threads and it is desirable for test
-// code to behave the same way. Also, some operations like validating
-// the transferred data are expensive, and best done in thread context.
-
-typedef struct PoolEntry {
- cyg_sem_t wakeup;
- cyg_thread thread_data;
- cyg_handle_t thread_handle;
- char thread_name[16];
- char thread_stack[2 * CYGNUM_HAL_STACK_SIZE_TYPICAL];
- cyg_bool in_use;
- cyg_bool running;
- UsbTest test;
-} PoolEntry;
-
-// This array must be uninitialized, or the executable size would
-// be ludicrous.
-PoolEntry pool[USBTEST_MAX_CONCURRENT_TESTS];
-
-// The entry point for every thread in the pool. It just loops forever,
-// waiting until it is supposed to run a test.
-static void
-pool_thread_function(cyg_addrword_t arg)
-{
- PoolEntry* pool_entry = (PoolEntry*) arg;
-
- for ( ; ; ) {
- cyg_semaphore_wait(&(pool_entry->wakeup));
- run_test(&(pool_entry->test));
- pool_entry->running = 0;
- }
-}
-
-// Initialize all threads in the pool.
-static void
-pool_initialize(void)
-{
- int i;
- for (i = 0; i < USBTEST_MAX_CONCURRENT_TESTS; i++) {
- cyg_semaphore_init(&(pool[i].wakeup), 0);
- pool[i].in_use = 0;
- pool[i].running = 0;
- sprintf(pool[i].thread_name, "worker%d", i);
- cyg_thread_create( 0, &pool_thread_function, (cyg_addrword_t) &(pool[i]),
- pool[i].thread_name, pool[i].thread_stack, 2 * CYGNUM_HAL_STACK_SIZE_TYPICAL,
- &(pool[i].thread_handle), &(pool[i].thread_data));
- cyg_thread_resume(pool[i].thread_handle);
- }
-}
-
-// Allocate a single entry in the thread pool
-static UsbTest*
-pool_allocate(void)
-{
- UsbTest* result = (UsbTest*) 0;
-
- if (thread_counter == USBTEST_MAX_CONCURRENT_TESTS) {
- CYG_TEST_FAIL_EXIT("Internal error, thread resources exhaused.\n");
- }
-
- result = &(pool[thread_counter].test);
- thread_counter++;
- reset_usbtest(result);
- return result;
-}
-
-// Start all the threads that are supposed to be running tests.
-static void
-pool_start(void)
-{
- int i;
- for (i = 0; i < thread_counter; i++) {
- pool[i].running = 1;
- cyg_semaphore_post(&(pool[i].wakeup));
- }
-}
-
-/*}}}*/
-/*{{{ Class control messages */
-
-// ----------------------------------------------------------------------------
-// Handle class control messages. These provide the primary form of
-// communication between host and target. There are requests to find out
-// the number of endpoints, details of each endpoint, prepare a test run,
-// abort a test run, get status, terminate the target-side, and so on.
-// The handlers for starting specific test cases are kept alongside
-// the test cases themselves.
-//
-// Note that these handlers will typically be invoked from DSR context
-// and hence they are subject to the usual DSR restrictions.
-//
-// Problems have been experienced in some hosts sending control messages
-// that involve additional host->target data. An ugly workaround is
-// in place whereby any such data is sent in advance using separate
-// control messages.
-
-/*{{{ endpoint count */
-
-// How many endpoints are supported by this device? That information is
-// determined during initialization.
-static usbs_control_return
-handle_endpoint_count(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));
-
- class_reply[0] = (unsigned char) number_endpoints;
- control_endpoint->buffer = class_reply;
- control_endpoint->buffer_size = 1;
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ endpoint details */
-
-// The host wants to know the details of a specific USB endpoint.
-// The format is specified in protocol.h
-static usbs_control_return
-handle_endpoint_details(usb_devreq* req)
-{
- int buf_index;
-
- CYG_ASSERTC((req->type & USB_DEVREQ_DIRECTION_MASK) == USB_DEVREQ_DIRECTION_IN);
- CYG_ASSERTC((USBTEST_MAX_CONTROL_DATA == req->length_lo) && (0 == req->length_hi));
- CYG_ASSERTC(req->index_lo < number_endpoints);
- CYG_ASSERTC((0 == req->index_hi) && (0 == req->value_lo) && (0 == req->value_hi));
-
- class_reply[0] = (unsigned char) usbs_testing_endpoints[req->index_lo].endpoint_type;
- class_reply[1] = (unsigned char) usbs_testing_endpoints[req->index_lo].endpoint_number;
- class_reply[2] = (unsigned char) usbs_testing_endpoints[req->index_lo].endpoint_direction;
- class_reply[3] = (unsigned char) usbs_testing_endpoints[req->index_lo].max_in_padding;
- buf_index = 4;
- pack_int(usbs_testing_endpoints[req->index_lo].min_size, class_reply, &buf_index);
- pack_int(usbs_testing_endpoints[req->index_lo].max_size, class_reply, &buf_index);
- if (NULL == usbs_testing_endpoints[req->index_lo].devtab_entry) {
- class_reply[buf_index] = '\0';
- control_endpoint->buffer_size = buf_index + 1;
- } else {
- int len = strlen(usbs_testing_endpoints[req->index_lo].devtab_entry) + buf_index + 1;
- if (len > USBTEST_MAX_CONTROL_DATA) {
- return USBS_CONTROL_RETURN_STALL;
- } else {
- strcpy(&(class_reply[buf_index]), usbs_testing_endpoints[req->index_lo].devtab_entry);
- control_endpoint->buffer_size = len;
- }
- }
- control_endpoint->buffer = class_reply;
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ sync */
-
-// The host wants to know whether or not the target is currently busy doing
-// stuff. This information is held in a static.
-static usbs_control_return
-handle_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 context
-static void
-handle_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 context
-static usbs_control_return
-handle_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 void
-handle_abort_action(void)
-{
- CYG_TEST_FAIL_EXIT("Test abort requested by host application");
-}
-
-static usbs_control_return
-handle_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 void
-handle_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 context
-static usbs_control_return
-handle_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_return
-handle_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_return
-handle_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_return
-handle_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_return
-handle_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 void
-recovery_callback(void* callback_arg, int transferred)
-{
- CYG_UNUSED_PARAM(void*, callback_arg);
- CYG_UNUSED_PARAM(int, transferred);
-}
-
-static usbs_control_return
-handle_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 byte for
-// a pass, or a single byte plus a message for a failure.
-
-static usbs_control_return
-handle_get_result(usb_devreq* req)
-{
- CYG_ASSERTC((USBTEST_MAX_CONTROL_DATA == 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-result operation should not involve any data");
- CYG_ASSERT(running, "Results can only be sent if a run is in progress");
- CYG_ASSERT(!pool[req->index_lo].running, "Cannot request results for a test that has not completed");
-
- class_reply[0] = pool[req->index_lo].test.result_pass;
- if (class_reply[0]) {
- control_endpoint->buffer_size = 1;
- } else {
- strncpy(&(class_reply[1]), pool[req->index_lo].test.result_message, USBTEST_MAX_CONTROL_DATA - 2);
- class_reply[USBTEST_MAX_CONTROL_DATA - 1] = '\0';
- control_endpoint->buffer_size = 1 + strlen(&(class_reply[1])) + 1;
- }
- control_endpoint->buffer = class_reply;
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ batch done */
-
-// A batch of test has been completed - at least, the host thinks so.
-// If the host is correct then all that is required here is to reset
-// the thread pool and clear the global running flag - that is sufficient
-// to allow a new batch of tests to be started.
-
-static usbs_control_return
-handle_batch_done(usb_devreq* req)
-{
- int i;
-
- 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 batch-done operation should not involve any data");
- CYG_ASSERT(running, "There must be a current batch of tests");
-
- for (i = 0; i < thread_counter; i++) {
- CYG_ASSERTC(!pool[i].running);
- }
- thread_counter = 0;
- running = false;
-
- return USBS_CONTROL_RETURN_HANDLED;
-
-}
-
-/*}}}*/
-/*{{{ verbosity */
-
-static usbs_control_return
-handle_verbose(usb_devreq* req)
-{
- CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));
- CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi));
- CYG_ASSERT(0 == class_request_size, "A set-verbosity operation should not involve any data");
-
- verbose = (req->value_hi << 8) + req->value_lo;
-
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ initialise bulk out endpoint */
-
-// ----------------------------------------------------------------------------
-// Accept an initial endpoint on a bulk endpoint. This avoids problems
-// on some hardware such as the SA11x0 which can start to accept data
-// before the software is ready for it.
-
-static void handle_init_callback(void* arg, int result)
-{
- idle = true;
-}
-
-static usbs_control_return
-handle_init_bulk_out(usb_devreq* req)
-{
- static char buf[64];
- int ep_index;
- usbs_rx_endpoint* endpoint;
-
- CYG_ASSERTC((0 == req->length_lo) && (0 == req->length_hi));
- CYG_ASSERTC((0 == req->index_lo) && (0 == req->index_hi));
- CYG_ASSERTC((0 == req->value_hi) && (0 < req->value_lo) && (req->value_lo < 16));
- CYG_ASSERT(0 == class_request_size, "An init_bulk_out operation should not involve any data");
-
- ep_index = lookup_endpoint(req->value_lo, USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT, USB_ENDPOINT_DESCRIPTOR_ATTR_BULK);
- CYG_ASSERTC(-1 != ep_index);
- endpoint = (usbs_rx_endpoint*) usbs_testing_endpoints[ep_index].endpoint;
-
- idle = false;
- usbs_start_rx_buffer(endpoint, buf, 64, &handle_init_callback, (void*) 0);
-
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-/*{{{ additional control data */
-
-// Accumulate some more data in the control buffer, ahead of an upcoming
-// request.
-static usbs_control_return
-handle_control_data(usb_devreq* req)
-{
- class_request[class_request_size + 0] = req->value_hi;
- class_request[class_request_size + 1] = req->value_lo;
- class_request[class_request_size + 2] = req->index_hi;
- class_request[class_request_size + 3] = req->index_lo;
-
- switch(req->request) {
- case USBTEST_CONTROL_DATA1 : class_request_size += 1; break;
- case USBTEST_CONTROL_DATA2 : class_request_size += 2; break;
- case USBTEST_CONTROL_DATA3 : class_request_size += 3; break;
- case USBTEST_CONTROL_DATA4 : class_request_size += 4; break;
- }
-
- return USBS_CONTROL_RETURN_HANDLED;
-}
-
-/*}}}*/
-
-typedef struct class_handler {
- int request;
- usbs_control_return (*handler)(usb_devreq*);
-} class_handler;
-static class_handler class_handlers[] = {
- { USBTEST_ENDPOINT_COUNT, &handle_endpoint_count },
- { USBTEST_ENDPOINT_DETAILS, &handle_endpoint_details },
- { USBTEST_PASS, &handle_passfail },
- { USBTEST_PASS_EXIT, &handle_passfail },
- { USBTEST_FAIL, &handle_passfail },
- { USBTEST_FAIL_EXIT, &handle_passfail },
- { USBTEST_SYNCH, &handle_sync },
- { USBTEST_ABORT, &handle_abort },
- { USBTEST_CANCEL, &handle_cancel },
- { USBTEST_START, &handle_start },
- { USBTEST_FINISHED, &handle_finished },
- { USBTEST_SET_TERMINATED, &handle_set_terminated },
- { USBTEST_GET_RECOVERY, &handle_get_recovery },
- { USBTEST_PERFORM_RECOVERY, &handle_perform_recovery },
- { USBTEST_GET_RESULT, &handle_get_result },
- { USBTEST_BATCH_DONE, &handle_batch_done },
- { USBTEST_VERBOSE, &handle_verbose },
- { USBTEST_INIT_BULK_OUT, &handle_init_bulk_out },
- { USBTEST_TEST_BULK, &handle_test_bulk },
- { USBTEST_TEST_CONTROL_IN, &handle_test_control_in },
- { USBTEST_CONTROL_DATA1, &handle_control_data },
- { USBTEST_CONTROL_DATA2, &handle_control_data },
- { USBTEST_CONTROL_DATA3, &handle_control_data },
- { USBTEST_CONTROL_DATA4, &handle_control_data },
- { -1, (usbs_control_return (*)(usb_devreq*)) 0 }
-};
-
-static usbs_control_return
-handle_class_control_messages(usbs_control_endpoint* endpoint, void* data)
-{
- usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
- int request = req->request;
- usbs_control_return result;
- int i;
-
- VERBOSE(3, "Received control message %02x\n", request);
-
- CYG_ASSERT(endpoint == control_endpoint, "control endpoint mismatch");
- result = USBS_CONTROL_RETURN_UNKNOWN;
- for (i = 0; (usbs_control_return (*)(usb_devreq*))0 != class_handlers[i].handler; i++) {
- if (request == class_handlers[i].request) {
- result = (*(class_handlers[i].handler))(req);
- if ((USBTEST_CONTROL_DATA1 != request) &&
- (USBTEST_CONTROL_DATA2 != request) &&
- (USBTEST_CONTROL_DATA3 != request) &&
- (USBTEST_CONTROL_DATA4 != request)) {
- // Reset the request data buffer after all normal requests.
- class_request_size = 0;
- }
- break;
- }
- }
- CYG_UNUSED_PARAM(void*, data);
- if (USBS_CONTROL_RETURN_HANDLED != result) {
- VERBOSE(1, "Control message %02x not handled\n", request);
- }
-
- return result;
-}
-
-/*}}}*/
-/*{{{ main() */
-
-// ----------------------------------------------------------------------------
-// Initialization.
-int
-main(int argc, char** argv)
-{
- int i;
-
- CYG_TEST_INIT();
-
- // The USB device driver should have provided an array of endpoint
- // descriptors, usbs_testing_endpoints(). One entry in this array
- // should be a control endpoint, which is needed for initialization.
- // It is also useful to know how many endpoints there are.
- for (i = 0; !USBS_TESTING_ENDPOINTS_IS_TERMINATOR(usbs_testing_endpoints[i]); i++) {
- if ((0 == usbs_testing_endpoints[i].endpoint_number) &&
- (USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL== usbs_testing_endpoints[i].endpoint_type)) {
- CYG_ASSERT((usbs_control_endpoint*)0 == control_endpoint, "There should be only one control endpoint");
- control_endpoint = (usbs_control_endpoint*) usbs_testing_endpoints[i].endpoint;
- }
- }
- if ((usbs_control_endpoint*)0 == control_endpoint) {
- CYG_TEST_FAIL_EXIT("Unable to find a USB control endpoint");
- }
- number_endpoints = i;
- CYG_ASSERT(number_endpoints <= USBTEST_MAX_ENDPOINTS, "impossible number of endpoints");
-
- // Some of the information provided may not match the actual capabilities
- // of the testing code, e.g. max_size limits.
- fix_driver_endpoint_data();
-
- // This semaphore is used for communication between the DSRs that process control
- // messages and the main thread
- cyg_semaphore_init(&main_wakeup, 0);
-
- // Take care of the pool of threads and related data.
- pool_initialize();
-
- // Start the heartbeat thread, to make sure that the gdb session stays
- // alive.
- start_heartbeat();
-
- // Now it is possible to start up the USB device driver. The host can detect
- // this, connect, get the enumeration data, and then testing will proceed
- // in response to class control messages.
- provide_endpoint_enumeration_data();
- control_endpoint->enumeration_data = &usb_enum_data;
- control_endpoint->class_control_fn = &handle_class_control_messages;
- control_endpoint->reserved_control_fn = &handle_reserved_control_messages;
- usbs_start(control_endpoint);
-
- // Now it is over to the host to detect this target and start performing tests.
- // Much of this is handled at DSR level, in response to USB control messages.
- // Some of those control messages require action at thread level, and that is
- // achieved by signalling a semaphore and waking up this thread. A static
- // function pointer is used to keep track of what operation is actually required.
- for (;;) {
- void (*handler)(void);
-
- cyg_semaphore_wait(&main_wakeup);
- handler = main_thread_action;
- main_thread_action = 0;
- CYG_CHECK_FUNC_PTR(handler, "Main thread woken up when there is nothing to be done");
- (*handler)();
- idle = true;
- }
-}
-
-/*}}}*/
Index: slave/v2_0/tests/protocol.h
===================================================================
--- slave/v2_0/tests/protocol.h (revision 174)
+++ slave/v2_0/tests/protocol.h (nonexistent)
@@ -1,194 +0,0 @@
-//=================================================================
-//
-// protocol.h
-//
-// USB testing - host<->target protocol
-//
-//==========================================================================
-//####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 header file is shared between target and host, and serves to
-// define certain aspects of the protocol used between the two such
-// as request codes.
-//
-// Author(s): bartv
-// Date: 2001-07-04
-//####DESCRIPTIONEND####
-//==========================================================================
-
-// The largest control packet that will be sent or expected.
-#define USBTEST_MAX_CONTROL_DATA 255
-
-// The largest error message that can be sent.
-#define USBTEST_MAX_MESSAGE 254
-
-// The largest bulk transfer that will be sent or expected. Because of
-// the use of the USB devfs support in the Linux kernel this is
-// currently limited to a single page, i.e. 4096 bytes. To allow for
-// padding, it is actually reduced to a slightly smaller size of 4090
-// bytes. This should still be sufficient to test most interesting
-// boundary conditions, apart from the transition to >64K.
-//
-// A small amount of additional buffer space should be allocated by
-// both host and target to allow for padding and possibly cache
-// alignment. All other protocols involve smaller transfers than this,
-// <= 64 bytes for interrupt transfers, <= 1023 for isochronous.
-#define USBTEST_MAX_BULK_DATA (4096)
-#define USBTEST_MAX_BULK_DATA_EXTRA 1024
-
-// The maximum number of tests that can be run concurrently. Each
-// needs a separate thread, stack, and buffer so there are memory
-// consumption implications.
-#define USBTEST_MAX_CONCURRENT_TESTS 8
-
-// Allow the host to find out the number of endpoints supported on
-// this target. The theoretical maximum number of endpoints is 91
-// (endpoint 0 control, endpoint 1-15 for both IN and OUT bulk, iso
-// and interrupt) so a single byte response will suffice. The value
-// and index fields are not used.
-#define USBTEST_MAX_ENDPOINTS 91
-#define USBTEST_ENDPOINT_COUNT 0x001
-
-// Get hold of additional information about a specific entry in the
-// array of endpoint details. The index field in the request
-// identifies the entry of interest. The reply information is as per
-// the usbs_testing_endpoint structure, and consists of:
-// 1) one byte, the endpoint type (control, bulk, ...)
-// 2) one byte, the endpoint number (as opposed to the array index number)
-// 3) one byte for direction, USB_DIR_IN or USB_DIR_OUT
-// 4) one byte for max_in_padding, usually 0
-// 5) four bytes for min_size, 32-bit little-endian integer
-// 6) four bytes for max_size, 32-bit little-endian integer
-// 7) an additional n bytes for the devtab name, max ~240 bytes
-// although usually far less.
-#define USBTEST_ENDPOINT_DETAILS 0x002
-
-// Report pass or failure. The host will send a string of up to
-// MAX_CONTROL_DATA bytes. The value and index fields are not used.
-#define USBTEST_PASS 0x003
-#define USBTEST_PASS_EXIT 0x004
-#define USBTEST_FAIL 0x005
-#define USBTEST_FAIL_EXIT 0x006
-
-// Synchronise. One problem with the current eCos USB API is that
-// there is no way to have a delayed response to a control message.
-// Any such support would be tricky, there are significant differences
-// in the hardware implementations and also timing constraints that
-// need to be satisfied. Instead the entire response to any control
-// request has to be prepared at DSR level. Usually this does not
-// cause any problems, e.g. for handling the standard control
-// messages, but for USB testing it may not be possible to handle a
-// request entirely at DSR level - yet the next full request should
-// not come in until the current one has been handled at thread-level.
-// To work around this there is support for a synchronization control
-// message. The return value is a single byte, 1 if the target is
-// ready for new requests, 0 if there is a still a request being
-// processed. The host can then perform some polling.
-#define USBTEST_SYNCH 0x007
-
-// Abort. There is no easy way to get both host and target back to a
-// known state, so abort the current test run.
-#define USBTEST_ABORT 0x008
-
-// Cancel the current batch of tests. Something has gone wrong at the
-// Tcl level, so any tests already prepared must be abandoned. No
-// additional data is required.
-#define USBTEST_CANCEL 0x009
-
-// Start the current batch of tests. No additional data is involved
-// or expected.
-#define USBTEST_START 0x00A
-
-// Has the current batch of tests finished? The host side polls the
-// target at regular intervals for this information.
-#define USBTEST_FINISHED 0x00B
-
-// Set the test-terminated flag. Something has gone wrong, probably a
-// timeout.
-#define USBTEST_SET_TERMINATED 0x00C
-
-// Get hold of recovery information for thread i in the target, where
-// the index field of the request identifies the thread. The result
-// is zero-bytes if the specified test has already finished, otherwise
-// a recovery structure.
-#define USBTEST_GET_RECOVERY 0x00D
-
-// The target should perform a recovery action to unlock a thread
-// on the host. The request holds a recovery structure.
-#define USBTEST_PERFORM_RECOVERY 0x00E
-
-// Collect the test result. The result is a single byte that indicates
-// pass or fail, optionally followed by a failure message.
-#define USBTEST_GET_RESULT 0x00F
-
-// The current batch of tests has completed. Perform any final clean-ups.
-#define USBTEST_BATCH_DONE 0x010
-
-// Set the verbosity level on the target-side
-#define USBTEST_VERBOSE 0x011
-
-// Perform endpoint initialization to ensure host and target
-// can actually communicate over a given endpoint
-#define USBTEST_INIT_CONTROL 0x012
-#define USBTEST_INIT_BULK_IN 0x013
-#define USBTEST_INIT_BULK_OUT 0x014
-#define USBTEST_INIT_ISO_IN 0x015
-#define USBTEST_INIT_ISO_OUT 0x016
-#define USBTEST_INIT_INTERRUPT_IN 0x017
-#define USBTEST_INIT_INTERRUPT_OUT 0x018
-
-
-// A standard bulk test. The data consists of a UsbTest_Bulk
-// structure, suitably packed.
-#define USBTEST_TEST_BULK 0x040
-
-// A control-IN test. The host will send reserved control messages with
-// an appropriate length field, and the target should return that data.
-#define USBTEST_TEST_CONTROL_IN 0x041
-
-// Sub-protocols for reserved control messages, supporting test operations
-// other than control-IN.
-#define USBTEST_RESERVED_CONTROL_IN 0x01
-
-// Work around a problem with control messages that involve additional
-// data from host to target. This problem is not yet well-understood.
-// The workaround involves sending multiple control packets with
-// up to four bytes encoded in the index and value fields.
-#define USBTEST_CONTROL_DATA1 0x0F1
-#define USBTEST_CONTROL_DATA2 0x0F2
-#define USBTEST_CONTROL_DATA3 0x0F3
-#define USBTEST_CONTROL_DATA4 0x0F4
-
Index: slave/v2_0/tests/common.c
===================================================================
--- slave/v2_0/tests/common.c (revision 174)
+++ slave/v2_0/tests/common.c (nonexistent)
@@ -1,681 +0,0 @@
-/*{{{ Banner */
-
-/*=================================================================
-//
-// common.c
-//
-// USB testing - code common to host and target
-//
-//==========================================================================
-//####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 module contains some definitions and functions that are common to
-// both the host and target side of USB testing, for example filling in
-// a buffer with well-known data and validating the contents at the other end.
-// The module is #include'd by other code rather than compiled separately,
-// which simplifies the build process.
-//
-// Author(s): bartv
-// Date: 2001-08-14
-//####DESCRIPTIONEND####
-//==========================================================================
-*/
-
-/*}}}*/
-
-/*{{{ Simple data pack and unpack operations */
-
-// ----------------------------------------------------------------------------
-// Utilities to pack and unpack data into buffers.
-//
-// Integers are transferred with 32 bits of precision, irrespective
-// of the capabilities of either target and host.
-
-static inline void
-pack_int(int datum, unsigned char* buffer, int* index_ptr)
-{
- int index = *index_ptr;
- buffer[index++] = (datum >> 0) & 0x0FF;
- buffer[index++] = (datum >> 8) & 0x0FF;
- buffer[index++] = (datum >> 16) & 0x0FF;
- buffer[index++] = (datum >> 24) & 0x0FF;
- *index_ptr = index;
-}
-
-static inline int
-unpack_int(unsigned char* buffer, int* index_ptr)
-{
- int index = *index_ptr;
- int result;
-
- result = (buffer[index++] << 0);
- result |= (buffer[index++] << 8);
- result |= (buffer[index++] << 16);
- result |= (buffer[index++] << 24);
- *index_ptr = index;
- return result;
-}
-
-/*}}}*/
-/*{{{ Buffer data and validation */
-
-// ----------------------------------------------------------------------------
-// The data required for a given test. For some test cases, for
-// example when trying to achieve maximum throughput, it does not
-// matter what data is transferred. For other tests it is important to
-// validate that the data sent and received match up, and there should
-// be some control over the actual data: some tests might want to send
-// a long sequence of byte 0, while others want to send more random data
-// for which a simple random number generator is useful.
-//
-// Exactly the same routines are used on both host and target to fill in
-// and check buffers, and they are sufficiently simple that the routines
-// should get compiled in compatible ways.
-//
-// There is no support at present for sending specific data, e.g. a
-// specific ethernet packet that appears to be causing problems. Knowledge
-// of specific data cannot be compiled into the test code, so the only
-// way to implement something like this would be to transfer the
-// problematical data over the USB bus in order to determine whether or
-// not the bus is capable of reliably transferring this data. That is
-// not entirely impossible (checksums, use of alternative endpoints),
-// but it is not implemented.
-//
-// An alternative approach would be to support a bounce operation
-// involving both an IN and an OUT endpoint, doing validation only on
-// the host. Again that is not yet implemented.
-//
-// The byte_fill and int_fill options are actually redundant because the
-// same effect can be achieved using a multiplier of 1 and an increment
-// of 0, but they can be implemented much more efficiently so may be
-// useful for benchmarks.
-
-typedef enum usbtestdata {
- usbtestdata_none = 0, // There is nothing useful in the data
- usbtestdata_bytefill = 1, // The data consists of a single byte, repeated
- usbtestdata_wordfill = 2, // Or a single integer
- usbtestdata_byteseq = 3, // Or a pseudo-random sequence (a * seed) + b
- usbtestdata_wordseq = 4 // as either bytes or integers
-} usbtestdata;
-
-typedef struct UsbTestData {
- usbtestdata format;
- int seed;
- int multiplier; // 1103515245
- int increment; // 12345
- int transfer_seed_multiplier;
- int transfer_seed_increment;
- int transfer_multiplier_multiplier;
- int transfer_multiplier_increment;
- int transfer_increment_multiplier;
- int transfer_increment_increment;
-} UsbTestData;
-
-static void
-usbtest_fill_buffer(UsbTestData* how, unsigned char* buffer, int length)
-{
- switch(how->format)
- {
- case usbtestdata_none:
- return;
-
- case usbtestdata_bytefill:
- // Leave it to the system to optimise memset().
- memset(buffer, (how->seed & 0x0FF), length);
- break;
-
- case usbtestdata_wordfill:
- {
- // The buffer may not be a multiple of four bytes, so the last entry is always
- // zero'd.
- int i;
- int index = 0;
- for (i = 0; i < (length / 4); i++) {
- pack_int(how->seed, buffer, &index);
- }
- pack_int(0, buffer, &index);
- break;
- }
-
- case usbtestdata_byteseq:
- {
- int i;
- for (i = 0; i < length; i++) {
- buffer[i] = (how->seed & 0x00FF);
- how->seed *= how->multiplier;
- how->seed += how->increment;
- }
- break;
- }
-
- case usbtestdata_wordseq:
- {
- int i;
- int index = 0;
- for (i = 0; i < (length / 4); i++) {
- pack_int(how->seed, buffer, &index);
- how->seed *= how->multiplier;
- how->seed += how->increment;
- }
- pack_int(0, buffer, &index);
- break;
- }
- }
-
- // After each transfer update the seed, multiplier and increment
- // ready for the next one.
- how->seed *= how->transfer_seed_multiplier;
- how->seed += how->transfer_seed_increment;
- how->multiplier *= how->transfer_multiplier_multiplier;
- how->multiplier += how->transfer_multiplier_increment;
- how->increment *= how->transfer_increment_multiplier;
- how->increment += how->transfer_increment_increment;
-}
-
-static int
-usbtest_check_buffer(UsbTestData* how, unsigned char* buffer, int length)
-{
- int result = 1;
-
- switch(how->format) {
- case usbtestdata_none:
- break;
-
- case usbtestdata_bytefill:
- {
- int i;
- result = 1;
- for (i = 0; i < length; i++) {
- if (buffer[i] != (how->seed & 0x00FF)) {
- result = 0;
- break;
- }
- }
- break;
- }
-
- case usbtestdata_wordfill:
- {
- int i;
- int index = 0;
- for (i = 0; i < (length / 4); i++) {
- int datum = unpack_int(buffer, &index);
- if (datum != (how->seed & 0x0FFFFFFFF)) {
- result = 0;
- break;
- }
- }
- for (i = 4 * i; result && (i < length); i++) {
- if (0 != buffer[i]) {
- result = 0;
- break;
- }
- }
- break;
- }
-
- case usbtestdata_byteseq:
- {
- int i;
- for (i = 0; i < length; i++) {
- if (buffer[i] != (how->seed & 0x00FF)) {
- result = 0;
- break;
- }
- how->seed *= how->multiplier;
- how->seed += how->increment;
- }
- break;
- }
-
- case usbtestdata_wordseq:
- {
- int i;
- int index = 0;
-
- for (i = 0; i < (length / 4); i++) {
- int datum = unpack_int(buffer, &index);
- if (datum != (how->seed & 0x0FFFFFFFF)) {
- result = 0;
- break;
- }
- how->seed *= how->multiplier;
- how->seed += how->increment;
- }
- for (i = 4 * i; result && (i < length); i++) {
- if (0 != buffer[i]) {
- result = 0;
- break;
- }
- }
- break;
- }
- }
-
- // After each transfer update the seed, multiplier and increment
- // ready for the next transfer.
- how->seed *= how->transfer_seed_multiplier;
- how->seed += how->transfer_seed_increment;
- how->multiplier *= how->transfer_multiplier_multiplier;
- how->multiplier += how->transfer_multiplier_increment;
- how->increment *= how->transfer_increment_multiplier;
- how->increment += how->transfer_increment_increment;
-
- return result;
-}
-
-#ifdef HOST
-static void
-pack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
-{
- pack_int((int)data->format, buf, index);
- pack_int((int)data->seed, buf, index);
- pack_int((int)data->multiplier, buf, index);
- pack_int((int)data->increment, buf, index);
- pack_int((int)data->transfer_seed_multiplier, buf, index);
- pack_int((int)data->transfer_seed_increment, buf, index);
- pack_int((int)data->transfer_multiplier_multiplier, buf, index);
- pack_int((int)data->transfer_multiplier_increment, buf, index);
- pack_int((int)data->transfer_increment_multiplier, buf, index);
- pack_int((int)data->transfer_increment_increment, buf, index);
-}
-#endif
-
-#ifdef TARGET
-static void
-unpack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
-{
- data->format = (usbtestdata) unpack_int(buf, index);
- data->seed = unpack_int(buf, index);
- data->multiplier = unpack_int(buf, index);
- data->increment = unpack_int(buf, index);
- data->transfer_seed_multiplier = unpack_int(buf, index);
- data->transfer_seed_increment = unpack_int(buf, index);
- data->transfer_multiplier_multiplier= unpack_int(buf, index);
- data->transfer_multiplier_increment = unpack_int(buf, index);
- data->transfer_increment_multiplier = unpack_int(buf, index);
- data->transfer_increment_increment = unpack_int(buf, index);
-}
-#endif
-
-/*}}}*/
-/*{{{ Testcase definitions */
-
-// ----------------------------------------------------------------------------
-// Definitions of the supported test cases. The actual implementations need
-// to vary between host and target.
-
-typedef enum usbtest {
- usbtest_invalid = 0,
- usbtest_bulk_out = 1,
- usbtest_bulk_in = 2,
- usbtest_control_in = 3
-} usbtest;
-
-// What I/O mechanism should be used on the target to process data?
-typedef enum usb_io_mechanism {
- usb_io_mechanism_usb = 1, // The low-level USB-specific API
- usb_io_mechanism_dev = 2 // cyg_devio_cread() et al
-} usb_io_mechanism;
-
-// Bulk transfers. The same structure can be used for IN and OUT transfers.
-// The endpoint number will be or'd with either USB_DIR_IN or USB_DIR_OUT,
-// or the equivalent under eCos.
-typedef struct UsbTest_Bulk {
- int number_packets;
- int endpoint;
- int tx_size;
- int tx_size_min;
- int tx_size_max;
- int tx_size_multiplier;
- int tx_size_divisor;
- int tx_size_increment;
- int rx_size;
- int rx_size_min;
- int rx_size_max;
- int rx_size_multiplier;
- int rx_size_divisor;
- int rx_size_increment;
- int rx_padding;
- int tx_delay;
- int tx_delay_min;
- int tx_delay_max;
- int tx_delay_multiplier;
- int tx_delay_divisor;
- int tx_delay_increment;
- int rx_delay;
- int rx_delay_min;
- int rx_delay_max;
- int rx_delay_multiplier;
- int rx_delay_divisor;
- int rx_delay_increment;
- usb_io_mechanism io_mechanism;
- UsbTestData data;
-} UsbTest_Bulk;
-
-#ifdef HOST
-static void
-pack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
-{
- pack_int(test->number_packets, buffer, index);
- pack_int(test->endpoint, buffer, index);
- pack_int(test->tx_size, buffer, index);
- pack_int(test->tx_size_min, buffer, index);
- pack_int(test->tx_size_max, buffer, index);
- pack_int(test->tx_size_multiplier, buffer, index);
- pack_int(test->tx_size_divisor, buffer, index);
- pack_int(test->tx_size_increment, buffer, index);
- pack_int(test->rx_size, buffer, index);
- pack_int(test->rx_size_min, buffer, index);
- pack_int(test->rx_size_max, buffer, index);
- pack_int(test->rx_size_multiplier, buffer, index);
- pack_int(test->rx_size_divisor, buffer, index);
- pack_int(test->rx_size_increment, buffer, index);
- // There is no need to transfer the padding field. It is only of
- // interest on the host, and this message is being packed
- // for the target side.
- pack_int(test->tx_delay, buffer, index);
- pack_int(test->tx_delay_min, buffer, index);
- pack_int(test->tx_delay_max, buffer, index);
- pack_int(test->tx_delay_multiplier, buffer, index);
- pack_int(test->tx_delay_divisor, buffer, index);
- pack_int(test->tx_delay_increment, buffer, index);
- pack_int(test->rx_delay, buffer, index);
- pack_int(test->rx_delay_min, buffer, index);
- pack_int(test->rx_delay_max, buffer, index);
- pack_int(test->rx_delay_multiplier, buffer, index);
- pack_int(test->rx_delay_divisor, buffer, index);
- pack_int(test->rx_delay_increment, buffer, index);
- pack_int((int)test->io_mechanism, buffer, index);
- pack_usbtestdata(&(test->data), buffer, index);
-}
-#endif
-
-#ifdef TARGET
-static void
-unpack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
-{
- test->number_packets = unpack_int(buffer, index);
- test->endpoint = unpack_int(buffer, index);
- test->tx_size = unpack_int(buffer, index);
- test->tx_size_min = unpack_int(buffer, index);
- test->tx_size_max = unpack_int(buffer, index);
- test->tx_size_multiplier = unpack_int(buffer, index);
- test->tx_size_divisor = unpack_int(buffer, index);
- test->tx_size_increment = unpack_int(buffer, index);
- test->rx_size = unpack_int(buffer, index);
- test->rx_size_min = unpack_int(buffer, index);
- test->rx_size_max = unpack_int(buffer, index);
- test->rx_size_multiplier = unpack_int(buffer, index);
- test->rx_size_divisor = unpack_int(buffer, index);
- test->rx_size_increment = unpack_int(buffer, index);
- test->tx_delay = unpack_int(buffer, index);
- test->tx_delay_min = unpack_int(buffer, index);
- test->tx_delay_max = unpack_int(buffer, index);
- test->tx_delay_multiplier = unpack_int(buffer, index);
- test->tx_delay_divisor = unpack_int(buffer, index);
- test->tx_delay_increment = unpack_int(buffer, index);
- test->rx_delay = unpack_int(buffer, index);
- test->rx_delay_min = unpack_int(buffer, index);
- test->rx_delay_max = unpack_int(buffer, index);
- test->rx_delay_multiplier = unpack_int(buffer, index);
- test->rx_delay_divisor = unpack_int(buffer, index);
- test->rx_delay_increment = unpack_int(buffer, index);
- test->io_mechanism = (usb_io_mechanism) unpack_int(buffer, index);
- unpack_usbtestdata(&(test->data), buffer, index);
-}
-#endif
-
-// A macro for moving on the next packet size. This also has to be shared between host
-// and target, if the two got out of synch then testing would go horribly wrong.
-//
-// The new packet size is determined using a multiplier and increment,
-// so to e.g. increase packet sizes by 4 bytes each time the
-// multiplier would be 1 and the increment would be 4, or to double
-// packet sizes the multiplier would be 2 and the increment would be
-// 0. On underflow or overflow the code tries to adjust the packet size
-// back to within the accepted range.
-
-#define USBTEST_NEXT_TX_SIZE(_x_) \
- do { \
- _x_.tx_size *= _x_.tx_size_multiplier; \
- _x_.tx_size /= _x_.tx_size_divisor; \
- _x_.tx_size += _x_.tx_size_increment; \
- if (_x_.tx_size < _x_.tx_size_min) { \
- if (_x_.tx_size_min == _x_.tx_size_max) { \
- _x_.tx_size = _x_.tx_size_min; \
- } else { \
- int tmp = _x_.tx_size_min - _x_.tx_size; \
- tmp %= _x_.tx_size_max - _x_.tx_size_min; \
- _x_.tx_size = tmp + _x_.tx_size_min; \
- } \
- } else if (_x_.tx_size > _x_.tx_size_max) { \
- if (_x_.tx_size_min == _x_.tx_size_max) { \
- _x_.tx_size = _x_.tx_size_max; \
- } else { \
- int tmp = _x_.tx_size - _x_.tx_size_max; \
- tmp %= _x_.tx_size_max - _x_.tx_size_min; \
- _x_.tx_size = tmp + _x_.tx_size_min; \
- } \
- } \
- } while ( 0 )
-
-// A similar macro for moving on to the next receive size. This is less
-// critical since care is taken to always receive at least the current
-// tx size plus padding.
-// Note that padding needs to be added by the calling code, not here,
-// since padding is only applicable on the host-side and this macro
-// is used on both host and target.
-#define USBTEST_NEXT_RX_SIZE(_x_) \
- do { \
- _x_.rx_size *= _x_.rx_size_multiplier; \
- _x_.rx_size /= _x_.rx_size_divisor; \
- _x_.rx_size += _x_.rx_size_increment; \
- if (_x_.rx_size < _x_.rx_size_min) { \
- if (_x_.rx_size_min == _x_.rx_size_max) { \
- _x_.rx_size = _x_.rx_size_min; \
- } else { \
- int tmp = _x_.rx_size_min - _x_.rx_size; \
- tmp %= _x_.rx_size_max - _x_.rx_size_min; \
- _x_.rx_size = tmp + _x_.rx_size_min; \
- } \
- } else if (_x_.rx_size > _x_.rx_size_max) { \
- if (_x_.rx_size_min == _x_.rx_size_max) { \
- _x_.rx_size = _x_.rx_size_max; \
- } else { \
- int tmp = _x_.rx_size - _x_.rx_size_max; \
- tmp %= _x_.rx_size_max - _x_.rx_size_min; \
- _x_.rx_size = tmp + _x_.rx_size_min; \
- } \
- } \
- } while ( 0 )
-
-// And a macro for adjusting the transmit delay.
-#define USBTEST_NEXT_TX_DELAY(_x_) \
- do { \
- _x_.tx_delay *= _x_.tx_delay_multiplier; \
- _x_.tx_delay /= _x_.tx_delay_divisor; \
- _x_.tx_delay += _x_.tx_delay_increment; \
- if (_x_.tx_delay < _x_.tx_delay_min) { \
- if (_x_.tx_delay_min == _x_.tx_delay_max) { \
- _x_.tx_delay = _x_.tx_delay_min; \
- } else { \
- int tmp = _x_.tx_delay_min - _x_.tx_delay; \
- tmp %= _x_.tx_delay_max - _x_.tx_delay_min; \
- _x_.tx_delay = tmp + _x_.tx_delay_min; \
- } \
- } else if (_x_.tx_delay > _x_.tx_delay_max) { \
- if (_x_.tx_delay_min == _x_.tx_delay_max) { \
- _x_.tx_delay = _x_.tx_delay_max; \
- } else { \
- int tmp = _x_.tx_delay - _x_.tx_delay_max; \
- tmp %= _x_.tx_delay_max - _x_.tx_delay_min; \
- _x_.tx_delay = tmp + _x_.tx_delay_min; \
- } \
- } \
- } while ( 0 )
-
-#define USBTEST_NEXT_RX_DELAY(_x_) \
- do { \
- _x_.rx_delay *= _x_.rx_delay_multiplier; \
- _x_.rx_delay /= _x_.rx_delay_divisor; \
- _x_.rx_delay += _x_.rx_delay_increment; \
- if (_x_.rx_delay < _x_.rx_delay_min) { \
- if (_x_.rx_delay_min == _x_.rx_delay_max) { \
- _x_.rx_delay = _x_.rx_delay_min; \
- } else { \
- int tmp = _x_.rx_delay_min - _x_.rx_delay; \
- tmp %= _x_.rx_delay_max - _x_.rx_delay_min; \
- _x_.rx_delay = tmp + _x_.rx_delay_min; \
- } \
- } else if (_x_.rx_delay > _x_.rx_delay_max) { \
- if (_x_.rx_delay_min == _x_.rx_delay_max) { \
- _x_.rx_delay = _x_.rx_delay_max; \
- } else { \
- int tmp = _x_.rx_delay - _x_.rx_delay_max; \
- tmp %= _x_.rx_delay_max - _x_.rx_delay_min; \
- _x_.rx_delay = tmp + _x_.rx_delay_min; \
- } \
- } \
- } while ( 0 )
-
-#define USBTEST_BULK_NEXT(_bulk_) \
- USBTEST_NEXT_TX_SIZE(_bulk_); \
- USBTEST_NEXT_RX_SIZE(_bulk_); \
- USBTEST_NEXT_TX_DELAY(_bulk_); \
- USBTEST_NEXT_RX_DELAY(_bulk_);
-
-// Control transfers, receives
-typedef struct UsbTest_ControlIn {
- int number_packets;
- int packet_size_initial;
- int packet_size_min;
- int packet_size_max;
- int packet_size_multiplier;
- int packet_size_increment;
- UsbTestData data;
-} UsbTest_ControlIn;
-
-#ifdef HOST
-static void
-pack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
-{
- pack_int(test->number_packets, buffer, index);
- pack_int(test->packet_size_initial, buffer, index);
- pack_int(test->packet_size_min, buffer, index);
- pack_int(test->packet_size_max, buffer, index);
- pack_int(test->packet_size_multiplier, buffer, index);
- pack_int(test->packet_size_increment, buffer, index);
- pack_usbtestdata(&(test->data), buffer, index);
-}
-#endif
-
-#ifdef TARGET
-static void
-unpack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
-{
- test->number_packets = unpack_int(buffer, index);
- test->packet_size_initial = unpack_int(buffer, index);
- test->packet_size_min = unpack_int(buffer, index);
- test->packet_size_max = unpack_int(buffer, index);
- test->packet_size_multiplier = unpack_int(buffer, index);
- test->packet_size_increment = unpack_int(buffer, index);
- unpack_usbtestdata(&(test->data), buffer, index);
-}
-#endif
-
-// For now control packet sizes are adjusted in exactly the same way as bulk transfers.
-#define USBTEST_CONTROL_NEXT_PACKET_SIZE(_packet_size_, _control_) \
- _packet_size_ = (_packet_size_ * _control_.packet_size_multiplier) + _control_.packet_size_increment; \
- if (_packet_size_ < _control_.packet_size_min) { \
- _packet_size_ += _control_.packet_size_max - _control_.packet_size_min; \
- if (_packet_size_ < _control_.packet_size_min) { \
- _packet_size_ = _control_.packet_size_initial; \
- } \
- } else if (_packet_size_ > _control_.packet_size_max) { \
- _packet_size_ -= _control_.packet_size_max - _control_.packet_size_min; \
- if (_packet_size_ > _control_.packet_size_max) { \
- _packet_size_ = _control_.packet_size_initial; \
- } \
- }
-
-/*}}}*/
-/*{{{ Recovery support */
-
-// ----------------------------------------------------------------------------
-// When things go wrong threads on either the host or the target may get
-// locked up waiting for further communication that never happens, because
-// the other side has already raised an error. Recovery is possible by
-// performing an extra I/O operation. For example, if a thread on the
-// target is blocked waiting on an OUT endpoint then recovery is possible
-// by the host sending some data to that endpoint. Similarly if a thread
-// on the host is blocked then recovery involves the target either sending
-// or receiving some additional data. There are alternative approaches such
-// as stalling endpoints, but making sure that the requested communication
-// actually happens involves fewer dependencies on exactly how those
-// operations behave.
-
-typedef struct UsbTest_Recovery {
- int endpoint; // Top bit indicates direction, -1 indicates invalid
- int protocol;
- int size;
-} UsbTest_Recovery;
-
-static void
-pack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int* index)
-{
- pack_int(recovery->endpoint, buffer, index);
- pack_int(recovery->protocol, buffer, index);
- pack_int(recovery->size, buffer, index);
-}
-
-static void
-unpack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int *index)
-{
- recovery->endpoint = unpack_int(buffer, index);
- recovery->protocol = unpack_int(buffer, index);
- recovery->size = unpack_int(buffer, index);
-}
-
-static void
-usbtest_recovery_reset(UsbTest_Recovery* recovery)
-{
- recovery->endpoint = -1;
- recovery->protocol = 0;
- recovery->size = 0;
-}
-
-/*}}}*/
Index: slave/v2_0/include/usbs.h
===================================================================
--- slave/v2_0/include/usbs.h (revision 174)
+++ slave/v2_0/include/usbs.h (nonexistent)
@@ -1,426 +0,0 @@
-#ifndef CYGONCE_USBS_H
-# define CYGONCE_USBS_H
-//==========================================================================
-//
-// include/usbs.h
-//
-// The generic USB slave-side support
-//
-//==========================================================================
-//####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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-10-04
-// Purpose:
-// Description: USB slave-side support
-//
-//
-//####DESCRIPTIONEND####
-//==========================================================================
-
-# include
-# include
-# include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// The USB slave-side eCos support involves a number of different
-// components:
-//
-// 1) a hardware-specific package to drive a specific chip implementation.
-// This provides access to the endpoints. All the hardware-specific
-// packages implement a common interface.
-//
-// 2) a common package (this one). This defines the interface implemented
-// by the hardware-specific packages. It also provides support for
-// the various generic control messages, using information provided
-// by higher-level code and invoking callbacks as appropriate.
-//
-// 3) some number of support packages for particular types of
-// application, for example ethernet or mass-storage.
-//
-// Typically there will only be one USB slave device, although the design
-// does allow for multiple devices. Each device should provide a
-// usbs_control_endpoint structure and zero or more usbs_data_endpoint
-// structures. Each usbs_data_endpoint structure supports uni-directional
-// transfers on a single endpoint. If an endpoint can support multiple
-// types of transfer then there will be some control operation to switch
-// between bulk, interrupt and isochronous.
-//
-// Access to the USB endpoints can go either via usbs_ calls which
-// take a usbs_endpoint structure, or via open/read/write calls. The
-// latter is more likely to be used in application code since it
-// involves a familiar interface. The former is more appropriate for
-// eCos packages layered on top of the USB code. The difference is
-// synchronous vs. asynchronous: the open/read/write model involves
-// blocking operations, implying a need for extra threads; the usbs_
-// calls involve start operations and a completion callback. In
-// practice the read and write calls are implemented using the
-// lower-level code.
-
-// Enumeration data. This requires information about the hardware,
-// specifically what endpoints are available and what they get used
-// for. It also requires information about the application class
-// packages that are in the configuration, and quite possibly about
-// things in application space. Some of the enumeration info such as
-// the vendor id is inherently application-specific. Hence there is no
-// way of generating part or all of the the enumeration information
-// automatically, instead it is up to application code to supply this.
-//
-// The intention is that application provides all the data via const
-// static objects, allowing the data to live in ROM. Alternatively the
-// data structures can go into the .data section as normal, allowing
-// them to be edited at run-time.
-//
-// There can be only one device descriptor, so that is part of the
-// main enumeration data structure. There can be an unknown number of
-// configurations so application code has to initialize an array of
-// these. Ditto for interfaces and endpoints. The first x interfaces
-// in the array correspond to the first configuration, the next y
-// interfaces to the second configuration, etc. The endpoints array
-// works in the same way.
-//
-// In the initial implementation multiple languages are not supported
-// so a simple array of strings suffices. The first entry of these
-// is still special in that it should define a single supported
-// LANGID. All strings should be encoded as per the USB standard:
-// a length field, a type code of USB_STRING_DESCRIPTOR_TYPE,
-// and data in unicode format. In future multiple language support
-// may be supported via configury with the default case remaining
-// a single language, thus avoiding incompatibility problems.
-
-typedef struct usbs_enumeration_data {
- usb_device_descriptor device;
- int total_number_interfaces;
- int total_number_endpoints;
- int total_number_strings;
- const usb_configuration_descriptor* configurations;
- const usb_interface_descriptor* interfaces;
- const usb_endpoint_descriptor* endpoints;
- const unsigned char** strings;
-} usbs_enumeration_data;
-
-// The current state of a USB device. This involves a bit to mark
-// whether or not the device has been suspended, plus a state machine.
-// On some hardware it may not be possible to distinguish between the
-// detached, attached and powered states. If so then the initial state
-// will be POWERED.
-
-#define USBS_STATE_DETACHED 0x01
-#define USBS_STATE_ATTACHED 0x02
-#define USBS_STATE_POWERED 0x03
-#define USBS_STATE_DEFAULT 0x04
-#define USBS_STATE_ADDRESSED 0x05
-#define USBS_STATE_CONFIGURED 0x06
-#define USBS_STATE_MASK 0x7F
-#define USBS_STATE_SUSPENDED (1 << 7)
-
-// State changes. Application code or higher-level packages should
-// install an appropriate state change function which will get
-// invoked with details of the state change.
-typedef enum {
- USBS_STATE_CHANGE_DETACHED = 1,
- USBS_STATE_CHANGE_ATTACHED = 2,
- USBS_STATE_CHANGE_POWERED = 3,
- USBS_STATE_CHANGE_RESET = 4,
- USBS_STATE_CHANGE_ADDRESSED = 5,
- USBS_STATE_CHANGE_CONFIGURED = 6,
- USBS_STATE_CHANGE_DECONFIGURED = 7,
- USBS_STATE_CHANGE_SUSPENDED = 8,
- USBS_STATE_CHANGE_RESUMED = 9
-} usbs_state_change;
-
-typedef enum {
- USBS_CONTROL_RETURN_HANDLED = 0,
- USBS_CONTROL_RETURN_UNKNOWN = 1,
- USBS_CONTROL_RETURN_STALL = 2
-} usbs_control_return;
-
-typedef struct usbs_control_endpoint {
- // The state is maintained by the USB code and should not be
- // modified by anything higher up.
- int state;
-
- // The enumeration data should be supplied by higher level code,
- // usually the application. Often this data will be constant.
- const usbs_enumeration_data* enumeration_data;
-
- // This function pointer is supplied by the USB device driver.
- // Application code should invoke it directly or via the
- // usbs_start() function when the system is ready. Typically it
- // will cause the USB lines to switch from tristate to active,
- // and the USB host/hub should detect this.
- void (*start_fn)(struct usbs_control_endpoint*);
-
- // This function is used for polled operation when interrupts
- // are disabled. This can happen in some debugging contexts.
- // Higher-level code may also need to know about the interrupt
- // number(s) used.
- void (*poll_fn)(struct usbs_control_endpoint*);
- int interrupt_vector;
-
- // When a new control message arrives it will be in this buffer
- // where the appropriate callback functions can examine it. The
- // USB code will not modify the buffer unless a new control
- // message arrives. The control_buffer can also be re-used
- // by handlers to maintain some state information, e.g.
- // for coping with complicated IN requests, but this is only
- // allowed if they actually handle the request.
- unsigned char control_buffer[8];
-
- // This callback will be invoked by the USB code following a
- // change in USB state, e.g. to SUSPENDED mode. Higher-level code
- // should install a suitable function. There is some callback data
- // as well. This gets passed explicitly to the callback function,
- // in addition to the control endpoint structure. The reason is
- // that the actual state change callback may be some sort of
- // multiplexer inside a multifunction peripheral, and this
- // multiplexer wants to invoke device-specific state change
- // functions. However in simple devices those device-specific
- // state change functions could be invoked directly.
- void (*state_change_fn)(struct usbs_control_endpoint*, void*, usbs_state_change, int /* old state */);
- void* state_change_data;
- // When a standard control message arrives, the device driver will
- // detect some requests such as SET_ADDRESS and handle it
- // internally. Otherwise if higher-level code has installed a
- // callback then that will be invoked. If the callback returns
- // UNKNOWN then the default handler usbs_handle_standard_control()
- // is used to process the request.
- usbs_control_return (*standard_control_fn)(struct usbs_control_endpoint*, void*);
- void* standard_control_data;
-
- // These three callbacks are used for other types of control
- // messages. The generic USB code has no way of knowing what
- // such control messages are about.
- usbs_control_return (*class_control_fn)(struct usbs_control_endpoint*, void*);
- void* class_control_data;
- usbs_control_return (*vendor_control_fn)(struct usbs_control_endpoint*, void*);
- void* vendor_control_data;
- usbs_control_return (*reserved_control_fn)(struct usbs_control_endpoint*, void*);
- void* reserved_control_data;
-
- // If a control operation involves transferring more data than
- // just the initial eight-byte packet, the following fields are
- // used to keep track of the current operation. The original
- // control request indicates the direction of the transfer (IN or
- // OUT) and a length field. For OUT this length is exact, for IN
- // it is an upper bound. The transfer operates mostly as per the
- // bulk protocol, but if the length requested is an exact multiple
- // of the control fifo size (typically eight bytes) then there
- // is no need for an empty packet at the end.
- //
- // For an OUT operation the control message handler should supply
- // a suitable buffer via the "buffer" field below. The only other
- // field of interest is the complete_fn which must be provided and
- // will be invoked once all the data has arrived. Alternatively
- // the OUT operation may get aborted if a new control message
- // arrives. The second argument is an error code -EPIPE or -EIO,
- // or zero to indicate success. The return code is used by the
- // device driver during the status phase.
- //
- // IN is more complicated and the defined interface makes it
- // possible to gather data from multiple locations, eliminating
- // the need for copying into large buffers in some circumstances.
- // Basically when an IN request arrives the device driver will
- // look at the buffer and buffer_size fields, extracting data from
- // there if possible. If the current buffer has been exhausted
- // then the the refill function will be invoked, and this can
- // reset the buffer and size fields to point somewhere else.
- // This continues until such time that there is no longer
- // a refill function and the current buffer is empty. The
- // refill function can use the refill_data and refill_index
- // to keep track of the current state. The control_buffer
- // fields are available as well. At the end of the transfer,
- // if a completion function has been supplied then it will
- // be invoked. The return code will be ignored.
- unsigned char* buffer;
- int buffer_size;
- void (*fill_buffer_fn)(struct usbs_control_endpoint*);
- void* fill_data;
- int fill_index;
- usbs_control_return (*complete_fn)(struct usbs_control_endpoint*, int);
-} usbs_control_endpoint;
-
-// Data endpoints are a little bit simpler, but not much. From the
-// perspective of a device driver things a single buffer is most
-// convenient, but that is quite likely to require a max-size buffer
-// at a higher level and an additional copy operation. Supplying
-// a vector of buffers is a bit more general, but in a layered
-// system it may be desirable to prepend to this vector...
-// A combination of a current buffer and a refill/empty function
-// offers flexibility, at the cost of additional function calls
-// from inside the device driver.
-//
-// FIXME: implement support for fill/empty functions.
-//
-// Some USB devices may prefer buffers of particular alignment,
-// e.g. for DMA purposes. This is hard to reconcile with the
-// current interface. However pushing such alignment restrictions
-// etc. up into the higher levels is difficult, e.g. it does
-// not map at all onto a conventional read/write interface.
-// The device driver will just have to do the best it can.
-//
-// The completion function will be invoked at the end of the transfer.
-// The second argument indicates per-transfer completion data. The
-// third argument indicates the total amount received, or an error
-// code: typically -EPIPE to indicate a broken conenction; -EAGAIN to
-// indicate a stall condition; -EMSGSIZE if the host is sending more
-// data than the target is expecting; or -EIO to indicate some other
-// error. Individual device drivers should avoid generating other
-// errors.
-typedef struct usbs_rx_endpoint {
- void (*start_rx_fn)(struct usbs_rx_endpoint*);
- void (*set_halted_fn)(struct usbs_rx_endpoint*, cyg_bool);
- void (*complete_fn)(void*, int);
- void* complete_data;
- unsigned char* buffer;
- int buffer_size;
- cyg_bool halted;
-} usbs_rx_endpoint;
-
-typedef struct usbs_tx_endpoint {
- void (*start_tx_fn)(struct usbs_tx_endpoint*);
- void (*set_halted_fn)(struct usbs_tx_endpoint*, cyg_bool);
- void (*complete_fn)(void*, int);
- void* complete_data;
- const unsigned char*buffer;
- int buffer_size;
- cyg_bool halted;
-} usbs_tx_endpoint;
-
-// Functions called by device drivers.
-extern usbs_control_return usbs_handle_standard_control(struct usbs_control_endpoint*);
-
-// Utility functions. These just invoke the corresponding function
-// pointers in the endpoint structures. It is assumed that the
-// necessary fields in the endpoint structures will have been
-// filled in already.
-extern void usbs_start(usbs_control_endpoint*);
-extern void usbs_start_rx(usbs_rx_endpoint*);
-extern void usbs_start_tx(usbs_tx_endpoint*);
-extern void usbs_start_rx_buffer(usbs_rx_endpoint*, unsigned char*, int, void (*)(void*, int), void*);
-extern void usbs_start_tx_buffer(usbs_tx_endpoint*, const unsigned char*, int, void (*)(void*, int), void*);
-extern cyg_bool usbs_rx_endpoint_halted(usbs_rx_endpoint*);
-extern cyg_bool usbs_tx_endpoint_halted(usbs_tx_endpoint*);
-extern void usbs_set_rx_endpoint_halted(usbs_rx_endpoint*, cyg_bool);
-extern void usbs_set_tx_endpoint_halted(usbs_tx_endpoint*, cyg_bool);
-extern void usbs_start_rx_endpoint_wait(usbs_rx_endpoint*, void (*)(void*, int), void*);
-extern void usbs_start_tx_endpoint_wait(usbs_tx_endpoint*, void (*)(void*, int), void*);
-
-// Functions that can go into devtab entries. These should not be
-// called directly, they are intended only for use by USB device
-// drivers.
-#if defined(CYGPKG_IO) && defined(CYGPKG_ERROR)
-#include
-extern Cyg_ErrNo usbs_devtab_cwrite(cyg_io_handle_t, const void*, cyg_uint32*);
-extern Cyg_ErrNo usbs_devtab_cread(cyg_io_handle_t, void*, cyg_uint32*);
-extern Cyg_ErrNo usbs_devtab_get_config(cyg_io_handle_t, cyg_uint32, void*, cyg_uint32*);
-extern Cyg_ErrNo usbs_devtab_set_config(cyg_io_handle_t, cyg_uint32, const void*, cyg_uint32*);
-#endif
-
-// Additional support for testing.
-// Test cases need to have some way of finding out about what support is
-// actually provided by the USB device driver, for example what endpoints
-// are available. There is no perfect way of achieving this. One approach
-// would be to scan through the devtab table looking for devices of the
-// form /dev/usbs1r. That is not reliable: the devtab entries may have been
-// configured out if higher-level code uses the usb-specific API; or the
-// devtab entries may have been renamed. Also having a devtab entry does not
-// really give the kind of information a general-purpose testcase needs,
-// for example upper bounds on transfer size.
-//
-// An alternative approach is to have a data structure that somehow
-// defines the USB hardware, and the USB device driver then creates an
-// instance of this. This is the approach actually taken. The problem
-// now is how the test code can access this instance. Accessing by
-// unique name is simple, as long as there is only one USB device in
-// the system (which of course will usually be the case on the USB
-// slave side). Alternative approaches such as creating a table at
-// link time or a list during static construction time are vulnerable
-// either to selective linking or to having these structures present
-// in applications other than the test cases. In future it might be
-// possible to address the latter issue by extending the build system
-// support, e.g. a new library libtesting.a and a new object file
-// testing.o.
-//
-// Note that a given endpoint could be used for bulk transfers some
-// of the time, then for isochronous transfers, etc. It is the
-// responsibility of the host to only perform one type of IN operation
-// for a given endpoint number, and ditto for OUT.
-
-typedef struct usbs_testing_endpoint {
- int endpoint_type; // One of ATTR_CONTROL, ATTR_BULK, ...
- int endpoint_number; // Between 0 and 15
- int endpoint_direction; // ENDPOINT_IN or ENDPOINT_OUT
- void* endpoint; // pointer to the usbs_control_endpoint, usbs_rx_endpoint, ...
- const char* devtab_entry; // e.g. "/dev/usbs1r", or 0 if inaccessible via devtab
- int min_size; // Minimum transfer size
- int max_size; // -1 indicates no specific upper bound
- int max_in_padding; // extra bytes that the target may send, usually 0.
- // Primarily for SA11x0 hardware. It is assumed
- // for now that no other hardware will exhibit
- // comparable problems.
- int alignment; // Buffer should be aligned to a suitable boundary
-} usbs_testing_endpoint;
-
-// A specific instance provided by the device driver. The end of
-// the table is indicated by a NULL endpoint field.
-extern usbs_testing_endpoint usbs_testing_endpoints[];
-
-#define USBS_TESTING_ENDPOINTS_TERMINATOR \
- { \
- endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, \
- endpoint_number : 0, \
- endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, \
- endpoint : (void*) 0, \
- devtab_entry : (const char*) 0, \
- min_size : 0, \
- max_size : 0, \
- max_in_padding : 0, \
- alignment : 0 \
- }
-
-#define USBS_TESTING_ENDPOINTS_IS_TERMINATOR(_endpoint_) ((void*)0 == (_endpoint_).endpoint)
-
-#ifdef __cplusplus
-} // extern "C" {
-#endif
-
-#endif // CYGONCE_USBS_H
-
Index: slave/v2_0/doc/usbs-writing.html
===================================================================
--- slave/v2_0/doc/usbs-writing.html (revision 174)
+++ slave/v2_0/doc/usbs-writing.html (nonexistent)
@@ -1,937 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-Writing a USB Device Driver
-
Writing a USB Device Driver -- USB Device Driver Porting Guide
Introduction
Often the best way to write a USB device driver will be to start with
-an existing one and modify it as necessary. The information given here
-is intended primarily as an outline rather than as a complete guide.
Note: At the time of writing only one USB device driver has been
-implemented. Hence it is possible, perhaps probable, that some
-portability issues have not yet been addressed. One issue
-involves the different types of transfer, for example the initial
-target hardware had no support for isochronous or interrupt transfers,
-so additional functionality may be needed to switch between transfer
-types. Another issue would be hardware where a given endpoint number,
-say endpoint 1, could be used for either receiving or transmitting
-data, but not both because a single fifo is used. Issues like these
-will have to be resolved as and when additional USB device drivers are
-written.
The Control Endpoint
A USB device driver should provide a single usbs_control_endpoint
-data structure for every USB device. Typical peripherals will have
-only one USB port so there will be just one such data structure in the
-entire system, but theoretically it is possible to have multiple USB
-devices. These may all involve the same chip, in which case a single
-device driver should support multiple device instances, or they may
-involve different chips. The name or names of these data structures
-are determined by the device driver, but appropriate care should be
-taken to avoid name clashes.
A USB device cannot be used unless the control endpoint data structure
-exists. However, the presence of USB hardware in the target processor
-or board does not guarantee that the application will necessarily want
-to use that hardware. To avoid unwanted code or data overheads, the
-device driver can provide a configuration option to determine whether
-or not the endpoint 0 data structure is actually provided. A default
-value of CYGINT_IO_USB_SLAVE_CLIENTS ensures that
-the USB driver will be enabled automatically if higher-level code does
-require USB support, while leaving ultimate control to the user.
The USB device driver is responsible for filling in the
-start_fn,
-poll_fn and
-interrupt_vector fields. Usually this can
-be achieved by static initialization. The driver is also largely
-responsible for maintaining the state
-field. The control_buffer array should be
-used to hold the first packet of a control message. The
-buffer and other fields related to data
-transfers will be managed jointly by higher-level code and
-the device driver. The remaining fields are generally filled in by
-higher-level code, although the driver should initialize them to NULL
-values.
Hardware permitting, the USB device should be inactive until the
-start_fn is invoked, for example by
-tristating the appropriate pins. This prevents the host from
-interacting with the peripheral before all other parts of the system
-have initialized. It is expected that the
-start_fn will only be invoked once, shortly
-after power-up.
Where possible the device driver should detect state changes, such as
-when the connection between host and peripheral is established, and
-report these to higher-level
-code via the state_change_fn callback, if
-any. The state change to and from configured state cannot easily be
-handled by the device driver itself, instead higher-level code such as
-the common USB slave package will take care of this.
Once the connection between host and peripheral has been established,
-the peripheral must be ready to accept control messages at all times,
-and must respond to these within certain time constraints. For
-example, the standard set-address control message must be handled
-within 50ms. The USB specification provides more information on these
-constraints. The device driver is responsible for receiving the
-initial packet of a control message. This packet will always be eight
-bytes and should be stored in the
-control_buffer field. Certain standard
-control messages should be detected and handled by the device driver
-itself. The most important is set-address, but usually the get-status,
-set-feature and clear-feature requests when applied to halted
-endpoints should also be handled by the driver. Other standard control
-messages should first be passed on to the
-standard_control_fn callback (if any), and
-finally to the default handler
-usbs_handle_standard_control provided by the
-common USB slave package. Class, vendor and reserved control messages
-should always be dispatched to the appropriate callback and there is
-no default handler for these.
Some control messages will involve further data transfer, not just the
-initial packet. The device driver must handle this in accordance with
-the USB specification and the buffer management strategy. The
-driver is also responsible for keeping track of whether or not the
-control operation has succeeded and generating an ACK or STALL
-handshake.
The polling support is optional and may not be feasible on all
-hardware. It is only used in certain specialised environments such as
-RedBoot. A typical implementation of the polling function would just
-check whether or not an interrupt would have occurred and, if so, call
-the same code that the interrupt handler would.
Data Endpoints
In addition to the control endpoint data structure, a USB device
-driver should also provide appropriate data
-endpoint data structures. Obviously this is only relevant if
-the USB support generally is desired, that is if the control endpoint is
-provided. In addition, higher-level code may not require all the
-endpoints, so it may be useful to provide configuration options that
-control the presence of each endpoint. For example, the intended
-application might only involve a single transmit endpoint and of
-course control messages, so supporting receive endpoints might waste
-memory.
Conceptually, data endpoints are much simpler than the control
-endpoint. The device driver has to supply two functions, one for
-data transfers and another to control the halted condition. These
-implement the functionality for
-usbs_start_rx_buffer,
-usbs_start_tx_buffer,
-usbs_set_rx_endpoint_halted and
-usbs_set_tx_endpoint_halted.
-The device driver is also responsible for maintaining the
-halted status.
For data transfers, higher-level code will have filled in the
-buffer,
-buffer_size,
-complete_fn and
-complete_data fields. The transfer function
-should arrange for the transfer to start, allowing the host to send or
-receive packets. Typically this will result in an interrupt at the end
-of the transfer or after each packet. Once the entire transfer has
-been completed, the driver's interrupt handling code should invoke the
-completion function. This can happen either in DSR context or thread
-context, depending on the driver's implementation. There are a number
-of special cases to consider. If the endpoint is halted when the
-transfer is started then the completion function can be invoked
-immediately with -EAGAIN. If the transfer cannot be
-completed because the connection is broken then the completion
-function should be invoked with -EPIPE. If the
-endpoint is stalled during the transfer, either because of a standard
-control message or because higher-level code calls the appropriate
-set_halted_fn, then again the completion
-function should be invoked with -EAGAIN. Finally,
-the <usbs_start_rx_endpoint_wait and
-usbs_start_tx_endpoint_wait functions involve
-calling the device driver's data transfer function with a buffer size
-of 0 bytes.
Note: Giving a buffer size of 0 bytes a special meaning is problematical
-because it prevents transfers of that size. Such transfers are allowed
-by the USB protocol, consisting of just headers and acknowledgements
-and an empty data phase, although rarely useful. A future modification
-of the device driver specification will address this issue, although
-care has to be taken that the functionality remains accessible through
-devtab entries as well as via low-level accesses.
Devtab Entries
For some applications or higher-level packages it may be more
-convenient to use traditional open/read/write I/O calls rather than
-the non-blocking USB I/O calls. To support this the device driver can
-provide a devtab entry for each endpoint, for example:
Again care must be taken to avoid name clashes. This can be achieved
-by having a configuration option to control the base name, with a
-default value of e.g. /dev/usbs, and appending an
-endpoint-specific string. This gives the application developer
-sufficient control to eliminate any name clashes. The common USB slave
-package provides functions usbs_devtab_cwrite and
-usbs_devtab_cread, which can be used in the
-function tables for transmit and receive endpoints respectively. The
-private field priv of the devtab entry
-should be a pointer to the underlying endpoint data structure.
Because devtab entries are never accessed directly, only indirectly,
-they would usually be eliminated by the linker. To avoid this the
-devtab entries should normally be defined in a separate source file
-which ends up the special library libextras.a
-rather than in the default library libtarget.a.
Not all applications or higher-level packages will want to use the
-devtab entries and the blocking I/O facilities. It may be appropriate
-for the device driver to provide additional configuration options that
-control whether or not any or all of the devtab entries should be
-provided, to avoid unnecessary memory overheads.
Interrupt Handling
A typical USB device driver will need to service interrupts for all of
-the endpoints and possibly for additional USB events such as entering
-or leaving suspended mode. Usually these interrupts need not be
-serviced directly by the ISR. Instead, they can be left to a DSR. If
-the peripheral is not able to accept or send another packet just yet,
-the hardware will generate a NAK and the host will just retry a little
-bit later. If high throughput is required then it may be desirable to
-handle the bulk transfer protocol largely at ISR level, that is take
-care of each packet in the ISR and only activate the DSR once the
-whole transfer has completed.
Control messages may involve invoking arbitrary callback functions in
-higher-level code. This should normally happen at DSR level. Doing it
-at ISR level could seriously affect the system's interrupt latency and
-impose unacceptable constraints on what operations can be performed by
-those callbacks. If the device driver requires a thread anyway then it
-may be appropriate to use this thread for invoking the callbacks, but
-usually it is not worthwhile to add a new thread to the system just
-for this; higher-level code is expected to write callbacks that
-function sensibly at DSR level. Much the same applies to the
-completion functions associated with data transfers. These should also
-be invoked at DSR or thread level.
Support for USB Testing
Optionally a USB device driver can provide support for the
-USB test software. This requires
-defining a number of additional data structures, allowing the
-generic test code to work out just what the hardware is capable of and
-hence what testing can be performed.
The key data structure is
-usbs_testing_endpoint, defined in cyg/io/usb/usbs.h. In addition some
-commonly required constants are provided by the common USB package in
-cyg/io/usb/usb.h. One
-usbs_testing_endpoint structure should be
-defined for each supported endpoint. The following fields need to be
-filled in:
endpoint_type
This specifies the type of endpoint and should be one of
- USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL,
- BULK, ISOCHRONOUS or
- INTERRUPT.
-
endpoint_number
This identifies the number that should be used by the host
- to address this endpoint. For a control endpoint it should
- be 0. For other types of endpoints it should be between
- 1 and 15.
-
endpoint_direction
For control endpoints this field is irrelevant. For other
- types of endpoint it should be either
- USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN or
- USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT. If a given
- endpoint number can be used for traffic in both directions then
- there should be two entries in the array, one for each direction.
-
endpoint
This should be a pointer to the appropriate
- usbs_control_endpoint,
- usbs_rx_endpoint or
- usbs_tx_endpoint structure, allowing the
- generic testing code to perform low-level I/O.
-
devtab_entry
If the endpoint also has an entry in the system's device table then
- this field should give the corresponding string, for example
- "/dev/usbs1r". This allows the
- generic testing code to access the device via higher-level
- calls like open and read.
-
min_size
This indicates the smallest transfer size that the hardware can
- support on this endpoint. Typically this will be one.
-
Note: Strictly speaking a minimum size of one is not quite right since it
- is valid for a USB transfer to involve zero bytes, in other words a
- transfer that involves just headers and acknowledgements and an
- empty data phase, and that should be tested as well. However current
- device drivers interpret a transfer size of 0 as special, so that
- would have to be resolved first.
-
max_size
Similarly, this specifies the largest transfer size. For control
- endpoints the USB protocol uses only two bytes to hold the transfer
- length, so there is an upper bound of 65535 bytes. In practice
- it is very unlikely that any control transfers would ever need to
- be this large, and in fact such transfers would take a long time
- and probably violate timing constraints. For other types of endpoint
- any of the protocol, the hardware, or the device driver may impose
- size limits. For example a given device driver might be unable to
- cope with transfers larger than 65535 bytes. If it should be
- possible to transfer arbitrary amounts of data then a value of
- -1 indicates no upper limit, and transfer
- sizes will be limited by available memory and by the capabilities
- of the host machine.
-
max_in_padding
This field is needed on some hardware where it is impossible to
- send packets of a certain size. For example the hardware may be
- incapable of sending an empty bulk packet to terminate a transfer
- that is an exact multiple of the 64-byte bulk packet size.
- Instead the driver has to do some padding and send an extra byte,
- and the host has to be prepared to receive this extra byte. Such a
- driver should specify a value of 1 for the
- padding field. For most drivers this field should be set to
- 0.
-
A better solution would be for the device driver to supply a
- fragment of Tcl code that would adjust the receive buffer size
- only when necessary, rather than for every transfer. Forcing
- receive padding on all transfers when only certain transfers
- will actually be padded reduces the accuracy of certain tests.
-
alignment
On some hardware data transfers may need to be aligned to certain
- boundaries, for example a word boundary or a cacheline boundary.
- Although in theory device drivers could hide such alignment
- restrictions from higher-level code by having their own buffers and
- performing appropriate copying, that would be expensive in terms of
- both memory and cpu cycles. Instead the generic testing code will
- align any buffers passed to the device driver to the specified
- boundary. For example, if the driver requires that buffers be
- aligned to a word boundary then it should specify an alignment
- value of 4.
-
The device driver should provide an array of these structures
-usbs_testing_endpoints[]. The USB testing code
-examines this array and uses the information to perform appropriate
-tests. Because different USB devices support different numbers of
-endpoints the number of entries in the array is not known in advance,
-so instead the testing code looks for a special terminator
-USBS_TESTING_ENDPOINTS_TERMINATOR. An example
-array, showing just the control endpoint and the terminator, might
-look like this:
Note: The use of a single array usbs_testing_endpoints
-limits USB testing to platforms with a single USB device: if there
-were multiple devices, each defining their own instance of this array,
-then there would a collision at link time. In practice this should not
-be a major problem since typical USB peripherals only interact with a
-single host machine via a single slave port. In addition, even if a
-peripheral did have multiple slave ports the current USB testing code
-would not support this since it would not know which port to use.
When a USB host detects that a peripheral has been plugged in or
-powered up, one of the first steps is to ask the peripheral to
-describe itself by supplying enumeration data. Some of this data
-depends on the class of peripheral. Other fields are vendor-specific.
-There is also a dependency on the hardware, specifically which
-endpoints are available should be used. In general it is not possible
-for generic code to provide this information, so it is the
-responsibility of application code to provide a suitable
-usbs_enumeration_data data structure and
-install it in the endpoint 0 data structure during initialization.
-This must happen before the USB device is enabled by a call to
-usbs_start, for example:
For most applications the enumeration data will be static, although
-the usbs_enumeration_data structure can be
-filled in at run-time if necessary. Full details of the enumeration
-data can be found in the Universal Serial Bus specification obtainable
-from the USB Implementers Forum web
-site, although the meaning of most fields is fairly obvious.
-The various data structures and utility macros are defined in the
-header files cyg/io/usb/usb.h
-and cyg/io/usb/usbs.h. Note
-that the example code below makes use of the gcc labelled element
-extension.
usb_device_descriptor
The main information about a USB peripheral comes from a single
-usb_device_descriptor structure, which is
-embedded in the usbs_enumeration_data
-structure. A typical example might look like this:
The length and type fields are specified by the USB standard. The
-usb_spec_lo and
-usb_spec_hi fields identify the particular
-revision of the standard that the peripheral implements, for example
-revision 1.1.
The device class, subclass, and protocol fields are used by generic
-host-side USB software to determine which host-side device driver
-should be loaded to interact with the peripheral. A number of standard
-classes are defined, for example mass-storage devices and
-human-interface devices. If a peripheral implements one of the
-standard classes then a standard existing host-side device driver may
-exist, eliminating the need to write a custom driver. The value
-0xFF (VENDOR) is reserved for
-peripherals that implement a vendor-specific protocol rather than a
-standard one. Such peripherals will require a custom host-side device
-driver. The value 0x00
-(INTERFACE) is reserved and indicates that the
-protocol used by the peripheral is defined at the interface level
-rather than for the peripheral as a whole.
The max_package_size field specifies the
-maximum length of a control message. There is a lower bound of eight
-bytes, and typical hardware will not support anything larger because
-control messages are usually small and not performance-critical.
The vendor_lo and
-vendor_hi fields specify a vendor id, which
-must be obtained from the USB Implementor's Forum. The numbers used in
-the code fragment above are examples only and must not be used in real
-USB peripherals. The product identifier is determined by the vendor,
-and different USB peripherals should use different identifiers. The
-device identifier field should indicate a release number in
-binary-coded decimal.
The above fields are all numerical in nature. A USB peripheral can
-also provide a number of strings as described below, for example the name of the
-vendor can be provided. The various _str
-fields act as indices into an array of strings, with index 0
-indicating that no string is available.
A typical USB peripheral involves just a single configuration. However
-more complicated peripherals can support multiple configurations. Only
-one configuration will be active at any one time, and the host will
-switch between them as appropriate. If a peripheral does involve
-multiple configurations then typically it will be the responsibility
-of application code to handle the standard
-set-configuration control message.
usb_configuration_descriptor
A USB peripheral involves at least one and possible several different
-configurations. The usbs_enumeration_data
-structure requires a pointer to an array, possibly of length 1, of
-usb_configuration_descriptor structures.
-Usually a single structure suffices:
The values for the length and
-type fields are determined by the standard.
-The total_length field depends on the
-number of interfaces and endpoints used by this configuration, and
-convenience macros are provided to calculate this: the first argument
-to the macros specify the number of interfaces, the second the number
-of endpoints. The number_interfaces field
-is self-explanatory. If the peripheral involves multiple
-configurations then each one must have a unique id, and this will be
-used in the set-configuration control message. The id
-0 is reserved, and a set-configuration control
-message that uses this id indicates that the peripheral should be
-inactive. Configurations can have a string description if required.
-The attributes field must have the
-REQUIRED bit set; the
-SELF_POWERED bit informs the host that the
-peripheral has its own power supply and will not draw any power over
-the bus, leaving more bus power available to other peripherals; the
-REMOTE_WAKEUP bit is used if the peripheral can
-interrupt the host when the latter is in power-saving mode. For
-peripherals that are not self-powered, the
-max_power field specifies the power
-requirements in units of 2mA.
usb_interface_descriptor
A USB configuration involves one or more interfaces, typically
-corresponding to different streams of data. For example, one interface
-might involve video data while another interface is for audio.
-Multiple interfaces in a single configuration will be active at the
-same time.
Again, the length and
-type fields are specified by the standard.
-Each interface within a configuration requires its own id. However, a
-given interface may have several alternate settings, in other words
-entries in the interfaces array with the same id but different
-alternate_setting fields. For example,
-there might be one setting which requires a bandwidth of 100K/s and
-another setting that only needs 50K/s. The host can use the standard
-set-interface control message to choose the most appropriate setting.
-The handling of this request is the responsibility of higher-level
-code, so the application may have to install its own handler.
The number of endpoints used by an interface is specified in the
-number_endpoints field. Exact details of
-which endpoints are used is held in a separate array of endpoint
-descriptors. The class, subclass and protocol fields are used by
-host-side code to determine which host-side device driver should
-handle this specific interface. Usually this is determined on a
-per-peripheral basis in the
-usb_device_descriptor structure, but that can
-defer the details to individual interfaces. A per-interface string
-is allowed as well.
For USB peripherals involving multiple configurations, the array of
-usb_interface_descriptor structures should
-first contain all the interfaces for the first configuration, then all
-the interfaces for the second configuration, and so on.
usb_endpoint_descriptor
The host also needs information about which endpoint should be used
-for what. This involves an array of endpoint descriptors:
As usual the values for the length and
-type fields are specified by the standard.
-The endpoint field gives both the endpoint
-number and the direction, so in the above example endpoint 1 is used
-for OUT (host to peripheral) transfers and endpoint 2 is used for IN
-(peripheral to host) transfers. The
-attributes field indicates the USB protocol
-that should be used on this endpoint: CONTROL,
-ISOCHRONOUS, BULK or
-INTERRUPT. The
-max_packet field specifies the maximum size
-of a single USB packet. For bulk transfers this will typically be 64
-bytes. For isochronous transfers this can be up to 1023 bytes. For
-interrupt transfers it can be up to 64 bytes, although usually a
-smaller value will be used. The interval
-field is ignored for control and bulk transfers. For isochronous
-transfers it should be set to 1. For interrupt transfers it can be a
-value between 1 and 255, and indicates the number of milliseconds
-between successive polling operations.
For USB peripherals involving multiple configurations or interfaces
-the array of endpoint descriptors should be organized sequentially:
-first the endpoints corresponding to the first interface of the first
-configuration, then the second interface in that configuration, and so
-on; then all the endpoints for all the interfaces in the second
-configuration; etc.
Strings
The enumeration data can contain a number of strings with additional
-information. Unicode encoding is used for the strings, and it is
-possible for a peripheral to supply a given string in multiple
-languages using the appropriate characters. The first two bytes of
-each string give a length and type field. The first string is special;
-after the two bytes header it consists of an array of 2-byte language
-id codes, indicating the supported languages. The language code
-0x0409 corresponds to English (United States).
The default handler for standard control messages assumes that the
-peripheral only uses a single language. If this is not the case then
-higher-level code will have to handle the standard get-descriptor
-control messages when a string descriptor is requested.
usbs_enumeration_data
The usbs_enumeration_data data structure
-collects together all the various descriptors that make up the
-enumeration data. It is the responsibility of application code to
-supply a suitable data structure and install it in the control
-endpoints's enumeration_data field before
-the USB device is started.
usbs_start_rx_buffer is a USB-specific function
-to accept a transfer from host to peripheral. It can be used for bulk,
-interrupt or isochronous transfers, but not for control messages.
-Instead those involve manipulating the usbs_control_endpoint
-data structure directly. The function takes five arguments:
The first argument identifies the specific endpoint that should be
-used. Different USB devices will support different sets of endpoints
-and the device driver will provide appropriate data structures. The
-device driver's documentation should be consulted for details of which
-endpoints are available.
The buffer and length
-arguments control the actual transfer. USB device drivers are not
-expected to perform any buffering or to support partial transfers, so
-the length specified should correspond to the maximum transfer that is
-currently possible and the buffer should be at least this large. For
-isochronous transfers the USB specification imposes an upper bound of
-1023 bytes, and a smaller limit may be set in the enumeration data. Interrupt
-transfers are similarly straightforward with an upper bound of 64
-bytes, or less as per the enumeration data. Bulk transfers are more
-complicated because they can involve multiple 64-byte packets plus a
-terminating packet of less than 64 bytes, so there is no predefined
-limit on the transfer size. Instead it is left to higher-level
-protocols to specify an appropriate upper bound.
One technique that may work for bulk transfers is to exploit the fact
-that such transfers happen in 64-byte packets: it may be possible to
-receive an initial 64 bytes, corresponding to the first packet in the
-transfer; these 64 bytes can then be examined to determine the total
-transfer size, and the remaining data can be transferred in another
-receive operation. This technique is not guaranteed to work with all
-USB hardware. Also, if the delay between accepting the first packet and
-the remainder of the transfer is excessive then this could cause
-timeout problems for the host-side software. For these reasons this
-technique should be avoided.
usbs_start_rx_buffer is non-blocking. It merely
-starts the receive operation, and does not wait for completion. At
-some later point the USB device driver will invoke the completion
-function parameter with two arguments: the completion data defined by
-the last parameter and a result field. A result >=
-0 indicates a successful transfer of that many
-bytes, which may be less than the upper bound imposed by the
-length argument. A result <
-0 indicates an error. The most likely errors are
--EPIPE to indicate that the connection between the
-host and the target has been broken, and -EAGAIN
-for when the endpoint has been halted. Specific USB device drivers may
-specify additional error conditions.
The normal sequence of events is that the USB device driver will
-update the appropriate hardware registers. At some point after that
-the host will attempt to send data by transmitting an OUT token
-followed by a data packet, and since a receive operation is now in
-progress the data will be accepted and ACK'd. If there were no receive
-operation then the peripheral would instead generate a NAK. The USB
-hardware will generate an interrupt once the whole packet has been
-received, and the USB device driver will service this interrupt and
-arrange for a DSR to be called. Isochronous and interrupt transfers
-involve just a single packet. However, bulk transfers may involve
-multiple packets so the device driver has to check whether the packet
-was a full 64 bytes or whether it was a terminating packet of less
-than this. When the device driver DSR detects a complete transfer it
-will inform higher-level code by invoking the supplied completion
-function.
This means that the completion function will normally be invoked by a
-DSR and not in thread context - although some USB device drivers may
-have a different implementation. Therefore the completion function is
-restricted in what it can do. In particular it must not make any
-calls that will or may block such as locking a mutex or allocating
-memory. The kernel documentation should be consulted for more details
-of DSR's and interrupt handling generally.
It is possible that the completion function will be invoked before
-usbs_start_rx_buffer returns. Such an event would
-be unusual because the transfer cannot happen until the next time the
-host tries to send data to this peripheral, but it may happen if for
-example another interrupt happens and a higher priority thread is
-scheduled to run. Also, if the endpoint is currently halted then the
-completion function will be invoked immediately with
--EAGAIN: typically this will happen in the current
-thread rather than in a separate DSR. The completion function is
-allowed to start another transfer immediately by calling
-usbs_start_rx_buffer again.
USB device drivers are not expected to perform any locking. It is the
-responsibility of higher-level code to ensure that there is only one
-receive operation for a given endpoint in progress at any one time. If
-there are concurrent calls to
-usbs_start_rx_buffer then the resulting behaviour
-is undefined. For typical USB applications this does not present any
-problems, because only one piece of code will access a given endpoint
-at any particular time.
The following code fragment illustrates a very simple use of
-usbs_start_rx_buffer to implement a blocking
-receive, using a semaphore to synchronise between the foreground
-thread and the DSR. For a simple example like this no completion data
-is needed.
There is also a utility function usbs_start_rx. This
-can be used by code that wants to manipulate data endpoints directly, specifically the
-complete_fn,
-complete_data,
-buffer and
-buffer_size fields.
-usbs_start_tx just invokes a function
-supplied by the device driver.
USB device drivers provide two ways of transferring data between host
-and peripheral. The first involves USB-specific functionality such as
-usbs_start_rx_buffer.
-This provides non-blocking I/O: a transfer is started, and some time
-later the device driver will call a supplied completion function. The
-second uses the conventional I/O model: there are entries in the
-device table corresponding to the various endpoints. Standard calls
-such as open can then be used to get a suitable
-handle. Actual I/O happens via blocking read and
-write calls. In practice the blocking operations
-are simply implemented using the underlying non-blocking
-functionality.
Each endpoint will have its own devtab entry. The exact names are
-controlled by the device driver package, but typically the root will
-be /dev/usb. This is followed by one or more
-decimal digits giving the endpoint number, followed by
-c for a control endpoint, r for
-a receive endpoint (host to peripheral), and w for
-a transmit endpoint (peripheral to host). If the target hardware
-involves more than one USB device then different roots should be used,
-for example /dev/usb0c and
-/dev/usb1_0c. This may require explicit
-manipulation of device driver configuration options by the application
-developer.
At present the devtab entry for a control endpoint does not support
-any I/O operations.
write operations
cyg_io_write and similar functions in
-higher-level packages can be used to perform a transfer from
-peripheral to host. Successive write operations will not be coalesced.
-For example, when doing a 1000 byte write to an endpoint that uses the
-bulk transfer protocol this will involve 15 full-size 64-byte packets
-and a terminating 40-byte packet. USB device drivers are not expected
-to do any locking, and if higher-level code performs multiple
-concurrent write operations on a single endpoint then the resulting
-behaviour is undefined.
A USB write operation will never transfer less
-data than specified. It is the responsibility of higher-level code to
-ensure that the amount of data being transferred is acceptable to the
-host-side code. Usually this will be defined by a higher-level
-protocol. If an attempt is made to transfer more data than the host
-expects then the resulting behaviour is undefined.
There are two likely error conditions. EPIPE
-indicates that the connection between host and target has been broken.
-EAGAIN indicates that the endpoint has been
-stalled, either at the request of the host or by other activity
-inside the peripheral.
read operations
cyg_io_read and similar functions in higher-level
-packages can be used to perform a transfer from host to peripheral.
-This should be a complete transfer: higher-level protocols should
-define an upper bound on the amount of data being transferred, and the
-read operation should involve at least this
-amount of data. The return value will indicate the actual transfer
-size, which may be less than requested.
Some device drivers may support partial reads, but USB device drivers
-are not expected to perform any buffering because that involves both
-memory and code overheads. One technique that may work for bulk
-transfers is to exploit the fact that such transfers happen in 64-byte
-packets. It is possible to read an initial 64
-bytes, corresponding to the first packet in the transfer. These 64
-bytes can then be examined to determine the total transfer size, and
-the remaining data can be transferred in another
-read operation. This technique is not guaranteed
-to work with all USB hardware. Also, if the delay between accepting
-the first packet and the remainder of the transfer is excessive then
-this could cause timeout problems for the host-side software. For
-these reasons the use of partial reads should be avoided.
There are two likely error conditions. EPIPE
-indicates that the connection between host and target has been broken.
-EAGAIN indicates that the endpoint has been
-stalled, either at the request of the host or by other activity
-inside the peripheral.
USB device drivers are not expected to do any locking. If higher-level
-code performs multiple concurrent read operations on a single endpoint
-then the resulting behaviour is undefined.
select operations
Typical USB device drivers will not provide any support for
-select. Consider bulk transfers from the host to
-the peripheral. At the USB device driver level there is no way of
-knowing in advance how large a transfer will be, so it is not feasible
-for the device driver to buffer the entire transfer. It may be
-possible to buffer part of the transfer, for example the first 64-byte
-packet, and copy this into application space at the start of a
-read, but this adds code and memory overheads.
-Worse, it means that there is an unknown but potentially long delay
-between a peripheral accepting the first packet of a transfer and the
-remaining packets, which could confuse or upset the host-side
-software.
With some USB hardware it may be possible for the device driver to
-detect OUT tokens from the host without actually accepting the data,
-and this would indicate that a read is likely to
-succeed. However, it would not be reliable since the host-side I/O
-operation could time out. A similar mechanism could be used to
-implement select for outgoing data, but again
-this would not be reliable.
Some device drivers may provide partial support for
-select anyway, possibly under the control of a
-configuration option. The device driver's documentation should be
-consulted for further information. It is also worth noting that the
-USB-specific non-blocking API can often be used as an alternative to
-select.
get_config and
-set_config operations
There are no set_config or
-get_config (also known as
-ioctl) operations defined for USB devices.
-Some device drivers may provide hardware-specific facilities this way.
Note: Currently the USB-specific functions related to halted endpoints cannot be accessed readily
-via devtab entries. This functionality should probably be made
-available via set_config and
-get_config. It may also prove useful to provide
-a get_config operation that maps from the
-devtab entries to the underlying endpoint data structures.
Presence
The devtab entries are optional. If the USB device is accessed
-primarily by class-specific code such as the USB-ethernet package and
-that package uses the USB-specific API directly, the devtab entries
-are redundant. Even if application code does need to access the USB
-device, the non-blocking API may be more convenient than the blocking
-I/O provided via the devtab entries. In these cases the devtab entries
-serve no useful purpose, but they still impose a memory overhead. It
-is possible to suppress the presence of these entries by disabling the
-configuration option
-CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES.
usbs_start_tx_buffer is a USB-specific function
-to transfer data from peripheral to host. It can be used for bulk,
-interrupt or isochronous transfers, but not for control messages;
-instead those involve manipulating the usbs_control_endpoint
-data structure directly. The function takes five arguments:
The first argument identifies the specific endpoint that should be
-used. Different USB devices will support different sets of endpoints
-and the device driver will provide appropriate data structures. The
-device driver's documentation should be consulted for details of which
-endpoints are available.
The buffer and length
-arguments control the actual transfer. USB device drivers are not
-allowed to modify the buffer during the transfer, so the data can
-reside in read-only memory. The transfer will be for all the data
-specified, and it is the responsibility of higher-level code to make
-sure that the host is expecting this amount of data. For isochronous
-transfers the USB specification imposes an upper bound of 1023 bytes,
-but a smaller limit may be set in the enumeration data. Interrupt
-transfers have an upper bound of 64 bytes or less, as per the
-enumeration data. Bulk transfers are more complicated because they can
-involve multiple 64-byte packets plus a terminating packet of less
-than 64 bytes, so the basic USB specification does not impose an upper
-limit on the total transfer size. Instead it is left to higher-level
-protocols to specify an appropriate upper bound. If the peripheral
-attempts to send more data than the host is willing to accept then the
-resulting behaviour is undefined and may well depend on the specific
-host operating system being used.
For bulk transfers, the USB device driver or the underlying hardware
-will automatically split the transfer up into the appropriate number
-of full-size 64-byte packets plus a single terminating packet, which
-may be 0 bytes.
usbs_start_tx_buffer is non-blocking. It merely
-starts the transmit operation, and does not wait for completion. At
-some later point the USB device driver will invoke the completion
-function parameter with two arguments: the completion data defined by
-the last parameter, and a result field. This result will be either an
-error code < 0, or the amount of data
-transferred which should correspond to the
-length argument. The most likely errors are
--EPIPE to indicate that the connection between the
-host and the target has been broken, and -EAGAIN
-for when the endpoint has been halted. Specific USB device drivers may
-define additional error conditions.
The normal sequence of events is that the USB device driver will
-update the appropriate hardware registers. At some point after that
-the host will attempt to fetch data by transmitting an IN token. Since
-a transmit operation is now in progress the peripheral can send a
-packet of data, and the host will generate an ACK. At this point the
-USB hardware will generate an interrupt, and the device driver will
-service this interrupt and arrange for a DSR to be called. Isochronous
-and interrupt transfers involve just a single packet. However, bulk
-transfers may involve multiple packets so the device driver has to
-check whether there is more data to send and set things up for the
-next packet. When the device driver DSR detects a complete transfer it
-will inform higher-level code by invoking the supplied completion
-function.
This means that the completion function will normally be invoked by a
-DSR and not in thread context - although some USB device drivers may
-have a different implementation. Therefore the completion function is
-restricted in what it can do, in particular it must not make any
-calls that will or may block such as locking a mutex or allocating
-memory. The kernel documentation should be consulted for more details
-of DSR's and interrupt handling generally.
It is possible that the completion function will be invoked before
-usbs_start_tx_buffer returns. Such an event would
-be unusual because the transfer cannot happen until the next time the
-host tries to fetch data from this peripheral, but it may happen if,
-for example, another interrupt happens and a higher priority thread is
-scheduled to run. Also, if the endpoint is currently halted then the
-completion function will be invoked immediately with
--EAGAIN: typically this will happen in the current
-thread rather than in a separate DSR. The completion function is
-allowed to start another transfer immediately by calling
-usbs_start_tx_buffer again.
USB device drivers are not expected to perform any locking. It is the
-responsibility of higher-level code to ensure that there is only one
-transmit operation for a given endpoint in progress at any one time.
-If there are concurrent calls to
-usbs_start_tx_buffer then the resulting behaviour
-is undefined. For typical USB applications this does not present any
-problems because only piece of code will access a given endpoint at
-any particular time.
The following code fragment illustrates a very simple use of
-usbs_start_tx_buffer to implement a blocking
-transmit, using a semaphore to synchronise between the foreground
-thread and the DSR. For a simple example like this no completion data
-is needed.
There is also a utility function usbs_start. This
-can be used by code that wants to manipulate data endpoints directly, specifically the
-complete_fn,
-complete_data,
-buffer and
-buffer_size fields.
-usbs_start_tx just calls a function supplied by
-the device driver.
Normal USB traffic involves straightforward handshakes, with either an
-ACK to indicate that a packet was transferred
-without errors, or a NAK if an error occurred, or
-if a peripheral is currently unable to process another packet from the
-host, or has no packet to send to the host. There is a third form of
-handshake, a STALL, which indicates that the
-endpoint is currently halted.
When an endpoint is halted it means that the host-side code needs to
-take some sort of recovery action before communication over that
-endpoint can resume. The exact circumstances under which this can
-happen are not defined by the USB specification, but one example would
-be a protocol violation if say the peripheral attempted to transmit
-more data to the host than was permitted by the protocol in use. The
-host can use the standard control messages get-status, set-feature and
-clear-feature to examine and manipulate the halted status of a given
-endpoint. There are USB-specific functions which can be used inside
-the peripheral to achieve the same effect. Once an endpoint has been
-halted the host can then interact with the peripheral using class or
-vendor control messages to perform appropriate recovery, and then the
-halted condition can be cleared.
Halting an endpoint does not constitute a device state change, and
-there is no mechanism by which higher-level code can be informed
-immediately. However, any ongoing receive or transmit operations will
-be aborted with an -EAGAIN error, and any new
-receives or transmits will fail immediately with the same error.
There are six functions to support halted endpoints, one set for
-receive endpoints and another for transmit endpoints, with both sets
-behaving in essentially the same way. The first,
-usbs_rx_endpoint_halted, can be used to determine
-whether or not an endpoint is currently halted: it takes a single
-argument that identifies the endpoint of interest. The second
-function, usbs_set_rx_endpoint_halted, can be
-used to change the halted condition of an endpoint: it takes two
-arguments; one to identify the endpoint and another to specify the new
-state. The last function
-usbs_start_rx_endpoint_wait operates in much the
-same way as usbs_start_rx_buffer: when the
-endpoint is no longer halted the device driver will invoke the
-supplied completion function with a status of 0. The completion
-function has the same signature as that for a transfer operation.
-Often it will be possible to use a single completion function and have
-the foreground code invoke either
-usbs_start_rx_buffer or
-usbs_start_rx_endpoint_wait depending on the
-current state of the endpoint.
In addition to a single usbs_control_endpoint
-data structure per USB slave device, the USB device driver should also
-provide receive and transmit data structures corresponding to the
-other endpoints. The names of these are determined by the device
-driver. For example, the SA1110 USB device driver package provides
-usbs_sa11x0_ep1 for receives and
-usbs_sa11x0_ep2 for transmits.
Unlike control endpoints, the common USB slave package does provide a
-number of utility routines to manipulate data endpoints. For example
-usbs_start_rx_buffer
-can be used to receive data from the host into a buffer. In addition
-the USB device driver can provide devtab entries such as
-/dev/usbs1r and /dev/usbs2w, so
-higher-level code can open these devices and then
-perform blocking read and
-write operations.
However, the operation of data endpoints and the various
-endpoint-related functions is relatively straightforward. First
-consider a usbs_rx_endpoint structure. The
-device driver will provide the members
-start_rx_fn and
-set_halted_fn, and it will maintain the
-halted field. To receive data, higher-level
-code sets the buffer,
-buffer_size,
-complete_fn and optionally the
-complete_data fields. Next the
-start_rx_fn member should be called. When
-the transfer has finished the device driver will invoke the completion
-function, using complete_data as the first
-argument and a size field for the second argument. A negative size
-indicates an error of some sort: -EGAIN indicates
-that the endpoint has been halted, usually at the request of the host;
--EPIPE indicates that the connection between the
-host and the peripheral has been broken. Certain device drivers may
-generate other error codes.
If higher-level code needs to halt or unhalt an endpoint then it can
-invoke the set_halted_fn member. When an
-endpoint is halted, invoking start_rx_fn
-wit buffer_size set to 0 indicates that
-higher-level code wants to block until the endpoint is no longer
-halted; at that point the completion function will be invoked.
USB device drivers are allowed to assume that higher-level protocols
-ensure that host and peripheral agree on the amount of data that will
-be transferred, or at least on an upper bound. Therefore there is no
-need for the device driver to maintain its own buffers, and copy
-operations are avoided. If the host sends more data than expected then
-the resulting behaviour is undefined.
Transmit endpoints work in essentially the same way as receive
-endpoints. Higher-level code should set the
-buffer and
-buffer_size fields to point at the data to
-be transferred, then call start_tx_fn, and
-the device driver will invoked the completion function when the
-transfer has completed.
USB device drivers are not expected to perform any locking. If at any
-time there are two concurrent receive operations for a given endpoint,
-or two concurrent transmit operations, then the resulting behaviour is
-undefined. It is the responsibility of higher-level code to perform
-any synchronisation that may be necessary. In practice, conflicts are
-unlikely because typically a given endpoint will only be accessed
-sequentially by just one part of the overall system.
Introduction -- eCos support for USB slave devices
Introduction
The eCos USB slave support allows developers to produce USB
-peripherals. It consists of a number of different eCos packages:
Device drivers for specific implementations of USB slave hardware, for
-example the on-chip USB Device Controller provided by the Intel SA1110
-processor. A typical USB peripheral will only provide one USB slave
-port and therefore only one such device driver package will be needed.
-Usually the device driver package will be loaded automatically when
-you create an eCos configuration for target hardware that has a USB
-slave device. If you select a target which does have a USB slave
-device but no USB device driver is loaded, this implies that no such
-device driver is currently available.
The common USB slave package. This serves two purposes. It defines the
-API that specific device drivers should implement. It also provides
-various utilities that will be needed by most USB device drivers and
-applications, such as handlers for standard control messages.
-Usually this package will be loaded automatically at the same time as
-the USB device driver.
The common USB package. This merely provides some information common
-to both the host and slave sides of USB, such as details of the
-control protocol. It is also used to place the other USB-related
-packages appropriately in the overall configuration hierarchy. Usually
-this package will be loaded at the same time as the USB device driver.
Class-specific USB support packages. These make it easier to develop
-specific classes of USB peripheral, such as a USB-ethernet device. If
-no suitable package is available for a given class of peripheral then
-the USB device driver can instead be accessed directly from
-application code. Such packages will never be loaded automatically
-since the configuration system has no way of knowing what class of USB
-peripheral is being developed. Instead developers have to add the
-appropriate package or packages explicitly.
These packages only provide support for developing USB peripherals,
-not USB hosts.
USB Concepts
Information about USB can be obtained from a number of sources
-including the USB Implementers Forum
-web site. Only a brief summary is provided here.
A USB network is asymmetrical: it consists of a single host, one or
-more slave devices, and possibly some number of intermediate hubs. The
-host side is significantly more complicated than the slave side.
-Essentially, all operations are initiated by the host. For example, if
-the host needs to receive some data from a particular USB peripheral
-then it will send an IN token to that peripheral; the latter should
-respond with either a NAK or with appropriate data. Similarly, when
-the host wants to transmit data to a peripheral it will send an OUT
-token followed by the data; the peripheral will return a NAK if it is
-currently unable to receive more data or if there was corruption,
-otherwise it will return an ACK. All transfers are check-summed and
-there is a clearly-defined error recovery process. USB peripherals can
-only interact with the host, not with each other.
USB supports four different types of communication: control messages,
-interrupt transfers, isochronous transfers, and bulk transfers.
-Control messages are further subdivided into four categories:
-standard, class, vendor and a reserved category. All USB peripherals
-must respond to certain standard control messages, and usually this
-will be handled by the common USB slave package (for complicated
-peripherals, application support will be needed). Class and vendor
-control messages may be handled by an class-specific USB support
-package, for example the USB-ethernet package will handle control
-messages such as getting the MAC address or enabling/disabling
-promiscuous mode. Alternatively, some or all of these messages will
-have to be handled by application code.
Interrupt transfers are used for devices which need to be polled
-regularly. For example, a USB keyboard might be polled once every
-millisecond. The host will not poll the device more frequently than
-this, so interrupt transfers are best suited to peripherals that
-involve a relatively small amount of data. Isochronous transfers are
-intended for multimedia-related peripherals where typically a large
-amount of video or audio data needs to be exchanged continuously.
-Given appropriate host support a USB peripheral can reserve some of
-the available bandwidth. Isochronous transfers are not reliable; if a
-particular packet is corrupted then it will just be discarded and
-software is expected to recover from this. Bulk transfers are used for
-everything else: after taking care of any pending control, isochronous
-and interrupt transfers the host will use whatever bandwidth remains
-for bulk transfers. Bulk transfers are reliable.
Transfers are organized into USB packets, with the details depending
-on the transfer type. Control messages always involve an initial
-8-byte packet from host to peripheral, optionally followed by some
-additional packets; in theory these additional packets can be up to 64
-bytes, but hardware may limit it to 8 bytes. Interrupt transfers
-involve a single packet of up to 64 bytes. Isochronous transfers
-involve a single packet of up to 1024 bytes. Bulk transfers involve
-multiple packets. There will be some number, possibly zero, of 64-byte
-packets. The transfer is terminated by a single packet of less than 64
-bytes. If the transfer involves an exact multiple of 64 bytes than the
-final packet will be 0 bytes, consisting of just a header and checksum
-which typically will be generated by the hardware. There is no
-pre-defined limit on the size of a bulk transfer. Instead higher-level
-protocols are expected to handle this, so for a USB-ethernet
-peripheral the protocol could impose a limit of 1514 bytes of data
-plus maybe some additional protocol overhead.
Transfers from the host to a peripheral are addressed not just to that
-peripheral but to a specific endpoint within that peripheral.
-Similarly, the host requests incoming data from a specific endpoint
-rather than from the peripheral as a whole. For example, a combined
-keyboard/touchpad device could provide the keyboard events on endpoint
-1 and the mouse events on endpoint 2. A given USB peripheral can have
-up to 16 endpoints for incoming data and another 16 for outgoing data.
-However, given the comparatively high speed of USB I/O this endpoint
-addressing is typically implemented in hardware rather than software,
-and the hardware will only implement a small number of endpoints.
-Endpoint 0 is generally used only for control messages.
In practice, many of these details are irrelevant to application code
-or to class packages. Instead, such higher-level code usually just
-performs blocking read and
-write, or non-blocking USB-specific calls, to
-transfer data between host and target via a specific endpoint. Control
-messages are more complicated but are usually handled by existing
-code.
When a USB peripheral is plugged into the host there is an initial
-enumeration and configuration process. The peripheral provides
-information such as its class of device (audio, video, etc.), a
-vendor id, which endpoints should be used for what kind of data, and
-so on. The host OS uses this information to identify a suitable host
-device driver. This could be a generic driver for a class of
-peripherals, or it could be a vendor-specific driver. Assuming a
-suitable driver is installed the host will then activate the USB
-peripheral and perform additional application-specific initialisation.
-For example for a USB-ethernet device this would involve obtaining an
-ethernet MAC address. Most USB peripherals will be fairly simple, but
-it is possible to build multifunction peripherals with multiple
-configurations, interfaces, and alternate interface settings.
It is not possible for any of the eCos packages to generate all the
-enumeration data automatically. Some of the required information such
-as the vendor id cannot be supplied by generic packages; only by the
-application developer. Class support code such as the USB-ethernet
-package could in theory supply some of the information automatically,
-but there are also hardware dependencies such as which endpoints get
-used for incoming and outgoing ethernet frames. Instead it is the
-responsibility of the application developer to provide all the
-enumeration data and perform some additional initialisation. In
-addition, the common USB slave package can handle all the standard
-control messages for a simple USB peripheral, but for something like a
-multifunction peripheral additional application support is needed.
Note: The initial implementation of the eCos USB slave packages involved
-hardware that only supported control and bulk transfers, not
-isochronous or interrupt. There may be future changes to the USB
-code and API to allow for isochronous and interrupt transfers,
-especially the former. Other changes may be required to support
-different USB devices. At present there is no support for USB remote
-wakeups, since again it is not supported by the hardware.
eCos USB I/O Facilities
For protocols other than control messages, eCos provides two ways of
-performing USB I/O. The first involves device table or devtab entries such
-as /dev/usb1r,
-with one entry per endpoint per USB device. It is possible to
-open these devices and use conventional blocking
-I/O functions such as read and
-write to exchange data between host and
-peripheral.
There is also a lower-level USB-specific API, consisting of functions
-such as usbs_start_rx_buffer.
-A USB device driver will supply a data structure for each endpoint,
-for example a usbs_rx_endpoint
-structure for every receive endpoint. The first argument to
-usbs_start_rx_buffer should be a pointer to such
-a data structure. The USB-specific API is non-blocking: the initial
-call merely starts the transfer; some time later, once the transfer
-has completed or has been aborted, the device driver will invoke a
-completion function.
Control messages are different. With four different categories of
-control messages including application and vendor specific ones, the
-conventional
-open/read/write
-model of I/O cannot easily be applied. Instead, a USB device driver
-will supply a usbs_control_endpoint
-data structure which can be manipulated appropriately. In practice the
-standard control messages will usually be handled by the common USB
-slave package, and other control messages will be handled by
-class-specific code such as the USB-ethernet package. Typically,
-application code remains responsible for supplying the enumeration data and for actually starting up the USB device.
Enabling the USB code
If the target hardware contains a USB slave device then the
-appropriate USB device driver and the common packages will typically
-be loaded into the configuration automatically when that target is
-selected (assuming a suitable device driver exists). However, the
-driver will not necessarily be active. For example a processor might
-have an on-chip USB device, but not all applications using that
-processor will want to use USB functionality. Hence by default the USB
-device is disabled, ensuring that applications do not suffer any
-memory or other penalties for functionality that is not required.
If the application developer explicitly adds a class support package
-such as the USB-ethernet one then this implies that the USB device is
-actually needed, and the device will be enabled automatically.
-However, if no suitable class package is available and the USB device
-will instead be accessed by application code, it is necessary to
-enable the USB device manually. Usually the easiest way to do this is
-to enable the configuration option
-CYGGLO_IO_USB_SLAVE_APPLICATION, and the USB device
-driver and related packages will adjust accordingly. Alternatively,
-the device driver may provide some configuration options to provide
-more fine-grained control.
Initializing a USB device requires some support from higher-level
-code, typically the application, in the form of enumeration data.
-Hence it is not possible for the low-level USB driver to activate a
-USB device itself. Instead the higher-level code has to take care of
-this by invoking usbs_start. This function takes
-a pointer to a USB control endpoint data structure. USB device drivers
-should provide exactly one such data structure for every USB device,
-so the pointer uniquely identifies the device.
The exact behaviour of usbs_start depends on the
-USB hardware and the device driver. A typical implementation would
-change the USB data pins from tristated to active. If the peripheral
-is already plugged into a host then the latter should detect this
-change and start interacting with the peripheral, including requesting
-the enumeration data. Some of this may happen before
-usbs_start returns, but given that multiple
-interactions between USB host and peripheral are required it is likely
-that the function will return before the peripheral is fully
-configured. Control endpoints provide a mechanism for informing
-higher-level code of USB state changes.
-usbs_start will return even if the peripheral is
-not currently connected to a host: it will not block until the
-connection is established.
usbs_start should only be called once for a given
-USB device. There are no defined error conditions. Note that the
-function affects the entire USB device and not just the control
-endpoint: there is no need to start any data endpoints as well.
The support for USB testing provided by the eCos USB common slave
-package is somewhat different in nature from the kind of testing used
-in many other packages. One obvious problem is that USB tests cannot
-be run on just a bare target platform: instead the target platform
-must be connected to a suitable USB host machine, and that host
-machine must be running appropriate software for the test code to
-interact with. This is very different from say a kernel test which
-typically will have no external dependencies. Another important
-difference between USB testing and say a C library
-strcmp test is sensitivity to timing and to
-hardware boundary conditions: although a simple test case that just
-performs a small number of USB transfers is better than no testing at
-all, it should also be possible to run tests for hours or days on end,
-under a variety of loads. In order to provide the required
-functionality the basic architecture of the USB testing support is as
-follows:
There is a single target-side program
- usbtarget. By default when this is run
- on a target platform it will appear to do nothing. In fact it is
- waiting to be contacted by another program
- usbhost which will tell it what test or
- tests to run. usbtarget provides
- mechanisms for running a wide range of tests.
-
usbtarget is a generic program, but USB
- testing depends to some extent on the functionality provided by the
- hardware. For example there is no point in testing bulk transmits
- to endpoint 12 if the target hardware does not support an endpoint
- 12. Therefore each USB device driver should supply information about
- what the hardware is actually capable of, in the form of an array of
- usbs_testing_endpoint data structures.
-
There is a single host-side program
- usbhost, which acts as a counterpart to
- usbtarget. Again
- usbhost has no built-in knowledge of
- the test or tests that are supposed to run, it only provides
- mechanisms for running a wide range of tests. On start-up
- usbhost will search the USB bus for
- hardware running the target-side program, specifically a USB device
- that identifies itself as the product "Red Hat eCos
- USB test".
-
usbhost contains a Tcl interpreter, and
- will execute any Tcl scripts specified on the command line
- together with appropriate arguments. The Tcl interpreter has been
- extended with various commands such as
- usbtest::bulktest, so the script can perform
- the desired test or tests.
-
Adding a new test simply involves writing a short Tcl script that
- invokes the appropriate USB-specific commands. Running multiple
- tests involves passing appropriate arguments to
- usbhost, or alternatively writing a
- single script that just invokes other scripts.
-
The current implementation of usbhost
-depends heavily on functionality provided by the Linux kernel and in
-particular the usbdevfs support. It uses
-/proc/bus/usb/devices to find out what devices
-are attached to the bus, and will then access the device by opening
-/proc/bus/usb/xxx/yyy and performing
-ioctl operations. This allows USB testing to take
-place without having to write a new host-side device driver, but
-getting the code working on host machines not running Linux would
-obviously be problematical.
Building and Running the Target-side Code
The target-side component of the USB testing software consists of a
-single program usbtarget which contains
-support for a range of different tests, under the control of host-side
-software. This program is not built by default alongside other eCos
-test cases since it will only operate in certain environments,
-specifically when the target board's connector is plugged into a Linux
-host, and when the appropriate host-side software has been installed
-on that host. Instead the user must enable a configuration option
-CYGBLD_IO_USB_SLAVE_USBTEST to add the program to
-the list of tests for the current configuration.
Starting the usbtarget program does not
-require anything unusual, so it can be run in a normal
-gdb session just like any eCos application.
-After initialization the program will wait for activity from the host.
-Depending on the hardware, the Linux host will detect that a new USB
-peripheral is present on the bus either when the
-usbtarget initialization is complete or
-when the cable between target and host is connected. The host will
-perform the normal USB enumeration sequence and discover that the
-peripheral does not match any known vendor or product id and that
-there is no device driver for "Red Hat eCos USB
-test", so it will ignore the peripheral. When the
-usbhost program is run on the host it will
-connect to the target-side software, and testing can now commence.
Building and Running the Host-side Code
Note: In theory the host-side software should be built when the package is
-installed in the component repository, and removed when a package
-is uninstalled. The current eCos administration tool does not provide
-this functionality.
The host-side software should be built via the usual sequence of
-"configure/make/make install". It can only be built on a
-Linux host and the configure script contains an
-explicit test for this. Because the eCos component repository should
-generally be treated as a read-only resource the configure script will
-also prevent you from trying to build inside the source tree. Instead
-a separate build tree is required. Hence a typical sequence for
-building the host-side software would be as follows:
$ mkdir usbhost_build
-$ cd usbhost_build
-$ <repo>packages/io/usb/slave/current/host/configure <args>
-$ make
-<output from make>
-$ su
-$ make install
-<output from make install>
-$
The location of the eCos component repository should be substituted
-for <repo>.
If the package has been obtained via CVS or anonymous CVS then the
-package version will be current, as per the
-example. If instead the package has been obtained as part of a full
-eCos release or as a separate .epk file then the
-appropriate package version should be used instead of
-current.
The configure script takes the usual arguments such
-as --prefix= to specify where the executables
-and support files should be installed. The only other parameter that
-some users may wish to specify is the location of a suitable Tcl
-installation. By default usbhost will use
-the existing Tcl installation in /usr,
-as provided by your Linux distribution. An alternative Tcl
-installation can be specified using the parameter
---with-tcl=, or alternatively using some
-combination of --with-tcl-include,
---with-tcl-lib and
---with-tcl-version.
One of the host-side executables that gets built,
-usbchmod, needs to be installed with suid
-root privileges. Although the Linux kernel makes it possible for
-applications to perform low-level USB operations such as transmitting
-bulk packets, by default access to this functionality is restricted to
-programs with superuser privileges. It is undesirable to run a complex
-program such as usbhost with such
-privileges, especially since the program contains a general-purpose
-Tcl interpreter. Therefore when usbhost
-starts up and discovers that it does not have sufficient access to the
-appropriate entries in /proc/bus/usb,
-it spawns an instance of usbchmod to modify
-the permissions on these entries. usbchmod
-will only do this for a USB device "Red Hat eCos USB
-test", so installing this program suid root should not
-introduce any security problems.
During make install the following actions will take
-place:
usbhost will be installed in /usr/local/bin,
-or some other bin directory if
-the default location is changed at configure-time using a
---prefix= or similar option. It will be
-installed as the executable
-usbhost_<version>, for example
-usbhost_current, thus allowing several
-releases of the USB slave package to co-exist. For convenience a
-symbolic link from usbhost to this executable
-will be created, so users can just run usbhost to
-access the most recently-installed version.
usbchmod will be installed in
-/usr/local/libexec/ecos/io_usb_slave_<version>.
-This program should only be run by usbhost,
-not invoked directly, so it is not placed in the bin
-directory. Again the presence of the package version in the directory
-name allows multiple releases of the package to co-exist.
A Tcl script usbhost.tcl will get installed in
-the same directory as usbchmod. This Tcl
-script is loaded automatically by the
-usbhost executable.
A number of additional Tcl scripts, for example
-list.tcl will get installed alongside
-usbhost.tcl. These correspond to various test
-cases provided as standard. If a given test case is specified on the
-command line and cannot be found relative to the current directory
-then usbhost will search the install
-directory for these test cases.
Note: Strictly speaking installing the usbhost.tcl and
-other Tcl scripts below the libexec
-directory deviates from standard practice: they are
-architecture-independent data files so should be installed below
-the share subdirectory. In
-practice the files are sufficiently small that there is no point in
-sharing them, and keeping them below libexec
-simplifies the host-side software somewhat.
The usbhost should be run only when there is a
-suitable target attached to the USB bus and running the
-usbtarget program. It will search
-/proc/bus/usb/devices for an entry corresponding
-to this program, invoke usbchmod if
-necessary to change the access rights, and then interact with
-usbtarget over the USB bus.
-usbhost should be invoked as follows:
The -v or --version
-option will display version information for
-usbhost including the version of the USB
-slave package that was used to build the executable.
The -h or --help option
-will display usage information.
The -V or --verbose
-option can be used to obtain more information at run-time, for example
-some output for every USB transfer. This option can be repeated
-multiple times to increase the amount of output.
The first argument that does not begin with a hyphen specifies a test
-that should be run, in the form of a Tcl script. For example an
-argument of list.tcl will cause
-usbhost to look for a script with that
-name, adding a .tcl suffix if necessarary, and
-run that script. usbhost will look in the
-current directory first, then in the install tree for standard test
-scripts provided by the USB slave package.
Some test scripts may want their own parameters, for example a
-duration in seconds. These can be passed on the command line after
-the name of the test, for example
-usbhost mytest 60.
Writing a Test
Each test is defined by a Tcl script, running inside an interpreter
-provided by usbhost. In addition to the
-normal Tcl functionality this interpreter provides a number of
-variables and functions related to USB testing. For example there is a
-variable bulk_in_endpoints that lists all the
-endpoints on the target that can perform bulk IN operations, and a
-related array bulk_in which contains information
-such as the minimum and maximum packets sizes. There is a function
-bulktest which can be used to perform bulk tests
-on a particular endpoint. A simple test script aimed at specific
-hardware could ignore the information variables since it would know
-exactly what USB hardware is available on the target, whereas a
-general-purpose script would use the information to adapt to the
-hardware capabilities.
To avoid namespace pollution all USB-related Tcl variables and
-functions live in the usbtest:: namespace.
-Therefore accessing requires either explicitly including the
-namespace any references, for example
-$usbtest::bulk_in_endpoints, or by using Tcl's
-namespace import facility.
This would perform a test run involving 4000 bulk transfers from the
-host to the target's endpoint 1, and concurrently 4000 bulk transfers
-from endpoint 2. Default settings for packet sizes, contents, and
-delays would be used. The actual test would not start running until
-usbtest is invoked, and it is expected that the
-test would complete within 60 seconds. If any failures occur then they
-are reported.
Available Hardware
Each target-side USB device driver provides information about the
-actual capabilities of the hardware, for example which endpoints are
-available. Strictly speaking it provides information about what is
-actually supported by the device driver, which may be a subset of what
-the hardware is capable of. For example, the hardware may support
-isochronous transfers on a particular endpoint but if there is no
-software support for this in the driver then this endpoint will not be
-listed. When usbhost first contacts the
-usbtarget program running on the target
-platform, it obtains this information and makes it available to test
-scripts via Tcl variables:
bulk_in_endpoints
This is a simple list of the endpoints which can support bulk IN
- transfers. For example if the target-side hardware supports
- these transfers on endpoints 3 and 5 then the value would be
- "3 5" Typical test scripts would
- iterate over the list using something like:
-
This array holds additional information about each bulk IN endpoint.
- The array is indexed by two fields, the endpoint number and one of
- min_size, max_size,
- max_in_padding and devtab:
-
min_size
This field specifies a lower bound on the size of bulk transfers,
- and will typically will have a value of 1.
-
Note: The typical minimum transfer size of a single byte is not strictly
- speaking correct, since under some circumstances it can make sense
- to have a transfer size of zero bytes. However current target-side
- device drivers interpret a request to transfer zero bytes as a way
- for higher-level code to determine whether or not an endpoint is
- stalled, so it is not actually possible to perform zero-byte
- transfers. This issue will be addressed at some future point.
-
max_size
This field specifies an upper bound on the size of bulk transfers.
- Some target-side drivers may be limited to transfers of say
- 0x0FFFF bytes because of hardware limitations. In practice the
- transfer size is likely to be limited primarily to limit memory
- consumption of the test code on the target hardware, and to ensure
- that tests complete reasonably quickly. At the time of writing
- transfers are limited to 4K.
-
max_in_padding
On some hardware it may be necessary for the target-side device
- driver to send more data than is actually intended. For example
- the SA11x0 USB hardware cannot perform bulk transfers that are
- an exact multiple of 64 bytes, instead it must pad such
- transfers with an extra byte and the host must be ready to
- accept and discard this byte. The
- max_in_padding field indicates the amount of
- padding that is required. The low-level code inside
- usbhost will use this field
- automatically, and there is no need for test scripts to adjust
- packet sizes for padding. The field is provided for
- informational purposes only.
-
devtab
This is a string indicating whether or not the
- target-side USB device driver supports access to this endpoint
- via entries in the device table, in other words through
- conventional calls like open and
- write. Some device drivers may only
- support low-level USB access because typically that is what gets
- used by USB class-specific packages such as USB-ethernet.
- An empty string indicates that no devtab entry is available,
- otherwise it will be something like
- "/dev/usbs2w".
-
Typical test scripts would access this data using something like:
-
foreach endpoint $usbtest:bulk_in_endpoints {
- puts "Endpoint $endpoint: "
- puts " minimum transfer size $usbtest::bulk_in($endpoint,min_size)"
- puts " maximum transfer size $usbtest::bulk_in($endpoint,max_size)"
- if { 0 == $usbtest::bulk_in($endpoint,max_in_padding) } {
- puts " no IN padding required"
- } else {
- puts " $usbtest::bulk_in($endpoint,max_in_padding) bytes of IN padding required"
- }
- if { "" == $usbtest::bulk_in($endpoint,devtab) } {
- puts " no devtab entry provided"
- } else {
- puts " corresponding devtab entry is $usbtest::bulk_in($endpoint,devtab)"
- }
- }
-
bulk_out_endpoint
This is a simple list of the endpoints which can support bulk OUT
- transfers. It is analogous to
- bulk_in_endpoints.
-
bulk_out()
This array holds additional information about each bulk OUT
- endpoint. It can be accessed in the same way as
- bulk_in(), except that there is no
- max_in_padding field because that field only
- makes sense for IN transfers.
-
control()
This array holds information about the control endpoint. It contains
- two fields, min_size and
- max_size. Note that there is no variable
- control_endpoints because a USB target always
- supports a single control endpoint 0. Similarly
- the control array does not use an endpoint number
- as the first index because that would be redundant.
-
isochronous_in_endpoints and
- isochronous_in()
These variables provide the same information as
- bulk_in_endpoints and bulk_in,
- but for endpoints that support isochronous IN transfers.
-
isochronous_out_endpoints and
- isochronous_out()
These variables provide the same information as
- bulk_out_endpoints and bulk_out,
- but for endpoints that support isochronous OUT transfers.
-
interrupt_in_endpoints and
- interrupt_in()
These variables provide the same information as
- bulk_in_endpoints and bulk_in,
- but for endpoints that support interrupt IN transfers.
-
interrupt_out_endpoints and
- interrupt_out()
These variables provide the same information as
- bulk_out_endpoints and bulk_out,
- but for endpoints that support interrupt OUT transfers.
-
Testing Bulk Transfers
The main function for initiating a bulk test is
-usbtest::bulktest. This takes three compulsory
-arguments, and can be given a number of additional arguments to
-control the exact behaviour. The compulsory arguments are:
endpoint
This specifies the endpoint to use. It should correspond to
- one of the entries in
- usbtest::bulk_in_endpoints or
- usbtest::bulk_out_endpoints, depending on the
- transfer direction.
-
direction
This should be either in or out.
-
number of transfers
This specifies the number of transfers that should take place. The
- testing software does not currently support the concept of performing
- transfers for a given period of time because synchronising this on
- both the host and a wide range of targets is difficult. However it
- is relatively easy to work out the approximate time a number of bulk
- transfers should take place, based on a typical bandwidth of
- 1MB/second and assuming say a 1ms overhead per transfer.
- Alternatively a test script could perform a small initial run to
- determine what performance can actually be expected from a given
- target, and then use this information to run a much longer test.
-
Additional arguments can be used to control the exact transfer. For
-example a txdelay+ argument can be used to
-slowly increase the delay between transfers. All such arguments involve
-a value which can be passed either as part of the argument itself,
-for example txdelay+=5, or as a subsequent
-argument, txdelay+ 5. The possible arguments fall
-into a number of categories: data, I/O mechanism, transmit size,
-receive size, transmit delay, and receive delay.
Data
An obvious parameter to control is the actual data that gets sent.
-This can be controlled by the argument data
-which can take one of five values: none,
-bytefill, intfill,
-byteseq and wordseq. The default
-value is none.
none
The transmit code will not attempt to fill the buffer in any way,
- and the receive code will not check it. The actual data that gets
- transferred will be whatever happened to be in the buffer before
- the transfer started.
-
bytefill
The entire buffer will be filled with a single byte, as per
- memset.
-
intfill
The buffer will be treated as an array of 32-bit integers, and will
- be filled with the same integer repeated the appropriate number of
- times. If the buffer size is not a multiple of four bytes then
- the last few bytes will be set to 0.
-
byteseq
The buffer will be filled with a sequence of bytes, generated by
- a linear congruential generator. If the first byte in the buffer is
- filled with the value x, the next byte will be
- (m*x)+i. For example a sequence of slowly
- incrementing bytes can be achieved by setting both the multiplier
- and the increment to 1. Alternatively a pseudo-random number
- sequence can be achieved using values 1103515245 and 12345, as
- per the standard C library rand function.
- For convenience these two constants are available as Tcl
- variables usbtest::MULTIPLIER and
- usbtest::INCREMENT.
-
wordseq
This acts like byteseq, except that the buffer is
- treated as an array of 32-bit integers rather than as an array of
- bytes. If the buffer is not a multiple of four bytes then the last
- few bytes will be filled with zeroes.
-
The above requires three additional parameters
-data1, data* and
-data+. data1 specifies
-the value to be used for byte or word fills, or the first number when
-calculating a sequence. The default value is 0.
-data* and data+ specify
-the multiplier and increment for a sequence, and have default values
-of 1 and 0 respectively. For
-example, to perform a bulk transfer of a pseudo-random sequence of
-integers starting with 42 the following code could be used:
The above parameters define what data gets transferred for the first
-transfer, but a test can involve multiple transfers. The data format
-will be the same for all transfers, but it is possible to adjust the
-current value, the multiplier, and the increment between each
-transfer. This is achieved with parameters data1*,
-data1+, data**,
-data*+, data+*, and
-data++, with default values of 1 for each
-multiplier and 0 for each increment. For example, if the multiplier
-for the first transfer is set to 2 using
-data*, and arguments
-data** 2 and data*+ -1 are also
-supplied, then the multiplier for subsequent transfers will be
-3, 5, 9,
-….
Note: Currently it is not possible for a test script to send specific data,
-for example a specific sequence of bytes captured by a protocol analyser
-that caused a problem. If the transfer was from host to target then
-the target would have to know the exact sequence of bytes to expect,
-which means transferring data over the USB bus when that data is known
-to have caused problems in the past. Similarly for target to host
-transfers the target would have to know what bytes to send. A possible
-future extension of the USB testing support would allow for bounce
-operations, where a given message is first sent to the target and then
-sent back to the host, with only the host checking that the data was
-returned correctly.
I/O Mechanism
On the target side USB transfers can happen using either low-level
-USB calls such as usbs_start_rx_buffer, or by
-higher-level calls which go through the device table. By default the
-target-side code will use the low-level calls. If it is desired to
-test the higher-level calls instead, for example because those are
-what the application uses, then that can be achieved with an
-argument mechanism=devtab.
Transmit Size
The next set of arguments can be used to control the size of the
-transmitted buffer: txsize1,
-txsize>=, txsize<=
-txsize*, txsize/,
-and txsize+.
txsize1 determines the size of the first
-transfer, and has a default value of 32 bytes. The size of the next
-transfer is calculated by first multiplying by the
-txsize* value, then dividing by the
-txsize/ value, and finally adding the
-txsize+ value. The defaults for these are
-1, 1, and 0
-respectively, which means that the transfer size will remain
-unchanged. If for example the transfer size should increase by
-approximately 50 per cent each time then suitable values might be
-txsize* 3, txsize/ 2,
-and txsize+ 1.
The txsize>= and
-txsize<= arguments can be used to impose
-lower and upper bounds on the transfer. By default the
-min_size and max_size values
-appropriate for the endpoint will be used. If at any time the
-current size falls outside the bounds then it will be normalized.
Receive Size
The receive size, in other words the number of bytes that either host
-or target will expect to receive as opposed to the number of bytes
-that actually get sent, can be adjusted using a similar set of
-arguments: rxsize1,
-rxsize>=,
-rxsize<=,
-rxsize*, rxsize/ and
-rxsize+. The current receive size will be
-adjusted between transfers just like the transmit size. However when
-communicating over USB it is not a good idea to attempt to receive
-less data than will actually be sent: typically neither the hardware
-nor the software will be able to do anything useful with the excess,
-so there will be problems. Therefore if at any time the calculated
-receive size is less than the transmit size, the actual receive will
-be for the exact number of bytes that will get transmitted. However
-this will not affect the calculations for the next receive size.
The default values for rxsize1,
-rxsize*, rxsize/ and
-rxsize+ are 0,
-1, 1 and 0
-respectively. This means that the calculated receive size will always
-be less than the transmit size, so the receive operation will be for
-the exact number of bytes transmitted. For some USB protocols this
-would not accurately reflect the traffic that will happen. For example
-with USB-ethernet transfer sizes will vary between 16 and 1516 bytes,
-so the receiver will always expect up to 1516 bytes. This can be
-achieved using rxsize1 1516, leaving the
-other parameters at their default values.
For target hardware which involves non-zero
-max_in_padding, on the host side the padding will
-be added automatically to the receive size if necessary.
Transmit and Receive Delays
Typically during the testing there will be some minor delays between
-transfers on both host and target. Some of these delays will be caused
-by timeslicing, for example another process running on the host, or a
-concurrent test thread running inside the target. Other delays will be
-caused by the USB bus itself, for example activity from another device
-on the bus. However it is desirable that test cases be allowed to
-inject additional and somewhat more controlled delays into the system,
-for example to make sure that the target behaves correctly even if the
-target is not yet ready to receive data from the host.
The transmit delay is controlled by six parameters:
-txdelay1, txdelay*,
-txdelay/, txdelay+,
-txdelay>= and
-txdelay<=. The default values for these are
-0, 1, 1,
-0, 0 and
-1000000000 respectively, so that by default
-transmits will happen as quickly as possible. Delays are measured in
-nanoseconds, so a value of 1000000 would correspond
-to a delay of 0.001 seconds or one millisecond. By default delays have
-an upper bound of one second. Between transfers the transmit delay is
-updated in much the same was as the transfer sizes.
The receive delay is controlled by a similar set of six parameters:
-rxdelay1, rxdelay*,
-rxdelay/, rxdelay+,
-rxdelay>= and
-rxdelay<=. The default values for these are
-the same as for transmit delays.
The transmit delay is used on the side which sends data over the USB
-bus, so for a bulk IN transfer it is the target that sends data and
-hence sleeps for the specified transmit delay, while the host receives
-data sleeps for the receive delay. For an OUT transfer the positions
-are reversed.
It should be noted that although the delays are measured in
-nanoseconds, the actual delays will be much less precise and are
-likely to be of the order of milliseconds. The exact details will
-depend on the kernel clock speed.
Other Types of Transfer
Support for testing other types of USB traffic such as isochronous
-transfers is not yet implemented.
Starting a Test and Collecting Results
A USB test script should prepare one or more transfers using
-appropriate functions such as usbtest::bulktest.
-Once all the individual tests have been prepared they can be started
-by a call to usbtest::start. This takes a single
-argument, a maximum duration measured in seconds. If all transfers
-have not been completed in the specified time then any remaining
-transfers will be aborted.
usbtest::start will return 1
-if all the tests have succeeded, or 0 if any of
-them have failed. More detailed reports will be stored in the
-Tcl variable usbtests::results, which will be a
-list of string messages.
Existing Test Scripts
A number of test scripts are provided as standard. These are located
-in the host subdirectory of the
-common USB slave package, and will be installed as part of the process
-of building the host-side software. When a script is specified on the
-command line usbhost will first search for
-it in the current directory, then in the install tree. Standard
-test scripts include the following:
list.tcl
This script simply displays information about the capabilities
- of the target platform, as provided by the target-side USB
- device driver. It can help with tracking down problems, but its
- primary purpose is to let users check that everything is working
- correctly: if running usbhost list.tcl
- outputs sensible information then the user knows that the
- target side is running correctly and that communication between
- host and target is possible.
-
verbose.tcl
The target-side code can provide information about what
- is happening while tests are prepared and run. This facility
- should not normally be used since the extra I/O involved will
- significantly affect the behaviour of the system, but in some
- circumstances it may prove useful. Since an eCos application
- cannot easily be given command-line arguments the target-side
- verbosity level cannot be controlled using
- -V or --verbose
- options. Instead it can be controlled from inside
- gdb by changing the integer
- variable verbose. Alternatively it can
- be manipulated by running the test script
- verbose.tcl. This script takes a single
- argument, the desired verbosity level, which should be a small
- integer. For example, to disable target-side run-time logging
- the command usbhost verbose 0 can
- be used.
-
Possible Problems
If all transfers succeed within the specified time then both host and
-target remain in synch and further tests can be run without problem.
-However, if at any time a failure occurs then things get more
-complicated. For example, if the current test involves a series of
-bulk OUT transfers and the target detects that for one of these
-transfers it received less data than was expected then the test has
-failed, and the target will stop accepting data on this endpoint.
-However the host-side software may not have detected anything wrong
-and is now blocked trying to send the next lot of data.
The test code goes to considerable effort to recover from problems
-such as these. On the host-side separate threads are used for
-concurrent transfers, and on the target-side appropriate asynchronous
-I/O mechanisms are used. In addition there is a control thread on the
-host that checks the state of all the main host-side threads, and the
-state of the target using private control messages. If it discovers
-that one side has stopped sending or receiving data because of an
-error and the other side is blocked as a result, it will set certain
-flags and then cause one additional transfer to take place. That
-additional transfer will have the effect of unblocking the other side,
-which then discovers that an error has occurred by checking the
-appropriate flags. In this way both host and target should end up back
-in synch, and it is possible to move on to the next set of tests.
However, the above assumes that the testing has not triggered any
-serious hardware conditions. If instead the target-side hardware has
-been left in some strange state so that, for example, it will no
-longer raise an interrupt for traffic on a particular endpoint then
-recovery is not currently possible, and the testing software will just
-hang.
A possible future enhancement to the testing software would allow the
-host-side to raise a USB reset signal whenever a failure occurs, in
-the hope that this would clear any remaining problems within the
-target-side USB hardware.
\ No newline at end of file
Index: slave/v2_0/doc/makefile
===================================================================
--- slave/v2_0/doc/makefile (revision 174)
+++ slave/v2_0/doc/makefile (nonexistent)
@@ -1,55 +0,0 @@
-#=============================================================================
-#
-# makefile
-#
-# For building the USB slave package documentation
-#
-#=============================================================================
-#####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####
-#
-# Author(s): bartv
-# Date: 2001-01-11
-#####DESCRIPTIONEND####
-#=============================================================================
-
-TOPLEVEL := ../../../../..
-MAIN_SGML := usbs.sgml
-MAIN_HTML := io-usb-slave.html
-MAIN_PDF := io-usb-slave.pdf
-OTHER_SGML :=
-PICTURES :=
-
-include $(TOPLEVEL)/pkgconf/rules.doc
Index: slave/v2_0/doc/usbs-control.html
===================================================================
--- slave/v2_0/doc/usbs-control.html (revision 174)
+++ slave/v2_0/doc/usbs-control.html (nonexistent)
@@ -1,934 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-Control Endpoints
-
The device driver for a USB slave device should supply one
-usbs_control_endpoint data structure per USB
-device. This corresponds to endpoint 0 which will be used for all
-control message interaction between the host and that device. The data
-structure is also used for internal management purposes, for example
-to keep track of the current state. In a typical USB peripheral there
-will only be one such data structure in the entire system, but if
-there are multiple USB slave ports, allowing the peripheral to be
-connected to multiple hosts, then there will be a separate data
-structure for each one. The name or names of the data structures are
-determined by the device drivers. For example, the SA11x0 USB device
-driver package provides usbs_sa11x0_ep0.
The operations on a control endpoint do not fit cleanly into a
-conventional open/read/write I/O model. For example, when the host
-sends a control message to the USB peripheral this may be one of four
-types: standard, class, vendor and reserved. Some or all of the
-standard control messages will be handled automatically by the common
-USB slave package or by the device driver itself. Other standard
-control messages and the other types of control messages may be
-handled by a class-specific package or by application code. Although
-it would be possible to have devtab entries such as
-/dev/usbs_ep0/standard and
-/dev/usbs_ep0/class, and then support read and
-write operations on these devtab entries, this would add significant
-overhead and code complexity. Instead, all of the fields in the
-control endpoint data structure are public and can be manipulated
-directly by higher level code if and when required.
Control endpoints involve a number of callback functions, with
-higher-level code installing suitable function pointers in the control
-endpoint data structure. For example, if the peripheral involves
-vendor-specific control messages then a suitable handler for these
-messages should be installed. Although the exact details depend on the
-device driver, typically these callback functions will be invoked at
-DSR level rather than thread level. Therefore, only certain eCos
-functions can be invoked; specifically, those functions that are
-guaranteed not to block. If a potentially blocking function such as a
-semaphore wait or a mutex lock operation is invoked from inside the
-callback then the resulting behaviour is undefined, and the system as
-a whole may fail. In addition, if one of the callback functions
-involves significant processing effort then this may adversely affect
-the system's real time characteristics. The eCos kernel documentation
-should be consulted for more details of DSR handling.
Initialization
The usbs_control_endpoint data structure
-contains the following fields related to initialization.
It is the responsibility of higher-level code, usually the
-application, to define the USB enumeration data. This needs to be
-installed in the control endpoint data structure early on during
-system startup, before the USB device is actually started and any
-interaction with the host is possible. Details of the enumeration data
-are supplied in the section USB Enumeration
-Data. Typically, the enumeration data is constant for a given
-peripheral, although it can be constructed dynamically if necessary.
-However, the enumeration data cannot change while the peripheral is
-connected to a host: the peripheral cannot easily claim to be a
-keyboard one second and a printer the next.
The start_fn member is normally accessed
-via the utility usbs_start rather
-than directly. It is provided by the device driver and should be
-invoked once the system is fully initialized and interaction with the
-host is possible. A typical implementation would change the USB data
-pins from tristated to active. If the peripheral is already plugged
-into a host then the latter should detect this change and start
-interacting with the peripheral, including requesting the enumeration
-data.
State
There are three usbs_control_endpoint fields
-related to the current state of a USB slave device, plus some state
-constants and an enumeration of the possible state changes:
The USB standard defines a number of states for a given USB
-peripheral. The initial state is detached, where
-the peripheral is either not connected to a host at all or, from the
-host's perspective, the peripheral has not started up yet because the
-relevant pins are tristated. The peripheral then moves via
-intermediate attached and
-powered states to its default or
-reset state, at which point the host and
-peripheral can actually start exchanging data. The first message is
-from host to peripheral and provides a unique 7-bit address within the
-local USB network, resulting in a state change to
-addressed. The host then requests enumeration
-data and performs other initialization. If everything succeeds the
-host sends a standard set-configuration control message, after which
-the peripheral is configured and expected to be
-up and running. Note that some USB device drivers may be unable to
-distinguish between the detached,
-attached and powered states
-but generally this is not important to higher-level code.
A USB host should generate at least one token every millisecond. If a
-peripheral fails to detect any USB traffic for a period of time then
-typically this indicates that the host has entered a power-saving
-mode, and the peripheral should do the same if possible. This
-corresponds to the suspended bit. The actual
-state is a combination of suspended and the
-previous state, for example configured and
-suspended rather than just
-suspended. When the peripheral subsequently
-detects USB traffic it would switch back to the
-configured state.
The USB device driver and the common USB slave package will maintain
-the current state in the control endpoint's
-state field. There should be no need for
-any other code to change this field, but it can be examined whenever
-appropriate. In addition whenever a state change occurs the generic
-code can invoke a state change callback function. By default, no such
-callback function will be installed. Some class-specific packages such
-as the USB-ethernet package will install a suitable function to keep
-track of whether or not the host-peripheral connection is up, that is
-whether or not ethernet packets can be exchanged. Application code can
-also update this field. If multiple parties want to be informed of
-state changes, for example both a class-specific package and
-application code, then typically the application code will install its
-state change handler after the class-specific package and is
-responsible for chaining into the package's handler.
The state change callback function is invoked with four arguments. The
-first identifies the control endpoint. The second is an arbitrary
-pointer: higher-level code can fill in the
-state_change_data field to set this. The
-third argument specifies the state change that has occurred, and the
-last argument supplies the previous state (the new state is readily
-available from the control endpoint structure).
eCos does not provide any utility functions for updating or examining
-the state_change_fn or
-state_change_data fields. Instead, it is
-expected that the fields in the
-usbs_control_endpoint data structure will be
-manipulated directly. Any utility functions would do just this, but
-at the cost of increased code and cpu overheads.
When a USB peripheral is connected to the host it must always respond
-to control messages sent to endpoint 0. Control messages always
-consist of an initial eight-byte header, containing fields such as a
-request type. This may be followed by a further data transfer, either
-from host to peripheral or from peripheral to host. The way this is
-handled is described in the Buffer Management section below.
The USB device driver will always accept the initial eight-byte
-header, storing it in the control_buffer
-field. Then it determines the request type: standard, class, vendor,
-or reserved. The way in which the last three of these are processed is
-described in the section Other
-Control Messages. Some
-standard control messages will be handled by the device driver itself;
-typically the set-address request and the
-get-status, set-feature and
-clear-feature requests when applied to endpoints.
If a standard control message cannot be handled by the device driver
-itself, the driver checks the
-standard_control_fn field in the control
-endpoint data structure. If higher-level code has installed a suitable
-callback function then this will be invoked with two argument, the
-control endpoint data structure itself and the
-standard_control_data field. The latter
-allows the higher level code to associate arbitrary data with the
-control endpoint. The callback function can return one of three
-values: HANDLED to indicate that the request has
-been processed; UNKNOWN if the message should be
-handled by the default code; or STALL to indicate
-an error condition. If higher level code has not installed a callback
-function or if the callback function has returned
-UNKNOWN then the device driver will invoke a
-default handler, usbs_handle_standard_control
-provided by the common USB slave package.
The default handler can cope with all of the standard control messages
-for a simple USB peripheral. However, if the peripheral involves
-multiple configurations, multiple interfaces in a configuration, or
-alternate settings for an interface, then this cannot be handled by
-generic code. For example, a multimedia peripheral may support various
-alternate settings for a given data source with different bandwidth
-requirements, and the host can select a setting that takes into
-account the current load. Clearly higher-level code needs to be aware
-when the host changes the current setting, so that it can adjust the
-rate at which data is fed to or retrieved from the host. Therefore the
-higher-level code needs to install its own standard control callback
-and process appropriate messages, rather than leaving these to the
-default handler.
The default handler will take care of the
-get-descriptor request used to obtain the
-enumeration data. It has support for string descriptors but ignores
-language encoding issues. If language encoding is important for the
-peripheral then this will have to be handled by an
-application-specific standard control handler.
The header file <cyg/io/usb/usb.h> defines various
-constants related to control messages, for example the function codes
-corresponding to the standard request types. This header file is
-provided by the common USB package, not by the USB slave package,
-since the information is also relevant to USB hosts.
Non-standard control messages always have to be processed by
-higher-level code. This could be class-specific packages. For example,
-the USB-ethernet package will handle requests for getting the MAC
-address and for enabling or disabling promiscuous mode. In all cases
-the device driver will store the initial request in the
-control_buffer field, check for an
-appropriate handler, and invoke it with details of the control
-endpoint and any handler-specific data that has been installed
-alongside the handler itself. The handler should return either
-USBS_CONTROL_RETURN_HANDLED to report success or
-USBS_CONTROL_RETURN_STALL to report failure. The
-device driver will report this to the host.
If there are multiple parties interested in a particular type of
-control messages, it is the responsibility of application code to
-install an appropriate handler and process the requests appropriately.
Many USB control messages involve transferring more data than just the
-initial eight-byte header. The header indicates the direction of the
-transfer, OUT for host to peripheral or IN for peripheral to host.
-It also specifies a length field, which is exact for an OUT transfer
-or an upper bound for an IN transfer. Control message handlers can
-manipulate six fields within the control endpoint data structure to
-ensure that the transfer happens correctly.
For an OUT transfer, the handler should examine the length field in
-the header and provide a single buffer for all the data. A
-class-specific protocol would typically impose an upper bound on the
-amount of data, allowing the buffer to be allocated statically.
-The handler should update the buffer and
-complete_fn fields. When all the data has
-been transferred the completion callback will be invoked, and its
-return value determines the response sent back to the host. The USB
-standard allows for a new control message to be sent before the
-current transfer has completed, effectively cancelling the current
-operation. When this happens the completion function will also be
-invoked. The second argument to the completion function specifies what
-has happened, with a value of 0 indicating success and an error code
-such as -EPIPE or -EIO
-indicating that the current transfer has been cancelled.
IN transfers are a little bit more complicated. The required
-information, for example the enumeration data, may not be in a single
-contiguous buffer. Instead a mechanism is provided by which the buffer
-can be refilled, thus allowing the transfer to move from one record to
-the next. Essentially, the transfer operates as follows:
When the host requests another chunk of data (typically eight bytes),
-the USB device driver will examine the
-buffer_size field. If non-zero then
-buffer contains at least one more byte of
-data, and then buffer_size is decremented.
When buffer_size has dropped to 0, the
-fill_buffer_fn field will be examined. If
-non-null it will be invoked to refill the buffer.
The fill_data and
-fill_index fields are not used by the
-device driver. Instead these fields are available to the refill
-function to keep track of the current state of the transfer.
When buffer_size is 0 and
-fill_buffer_fn is NULL, no more data is
-available and the transfer has completed.
Optionally a completion function can be installed. This will be
-invoked with 0 if the transfer completes successfully, or with an
-error code if the transfer is cancelled because of another control
-messsage.
If the requested data is contiguous then the only fields that need
-to be manipulated are buffer and
-buffer_size, and optionally
-complete_fn. If the requested data is not
-contiguous then the initial control message handler should update
-fill_buffer_fn and some or all of the other
-fields, as required. An example of this is the handling of the
-standard get-descriptor control message by
-usbs_handle_standard_control.
In nearly all circumstances USB I/O should be interrupt-driven.
-However, there are special environments such as RedBoot where polled
-operation may be appropriate. If the device driver can operate in
-polled mode then it will provide a suitable function via the
-poll_fn field, and higher-level code can
-invoke this regularly. This polling function will take care of all
-endpoints associated with the device, not just the control endpoint.
-If the USB hardware involves a single interrupt vector then this will
-be identified in the data structure as well.
\ No newline at end of file
Index: slave/v2_0/doc/usbs.sgml
===================================================================
--- slave/v2_0/doc/usbs.sgml (revision 174)
+++ slave/v2_0/doc/usbs.sgml (nonexistent)
@@ -1,3540 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- eCos USB Slave Support
-
-
-
-
-
-Introduction
-
-
-Introduction
-eCos support for USB slave devices
-
-
-Introduction
-
-The eCos USB slave support allows developers to produce USB
-peripherals. It consists of a number of different eCos packages:
-
-
-
-
-
-Device drivers for specific implementations of USB slave hardware, for
-example the on-chip USB Device Controller provided by the Intel SA1110
-processor. A typical USB peripheral will only provide one USB slave
-port and therefore only one such device driver package will be needed.
-Usually the device driver package will be loaded automatically when
-you create an eCos configuration for target hardware that has a USB
-slave device. If you select a target which does have a USB slave
-device but no USB device driver is loaded, this implies that no such
-device driver is currently available.
-
-
-
-
-
-The common USB slave package. This serves two purposes. It defines the
-API that specific device drivers should implement. It also provides
-various utilities that will be needed by most USB device drivers and
-applications, such as handlers for standard control messages.
-Usually this package will be loaded automatically at the same time as
-the USB device driver.
-
-
-
-
-
-The common USB package. This merely provides some information common
-to both the host and slave sides of USB, such as details of the
-control protocol. It is also used to place the other USB-related
-packages appropriately in the overall configuration hierarchy. Usually
-this package will be loaded at the same time as the USB device driver.
-
-
-
-
-
-Class-specific USB support packages. These make it easier to develop
-specific classes of USB peripheral, such as a USB-ethernet device. If
-no suitable package is available for a given class of peripheral then
-the USB device driver can instead be accessed directly from
-application code. Such packages will never be loaded automatically
-since the configuration system has no way of knowing what class of USB
-peripheral is being developed. Instead developers have to add the
-appropriate package or packages explicitly.
-
-
-
-
-
-
-These packages only provide support for developing USB peripherals,
-not USB hosts.
-
-
-
-USB Concepts
-
-Information about USB can be obtained from a number of sources
-including the USB Implementers Forum
-web site. Only a brief summary is provided here.
-
-
-A USB network is asymmetrical: it consists of a single host, one or
-more slave devices, and possibly some number of intermediate hubs. The
-host side is significantly more complicated than the slave side.
-Essentially, all operations are initiated by the host. For example, if
-the host needs to receive some data from a particular USB peripheral
-then it will send an IN token to that peripheral; the latter should
-respond with either a NAK or with appropriate data. Similarly, when
-the host wants to transmit data to a peripheral it will send an OUT
-token followed by the data; the peripheral will return a NAK if it is
-currently unable to receive more data or if there was corruption,
-otherwise it will return an ACK. All transfers are check-summed and
-there is a clearly-defined error recovery process. USB peripherals can
-only interact with the host, not with each other.
-
-
-USB supports four different types of communication: control messages,
-interrupt transfers, isochronous transfers, and bulk transfers.
-Control messages are further subdivided into four categories:
-standard, class, vendor and a reserved category. All USB peripherals
-must respond to certain standard control messages, and usually this
-will be handled by the common USB slave package (for complicated
-peripherals, application support will be needed). Class and vendor
-control messages may be handled by an class-specific USB support
-package, for example the USB-ethernet package will handle control
-messages such as getting the MAC address or enabling/disabling
-promiscuous mode. Alternatively, some or all of these messages will
-have to be handled by application code.
-
-
-Interrupt transfers are used for devices which need to be polled
-regularly. For example, a USB keyboard might be polled once every
-millisecond. The host will not poll the device more frequently than
-this, so interrupt transfers are best suited to peripherals that
-involve a relatively small amount of data. Isochronous transfers are
-intended for multimedia-related peripherals where typically a large
-amount of video or audio data needs to be exchanged continuously.
-Given appropriate host support a USB peripheral can reserve some of
-the available bandwidth. Isochronous transfers are not reliable; if a
-particular packet is corrupted then it will just be discarded and
-software is expected to recover from this. Bulk transfers are used for
-everything else: after taking care of any pending control, isochronous
-and interrupt transfers the host will use whatever bandwidth remains
-for bulk transfers. Bulk transfers are reliable.
-
-
-Transfers are organized into USB packets, with the details depending
-on the transfer type. Control messages always involve an initial
-8-byte packet from host to peripheral, optionally followed by some
-additional packets; in theory these additional packets can be up to 64
-bytes, but hardware may limit it to 8 bytes. Interrupt transfers
-involve a single packet of up to 64 bytes. Isochronous transfers
-involve a single packet of up to 1024 bytes. Bulk transfers involve
-multiple packets. There will be some number, possibly zero, of 64-byte
-packets. The transfer is terminated by a single packet of less than 64
-bytes. If the transfer involves an exact multiple of 64 bytes than the
-final packet will be 0 bytes, consisting of just a header and checksum
-which typically will be generated by the hardware. There is no
-pre-defined limit on the size of a bulk transfer. Instead higher-level
-protocols are expected to handle this, so for a USB-ethernet
-peripheral the protocol could impose a limit of 1514 bytes of data
-plus maybe some additional protocol overhead.
-
-
-Transfers from the host to a peripheral are addressed not just to that
-peripheral but to a specific endpoint within that peripheral.
-Similarly, the host requests incoming data from a specific endpoint
-rather than from the peripheral as a whole. For example, a combined
-keyboard/touchpad device could provide the keyboard events on endpoint
-1 and the mouse events on endpoint 2. A given USB peripheral can have
-up to 16 endpoints for incoming data and another 16 for outgoing data.
-However, given the comparatively high speed of USB I/O this endpoint
-addressing is typically implemented in hardware rather than software,
-and the hardware will only implement a small number of endpoints.
-Endpoint 0 is generally used only for control messages.
-
-
-In practice, many of these details are irrelevant to application code
-or to class packages. Instead, such higher-level code usually just
-performs blocking read and
-write, or non-blocking USB-specific calls, to
-transfer data between host and target via a specific endpoint. Control
-messages are more complicated but are usually handled by existing
-code.
-
-
-When a USB peripheral is plugged into the host there is an initial
-enumeration and configuration process. The peripheral provides
-information such as its class of device (audio, video, etc.), a
-vendor id, which endpoints should be used for what kind of data, and
-so on. The host OS uses this information to identify a suitable host
-device driver. This could be a generic driver for a class of
-peripherals, or it could be a vendor-specific driver. Assuming a
-suitable driver is installed the host will then activate the USB
-peripheral and perform additional application-specific initialisation.
-For example for a USB-ethernet device this would involve obtaining an
-ethernet MAC address. Most USB peripherals will be fairly simple, but
-it is possible to build multifunction peripherals with multiple
-configurations, interfaces, and alternate interface settings.
-
-
-It is not possible for any of the eCos packages to generate all the
-enumeration data automatically. Some of the required information such
-as the vendor id cannot be supplied by generic packages; only by the
-application developer. Class support code such as the USB-ethernet
-package could in theory supply some of the information automatically,
-but there are also hardware dependencies such as which endpoints get
-used for incoming and outgoing ethernet frames. Instead it is the
-responsibility of the application developer to provide all the
-enumeration data and perform some additional initialisation. In
-addition, the common USB slave package can handle all the standard
-control messages for a simple USB peripheral, but for something like a
-multifunction peripheral additional application support is needed.
-
-
-
-The initial implementation of the eCos USB slave packages involved
-hardware that only supported control and bulk transfers, not
-isochronous or interrupt. There may be future changes to the USB
-code and API to allow for isochronous and interrupt transfers,
-especially the former. Other changes may be required to support
-different USB devices. At present there is no support for USB remote
-wakeups, since again it is not supported by the hardware.
-
-
-
-
-eCos USB I/O Facilities
-
-For protocols other than control messages, eCos provides two ways of
-performing USB I/O. The first involves device table or devtab entries such
-as /dev/usb1r,
-with one entry per endpoint per USB device. It is possible to
-open these devices and use conventional blocking
-I/O functions such as read and
-write to exchange data between host and
-peripheral.
-
-
-There is also a lower-level USB-specific API, consisting of functions
-such as usbs_start_rx_buffer.
-A USB device driver will supply a data structure for each endpoint,
-for example a usbs_rx_endpoint
-structure for every receive endpoint. The first argument to
-usbs_start_rx_buffer should be a pointer to such
-a data structure. The USB-specific API is non-blocking: the initial
-call merely starts the transfer; some time later, once the transfer
-has completed or has been aborted, the device driver will invoke a
-completion function.
-
-
-Control messages are different. With four different categories of
-control messages including application and vendor specific ones, the
-conventional
-open/read/write
-model of I/O cannot easily be applied. Instead, a USB device driver
-will supply a usbs_control_endpoint
-data structure which can be manipulated appropriately. In practice the
-standard control messages will usually be handled by the common USB
-slave package, and other control messages will be handled by
-class-specific code such as the USB-ethernet package. Typically,
-application code remains responsible for supplying the enumeration data and for actually starting up the USB device.
-
-
-
-Enabling the USB code
-
-If the target hardware contains a USB slave device then the
-appropriate USB device driver and the common packages will typically
-be loaded into the configuration automatically when that target is
-selected (assuming a suitable device driver exists). However, the
-driver will not necessarily be active. For example a processor might
-have an on-chip USB device, but not all applications using that
-processor will want to use USB functionality. Hence by default the USB
-device is disabled, ensuring that applications do not suffer any
-memory or other penalties for functionality that is not required.
-
-
-If the application developer explicitly adds a class support package
-such as the USB-ethernet one then this implies that the USB device is
-actually needed, and the device will be enabled automatically.
-However, if no suitable class package is available and the USB device
-will instead be accessed by application code, it is necessary to
-enable the USB device manually. Usually the easiest way to do this is
-to enable the configuration option
-CYGGLO_IO_USB_SLAVE_APPLICATION, and the USB device
-driver and related packages will adjust accordingly. Alternatively,
-the device driver may provide some configuration options to provide
-more fine-grained control.
-
-
-
-
-
-
-
-
-
-
-USB Enumeration Data
-
-
-Enumeration Data
-The USB enumeration data structures
-
-
-
-
-#include <cyg/io/usb/usb.h>
-#include <cyg/io/usb/usbs.h>
-
-typedef struct usb_device_descriptor {
- …
-} usb_device_descriptor __attribute__((packed));
-
-typedef struct usb_configuration_descriptor {
- …
-} usb_configuration_descriptor __attribute__((packed));
-
-typedef struct usb_interface_descriptor {
- …
-} usb_interface_descriptor __attribute__((packed));
-
-typedef struct usb_endpoint_descriptor {
- …
-} usb_endpoint_descriptor;
-
-typedef struct usbs_enumeration_data {
- usb_device_descriptor device;
- int total_number_interfaces;
- int total_number_endpoints;
- int total_number_strings;
- const usb_configuration_descriptor* configurations;
- const usb_interface_descriptor* interfaces;
- const usb_endpoint_descriptor* endpoints;
- const unsigned char** strings;
-} usbs_enumeration_data;
-
-
-
-USB Enumeration Data
-
-When a USB host detects that a peripheral has been plugged in or
-powered up, one of the first steps is to ask the peripheral to
-describe itself by supplying enumeration data. Some of this data
-depends on the class of peripheral. Other fields are vendor-specific.
-There is also a dependency on the hardware, specifically which
-endpoints are available should be used. In general it is not possible
-for generic code to provide this information, so it is the
-responsibility of application code to provide a suitable
-usbs_enumeration_data data structure and
-install it in the endpoint 0 data structure during initialization.
-This must happen before the USB device is enabled by a call to
-usbs_start, for example:
-
-
-const usbs_enumeration_data usb_enum_data = {
- …
-};
-
-int
-main(int argc, char** argv)
-{
- usbs_sa11x0_ep0.enumeration_data = &usb_enum_data;
- …
- usbs_start(&usbs_sa11x0_ep0);
- …
-}
-
-
-For most applications the enumeration data will be static, although
-the usbs_enumeration_data structure can be
-filled in at run-time if necessary. Full details of the enumeration
-data can be found in the Universal Serial Bus specification obtainable
-from the USB Implementers Forum web
-site, although the meaning of most fields is fairly obvious.
-The various data structures and utility macros are defined in the
-header files cyg/io/usb/usb.h
-and cyg/io/usb/usbs.h. Note
-that the example code below makes use of the gcc labelled element
-extension.
-
-
-usb_device_descriptor
-
-The main information about a USB peripheral comes from a single
-usb_device_descriptor structure, which is
-embedded in the usbs_enumeration_data
-structure. A typical example might look like this:
-
-
-const usbs_enumeration_data usb_enum_data = {
- {
- length: USB_DEVICE_DESCRIPTOR_LENGTH,
- type: USB_DEVICE_DESCRIPTOR_TYPE,
- usb_spec_lo: USB_DEVICE_DESCRIPTOR_USB11_LO,
- usb_spec_hi: USB_DEVICE_DESCRIPTOR_USB11_HI,
- device_class: USB_DEVICE_DESCRIPTOR_CLASS_VENDOR,
- device_subclass: USB_DEVICE_DESCRIPTOR_SUBCLASS_VENDOR,
- device_protocol: USB_DEVICE_DESCRIPTOR_PROTOCOL_VENDOR,
- max_packet_size: 8,
- vendor_lo: 0x42,
- vendor_hi: 0x42,
- product_lo: 0x42,
- product_hi: 0x42,
- device_lo: 0x00,
- device_hi: 0x01,
- manufacturer_str: 1,
- product_str: 2,
- serial_number_str: 0,
- number_configurations: 1
- },
- …
-};
-
-
-The length and type fields are specified by the USB standard. The
-usb_spec_lo and
-usb_spec_hi fields identify the particular
-revision of the standard that the peripheral implements, for example
-revision 1.1.
-
-
-The device class, subclass, and protocol fields are used by generic
-host-side USB software to determine which host-side device driver
-should be loaded to interact with the peripheral. A number of standard
-classes are defined, for example mass-storage devices and
-human-interface devices. If a peripheral implements one of the
-standard classes then a standard existing host-side device driver may
-exist, eliminating the need to write a custom driver. The value
-0xFF (VENDOR) is reserved for
-peripherals that implement a vendor-specific protocol rather than a
-standard one. Such peripherals will require a custom host-side device
-driver. The value 0x00
-(INTERFACE) is reserved and indicates that the
-protocol used by the peripheral is defined at the interface level
-rather than for the peripheral as a whole.
-
-
-The max_package_size field specifies the
-maximum length of a control message. There is a lower bound of eight
-bytes, and typical hardware will not support anything larger because
-control messages are usually small and not performance-critical.
-
-
-The vendor_lo and
-vendor_hi fields specify a vendor id, which
-must be obtained from the USB Implementor's Forum. The numbers used in
-the code fragment above are examples only and must not be used in real
-USB peripherals. The product identifier is determined by the vendor,
-and different USB peripherals should use different identifiers. The
-device identifier field should indicate a release number in
-binary-coded decimal.
-
-
-The above fields are all numerical in nature. A USB peripheral can
-also provide a number of strings as described below, for example the name of the
-vendor can be provided. The various _str
-fields act as indices into an array of strings, with index 0
-indicating that no string is available.
-
-
-A typical USB peripheral involves just a single configuration. However
-more complicated peripherals can support multiple configurations. Only
-one configuration will be active at any one time, and the host will
-switch between them as appropriate. If a peripheral does involve
-multiple configurations then typically it will be the responsibility
-of application code to handle the standard
-set-configuration control message.
-
-
-
-usb_configuration_descriptor
-
-A USB peripheral involves at least one and possible several different
-configurations. The usbs_enumeration_data
-structure requires a pointer to an array, possibly of length 1, of
-usb_configuration_descriptor structures.
-Usually a single structure suffices:
-
-
-const usb_configuration_descriptor usb_configuration = {
- length: USB_CONFIGURATION_DESCRIPTOR_LENGTH,
- type: USB_CONFIGURATION_DESCRIPTOR_TYPE,
- total_length_lo: USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(1, 2),
- total_length_hi: USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(1, 2),
- number_interfaces: 1,
- configuration_id: 1,
- configuration_str: 0,
- attributes: USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED |
- USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED,
- max_power: 50
-};
-
-const usbs_enumeration_data usb_enum_data = {
- …
- configurations: &usb_configuration,
- …
-};
-
-
-The values for the length and
-type fields are determined by the standard.
-The total_length field depends on the
-number of interfaces and endpoints used by this configuration, and
-convenience macros are provided to calculate this: the first argument
-to the macros specify the number of interfaces, the second the number
-of endpoints. The number_interfaces field
-is self-explanatory. If the peripheral involves multiple
-configurations then each one must have a unique id, and this will be
-used in the set-configuration control message. The id
-0 is reserved, and a set-configuration control
-message that uses this id indicates that the peripheral should be
-inactive. Configurations can have a string description if required.
-The attributes field must have the
-REQUIRED bit set; the
-SELF_POWERED bit informs the host that the
-peripheral has its own power supply and will not draw any power over
-the bus, leaving more bus power available to other peripherals; the
-REMOTE_WAKEUP bit is used if the peripheral can
-interrupt the host when the latter is in power-saving mode. For
-peripherals that are not self-powered, the
-max_power field specifies the power
-requirements in units of 2mA.
-
-
-
-usb_interface_descriptor
-
-A USB configuration involves one or more interfaces, typically
-corresponding to different streams of data. For example, one interface
-might involve video data while another interface is for audio.
-Multiple interfaces in a single configuration will be active at the
-same time.
-
-
-const usb_interface_descriptor usb_interface = {
- length: USB_INTERFACE_DESCRIPTOR_LENGTH,
- type: USB_INTERFACE_DESCRIPTOR_TYPE,
- interface_id: 0,
- alternate_setting: 0,
- number_endpoints: 2,
- interface_class: USB_INTERFACE_DESCRIPTOR_CLASS_VENDOR,
- interface_subclass: USB_INTERFACE_DESCRIPTOR_SUBCLASS_VENDOR,
- interface_protocol: USB_INTERFACE_DESCRIPTOR_PROTOCOL_VENDOR,
- interface_str: 0
-};
-
-const usbs_enumeration_data usb_enum_data = {
- …
- total_number_interfaces: 1,
- interfaces: &usb_interface,
- …
-};
-
-
-Again, the length and
-type fields are specified by the standard.
-Each interface within a configuration requires its own id. However, a
-given interface may have several alternate settings, in other words
-entries in the interfaces array with the same id but different
-alternate_setting fields. For example,
-there might be one setting which requires a bandwidth of 100K/s and
-another setting that only needs 50K/s. The host can use the standard
-set-interface control message to choose the most appropriate setting.
-The handling of this request is the responsibility of higher-level
-code, so the application may have to install its own handler.
-
-
-The number of endpoints used by an interface is specified in the
-number_endpoints field. Exact details of
-which endpoints are used is held in a separate array of endpoint
-descriptors. The class, subclass and protocol fields are used by
-host-side code to determine which host-side device driver should
-handle this specific interface. Usually this is determined on a
-per-peripheral basis in the
-usb_device_descriptor structure, but that can
-defer the details to individual interfaces. A per-interface string
-is allowed as well.
-
-
-For USB peripherals involving multiple configurations, the array of
-usb_interface_descriptor structures should
-first contain all the interfaces for the first configuration, then all
-the interfaces for the second configuration, and so on.
-
-
-
-usb_endpoint_descriptor
-
-The host also needs information about which endpoint should be used
-for what. This involves an array of endpoint descriptors:
-
-
-const usb_endpoint_descriptor usb_endpoints[] = {
- {
- length: USB_ENDPOINT_DESCRIPTOR_LENGTH,
- type: USB_ENDPOINT_DESCRIPTOR_TYPE,
- endpoint: USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT | 1,
- attributes: USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
- max_packet_lo: 64,
- max_packet_hi: 0,
- interval: 0
- },
- {
- length: USB_ENDPOINT_DESCRIPTOR_LENGTH,
- type: USB_ENDPOINT_DESCRIPTOR_TYPE,
- endpoint: USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | 2,
- attributes: USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
- max_packet_lo: 64,
- max_packet_hi: 0,
- interval: 0
- }
-};
-
-const usbs_enumeration_data usb_enum_data = {
- …
- total_number_endpoints: 2,
- endpoints: usb_endpoints,
- …
-};
-
-
-As usual the values for the length and
-type fields are specified by the standard.
-The endpoint field gives both the endpoint
-number and the direction, so in the above example endpoint 1 is used
-for OUT (host to peripheral) transfers and endpoint 2 is used for IN
-(peripheral to host) transfers. The
-attributes field indicates the USB protocol
-that should be used on this endpoint: CONTROL,
-ISOCHRONOUS, BULK or
-INTERRUPT. The
-max_packet field specifies the maximum size
-of a single USB packet. For bulk transfers this will typically be 64
-bytes. For isochronous transfers this can be up to 1023 bytes. For
-interrupt transfers it can be up to 64 bytes, although usually a
-smaller value will be used. The interval
-field is ignored for control and bulk transfers. For isochronous
-transfers it should be set to 1. For interrupt transfers it can be a
-value between 1 and 255, and indicates the number of milliseconds
-between successive polling operations.
-
-
-For USB peripherals involving multiple configurations or interfaces
-the array of endpoint descriptors should be organized sequentially:
-first the endpoints corresponding to the first interface of the first
-configuration, then the second interface in that configuration, and so
-on; then all the endpoints for all the interfaces in the second
-configuration; etc.
-
-
-
-Strings
-
-The enumeration data can contain a number of strings with additional
-information. Unicode encoding is used for the strings, and it is
-possible for a peripheral to supply a given string in multiple
-languages using the appropriate characters. The first two bytes of
-each string give a length and type field. The first string is special;
-after the two bytes header it consists of an array of 2-byte language
-id codes, indicating the supported languages. The language code
-0x0409 corresponds to English (United States).
-
-
-const unsigned char* usb_strings[] = {
- "\004\003\011\004",
- "\020\003R\000e\000d\000 \000H\000a\000t\000"
-};
-
-const usbs_enumeration_data usb_enum_data = {
- …
- total_number_strings: 2,
- strings: usb_strings,
- …
-};
-
-
-The default handler for standard control messages assumes that the
-peripheral only uses a single language. If this is not the case then
-higher-level code will have to handle the standard get-descriptor
-control messages when a string descriptor is requested.
-
-
-
-usbs_enumeration_data
-
-The usbs_enumeration_data data structure
-collects together all the various descriptors that make up the
-enumeration data. It is the responsibility of application code to
-supply a suitable data structure and install it in the control
-endpoints's enumeration_data field before
-the USB device is started.
-
-
-
-
-
-
-
-
-
-
-
-Starting up a USB Device
-
-
-usbs_start
-Starting up a USB Device
-
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-
-void usbs_start
-usbs_control_endpoint* ep0
-
-
-
-
-Description
-
-Initializing a USB device requires some support from higher-level
-code, typically the application, in the form of enumeration data.
-Hence it is not possible for the low-level USB driver to activate a
-USB device itself. Instead the higher-level code has to take care of
-this by invoking usbs_start. This function takes
-a pointer to a USB control endpoint data structure. USB device drivers
-should provide exactly one such data structure for every USB device,
-so the pointer uniquely identifies the device.
-
-
-const usbs_enumeration_data usb_enum_data = {
- …
-};
-
-int
-main(int argc, char** argv)
-{
- usbs_sa11x0_ep0.enumeration_data = &usb_enum_data;
- …
- usbs_start(&usbs_sa11x0_ep0);
- …
-}
-
-
-The exact behaviour of usbs_start depends on the
-USB hardware and the device driver. A typical implementation would
-change the USB data pins from tristated to active. If the peripheral
-is already plugged into a host then the latter should detect this
-change and start interacting with the peripheral, including requesting
-the enumeration data. Some of this may happen before
-usbs_start returns, but given that multiple
-interactions between USB host and peripheral are required it is likely
-that the function will return before the peripheral is fully
-configured. Control endpoints provide a mechanism for informing
-higher-level code of USB state changes.
-usbs_start will return even if the peripheral is
-not currently connected to a host: it will not block until the
-connection is established.
-
-
-usbs_start should only be called once for a given
-USB device. There are no defined error conditions. Note that the
-function affects the entire USB device and not just the control
-endpoint: there is no need to start any data endpoints as well.
-
-
-
-
-
-
-
-
-
-Devtab Entries
-
-
-Devtab Entries
-Data endpoint data structure
-
-
-
-
-/dev/usb0c
-/dev/usb1r
-/dev/usb2w
-
-
-
-Devtab Entries
-
-USB device drivers provide two ways of transferring data between host
-and peripheral. The first involves USB-specific functionality such as
-usbs_start_rx_buffer.
-This provides non-blocking I/O: a transfer is started, and some time
-later the device driver will call a supplied completion function. The
-second uses the conventional I/O model: there are entries in the
-device table corresponding to the various endpoints. Standard calls
-such as open can then be used to get a suitable
-handle. Actual I/O happens via blocking read and
-write calls. In practice the blocking operations
-are simply implemented using the underlying non-blocking
-functionality.
-
-
-Each endpoint will have its own devtab entry. The exact names are
-controlled by the device driver package, but typically the root will
-be /dev/usb. This is followed by one or more
-decimal digits giving the endpoint number, followed by
-c for a control endpoint, r for
-a receive endpoint (host to peripheral), and w for
-a transmit endpoint (peripheral to host). If the target hardware
-involves more than one USB device then different roots should be used,
-for example /dev/usb0c and
-/dev/usb1_0c. This may require explicit
-manipulation of device driver configuration options by the application
-developer.
-
-
-At present the devtab entry for a control endpoint does not support
-any I/O operations.
-
-
-write operations
-
-cyg_io_write and similar functions in
-higher-level packages can be used to perform a transfer from
-peripheral to host. Successive write operations will not be coalesced.
-For example, when doing a 1000 byte write to an endpoint that uses the
-bulk transfer protocol this will involve 15 full-size 64-byte packets
-and a terminating 40-byte packet. USB device drivers are not expected
-to do any locking, and if higher-level code performs multiple
-concurrent write operations on a single endpoint then the resulting
-behaviour is undefined.
-
-
-A USB write operation will never transfer less
-data than specified. It is the responsibility of higher-level code to
-ensure that the amount of data being transferred is acceptable to the
-host-side code. Usually this will be defined by a higher-level
-protocol. If an attempt is made to transfer more data than the host
-expects then the resulting behaviour is undefined.
-
-
-There are two likely error conditions. EPIPE
-indicates that the connection between host and target has been broken.
-EAGAIN indicates that the endpoint has been
-stalled, either at the request of the host or by other activity
-inside the peripheral.
-
-
-
-read operations
-
-cyg_io_read and similar functions in higher-level
-packages can be used to perform a transfer from host to peripheral.
-This should be a complete transfer: higher-level protocols should
-define an upper bound on the amount of data being transferred, and the
-read operation should involve at least this
-amount of data. The return value will indicate the actual transfer
-size, which may be less than requested.
-
-
-Some device drivers may support partial reads, but USB device drivers
-are not expected to perform any buffering because that involves both
-memory and code overheads. One technique that may work for bulk
-transfers is to exploit the fact that such transfers happen in 64-byte
-packets. It is possible to read an initial 64
-bytes, corresponding to the first packet in the transfer. These 64
-bytes can then be examined to determine the total transfer size, and
-the remaining data can be transferred in another
-read operation. This technique is not guaranteed
-to work with all USB hardware. Also, if the delay between accepting
-the first packet and the remainder of the transfer is excessive then
-this could cause timeout problems for the host-side software. For
-these reasons the use of partial reads should be avoided.
-
-
-There are two likely error conditions. EPIPE
-indicates that the connection between host and target has been broken.
-EAGAIN indicates that the endpoint has been
-stalled, either at the request of the host or by other activity
-inside the peripheral.
-
-
-USB device drivers are not expected to do any locking. If higher-level
-code performs multiple concurrent read operations on a single endpoint
-then the resulting behaviour is undefined.
-
-
-
-select operations
-
-Typical USB device drivers will not provide any support for
-select. Consider bulk transfers from the host to
-the peripheral. At the USB device driver level there is no way of
-knowing in advance how large a transfer will be, so it is not feasible
-for the device driver to buffer the entire transfer. It may be
-possible to buffer part of the transfer, for example the first 64-byte
-packet, and copy this into application space at the start of a
-read, but this adds code and memory overheads.
-Worse, it means that there is an unknown but potentially long delay
-between a peripheral accepting the first packet of a transfer and the
-remaining packets, which could confuse or upset the host-side
-software.
-
-
-With some USB hardware it may be possible for the device driver to
-detect OUT tokens from the host without actually accepting the data,
-and this would indicate that a read is likely to
-succeed. However, it would not be reliable since the host-side I/O
-operation could time out. A similar mechanism could be used to
-implement select for outgoing data, but again
-this would not be reliable.
-
-
-Some device drivers may provide partial support for
-select anyway, possibly under the control of a
-configuration option. The device driver's documentation should be
-consulted for further information. It is also worth noting that the
-USB-specific non-blocking API can often be used as an alternative to
-select.
-
-
-
-get_config and
-set_config operations
-
-There are no set_config or
-get_config (also known as
-ioctl) operations defined for USB devices.
-Some device drivers may provide hardware-specific facilities this way.
-
-
-
-Currently the USB-specific functions related to halted endpoints cannot be accessed readily
-via devtab entries. This functionality should probably be made
-available via set_config and
-get_config. It may also prove useful to provide
-a get_config operation that maps from the
-devtab entries to the underlying endpoint data structures.
-
-
-
-
-Presence
-
-The devtab entries are optional. If the USB device is accessed
-primarily by class-specific code such as the USB-ethernet package and
-that package uses the USB-specific API directly, the devtab entries
-are redundant. Even if application code does need to access the USB
-device, the non-blocking API may be more convenient than the blocking
-I/O provided via the devtab entries. In these cases the devtab entries
-serve no useful purpose, but they still impose a memory overhead. It
-is possible to suppress the presence of these entries by disabling the
-configuration option
-CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES.
-
-
-
-
-
-
-
-
-
-
-Receiving Data from the Host
-
-
-usbs_start_rx_buffer
-Receiving Data from the Host
-
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-
-void usbs_start_rx_buffer
-usbs_rx_endpoint* ep
-unsigned char* buffer
-int length
-void (*)(void*,int) complete_fn
-void * complete_data
-
-
-
-void usbs_start_rx
-usbs_rx_endpoint* ep
-
-
-
-
-
-Description
-
-usbs_start_rx_buffer is a USB-specific function
-to accept a transfer from host to peripheral. It can be used for bulk,
-interrupt or isochronous transfers, but not for control messages.
-Instead those involve manipulating the usbs_control_endpoint
-data structure directly. The function takes five arguments:
-
-
-
-
-The first argument identifies the specific endpoint that should be
-used. Different USB devices will support different sets of endpoints
-and the device driver will provide appropriate data structures. The
-device driver's documentation should be consulted for details of which
-endpoints are available.
-
-
-
-
-The buffer and length
-arguments control the actual transfer. USB device drivers are not
-expected to perform any buffering or to support partial transfers, so
-the length specified should correspond to the maximum transfer that is
-currently possible and the buffer should be at least this large. For
-isochronous transfers the USB specification imposes an upper bound of
-1023 bytes, and a smaller limit may be set in the enumeration data. Interrupt
-transfers are similarly straightforward with an upper bound of 64
-bytes, or less as per the enumeration data. Bulk transfers are more
-complicated because they can involve multiple 64-byte packets plus a
-terminating packet of less than 64 bytes, so there is no predefined
-limit on the transfer size. Instead it is left to higher-level
-protocols to specify an appropriate upper bound.
-
-
-One technique that may work for bulk transfers is to exploit the fact
-that such transfers happen in 64-byte packets: it may be possible to
-receive an initial 64 bytes, corresponding to the first packet in the
-transfer; these 64 bytes can then be examined to determine the total
-transfer size, and the remaining data can be transferred in another
-receive operation. This technique is not guaranteed to work with all
-USB hardware. Also, if the delay between accepting the first packet and
-the remainder of the transfer is excessive then this could cause
-timeout problems for the host-side software. For these reasons this
-technique should be avoided.
-
-
-
-
-usbs_start_rx_buffer is non-blocking. It merely
-starts the receive operation, and does not wait for completion. At
-some later point the USB device driver will invoke the completion
-function parameter with two arguments: the completion data defined by
-the last parameter and a result field. A result >=
-0 indicates a successful transfer of that many
-bytes, which may be less than the upper bound imposed by the
-length argument. A result <
-0 indicates an error. The most likely errors are
--EPIPE to indicate that the connection between the
-host and the target has been broken, and -EAGAIN
-for when the endpoint has been halted. Specific USB device drivers may
-specify additional error conditions.
-
-
-
-
-The normal sequence of events is that the USB device driver will
-update the appropriate hardware registers. At some point after that
-the host will attempt to send data by transmitting an OUT token
-followed by a data packet, and since a receive operation is now in
-progress the data will be accepted and ACK'd. If there were no receive
-operation then the peripheral would instead generate a NAK. The USB
-hardware will generate an interrupt once the whole packet has been
-received, and the USB device driver will service this interrupt and
-arrange for a DSR to be called. Isochronous and interrupt transfers
-involve just a single packet. However, bulk transfers may involve
-multiple packets so the device driver has to check whether the packet
-was a full 64 bytes or whether it was a terminating packet of less
-than this. When the device driver DSR detects a complete transfer it
-will inform higher-level code by invoking the supplied completion
-function.
-
-
-This means that the completion function will normally be invoked by a
-DSR and not in thread context - although some USB device drivers may
-have a different implementation. Therefore the completion function is
-restricted in what it can do. In particular it must not make any
-calls that will or may block such as locking a mutex or allocating
-memory. The kernel documentation should be consulted for more details
-of DSR's and interrupt handling generally.
-
-
-It is possible that the completion function will be invoked before
-usbs_start_rx_buffer returns. Such an event would
-be unusual because the transfer cannot happen until the next time the
-host tries to send data to this peripheral, but it may happen if for
-example another interrupt happens and a higher priority thread is
-scheduled to run. Also, if the endpoint is currently halted then the
-completion function will be invoked immediately with
--EAGAIN: typically this will happen in the current
-thread rather than in a separate DSR. The completion function is
-allowed to start another transfer immediately by calling
-usbs_start_rx_buffer again.
-
-
-USB device drivers are not expected to perform any locking. It is the
-responsibility of higher-level code to ensure that there is only one
-receive operation for a given endpoint in progress at any one time. If
-there are concurrent calls to
-usbs_start_rx_buffer then the resulting behaviour
-is undefined. For typical USB applications this does not present any
-problems, because only one piece of code will access a given endpoint
-at any particular time.
-
-
-The following code fragment illustrates a very simple use of
-usbs_start_rx_buffer to implement a blocking
-receive, using a semaphore to synchronise between the foreground
-thread and the DSR. For a simple example like this no completion data
-is needed.
-
-
-static int error_code = 0;
-static cyg_sem_t completion_wait;
-
-static void
-completion_fn(void* data, int result)
-{
- error_code = result;
- cyg_semaphore_post(&completion_wait);
-}
-
-int
-blocking_receive(usbs_rx_endpoint* ep, unsigned char* buf, int len)
-{
- error_code = 0;
- usbs_start_rx_buffer(ep, buf, len, &completion_fn, NULL);
- cyg_semaphore_wait(&completion_wait);
- return error_code;
-}
-
-
-There is also a utility function usbs_start_rx. This
-can be used by code that wants to manipulate data endpoints directly, specifically the
-complete_fn,
-complete_data,
-buffer and
-buffer_size fields.
-usbs_start_tx just invokes a function
-supplied by the device driver.
-
-
-
-
-
-
-
-
-
-Sending Data to the Host
-
-
-usbs_start_tx_buffer
-Sending Data to the Host
-
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-
-void usbs_start_tx_buffer
-usbs_tx_endpoint* ep
-const unsigned char* buffer
-int length
-void (*)(void*,int) complete_fn
-void * complete_data
-
-
-
-void usbs_start_tx
-usbs_tx_endpoint* ep
-
-
-
-
-
-Description
-
-usbs_start_tx_buffer is a USB-specific function
-to transfer data from peripheral to host. It can be used for bulk,
-interrupt or isochronous transfers, but not for control messages;
-instead those involve manipulating the usbs_control_endpoint
-data structure directly. The function takes five arguments:
-
-
-
-
-The first argument identifies the specific endpoint that should be
-used. Different USB devices will support different sets of endpoints
-and the device driver will provide appropriate data structures. The
-device driver's documentation should be consulted for details of which
-endpoints are available.
-
-
-
-
-The buffer and length
-arguments control the actual transfer. USB device drivers are not
-allowed to modify the buffer during the transfer, so the data can
-reside in read-only memory. The transfer will be for all the data
-specified, and it is the responsibility of higher-level code to make
-sure that the host is expecting this amount of data. For isochronous
-transfers the USB specification imposes an upper bound of 1023 bytes,
-but a smaller limit may be set in the enumeration data. Interrupt
-transfers have an upper bound of 64 bytes or less, as per the
-enumeration data. Bulk transfers are more complicated because they can
-involve multiple 64-byte packets plus a terminating packet of less
-than 64 bytes, so the basic USB specification does not impose an upper
-limit on the total transfer size. Instead it is left to higher-level
-protocols to specify an appropriate upper bound. If the peripheral
-attempts to send more data than the host is willing to accept then the
-resulting behaviour is undefined and may well depend on the specific
-host operating system being used.
-
-
-For bulk transfers, the USB device driver or the underlying hardware
-will automatically split the transfer up into the appropriate number
-of full-size 64-byte packets plus a single terminating packet, which
-may be 0 bytes.
-
-
-
-
-usbs_start_tx_buffer is non-blocking. It merely
-starts the transmit operation, and does not wait for completion. At
-some later point the USB device driver will invoke the completion
-function parameter with two arguments: the completion data defined by
-the last parameter, and a result field. This result will be either an
-error code < 0, or the amount of data
-transferred which should correspond to the
-length argument. The most likely errors are
--EPIPE to indicate that the connection between the
-host and the target has been broken, and -EAGAIN
-for when the endpoint has been halted. Specific USB device drivers may
-define additional error conditions.
-
-
-
-
-The normal sequence of events is that the USB device driver will
-update the appropriate hardware registers. At some point after that
-the host will attempt to fetch data by transmitting an IN token. Since
-a transmit operation is now in progress the peripheral can send a
-packet of data, and the host will generate an ACK. At this point the
-USB hardware will generate an interrupt, and the device driver will
-service this interrupt and arrange for a DSR to be called. Isochronous
-and interrupt transfers involve just a single packet. However, bulk
-transfers may involve multiple packets so the device driver has to
-check whether there is more data to send and set things up for the
-next packet. When the device driver DSR detects a complete transfer it
-will inform higher-level code by invoking the supplied completion
-function.
-
-
-This means that the completion function will normally be invoked by a
-DSR and not in thread context - although some USB device drivers may
-have a different implementation. Therefore the completion function is
-restricted in what it can do, in particular it must not make any
-calls that will or may block such as locking a mutex or allocating
-memory. The kernel documentation should be consulted for more details
-of DSR's and interrupt handling generally.
-
-
-It is possible that the completion function will be invoked before
-usbs_start_tx_buffer returns. Such an event would
-be unusual because the transfer cannot happen until the next time the
-host tries to fetch data from this peripheral, but it may happen if,
-for example, another interrupt happens and a higher priority thread is
-scheduled to run. Also, if the endpoint is currently halted then the
-completion function will be invoked immediately with
--EAGAIN: typically this will happen in the current
-thread rather than in a separate DSR. The completion function is
-allowed to start another transfer immediately by calling
-usbs_start_tx_buffer again.
-
-
-USB device drivers are not expected to perform any locking. It is the
-responsibility of higher-level code to ensure that there is only one
-transmit operation for a given endpoint in progress at any one time.
-If there are concurrent calls to
-usbs_start_tx_buffer then the resulting behaviour
-is undefined. For typical USB applications this does not present any
-problems because only piece of code will access a given endpoint at
-any particular time.
-
-
-The following code fragment illustrates a very simple use of
-usbs_start_tx_buffer to implement a blocking
-transmit, using a semaphore to synchronise between the foreground
-thread and the DSR. For a simple example like this no completion data
-is needed.
-
-
-static int error_code = 0;
-static cyg_sem_t completion_wait;
-
-static void
-completion_fn(void* data, int result)
-{
- error_code = result;
- cyg_semaphore_post(&completion_wait);
-}
-
-int
-blocking_transmit(usbs_tx_endpoint* ep, const unsigned char* buf, int len)
-{
- error_code = 0;
- usbs_start_tx_buffer(ep, buf, len, &completion_fn, NULL);
- cyg_semaphore_wait(&completion_wait);
- return error_code;
-}
-
-
-There is also a utility function usbs_start. This
-can be used by code that wants to manipulate data endpoints directly, specifically the
-complete_fn,
-complete_data,
-buffer and
-buffer_size fields.
-usbs_start_tx just calls a function supplied by
-the device driver.
-
-
-
-
-
-
-
-
-
-Halted Endpoints
-
-
-Halted Endpoints
-Support for Halting and Halted Endpoints
-
-
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-
-
-cyg_bool usbs_rx_endpoint_halted
-usbs_rx_endpoint* ep
-
-
-void usbs_set_rx_endpoint_halted
-usbs_rx_endpoint* ep
-cyg_bool new_state
-
-
-void usbs_start_rx_endpoint_wait
-usbs_rx_endpoint* ep
-void (*)(void*, int) complete_fn
-void * complete_data
-
-
-
-cyg_bool
-usbs_tx_endpoint_halted
-usbs_tx_endpoint* ep
-
-
-void usbs_set_tx_endpoint_halted
-usbs_tx_endpoint* ep
-cyg_bool new_state
-
-
-void usbs_start_tx_endpoint_wait
-usbs_tx_endpoint* ep
-void (*)(void*, int) complete_fn
-void * complete_data
-
-
-
-
-
-Description
-
-Normal USB traffic involves straightforward handshakes, with either an
-ACK to indicate that a packet was transferred
-without errors, or a NAK if an error occurred, or
-if a peripheral is currently unable to process another packet from the
-host, or has no packet to send to the host. There is a third form of
-handshake, a STALL, which indicates that the
-endpoint is currently halted.
-
-
-When an endpoint is halted it means that the host-side code needs to
-take some sort of recovery action before communication over that
-endpoint can resume. The exact circumstances under which this can
-happen are not defined by the USB specification, but one example would
-be a protocol violation if say the peripheral attempted to transmit
-more data to the host than was permitted by the protocol in use. The
-host can use the standard control messages get-status, set-feature and
-clear-feature to examine and manipulate the halted status of a given
-endpoint. There are USB-specific functions which can be used inside
-the peripheral to achieve the same effect. Once an endpoint has been
-halted the host can then interact with the peripheral using class or
-vendor control messages to perform appropriate recovery, and then the
-halted condition can be cleared.
-
-
-Halting an endpoint does not constitute a device state change, and
-there is no mechanism by which higher-level code can be informed
-immediately. However, any ongoing receive or transmit operations will
-be aborted with an -EAGAIN error, and any new
-receives or transmits will fail immediately with the same error.
-
-
-There are six functions to support halted endpoints, one set for
-receive endpoints and another for transmit endpoints, with both sets
-behaving in essentially the same way. The first,
-usbs_rx_endpoint_halted, can be used to determine
-whether or not an endpoint is currently halted: it takes a single
-argument that identifies the endpoint of interest. The second
-function, usbs_set_rx_endpoint_halted, can be
-used to change the halted condition of an endpoint: it takes two
-arguments; one to identify the endpoint and another to specify the new
-state. The last function
-usbs_start_rx_endpoint_wait operates in much the
-same way as usbs_start_rx_buffer: when the
-endpoint is no longer halted the device driver will invoke the
-supplied completion function with a status of 0. The completion
-function has the same signature as that for a transfer operation.
-Often it will be possible to use a single completion function and have
-the foreground code invoke either
-usbs_start_rx_buffer or
-usbs_start_rx_endpoint_wait depending on the
-current state of the endpoint.
-
-
-
-
-
-
-
-
-
-Control Endpoints
-
-
-Control Endpoints
-Control endpoint data structure
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-typedef struct usbs_control_endpoint {
- *hellip;
-} usbs_control_endpoint;
-
-
-
-usbs_control_endpoint Data Structure
-
-The device driver for a USB slave device should supply one
-usbs_control_endpoint data structure per USB
-device. This corresponds to endpoint 0 which will be used for all
-control message interaction between the host and that device. The data
-structure is also used for internal management purposes, for example
-to keep track of the current state. In a typical USB peripheral there
-will only be one such data structure in the entire system, but if
-there are multiple USB slave ports, allowing the peripheral to be
-connected to multiple hosts, then there will be a separate data
-structure for each one. The name or names of the data structures are
-determined by the device drivers. For example, the SA11x0 USB device
-driver package provides usbs_sa11x0_ep0.
-
-
-The operations on a control endpoint do not fit cleanly into a
-conventional open/read/write I/O model. For example, when the host
-sends a control message to the USB peripheral this may be one of four
-types: standard, class, vendor and reserved. Some or all of the
-standard control messages will be handled automatically by the common
-USB slave package or by the device driver itself. Other standard
-control messages and the other types of control messages may be
-handled by a class-specific package or by application code. Although
-it would be possible to have devtab entries such as
-/dev/usbs_ep0/standard and
-/dev/usbs_ep0/class, and then support read and
-write operations on these devtab entries, this would add significant
-overhead and code complexity. Instead, all of the fields in the
-control endpoint data structure are public and can be manipulated
-directly by higher level code if and when required.
-
-
-Control endpoints involve a number of callback functions, with
-higher-level code installing suitable function pointers in the control
-endpoint data structure. For example, if the peripheral involves
-vendor-specific control messages then a suitable handler for these
-messages should be installed. Although the exact details depend on the
-device driver, typically these callback functions will be invoked at
-DSR level rather than thread level. Therefore, only certain eCos
-functions can be invoked; specifically, those functions that are
-guaranteed not to block. If a potentially blocking function such as a
-semaphore wait or a mutex lock operation is invoked from inside the
-callback then the resulting behaviour is undefined, and the system as
-a whole may fail. In addition, if one of the callback functions
-involves significant processing effort then this may adversely affect
-the system's real time characteristics. The eCos kernel documentation
-should be consulted for more details of DSR handling.
-
-
-Initialization
-
-The usbs_control_endpoint data structure
-contains the following fields related to initialization.
-
-
-typedef struct usbs_control_endpoint {
- …
- const usbs_enumeration_data* enumeration_data;
- void (*start_fn)(usbs_control_endpoint*);
- …
-};
-
-
-It is the responsibility of higher-level code, usually the
-application, to define the USB enumeration data. This needs to be
-installed in the control endpoint data structure early on during
-system startup, before the USB device is actually started and any
-interaction with the host is possible. Details of the enumeration data
-are supplied in the section USB Enumeration
-Data. Typically, the enumeration data is constant for a given
-peripheral, although it can be constructed dynamically if necessary.
-However, the enumeration data cannot change while the peripheral is
-connected to a host: the peripheral cannot easily claim to be a
-keyboard one second and a printer the next.
-
-
-The start_fn member is normally accessed
-via the utility usbs_start rather
-than directly. It is provided by the device driver and should be
-invoked once the system is fully initialized and interaction with the
-host is possible. A typical implementation would change the USB data
-pins from tristated to active. If the peripheral is already plugged
-into a host then the latter should detect this change and start
-interacting with the peripheral, including requesting the enumeration
-data.
-
-
-
-State
-
-There are three usbs_control_endpoint fields
-related to the current state of a USB slave device, plus some state
-constants and an enumeration of the possible state changes:
-
-
-typedef struct usbs_control_endpoint {
- …
- int state;
- void (*state_change_fn)(struct usbs_control_endpoint*, void*,
- usbs_state_change, int);
- void* state_change_data;
- …
-};
-
-#define USBS_STATE_DETACHED 0x01
-#define USBS_STATE_ATTACHED 0x02
-#define USBS_STATE_POWERED 0x03
-#define USBS_STATE_DEFAULT 0x04
-#define USBS_STATE_ADDRESSED 0x05
-#define USBS_STATE_CONFIGURED 0x06
-#define USBS_STATE_MASK 0x7F
-#define USBS_STATE_SUSPENDED (1 << 7)
-
-typedef enum {
- USBS_STATE_CHANGE_DETACHED = 1,
- USBS_STATE_CHANGE_ATTACHED = 2,
- USBS_STATE_CHANGE_POWERED = 3,
- USBS_STATE_CHANGE_RESET = 4,
- USBS_STATE_CHANGE_ADDRESSED = 5,
- USBS_STATE_CHANGE_CONFIGURED = 6,
- USBS_STATE_CHANGE_DECONFIGURED = 7,
- USBS_STATE_CHANGE_SUSPENDED = 8,
- USBS_STATE_CHANGE_RESUMED = 9
-} usbs_state_change;
-
-
-The USB standard defines a number of states for a given USB
-peripheral. The initial state is detached, where
-the peripheral is either not connected to a host at all or, from the
-host's perspective, the peripheral has not started up yet because the
-relevant pins are tristated. The peripheral then moves via
-intermediate attached and
-powered states to its default or
-reset state, at which point the host and
-peripheral can actually start exchanging data. The first message is
-from host to peripheral and provides a unique 7-bit address within the
-local USB network, resulting in a state change to
-addressed. The host then requests enumeration
-data and performs other initialization. If everything succeeds the
-host sends a standard set-configuration control message, after which
-the peripheral is configured and expected to be
-up and running. Note that some USB device drivers may be unable to
-distinguish between the detached,
-attached and powered states
-but generally this is not important to higher-level code.
-
-
-A USB host should generate at least one token every millisecond. If a
-peripheral fails to detect any USB traffic for a period of time then
-typically this indicates that the host has entered a power-saving
-mode, and the peripheral should do the same if possible. This
-corresponds to the suspended bit. The actual
-state is a combination of suspended and the
-previous state, for example configured and
-suspended rather than just
-suspended. When the peripheral subsequently
-detects USB traffic it would switch back to the
-configured state.
-
-
-The USB device driver and the common USB slave package will maintain
-the current state in the control endpoint's
-state field. There should be no need for
-any other code to change this field, but it can be examined whenever
-appropriate. In addition whenever a state change occurs the generic
-code can invoke a state change callback function. By default, no such
-callback function will be installed. Some class-specific packages such
-as the USB-ethernet package will install a suitable function to keep
-track of whether or not the host-peripheral connection is up, that is
-whether or not ethernet packets can be exchanged. Application code can
-also update this field. If multiple parties want to be informed of
-state changes, for example both a class-specific package and
-application code, then typically the application code will install its
-state change handler after the class-specific package and is
-responsible for chaining into the package's handler.
-
-
-The state change callback function is invoked with four arguments. The
-first identifies the control endpoint. The second is an arbitrary
-pointer: higher-level code can fill in the
-state_change_data field to set this. The
-third argument specifies the state change that has occurred, and the
-last argument supplies the previous state (the new state is readily
-available from the control endpoint structure).
-
-
-eCos does not provide any utility functions for updating or examining
-the state_change_fn or
-state_change_data fields. Instead, it is
-expected that the fields in the
-usbs_control_endpoint data structure will be
-manipulated directly. Any utility functions would do just this, but
-at the cost of increased code and cpu overheads.
-
-
-
-Standard Control Messages
-
-typedef struct usbs_control_endpoint {
- …
- unsigned char control_buffer[8];
- usbs_control_return (*standard_control_fn)(struct usbs_control_endpoint*, void*);
- void* standard_control_data;
- …
-} usbs_control_endpoint;
-
-typedef enum {
- USBS_CONTROL_RETURN_HANDLED = 0,
- USBS_CONTROL_RETURN_UNKNOWN = 1,
- USBS_CONTROL_RETURN_STALL = 2
-} usbs_control_return;
-
-extern usbs_control_return usbs_handle_standard_control(struct usbs_control_endpoint*);
-
-
-When a USB peripheral is connected to the host it must always respond
-to control messages sent to endpoint 0. Control messages always
-consist of an initial eight-byte header, containing fields such as a
-request type. This may be followed by a further data transfer, either
-from host to peripheral or from peripheral to host. The way this is
-handled is described in the Buffer Management section below.
-
-
-The USB device driver will always accept the initial eight-byte
-header, storing it in the control_buffer
-field. Then it determines the request type: standard, class, vendor,
-or reserved. The way in which the last three of these are processed is
-described in the section Other
-Control Messages. Some
-standard control messages will be handled by the device driver itself;
-typically the set-address request and the
-get-status, set-feature and
-clear-feature requests when applied to endpoints.
-
-
-If a standard control message cannot be handled by the device driver
-itself, the driver checks the
-standard_control_fn field in the control
-endpoint data structure. If higher-level code has installed a suitable
-callback function then this will be invoked with two argument, the
-control endpoint data structure itself and the
-standard_control_data field. The latter
-allows the higher level code to associate arbitrary data with the
-control endpoint. The callback function can return one of three
-values: HANDLED to indicate that the request has
-been processed; UNKNOWN if the message should be
-handled by the default code; or STALL to indicate
-an error condition. If higher level code has not installed a callback
-function or if the callback function has returned
-UNKNOWN then the device driver will invoke a
-default handler, usbs_handle_standard_control
-provided by the common USB slave package.
-
-
-The default handler can cope with all of the standard control messages
-for a simple USB peripheral. However, if the peripheral involves
-multiple configurations, multiple interfaces in a configuration, or
-alternate settings for an interface, then this cannot be handled by
-generic code. For example, a multimedia peripheral may support various
-alternate settings for a given data source with different bandwidth
-requirements, and the host can select a setting that takes into
-account the current load. Clearly higher-level code needs to be aware
-when the host changes the current setting, so that it can adjust the
-rate at which data is fed to or retrieved from the host. Therefore the
-higher-level code needs to install its own standard control callback
-and process appropriate messages, rather than leaving these to the
-default handler.
-
-
-The default handler will take care of the
-get-descriptor request used to obtain the
-enumeration data. It has support for string descriptors but ignores
-language encoding issues. If language encoding is important for the
-peripheral then this will have to be handled by an
-application-specific standard control handler.
-
-
-The header file <cyg/io/usb/usb.h> defines various
-constants related to control messages, for example the function codes
-corresponding to the standard request types. This header file is
-provided by the common USB package, not by the USB slave package,
-since the information is also relevant to USB hosts.
-
-
-
-Other Control Messages
-
-typedef struct usbs_control_endpoint {
- …
- usbs_control_return (*class_control_fn)(struct usbs_control_endpoint*, void*);
- void* class_control_data;
- usbs_control_return (*vendor_control_fn)(struct usbs_control_endpoint*, void*);
- void* vendor_control_data;
- usbs_control_return (*reserved_control_fn)(struct usbs_control_endpoint*, void*);
- void* reserved_control_data;
- …
-} usbs_control_endpoint;
-
-
-Non-standard control messages always have to be processed by
-higher-level code. This could be class-specific packages. For example,
-the USB-ethernet package will handle requests for getting the MAC
-address and for enabling or disabling promiscuous mode. In all cases
-the device driver will store the initial request in the
-control_buffer field, check for an
-appropriate handler, and invoke it with details of the control
-endpoint and any handler-specific data that has been installed
-alongside the handler itself. The handler should return either
-USBS_CONTROL_RETURN_HANDLED to report success or
-USBS_CONTROL_RETURN_STALL to report failure. The
-device driver will report this to the host.
-
-
-If there are multiple parties interested in a particular type of
-control messages, it is the responsibility of application code to
-install an appropriate handler and process the requests appropriately.
-
-
-
-Buffer Management
-
-typedef struct usbs_control_endpoint {
- …
- unsigned char* buffer;
- int buffer_size;
- void (*fill_buffer_fn)(struct usbs_control_endpoint*);
- void* fill_data;
- int fill_index;
- usbs_control_return (*complete_fn)(struct usbs_control_endpoint*, int);
- …
-} usbs_control_endpoint;
-
-
-Many USB control messages involve transferring more data than just the
-initial eight-byte header. The header indicates the direction of the
-transfer, OUT for host to peripheral or IN for peripheral to host.
-It also specifies a length field, which is exact for an OUT transfer
-or an upper bound for an IN transfer. Control message handlers can
-manipulate six fields within the control endpoint data structure to
-ensure that the transfer happens correctly.
-
-
-For an OUT transfer, the handler should examine the length field in
-the header and provide a single buffer for all the data. A
-class-specific protocol would typically impose an upper bound on the
-amount of data, allowing the buffer to be allocated statically.
-The handler should update the buffer and
-complete_fn fields. When all the data has
-been transferred the completion callback will be invoked, and its
-return value determines the response sent back to the host. The USB
-standard allows for a new control message to be sent before the
-current transfer has completed, effectively cancelling the current
-operation. When this happens the completion function will also be
-invoked. The second argument to the completion function specifies what
-has happened, with a value of 0 indicating success and an error code
-such as -EPIPE or -EIO
-indicating that the current transfer has been cancelled.
-
-
-IN transfers are a little bit more complicated. The required
-information, for example the enumeration data, may not be in a single
-contiguous buffer. Instead a mechanism is provided by which the buffer
-can be refilled, thus allowing the transfer to move from one record to
-the next. Essentially, the transfer operates as follows:
-
-
-
-
-When the host requests another chunk of data (typically eight bytes),
-the USB device driver will examine the
-buffer_size field. If non-zero then
-buffer contains at least one more byte of
-data, and then buffer_size is decremented.
-
-
-
-
-When buffer_size has dropped to 0, the
-fill_buffer_fn field will be examined. If
-non-null it will be invoked to refill the buffer.
-
-
-
-
-The fill_data and
-fill_index fields are not used by the
-device driver. Instead these fields are available to the refill
-function to keep track of the current state of the transfer.
-
-
-
-
-When buffer_size is 0 and
-fill_buffer_fn is NULL, no more data is
-available and the transfer has completed.
-
-
-
-
-Optionally a completion function can be installed. This will be
-invoked with 0 if the transfer completes successfully, or with an
-error code if the transfer is cancelled because of another control
-messsage.
-
-
-
-
-If the requested data is contiguous then the only fields that need
-to be manipulated are buffer and
-buffer_size, and optionally
-complete_fn. If the requested data is not
-contiguous then the initial control message handler should update
-fill_buffer_fn and some or all of the other
-fields, as required. An example of this is the handling of the
-standard get-descriptor control message by
-usbs_handle_standard_control.
-
-
-
-Polling Support
-
-typedef struct usbs_control_endpoint {
- void (*poll_fn)(struct usbs_control_endpoint*);
- int interrupt_vector;
- …
-} usbs_control_endpoint;
-
-
-In nearly all circumstances USB I/O should be interrupt-driven.
-However, there are special environments such as RedBoot where polled
-operation may be appropriate. If the device driver can operate in
-polled mode then it will provide a suitable function via the
-poll_fn field, and higher-level code can
-invoke this regularly. This polling function will take care of all
-endpoints associated with the device, not just the control endpoint.
-If the USB hardware involves a single interrupt vector then this will
-be identified in the data structure as well.
-
-
-
-
-
-
-
-
-
-
-
-
-Data Endpoints
-
-
-Data Endpoints
-Data endpoint data structures
-
-
-
-
-#include <cyg/io/usb/usbs.h>
-
-typedef struct usbs_rx_endpoint {
- void (*start_rx_fn)(struct usbs_rx_endpoint*);
- void (*set_halted_fn)(struct usbs_rx_endpoint*, cyg_bool);
- void (*complete_fn)(void*, int);
- void* complete_data;
- unsigned char* buffer;
- int buffer_size;
- cyg_bool halted;
-} usbs_rx_endpoint;
-
-typedef struct usbs_tx_endpoint {
- void (*start_tx_fn)(struct usbs_tx_endpoint*);
- void (*set_halted_fn)(struct usbs_tx_endpoint*, cyg_bool);
- void (*complete_fn)(void*, int);
- void* complete_data;
- const unsigned char* buffer;
- int buffer_size;
- cyg_bool halted;
-} usbs_tx_endpoint;
-
-
-
-Receive and Transmit Data Structures
-
-In addition to a single usbs_control_endpoint
-data structure per USB slave device, the USB device driver should also
-provide receive and transmit data structures corresponding to the
-other endpoints. The names of these are determined by the device
-driver. For example, the SA1110 USB device driver package provides
-usbs_sa11x0_ep1 for receives and
-usbs_sa11x0_ep2 for transmits.
-
-
-Unlike control endpoints, the common USB slave package does provide a
-number of utility routines to manipulate data endpoints. For example
-usbs_start_rx_buffer
-can be used to receive data from the host into a buffer. In addition
-the USB device driver can provide devtab entries such as
-/dev/usbs1r and /dev/usbs2w, so
-higher-level code can open these devices and then
-perform blocking read and
-write operations.
-
-
-However, the operation of data endpoints and the various
-endpoint-related functions is relatively straightforward. First
-consider a usbs_rx_endpoint structure. The
-device driver will provide the members
-start_rx_fn and
-set_halted_fn, and it will maintain the
-halted field. To receive data, higher-level
-code sets the buffer,
-buffer_size,
-complete_fn and optionally the
-complete_data fields. Next the
-start_rx_fn member should be called. When
-the transfer has finished the device driver will invoke the completion
-function, using complete_data as the first
-argument and a size field for the second argument. A negative size
-indicates an error of some sort: -EGAIN indicates
-that the endpoint has been halted, usually at the request of the host;
--EPIPE indicates that the connection between the
-host and the peripheral has been broken. Certain device drivers may
-generate other error codes.
-
-
-If higher-level code needs to halt or unhalt an endpoint then it can
-invoke the set_halted_fn member. When an
-endpoint is halted, invoking start_rx_fn
-wit buffer_size set to 0 indicates that
-higher-level code wants to block until the endpoint is no longer
-halted; at that point the completion function will be invoked.
-
-
-USB device drivers are allowed to assume that higher-level protocols
-ensure that host and peripheral agree on the amount of data that will
-be transferred, or at least on an upper bound. Therefore there is no
-need for the device driver to maintain its own buffers, and copy
-operations are avoided. If the host sends more data than expected then
-the resulting behaviour is undefined.
-
-
-Transmit endpoints work in essentially the same way as receive
-endpoints. Higher-level code should set the
-buffer and
-buffer_size fields to point at the data to
-be transferred, then call start_tx_fn, and
-the device driver will invoked the completion function when the
-transfer has completed.
-
-
-USB device drivers are not expected to perform any locking. If at any
-time there are two concurrent receive operations for a given endpoint,
-or two concurrent transmit operations, then the resulting behaviour is
-undefined. It is the responsibility of higher-level code to perform
-any synchronisation that may be necessary. In practice, conflicts are
-unlikely because typically a given endpoint will only be accessed
-sequentially by just one part of the overall system.
-
-
-
-
-
-
-
-
-
-
-
-Writing a USB Device Driver
-
-
-Writing a USB Device Driver
-USB Device Driver Porting Guide
-
-
-Introduction
-
-Often the best way to write a USB device driver will be to start with
-an existing one and modify it as necessary. The information given here
-is intended primarily as an outline rather than as a complete guide.
-
-
-
-At the time of writing only one USB device driver has been
-implemented. Hence it is possible, perhaps probable, that some
-portability issues have not yet been addressed. One issue
-involves the different types of transfer, for example the initial
-target hardware had no support for isochronous or interrupt transfers,
-so additional functionality may be needed to switch between transfer
-types. Another issue would be hardware where a given endpoint number,
-say endpoint 1, could be used for either receiving or transmitting
-data, but not both because a single fifo is used. Issues like these
-will have to be resolved as and when additional USB device drivers are
-written.
-
-
-
-
-The Control Endpoint
-
-A USB device driver should provide a single usbs_control_endpoint
-data structure for every USB device. Typical peripherals will have
-only one USB port so there will be just one such data structure in the
-entire system, but theoretically it is possible to have multiple USB
-devices. These may all involve the same chip, in which case a single
-device driver should support multiple device instances, or they may
-involve different chips. The name or names of these data structures
-are determined by the device driver, but appropriate care should be
-taken to avoid name clashes.
-
-
-A USB device cannot be used unless the control endpoint data structure
-exists. However, the presence of USB hardware in the target processor
-or board does not guarantee that the application will necessarily want
-to use that hardware. To avoid unwanted code or data overheads, the
-device driver can provide a configuration option to determine whether
-or not the endpoint 0 data structure is actually provided. A default
-value of CYGINT_IO_USB_SLAVE_CLIENTS ensures that
-the USB driver will be enabled automatically if higher-level code does
-require USB support, while leaving ultimate control to the user.
-
-
-The USB device driver is responsible for filling in the
-start_fn,
-poll_fn and
-interrupt_vector fields. Usually this can
-be achieved by static initialization. The driver is also largely
-responsible for maintaining the state
-field. The control_buffer array should be
-used to hold the first packet of a control message. The
-buffer and other fields related to data
-transfers will be managed jointly by higher-level code and
-the device driver. The remaining fields are generally filled in by
-higher-level code, although the driver should initialize them to NULL
-values.
-
-
-Hardware permitting, the USB device should be inactive until the
-start_fn is invoked, for example by
-tristating the appropriate pins. This prevents the host from
-interacting with the peripheral before all other parts of the system
-have initialized. It is expected that the
-start_fn will only be invoked once, shortly
-after power-up.
-
-
-Where possible the device driver should detect state changes, such as
-when the connection between host and peripheral is established, and
-report these to higher-level
-code via the state_change_fn callback, if
-any. The state change to and from configured state cannot easily be
-handled by the device driver itself, instead higher-level code such as
-the common USB slave package will take care of this.
-
-
-Once the connection between host and peripheral has been established,
-the peripheral must be ready to accept control messages at all times,
-and must respond to these within certain time constraints. For
-example, the standard set-address control message must be handled
-within 50ms. The USB specification provides more information on these
-constraints. The device driver is responsible for receiving the
-initial packet of a control message. This packet will always be eight
-bytes and should be stored in the
-control_buffer field. Certain standard
-control messages should be detected and handled by the device driver
-itself. The most important is set-address, but usually the get-status,
-set-feature and clear-feature requests when applied to halted
-endpoints should also be handled by the driver. Other standard control
-messages should first be passed on to the
-standard_control_fn callback (if any), and
-finally to the default handler
-usbs_handle_standard_control provided by the
-common USB slave package. Class, vendor and reserved control messages
-should always be dispatched to the appropriate callback and there is
-no default handler for these.
-
-
-Some control messages will involve further data transfer, not just the
-initial packet. The device driver must handle this in accordance with
-the USB specification and the buffer management strategy. The
-driver is also responsible for keeping track of whether or not the
-control operation has succeeded and generating an ACK or STALL
-handshake.
-
-
-The polling support is optional and may not be feasible on all
-hardware. It is only used in certain specialised environments such as
-RedBoot. A typical implementation of the polling function would just
-check whether or not an interrupt would have occurred and, if so, call
-the same code that the interrupt handler would.
-
-
-
-Data Endpoints
-
-In addition to the control endpoint data structure, a USB device
-driver should also provide appropriate data
-endpoint data structures. Obviously this is only relevant if
-the USB support generally is desired, that is if the control endpoint is
-provided. In addition, higher-level code may not require all the
-endpoints, so it may be useful to provide configuration options that
-control the presence of each endpoint. For example, the intended
-application might only involve a single transmit endpoint and of
-course control messages, so supporting receive endpoints might waste
-memory.
-
-
-Conceptually, data endpoints are much simpler than the control
-endpoint. The device driver has to supply two functions, one for
-data transfers and another to control the halted condition. These
-implement the functionality for
-usbs_start_rx_buffer,
-usbs_start_tx_buffer,
-usbs_set_rx_endpoint_halted and
-usbs_set_tx_endpoint_halted.
-The device driver is also responsible for maintaining the
-halted status.
-
-
-For data transfers, higher-level code will have filled in the
-buffer,
-buffer_size,
-complete_fn and
-complete_data fields. The transfer function
-should arrange for the transfer to start, allowing the host to send or
-receive packets. Typically this will result in an interrupt at the end
-of the transfer or after each packet. Once the entire transfer has
-been completed, the driver's interrupt handling code should invoke the
-completion function. This can happen either in DSR context or thread
-context, depending on the driver's implementation. There are a number
-of special cases to consider. If the endpoint is halted when the
-transfer is started then the completion function can be invoked
-immediately with -EAGAIN. If the transfer cannot be
-completed because the connection is broken then the completion
-function should be invoked with -EPIPE. If the
-endpoint is stalled during the transfer, either because of a standard
-control message or because higher-level code calls the appropriate
-set_halted_fn, then again the completion
-function should be invoked with -EAGAIN. Finally,
-the <usbs_start_rx_endpoint_wait and
-usbs_start_tx_endpoint_wait functions involve
-calling the device driver's data transfer function with a buffer size
-of 0 bytes.
-
-
-Giving a buffer size of 0 bytes a special meaning is problematical
-because it prevents transfers of that size. Such transfers are allowed
-by the USB protocol, consisting of just headers and acknowledgements
-and an empty data phase, although rarely useful. A future modification
-of the device driver specification will address this issue, although
-care has to be taken that the functionality remains accessible through
-devtab entries as well as via low-level accesses.
-
-
-
-Devtab Entries
-
-For some applications or higher-level packages it may be more
-convenient to use traditional open/read/write I/O calls rather than
-the non-blocking USB I/O calls. To support this the device driver can
-provide a devtab entry for each endpoint, for example:
-
-
-#ifdef CYGVAR_DEVS_USB_SA11X0_EP1_DEVTAB_ENTRY
-
-static CHAR_DEVIO_TABLE(usbs_sa11x0_ep1_devtab_functions,
- &cyg_devio_cwrite,
- &usbs_devtab_cread,
- &cyg_devio_bwrite,
- &cyg_devio_bread,
- &cyg_devio_select,
- &cyg_devio_get_config,
- &cyg_devio_set_config);
-
-static CHAR_DEVTAB_ENTRY(usbs_sa11x0_ep1_devtab_entry,
- CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "1r",
- 0,
- &usbs_sa11x0_ep1_devtab_functions,
- &usbs_sa11x0_devtab_dummy_init,
- 0,
- (void*) &usbs_sa11x0_ep1);
-#endif
-
-
-Again care must be taken to avoid name clashes. This can be achieved
-by having a configuration option to control the base name, with a
-default value of e.g. /dev/usbs, and appending an
-endpoint-specific string. This gives the application developer
-sufficient control to eliminate any name clashes. The common USB slave
-package provides functions usbs_devtab_cwrite and
-usbs_devtab_cread, which can be used in the
-function tables for transmit and receive endpoints respectively. The
-private field priv of the devtab entry
-should be a pointer to the underlying endpoint data structure.
-
-
-Because devtab entries are never accessed directly, only indirectly,
-they would usually be eliminated by the linker. To avoid this the
-devtab entries should normally be defined in a separate source file
-which ends up the special library libextras.a
-rather than in the default library libtarget.a.
-
-
-Not all applications or higher-level packages will want to use the
-devtab entries and the blocking I/O facilities. It may be appropriate
-for the device driver to provide additional configuration options that
-control whether or not any or all of the devtab entries should be
-provided, to avoid unnecessary memory overheads.
-
-
-
-Interrupt Handling
-
-A typical USB device driver will need to service interrupts for all of
-the endpoints and possibly for additional USB events such as entering
-or leaving suspended mode. Usually these interrupts need not be
-serviced directly by the ISR. Instead, they can be left to a DSR. If
-the peripheral is not able to accept or send another packet just yet,
-the hardware will generate a NAK and the host will just retry a little
-bit later. If high throughput is required then it may be desirable to
-handle the bulk transfer protocol largely at ISR level, that is take
-care of each packet in the ISR and only activate the DSR once the
-whole transfer has completed.
-
-
-Control messages may involve invoking arbitrary callback functions in
-higher-level code. This should normally happen at DSR level. Doing it
-at ISR level could seriously affect the system's interrupt latency and
-impose unacceptable constraints on what operations can be performed by
-those callbacks. If the device driver requires a thread anyway then it
-may be appropriate to use this thread for invoking the callbacks, but
-usually it is not worthwhile to add a new thread to the system just
-for this; higher-level code is expected to write callbacks that
-function sensibly at DSR level. Much the same applies to the
-completion functions associated with data transfers. These should also
-be invoked at DSR or thread level.
-
-
-
-Support for USB Testing
-
-Optionally a USB device driver can provide support for the
-USB test software. This requires
-defining a number of additional data structures, allowing the
-generic test code to work out just what the hardware is capable of and
-hence what testing can be performed.
-
-
-The key data structure is
-usbs_testing_endpoint, defined in cyg/io/usb/usbs.h. In addition some
-commonly required constants are provided by the common USB package in
-cyg/io/usb/usb.h. One
-usbs_testing_endpoint structure should be
-defined for each supported endpoint. The following fields need to be
-filled in:
-
-
-
- endpoint_type
-
- This specifies the type of endpoint and should be one of
- USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL,
- BULK, ISOCHRONOUS or
- INTERRUPT.
-
-
-
- endpoint_number
-
- This identifies the number that should be used by the host
- to address this endpoint. For a control endpoint it should
- be 0. For other types of endpoints it should be between
- 1 and 15.
-
-
-
- endpoint_direction
-
- For control endpoints this field is irrelevant. For other
- types of endpoint it should be either
- USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN or
- USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT. If a given
- endpoint number can be used for traffic in both directions then
- there should be two entries in the array, one for each direction.
-
-
-
- endpoint
-
- This should be a pointer to the appropriate
- usbs_control_endpoint,
- usbs_rx_endpoint or
- usbs_tx_endpoint structure, allowing the
- generic testing code to perform low-level I/O.
-
-
-
- devtab_entry
-
- If the endpoint also has an entry in the system's device table then
- this field should give the corresponding string, for example
- "/dev/usbs1r". This allows the
- generic testing code to access the device via higher-level
- calls like open and read.
-
-
-
- min_size
-
- This indicates the smallest transfer size that the hardware can
- support on this endpoint. Typically this will be one.
-
-
- Strictly speaking a minimum size of one is not quite right since it
- is valid for a USB transfer to involve zero bytes, in other words a
- transfer that involves just headers and acknowledgements and an
- empty data phase, and that should be tested as well. However current
- device drivers interpret a transfer size of 0 as special, so that
- would have to be resolved first.
-
-
-
-
- max_size
-
- Similarly, this specifies the largest transfer size. For control
- endpoints the USB protocol uses only two bytes to hold the transfer
- length, so there is an upper bound of 65535 bytes. In practice
- it is very unlikely that any control transfers would ever need to
- be this large, and in fact such transfers would take a long time
- and probably violate timing constraints. For other types of endpoint
- any of the protocol, the hardware, or the device driver may impose
- size limits. For example a given device driver might be unable to
- cope with transfers larger than 65535 bytes. If it should be
- possible to transfer arbitrary amounts of data then a value of
- -1 indicates no upper limit, and transfer
- sizes will be limited by available memory and by the capabilities
- of the host machine.
-
-
-
- max_in_padding
-
- This field is needed on some hardware where it is impossible to
- send packets of a certain size. For example the hardware may be
- incapable of sending an empty bulk packet to terminate a transfer
- that is an exact multiple of the 64-byte bulk packet size.
- Instead the driver has to do some padding and send an extra byte,
- and the host has to be prepared to receive this extra byte. Such a
- driver should specify a value of 1 for the
- padding field. For most drivers this field should be set to
- 0.
-
-
- A better solution would be for the device driver to supply a
- fragment of Tcl code that would adjust the receive buffer size
- only when necessary, rather than for every transfer. Forcing
- receive padding on all transfers when only certain transfers
- will actually be padded reduces the accuracy of certain tests.
-
-
-
- alignment
-
- On some hardware data transfers may need to be aligned to certain
- boundaries, for example a word boundary or a cacheline boundary.
- Although in theory device drivers could hide such alignment
- restrictions from higher-level code by having their own buffers and
- performing appropriate copying, that would be expensive in terms of
- both memory and cpu cycles. Instead the generic testing code will
- align any buffers passed to the device driver to the specified
- boundary. For example, if the driver requires that buffers be
- aligned to a word boundary then it should specify an alignment
- value of 4.
-
-
-
-
-
-The device driver should provide an array of these structures
-usbs_testing_endpoints[]. The USB testing code
-examines this array and uses the information to perform appropriate
-tests. Because different USB devices support different numbers of
-endpoints the number of entries in the array is not known in advance,
-so instead the testing code looks for a special terminator
-USBS_TESTING_ENDPOINTS_TERMINATOR. An example
-array, showing just the control endpoint and the terminator, might
-look like this:
-
-
-usbs_testing_endpoint usbs_testing_endpoints[] = {
- {
- endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL,
- endpoint_number : 0,
- endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN,
- endpoint : (void*) &ep0.common,
- devtab_entry : (const char*) 0,
- min_size : 1,
- max_size : 0x0FFFF,
- max_in_padding : 0,
- alignment : 0
- },
- …,
- USBS_TESTING_ENDPOINTS_TERMINATOR
-};
-
-
-
-
-The use of a single array usbs_testing_endpoints
-limits USB testing to platforms with a single USB device: if there
-were multiple devices, each defining their own instance of this array,
-then there would a collision at link time. In practice this should not
-be a major problem since typical USB peripherals only interact with a
-single host machine via a single slave port. In addition, even if a
-peripheral did have multiple slave ports the current USB testing code
-would not support this since it would not know which port to use.
-
-
-
-
-
-
-
-
-
-
-
-
-Testing
-
-
-Testing
-Testing of USB Device Drivers
-
-
-Introduction
-
-The support for USB testing provided by the eCos USB common slave
-package is somewhat different in nature from the kind of testing used
-in many other packages. One obvious problem is that USB tests cannot
-be run on just a bare target platform: instead the target platform
-must be connected to a suitable USB host machine, and that host
-machine must be running appropriate software for the test code to
-interact with. This is very different from say a kernel test which
-typically will have no external dependencies. Another important
-difference between USB testing and say a C library
-strcmp test is sensitivity to timing and to
-hardware boundary conditions: although a simple test case that just
-performs a small number of USB transfers is better than no testing at
-all, it should also be possible to run tests for hours or days on end,
-under a variety of loads. In order to provide the required
-functionality the basic architecture of the USB testing support is as
-follows:
-
-
-
- There is a single target-side program
- usbtarget. By default when this is run
- on a target platform it will appear to do nothing. In fact it is
- waiting to be contacted by another program
- usbhost which will tell it what test or
- tests to run. usbtarget provides
- mechanisms for running a wide range of tests.
-
-
- usbtarget is a generic program, but USB
- testing depends to some extent on the functionality provided by the
- hardware. For example there is no point in testing bulk transmits
- to endpoint 12 if the target hardware does not support an endpoint
- 12. Therefore each USB device driver should supply information about
- what the hardware is actually capable of, in the form of an array of
- usbs_testing_endpoint data structures.
-
-
- There is a single host-side program
- usbhost, which acts as a counterpart to
- usbtarget. Again
- usbhost has no built-in knowledge of
- the test or tests that are supposed to run, it only provides
- mechanisms for running a wide range of tests. On start-up
- usbhost will search the USB bus for
- hardware running the target-side program, specifically a USB device
- that identifies itself as the product "Red Hat eCos
- USB test".
-
-
- usbhost contains a Tcl interpreter, and
- will execute any Tcl scripts specified on the command line
- together with appropriate arguments. The Tcl interpreter has been
- extended with various commands such as
- usbtest::bulktest, so the script can perform
- the desired test or tests.
-
-
- Adding a new test simply involves writing a short Tcl script that
- invokes the appropriate USB-specific commands. Running multiple
- tests involves passing appropriate arguments to
- usbhost, or alternatively writing a
- single script that just invokes other scripts.
-
-
-
-The current implementation of usbhost
-depends heavily on functionality provided by the Linux kernel and in
-particular the usbdevfs support. It uses
-/proc/bus/usb/devices to find out what devices
-are attached to the bus, and will then access the device by opening
-/proc/bus/usb/xxx/yyy and performing
-ioctl operations. This allows USB testing to take
-place without having to write a new host-side device driver, but
-getting the code working on host machines not running Linux would
-obviously be problematical.
-
-
-
-Building and Running the Target-side Code
-
-The target-side component of the USB testing software consists of a
-single program usbtarget which contains
-support for a range of different tests, under the control of host-side
-software. This program is not built by default alongside other eCos
-test cases since it will only operate in certain environments,
-specifically when the target board's connector is plugged into a Linux
-host, and when the appropriate host-side software has been installed
-on that host. Instead the user must enable a configuration option
-CYGBLD_IO_USB_SLAVE_USBTEST to add the program to
-the list of tests for the current configuration.
-
-
-Starting the usbtarget program does not
-require anything unusual, so it can be run in a normal
-gdb session just like any eCos application.
-After initialization the program will wait for activity from the host.
-Depending on the hardware, the Linux host will detect that a new USB
-peripheral is present on the bus either when the
-usbtarget initialization is complete or
-when the cable between target and host is connected. The host will
-perform the normal USB enumeration sequence and discover that the
-peripheral does not match any known vendor or product id and that
-there is no device driver for "Red Hat eCos USB
-test", so it will ignore the peripheral. When the
-usbhost program is run on the host it will
-connect to the target-side software, and testing can now commence.
-
-
-
-Building and Running the Host-side Code
-
-In theory the host-side software should be built when the package is
-installed in the component repository, and removed when a package
-is uninstalled. The current eCos administration tool does not provide
-this functionality.
-
-
-The host-side software should be built via the usual sequence of
-"configure/make/make install". It can only be built on a
-Linux host and the configure script contains an
-explicit test for this. Because the eCos component repository should
-generally be treated as a read-only resource the configure script will
-also prevent you from trying to build inside the source tree. Instead
-a separate build tree is required. Hence a typical sequence for
-building the host-side software would be as follows:
-
-
-$ mkdir usbhost_build
-$ cd usbhost_build
-$ <repo>packages/io/usb/slave/current/host/configure <args>
-$ make
-<output from make>
-$ su
-$ make install
-<output from make install>
-$
-
-
-
-
-The location of the eCos component repository should be substituted
-for <repo>.
-
-
-
-
-If the package has been obtained via CVS or anonymous CVS then the
-package version will be current, as per the
-example. If instead the package has been obtained as part of a full
-eCos release or as a separate .epk file then the
-appropriate package version should be used instead of
-current.
-
-
-
-
-The configure script takes the usual arguments such
-as --prefix= to specify where the executables
-and support files should be installed. The only other parameter that
-some users may wish to specify is the location of a suitable Tcl
-installation. By default usbhost will use
-the existing Tcl installation in /usr,
-as provided by your Linux distribution. An alternative Tcl
-installation can be specified using the parameter
---with-tcl=, or alternatively using some
-combination of --with-tcl-include,
---with-tcl-lib and
---with-tcl-version.
-
-
-
-
-One of the host-side executables that gets built,
-usbchmod, needs to be installed with suid
-root privileges. Although the Linux kernel makes it possible for
-applications to perform low-level USB operations such as transmitting
-bulk packets, by default access to this functionality is restricted to
-programs with superuser privileges. It is undesirable to run a complex
-program such as usbhost with such
-privileges, especially since the program contains a general-purpose
-Tcl interpreter. Therefore when usbhost
-starts up and discovers that it does not have sufficient access to the
-appropriate entries in /proc/bus/usb,
-it spawns an instance of usbchmod to modify
-the permissions on these entries. usbchmod
-will only do this for a USB device "Red Hat eCos USB
-test", so installing this program suid root should not
-introduce any security problems.
-
-
-
-
-
-During make install the following actions will take
-place:
-
-
-
-
-usbhost will be installed in /usr/local/bin,
-or some other bin directory if
-the default location is changed at configure-time using a
---prefix= or similar option. It will be
-installed as the executable
-usbhost_<version>, for example
-usbhost_current, thus allowing several
-releases of the USB slave package to co-exist. For convenience a
-symbolic link from usbhost to this executable
-will be created, so users can just run usbhost to
-access the most recently-installed version.
-
-
-
-
-usbchmod will be installed in
-/usr/local/libexec/ecos/io_usb_slave_<version>.
-This program should only be run by usbhost,
-not invoked directly, so it is not placed in the bin
-directory. Again the presence of the package version in the directory
-name allows multiple releases of the package to co-exist.
-
-
-
-
-A Tcl script usbhost.tcl will get installed in
-the same directory as usbchmod. This Tcl
-script is loaded automatically by the
-usbhost executable.
-
-
-
-
-A number of additional Tcl scripts, for example
-list.tcl will get installed alongside
-usbhost.tcl. These correspond to various test
-cases provided as standard. If a given test case is specified on the
-command line and cannot be found relative to the current directory
-then usbhost will search the install
-directory for these test cases.
-
-
-Strictly speaking installing the usbhost.tcl and
-other Tcl scripts below the libexec
-directory deviates from standard practice: they are
-architecture-independent data files so should be installed below
-the share subdirectory. In
-practice the files are sufficiently small that there is no point in
-sharing them, and keeping them below libexec
-simplifies the host-side software somewhat.
-
-
-
-
-
-The usbhost should be run only when there is a
-suitable target attached to the USB bus and running the
-usbtarget program. It will search
-/proc/bus/usb/devices for an entry corresponding
-to this program, invoke usbchmod if
-necessary to change the access rights, and then interact with
-usbtarget over the USB bus.
-usbhost should be invoked as follows:
-
-
-$ usbhost [-v|--version] [-h|--help] [-V|--verbose] <test> [<test parameters>]
-
-
-
-
-The -v or --version
-option will display version information for
-usbhost including the version of the USB
-slave package that was used to build the executable.
-
-
-
-
-The -h or --help option
-will display usage information.
-
-
-
-
-The -V or --verbose
-option can be used to obtain more information at run-time, for example
-some output for every USB transfer. This option can be repeated
-multiple times to increase the amount of output.
-
-
-
-
-The first argument that does not begin with a hyphen specifies a test
-that should be run, in the form of a Tcl script. For example an
-argument of list.tcl will cause
-usbhost to look for a script with that
-name, adding a .tcl suffix if necessarary, and
-run that script. usbhost will look in the
-current directory first, then in the install tree for standard test
-scripts provided by the USB slave package.
-
-
-
-
-Some test scripts may want their own parameters, for example a
-duration in seconds. These can be passed on the command line after
-the name of the test, for example
-usbhost mytest 60.
-
-
-
-
-
-Writing a Test
-
-Each test is defined by a Tcl script, running inside an interpreter
-provided by usbhost. In addition to the
-normal Tcl functionality this interpreter provides a number of
-variables and functions related to USB testing. For example there is a
-variable bulk_in_endpoints that lists all the
-endpoints on the target that can perform bulk IN operations, and a
-related array bulk_in which contains information
-such as the minimum and maximum packets sizes. There is a function
-bulktest which can be used to perform bulk tests
-on a particular endpoint. A simple test script aimed at specific
-hardware could ignore the information variables since it would know
-exactly what USB hardware is available on the target, whereas a
-general-purpose script would use the information to adapt to the
-hardware capabilities.
-
-
-To avoid namespace pollution all USB-related Tcl variables and
-functions live in the usbtest:: namespace.
-Therefore accessing requires either explicitly including the
-namespace any references, for example
-$usbtest::bulk_in_endpoints, or by using Tcl's
-namespace import facility.
-
-
-A very simple test script might look like this:
-
-
-usbtest::bulktest 1 out 4000
-usbtest::bulktest 2 in 4000
-if { [usbtest::start 60] } {
- puts "Test successful"
-} else
- puts "Test failed"
- foreach result $usbtest::results {
- puts $result
- }
-}
-
-
-This would perform a test run involving 4000 bulk transfers from the
-host to the target's endpoint 1, and concurrently 4000 bulk transfers
-from endpoint 2. Default settings for packet sizes, contents, and
-delays would be used. The actual test would not start running until
-usbtest is invoked, and it is expected that the
-test would complete within 60 seconds. If any failures occur then they
-are reported.
-
-
-
-Available Hardware
-
-Each target-side USB device driver provides information about the
-actual capabilities of the hardware, for example which endpoints are
-available. Strictly speaking it provides information about what is
-actually supported by the device driver, which may be a subset of what
-the hardware is capable of. For example, the hardware may support
-isochronous transfers on a particular endpoint but if there is no
-software support for this in the driver then this endpoint will not be
-listed. When usbhost first contacts the
-usbtarget program running on the target
-platform, it obtains this information and makes it available to test
-scripts via Tcl variables:
-
-
-
- bulk_in_endpoints
-
- This is a simple list of the endpoints which can support bulk IN
- transfers. For example if the target-side hardware supports
- these transfers on endpoints 3 and 5 then the value would be
- "3 5" Typical test scripts would
- iterate over the list using something like:
-
-
- if { 0 != [llength $usbtest::bulk_in_endpoints] } {
- puts"Bulk IN endpoints: $usbtest::bulk_in_endpoints"
- foreach endpoint $usbtest:bulk_in_endpoints {
- …
- }
- }
-
-
-
-
- bulk_in()
-
- This array holds additional information about each bulk IN endpoint.
- The array is indexed by two fields, the endpoint number and one of
- min_size, max_size,
- max_in_padding and devtab:
-
-
-
- min_size
-
- This field specifies a lower bound on the size of bulk transfers,
- and will typically will have a value of 1.
-
-
- The typical minimum transfer size of a single byte is not strictly
- speaking correct, since under some circumstances it can make sense
- to have a transfer size of zero bytes. However current target-side
- device drivers interpret a request to transfer zero bytes as a way
- for higher-level code to determine whether or not an endpoint is
- stalled, so it is not actually possible to perform zero-byte
- transfers. This issue will be addressed at some future point.
-
-
-
-
- max_size
-
- This field specifies an upper bound on the size of bulk transfers.
- Some target-side drivers may be limited to transfers of say
- 0x0FFFF bytes because of hardware limitations. In practice the
- transfer size is likely to be limited primarily to limit memory
- consumption of the test code on the target hardware, and to ensure
- that tests complete reasonably quickly. At the time of writing
- transfers are limited to 4K.
-
-
-
- max_in_padding
-
- On some hardware it may be necessary for the target-side device
- driver to send more data than is actually intended. For example
- the SA11x0 USB hardware cannot perform bulk transfers that are
- an exact multiple of 64 bytes, instead it must pad such
- transfers with an extra byte and the host must be ready to
- accept and discard this byte. The
- max_in_padding field indicates the amount of
- padding that is required. The low-level code inside
- usbhost will use this field
- automatically, and there is no need for test scripts to adjust
- packet sizes for padding. The field is provided for
- informational purposes only.
-
-
-
- devtab
-
- This is a string indicating whether or not the
- target-side USB device driver supports access to this endpoint
- via entries in the device table, in other words through
- conventional calls like open and
- write. Some device drivers may only
- support low-level USB access because typically that is what gets
- used by USB class-specific packages such as USB-ethernet.
- An empty string indicates that no devtab entry is available,
- otherwise it will be something like
- "/dev/usbs2w".
-
-
-
-
- Typical test scripts would access this data using something like:
-
-
- foreach endpoint $usbtest:bulk_in_endpoints {
- puts "Endpoint $endpoint: "
- puts " minimum transfer size $usbtest::bulk_in($endpoint,min_size)"
- puts " maximum transfer size $usbtest::bulk_in($endpoint,max_size)"
- if { 0 == $usbtest::bulk_in($endpoint,max_in_padding) } {
- puts " no IN padding required"
- } else {
- puts " $usbtest::bulk_in($endpoint,max_in_padding) bytes of IN padding required"
- }
- if { "" == $usbtest::bulk_in($endpoint,devtab) } {
- puts " no devtab entry provided"
- } else {
- puts " corresponding devtab entry is $usbtest::bulk_in($endpoint,devtab)"
- }
- }
-
-
-
-
- bulk_out_endpoint
-
- This is a simple list of the endpoints which can support bulk OUT
- transfers. It is analogous to
- bulk_in_endpoints.
-
-
-
- bulk_out()
-
- This array holds additional information about each bulk OUT
- endpoint. It can be accessed in the same way as
- bulk_in(), except that there is no
- max_in_padding field because that field only
- makes sense for IN transfers.
-
-
-
- control()
-
- This array holds information about the control endpoint. It contains
- two fields, min_size and
- max_size. Note that there is no variable
- control_endpoints because a USB target always
- supports a single control endpoint 0. Similarly
- the control array does not use an endpoint number
- as the first index because that would be redundant.
-
-
-
- isochronous_in_endpoints and
- isochronous_in()
-
- These variables provide the same information as
- bulk_in_endpoints and bulk_in,
- but for endpoints that support isochronous IN transfers.
-
-
-
- isochronous_out_endpoints and
- isochronous_out()
-
- These variables provide the same information as
- bulk_out_endpoints and bulk_out,
- but for endpoints that support isochronous OUT transfers.
-
-
-
- interrupt_in_endpoints and
- interrupt_in()
-
- These variables provide the same information as
- bulk_in_endpoints and bulk_in,
- but for endpoints that support interrupt IN transfers.
-
-
-
- interrupt_out_endpoints and
- interrupt_out()
-
- These variables provide the same information as
- bulk_out_endpoints and bulk_out,
- but for endpoints that support interrupt OUT transfers.
-
-
-
-
-
-
-Testing Bulk Transfers
-
-The main function for initiating a bulk test is
-usbtest::bulktest. This takes three compulsory
-arguments, and can be given a number of additional arguments to
-control the exact behaviour. The compulsory arguments are:
-
-
-
- endpoint
-
- This specifies the endpoint to use. It should correspond to
- one of the entries in
- usbtest::bulk_in_endpoints or
- usbtest::bulk_out_endpoints, depending on the
- transfer direction.
-
-
-
- direction
-
- This should be either in or out.
-
-
-
- number of transfers
-
- This specifies the number of transfers that should take place. The
- testing software does not currently support the concept of performing
- transfers for a given period of time because synchronising this on
- both the host and a wide range of targets is difficult. However it
- is relatively easy to work out the approximate time a number of bulk
- transfers should take place, based on a typical bandwidth of
- 1MB/second and assuming say a 1ms overhead per transfer.
- Alternatively a test script could perform a small initial run to
- determine what performance can actually be expected from a given
- target, and then use this information to run a much longer test.
-
-
-
-
-Additional arguments can be used to control the exact transfer. For
-example a txdelay+ argument can be used to
-slowly increase the delay between transfers. All such arguments involve
-a value which can be passed either as part of the argument itself,
-for example txdelay+=5, or as a subsequent
-argument, txdelay+ 5. The possible arguments fall
-into a number of categories: data, I/O mechanism, transmit size,
-receive size, transmit delay, and receive delay.
-
-
-Data
-
-An obvious parameter to control is the actual data that gets sent.
-This can be controlled by the argument data
-which can take one of five values: none,
-bytefill, intfill,
-byteseq and wordseq. The default
-value is none.
-
-
-
- none
-
- The transmit code will not attempt to fill the buffer in any way,
- and the receive code will not check it. The actual data that gets
- transferred will be whatever happened to be in the buffer before
- the transfer started.
-
-
-
- bytefill
-
- The entire buffer will be filled with a single byte, as per
- memset.
-
-
-
- intfill
-
- The buffer will be treated as an array of 32-bit integers, and will
- be filled with the same integer repeated the appropriate number of
- times. If the buffer size is not a multiple of four bytes then
- the last few bytes will be set to 0.
-
-
-
- byteseq
-
- The buffer will be filled with a sequence of bytes, generated by
- a linear congruential generator. If the first byte in the buffer is
- filled with the value x, the next byte will be
- (m*x)+i. For example a sequence of slowly
- incrementing bytes can be achieved by setting both the multiplier
- and the increment to 1. Alternatively a pseudo-random number
- sequence can be achieved using values 1103515245 and 12345, as
- per the standard C library rand function.
- For convenience these two constants are available as Tcl
- variables usbtest::MULTIPLIER and
- usbtest::INCREMENT.
-
-
-
- wordseq
-
- This acts like byteseq, except that the buffer is
- treated as an array of 32-bit integers rather than as an array of
- bytes. If the buffer is not a multiple of four bytes then the last
- few bytes will be filled with zeroes.
-
-
-
-
-The above requires three additional parameters
-data1, data* and
-data+. data1 specifies
-the value to be used for byte or word fills, or the first number when
-calculating a sequence. The default value is 0.
-data* and data+ specify
-the multiplier and increment for a sequence, and have default values
-of 1 and 0 respectively. For
-example, to perform a bulk transfer of a pseudo-random sequence of
-integers starting with 42 the following code could be used:
-
-
-bulktest 2 IN 1000 data=wordseq data1=42 \
- data* $usbtest::MULTIPLIER data+ $usbtest::INCREMENT
-
-
-The above parameters define what data gets transferred for the first
-transfer, but a test can involve multiple transfers. The data format
-will be the same for all transfers, but it is possible to adjust the
-current value, the multiplier, and the increment between each
-transfer. This is achieved with parameters data1*,
-data1+, data**,
-data*+, data+*, and
-data++, with default values of 1 for each
-multiplier and 0 for each increment. For example, if the multiplier
-for the first transfer is set to 2 using
-data*, and arguments
-data** 2 and data*+ -1 are also
-supplied, then the multiplier for subsequent transfers will be
-3, 5, 9,
-….
-
-
-
-Currently it is not possible for a test script to send specific data,
-for example a specific sequence of bytes captured by a protocol analyser
-that caused a problem. If the transfer was from host to target then
-the target would have to know the exact sequence of bytes to expect,
-which means transferring data over the USB bus when that data is known
-to have caused problems in the past. Similarly for target to host
-transfers the target would have to know what bytes to send. A possible
-future extension of the USB testing support would allow for bounce
-operations, where a given message is first sent to the target and then
-sent back to the host, with only the host checking that the data was
-returned correctly.
-
-
-
-I/O Mechanism
-
-On the target side USB transfers can happen using either low-level
-USB calls such as usbs_start_rx_buffer, or by
-higher-level calls which go through the device table. By default the
-target-side code will use the low-level calls. If it is desired to
-test the higher-level calls instead, for example because those are
-what the application uses, then that can be achieved with an
-argument mechanism=devtab.
-
-
-
-Transmit Size
-
-The next set of arguments can be used to control the size of the
-transmitted buffer: txsize1,
-txsize>=, txsize<=
-txsize*, txsize/,
-and txsize+.
-
-
-txsize1 determines the size of the first
-transfer, and has a default value of 32 bytes. The size of the next
-transfer is calculated by first multiplying by the
-txsize* value, then dividing by the
-txsize/ value, and finally adding the
-txsize+ value. The defaults for these are
-1, 1, and 0
-respectively, which means that the transfer size will remain
-unchanged. If for example the transfer size should increase by
-approximately 50 per cent each time then suitable values might be
-txsize* 3, txsize/ 2,
-and txsize+ 1.
-
-
-The txsize>= and
-txsize<= arguments can be used to impose
-lower and upper bounds on the transfer. By default the
-min_size and max_size values
-appropriate for the endpoint will be used. If at any time the
-current size falls outside the bounds then it will be normalized.
-
-
-
-Receive Size
-
-The receive size, in other words the number of bytes that either host
-or target will expect to receive as opposed to the number of bytes
-that actually get sent, can be adjusted using a similar set of
-arguments: rxsize1,
-rxsize>=,
-rxsize<=,
-rxsize*, rxsize/ and
-rxsize+. The current receive size will be
-adjusted between transfers just like the transmit size. However when
-communicating over USB it is not a good idea to attempt to receive
-less data than will actually be sent: typically neither the hardware
-nor the software will be able to do anything useful with the excess,
-so there will be problems. Therefore if at any time the calculated
-receive size is less than the transmit size, the actual receive will
-be for the exact number of bytes that will get transmitted. However
-this will not affect the calculations for the next receive size.
-
-
-The default values for rxsize1,
-rxsize*, rxsize/ and
-rxsize+ are 0,
-1, 1 and 0
-respectively. This means that the calculated receive size will always
-be less than the transmit size, so the receive operation will be for
-the exact number of bytes transmitted. For some USB protocols this
-would not accurately reflect the traffic that will happen. For example
-with USB-ethernet transfer sizes will vary between 16 and 1516 bytes,
-so the receiver will always expect up to 1516 bytes. This can be
-achieved using rxsize1 1516, leaving the
-other parameters at their default values.
-
-
-For target hardware which involves non-zero
-max_in_padding, on the host side the padding will
-be added automatically to the receive size if necessary.
-
-
-
-Transmit and Receive Delays
-
-Typically during the testing there will be some minor delays between
-transfers on both host and target. Some of these delays will be caused
-by timeslicing, for example another process running on the host, or a
-concurrent test thread running inside the target. Other delays will be
-caused by the USB bus itself, for example activity from another device
-on the bus. However it is desirable that test cases be allowed to
-inject additional and somewhat more controlled delays into the system,
-for example to make sure that the target behaves correctly even if the
-target is not yet ready to receive data from the host.
-
-
-The transmit delay is controlled by six parameters:
-txdelay1, txdelay*,
-txdelay/, txdelay+,
-txdelay>= and
-txdelay<=. The default values for these are
-0, 1, 1,
-0, 0 and
-1000000000 respectively, so that by default
-transmits will happen as quickly as possible. Delays are measured in
-nanoseconds, so a value of 1000000 would correspond
-to a delay of 0.001 seconds or one millisecond. By default delays have
-an upper bound of one second. Between transfers the transmit delay is
-updated in much the same was as the transfer sizes.
-
-
-The receive delay is controlled by a similar set of six parameters:
-rxdelay1, rxdelay*,
-rxdelay/, rxdelay+,
-rxdelay>= and
-rxdelay<=. The default values for these are
-the same as for transmit delays.
-
-
-The transmit delay is used on the side which sends data over the USB
-bus, so for a bulk IN transfer it is the target that sends data and
-hence sleeps for the specified transmit delay, while the host receives
-data sleeps for the receive delay. For an OUT transfer the positions
-are reversed.
-
-
-It should be noted that although the delays are measured in
-nanoseconds, the actual delays will be much less precise and are
-likely to be of the order of milliseconds. The exact details will
-depend on the kernel clock speed.
-
-
-
-
-
-Other Types of Transfer
-
-Support for testing other types of USB traffic such as isochronous
-transfers is not yet implemented.
-
-
-
-Starting a Test and Collecting Results
-
-A USB test script should prepare one or more transfers using
-appropriate functions such as usbtest::bulktest.
-Once all the individual tests have been prepared they can be started
-by a call to usbtest::start. This takes a single
-argument, a maximum duration measured in seconds. If all transfers
-have not been completed in the specified time then any remaining
-transfers will be aborted.
-
-
-usbtest::start will return 1
-if all the tests have succeeded, or 0 if any of
-them have failed. More detailed reports will be stored in the
-Tcl variable usbtests::results, which will be a
-list of string messages.
-
-
-
-Existing Test Scripts
-
-A number of test scripts are provided as standard. These are located
-in the host subdirectory of the
-common USB slave package, and will be installed as part of the process
-of building the host-side software. When a script is specified on the
-command line usbhost will first search for
-it in the current directory, then in the install tree. Standard
-test scripts include the following:
-
-
- list.tcl
-
- This script simply displays information about the capabilities
- of the target platform, as provided by the target-side USB
- device driver. It can help with tracking down problems, but its
- primary purpose is to let users check that everything is working
- correctly: if running usbhost list.tcl
- outputs sensible information then the user knows that the
- target side is running correctly and that communication between
- host and target is possible.
-
-
- verbose.tcl
-
- The target-side code can provide information about what
- is happening while tests are prepared and run. This facility
- should not normally be used since the extra I/O involved will
- significantly affect the behaviour of the system, but in some
- circumstances it may prove useful. Since an eCos application
- cannot easily be given command-line arguments the target-side
- verbosity level cannot be controlled using
- -V or --verbose
- options. Instead it can be controlled from inside
- gdb by changing the integer
- variable verbose. Alternatively it can
- be manipulated by running the test script
- verbose.tcl. This script takes a single
- argument, the desired verbosity level, which should be a small
- integer. For example, to disable target-side run-time logging
- the command usbhost verbose 0 can
- be used.
-
-
-
-
-
-Possible Problems
-
-If all transfers succeed within the specified time then both host and
-target remain in synch and further tests can be run without problem.
-However, if at any time a failure occurs then things get more
-complicated. For example, if the current test involves a series of
-bulk OUT transfers and the target detects that for one of these
-transfers it received less data than was expected then the test has
-failed, and the target will stop accepting data on this endpoint.
-However the host-side software may not have detected anything wrong
-and is now blocked trying to send the next lot of data.
-
-
-The test code goes to considerable effort to recover from problems
-such as these. On the host-side separate threads are used for
-concurrent transfers, and on the target-side appropriate asynchronous
-I/O mechanisms are used. In addition there is a control thread on the
-host that checks the state of all the main host-side threads, and the
-state of the target using private control messages. If it discovers
-that one side has stopped sending or receiving data because of an
-error and the other side is blocked as a result, it will set certain
-flags and then cause one additional transfer to take place. That
-additional transfer will have the effect of unblocking the other side,
-which then discovers that an error has occurred by checking the
-appropriate flags. In this way both host and target should end up back
-in synch, and it is possible to move on to the next set of tests.
-
-
-However, the above assumes that the testing has not triggered any
-serious hardware conditions. If instead the target-side hardware has
-been left in some strange state so that, for example, it will no
-longer raise an interrupt for traffic on a particular endpoint then
-recovery is not currently possible, and the testing software will just
-hang.
-
-
-A possible future enhancement to the testing software would allow the
-host-side to raise a USB reset signal whenever a failure occurs, in
-the hope that this would clear any remaining problems within the
-target-side USB hardware.
-
-
-
-
-
-
-
-
-
-
Index: slave/v2_0/ChangeLog
===================================================================
--- slave/v2_0/ChangeLog (revision 174)
+++ slave/v2_0/ChangeLog (nonexistent)
@@ -1,152 +0,0 @@
-2003-02-25 Jonathan Larmour
-
- * doc/usbs.sgml: Declare as not to get
- correct TOC numbering.
-
-2003-02-24 Jonathan Larmour
-
- * cdl/usbs.cdl: Update doc links.
-
- * doc/usbs.sgml: Comment out DOCTYPE for now to allow building
- with standard doc build.
-
-2003-02-12 Bart Veer
-
- * host/Makefile.in, host/configure:
- Regenerate after toplevel acinclude.m4 update
-
-2002-09-23 Bart Veer
-
- * host/configure.in:
- Only build if the required Linux kernel support is present.
-
-2002-09-21 Bart Veer
-
- * host/usbhost.c:
- Avoid const compatibility problems with Tcl 8.4
-
-2002-01-23 Bart Veer
-
- * host/Makefile.am, host/Makefile.in, host/acinclude.m4,
- host/aclocal.m4, host/configure, host/configure.in,
- host/usbhost.c, host/usbhost.tcl, host/verbose.tcl
- Host-side support for USB testing
-
- * tests/usbtarget.c, tests/common.c, tests/protocol.h:
- New files containing the target-side testing support and
- support files.
-
- * cdl/usbs.cdl:
- Add a configuration option to build the target-side testing
- support.
-
- * doc/usbs.sgml, doc/*.html:
- Document the testing support. Regenerate html.
-
-2001-09-14 Bart Veer
-
- * doc/usbs.sgml, doc/*.html:
- Fix the example strings in the enumeration data.
- Regenerate html.
-
- * include/usbs.h:
- Update the USB testing data structure
-
- * src/usbs.c (usbs_handle_standard_control):
- Fix an assertion for the special case of a USB configuration that
- defines no endpoints.
-
-2001-08-06 Bart Veer
-
- * include/usbs.h:
- Define additional data structures required for USB testing.
-
-2001-06-19 Bart Veer
-
- * src/usbs.c, include/usbs.h (usbs_devtab_cread):
- read operations should not take a const buffer
-
-2001-02-02 Bart Veer
-
- * cdl/usbs.cdl:
- Add doc property to point at the HTML
-
- * doc/usbs.sgml, *.html:
- Incorporate changes from docs department, regenerate HTML
-
-2001-01-25 Bart Veer
-
- * src/usbs.c:
- * include/usbs.h:
- Only declare the devtab support functions if the I/O package is
- present, since that provides required data types.
-
- * cdl/usbs.cdl:
- devtab support should be enabled by default iff the I/O package is
- present.
-
-2001-01-22 Bart Veer
-
- * doc/usbs.sgml, doc/makefile:
- Added documentation
-
-2001-01-16 Bart Veer
-
- * include/usbs.h:
- * src/usbs.c:
- Update the start() and poll() functions to match the documentation.
-
-2000-12-15 Bart Veer
-
- * src/usbs.c:
- Fix missing return statements.
-
-2000-11-28 Bart Veer
-
- * cdl/usbs.cdl
- * include/usbs.h:
- * usbs.c
- Update interface to USB device drivers
-
-2000-11-22 Bart Veer
-
- * include/usbs.h: Fix nested #include protection
-
-2000-11-21 Bart Veer
-
- * First check-in of eCos USB support.
-
-//===========================================================================
-//####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####
-//===========================================================================
Index: slave/v2_0/src/usbs.c
===================================================================
--- slave/v2_0/src/usbs.c (revision 174)
+++ slave/v2_0/src/usbs.c (nonexistent)
@@ -1,713 +0,0 @@
-//==========================================================================
-//
-// usbs.c
-//
-// Generic USB slave-side support
-//
-//==========================================================================
-//####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####
-//
-// Author(s): bartv
-// Contributors: bartv
-// Date: 2000-10-04
-//
-//####DESCRIPTIONEND####
-//
-//==========================================================================
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// ----------------------------------------------------------------------------
-// Devtab entry support. This code can be compiled with no overheads as
-// long as the necessary support package is in place.
-#ifdef CYGPKG_IO
-# include
-# include
-// ----------------------------------------------------------------------------
-// read()/write() functions applied to USB endpoints. These just
-// indirect via the usbs_endpoint structures and wait for the
-// callback to happen.
-
-typedef struct usbs_callback_data {
- bool completed;
- int result;
- cyg_drv_mutex_t lock;
- cyg_drv_cond_t signal;
-} usbs_callback_data;
-
-static void
-usbs_devtab_callback(void* arg, int result)
-{
- usbs_callback_data* callback_data = (usbs_callback_data*) arg;
- callback_data->result = result;
- callback_data->completed = true;
- cyg_drv_cond_signal(&(callback_data->signal));
-}
-
-Cyg_ErrNo
-usbs_devtab_cwrite(cyg_io_handle_t handle, const void* buf, cyg_uint32* size)
-{
- usbs_callback_data wait;
- cyg_devtab_entry_t* devtab_entry;
- usbs_tx_endpoint* endpoint;
- int result = ENOERR;
-
- CYG_REPORT_FUNCTION();
-
- wait.completed = 0;
- cyg_drv_mutex_init(&wait.lock);
- cyg_drv_cond_init(&wait.signal, &wait.lock);
-
- devtab_entry = (cyg_devtab_entry_t*) handle;
- CYG_CHECK_DATA_PTR( devtab_entry, "A valid endpoint must be supplied");
- endpoint = (usbs_tx_endpoint*) devtab_entry->priv;
-
- CYG_CHECK_DATA_PTR( endpoint, "The handle must correspond to a USB endpoint");
- CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The endpoint must have a start_tx function");
-
- endpoint->buffer = (unsigned char*) buf;
- endpoint->buffer_size = (int) *size;
- endpoint->complete_fn = &usbs_devtab_callback;
- endpoint->complete_data = (void*) &wait;
- (*endpoint->start_tx_fn)(endpoint);
-
- cyg_drv_mutex_lock(&wait.lock);
- while (!wait.completed) {
- cyg_drv_cond_wait(&wait.signal);
- }
- cyg_drv_mutex_unlock(&wait.lock);
- if (wait.result < 0) {
- result = wait.result;
- } else {
- *size = wait.result;
- }
-
- cyg_drv_cond_destroy(&wait.signal);
- cyg_drv_mutex_destroy(&wait.lock);
-
- CYG_REPORT_RETURN();
- return result;
-}
-
-Cyg_ErrNo
-usbs_devtab_cread(cyg_io_handle_t handle, void* buf, cyg_uint32* size)
-{
- usbs_callback_data wait;
- cyg_devtab_entry_t* devtab_entry;
- usbs_rx_endpoint* endpoint;
- int result = ENOERR;
-
- CYG_REPORT_FUNCTION();
-
- wait.completed = 0;
- cyg_drv_mutex_init(&wait.lock);
- cyg_drv_cond_init(&wait.signal, &wait.lock);
-
- devtab_entry = (cyg_devtab_entry_t*) handle;
- CYG_CHECK_DATA_PTR( devtab_entry, "A valid endpoint must be supplied");
- endpoint = (usbs_rx_endpoint*) devtab_entry->priv;
-
- CYG_CHECK_DATA_PTR( endpoint, "The handle must correspond to a USB endpoint");
- CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The endpoint must have a start_rx function");
-
- endpoint->buffer = (unsigned char*) buf;
- endpoint->buffer_size = (int) *size;
- endpoint->complete_fn = &usbs_devtab_callback;
- endpoint->complete_data = (void*) &wait;
- (*endpoint->start_rx_fn)(endpoint);
- cyg_drv_mutex_lock(&wait.lock);
- while (!wait.completed) {
- cyg_drv_cond_wait(&wait.signal);
- }
- cyg_drv_mutex_unlock(&wait.lock);
- if (wait.result < 0) {
- result = wait.result;
- } else {
- *size = wait.result;
- }
-
- cyg_drv_cond_destroy(&wait.signal);
- cyg_drv_mutex_destroy(&wait.lock);
-
- CYG_REPORT_RETURN();
- return result;
-}
-
-// ----------------------------------------------------------------------------
-// More devtab functions, this time related to ioctl() style operations.
-Cyg_ErrNo
-usbs_devtab_get_config(cyg_io_handle_t handle, cyg_uint32 code, void* buf, cyg_uint32* size)
-{
- return -EINVAL;
-}
-
-Cyg_ErrNo
-usbs_devtab_set_config(cyg_io_handle_t handle, cyg_uint32 code, const void* buf, cyg_uint32* size)
-{
- return -EINVAL;
-}
-
-#endif // CYGPKG_IO
-
-// ----------------------------------------------------------------------------
-// USB-specific functions that are useful for applications/packages which
-// do not want to use the devtab interface. These may get called in DSR
-// context.
-
-void
-usbs_start_rx(usbs_rx_endpoint* endpoint)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
- (*endpoint->start_rx_fn)(endpoint);
-}
-
-void
-usbs_start_rx_buffer(usbs_rx_endpoint* endpoint,
- unsigned char* buf, int size,
- void (*callback_fn)(void *, int), void* callback_arg)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
-
- endpoint->buffer = buf;
- endpoint->buffer_size = size;
- endpoint->complete_fn = callback_fn;
- endpoint->complete_data = callback_arg;
- (*endpoint->start_rx_fn)(endpoint);
-}
-
-void
-usbs_start_tx(usbs_tx_endpoint* endpoint)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
- (*endpoint->start_tx_fn)(endpoint);
-}
-
-void
-usbs_start_tx_buffer(usbs_tx_endpoint* endpoint,
- const unsigned char* buf, int size,
- void (*callback_fn)(void*, int), void *callback_arg)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
-
- endpoint->buffer = buf;
- endpoint->buffer_size = size;
- endpoint->complete_fn = callback_fn;
- endpoint->complete_data = callback_arg;
- (*endpoint->start_tx_fn)(endpoint);
-}
-
-void
-usbs_start(usbs_control_endpoint* endpoint)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->start_fn, "The USB endpoint should have a start function");
-
- (*endpoint->start_fn)(endpoint);
-}
-
-cyg_bool
-usbs_rx_endpoint_halted(usbs_rx_endpoint* endpoint)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- return endpoint->halted;
-}
-
-cyg_bool
-usbs_tx_endpoint_halted(usbs_tx_endpoint* endpoint)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- return endpoint->halted;
-}
-
-void
-usbs_set_rx_endpoint_halted(usbs_rx_endpoint* endpoint, cyg_bool halted)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
- (*endpoint->set_halted_fn)(endpoint, halted);
-}
-
-void
-usbs_set_tx_endpoint_halted(usbs_tx_endpoint* endpoint, cyg_bool halted)
-{
- CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
- CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
- (*endpoint->set_halted_fn)(endpoint, halted);
-}
-
-void
-usbs_start_rx_endpoint_wait(usbs_rx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
-{
- endpoint->buffer = (unsigned char*) 0;
- endpoint->buffer_size = 0;
- endpoint->complete_fn = callback_fn;
- endpoint->complete_data = callback_data;
- (*endpoint->start_rx_fn)(endpoint);
-}
-
-void
-usbs_start_tx_endpoint_wait(usbs_tx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
-{
- endpoint->buffer = (unsigned char*) 0;
- endpoint->buffer_size = 0;
- endpoint->complete_fn = callback_fn;
- endpoint->complete_data = callback_data;
- (*endpoint->start_tx_fn)(endpoint);
-}
-
-
-// ----------------------------------------------------------------------------
-// Handling of standard control messages. This will be invoked by
-// a USB device driver, usually at DSR level, to process any control
-// messages that cannot be handled by the hardware itself and that
-// have also not been handled by the application-specific handler
-// (if any).
-//
-// Because this function can run at DSR level performance is important.
-//
-// The various standard control messages are affected as follows:
-//
-// clear-feature: nothing can be done here about device requests to
-// disable remote-wakeup or about endpoint halt requests. It appears
-// to be legal to clear no features on an interface.
-//
-// get-configuration: if the device is not configured a single byte 0
-// should be returned. Otherwise this code assumes only one configuration
-// is supported and its id can be extracted from the enumeration data.
-// For more complicated devices get-configuration has to be handled
-// at a higher-level.
-//
-// get-descriptor: this is the big one. It is used to obtain
-// the enumeration data. An auxiliary refill function is needed.
-//
-// get-interface: this can be used to identify the current variant
-// for a given interface within a configuration. For simple devices
-// there will be only interface, 0. For anything more complicated
-// higher level code will have to take care of the request.
-//
-// get-status. Much the same as clear-feature.
-//
-// set-address. Must be handled at the device driver level.
-//
-// set-configuration: a value of 0 is used to deconfigure the device,
-// which can be handled here. Otherwise this code assumes that only
-// a single configuration is supported and enables that. For anything
-// more complicated higher-level code has to handle this request.
-//
-// set-descriptor: used to update the enumeration data. This is not
-// supported here, although higher-level code can choose to do so.
-//
-// set-feature. See clear-feature and get-status.
-//
-// set-interface. Variant interfaces are not supported by the
-// base code so this request has to be handled at a higher level.
-//
-// synch-frame. This is only relevant for isochronous transfers
-// which are not yet supported, and anyway it is not clear what
-// could be done about these requests here.
-
-// This refill function handles GET_DESCRIPTOR requests for a
-// configuration. For details of the control_buffer usage see
-// the relevant code in the main callback.
-static void
-usbs_configuration_descriptor_refill(usbs_control_endpoint* endpoint)
-{
- usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
- int length = (req->length_hi << 8) | req->length_lo;
- int sent = (req->index_hi << 8) | req->index_lo;
- int current_interface = req->type;
- int last_interface = req->request;
- int current_endpoint = req->value_lo;
- int last_endpoint = req->value_hi;
- cyg_bool done = false;
-
- if (current_endpoint == last_endpoint) {
- // The next transfer should be a single interface - unless we have already finished.
- if (current_interface == last_interface) {
- done = true;
- } else {
- endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->interfaces[current_interface]);
- if (USB_INTERFACE_DESCRIPTOR_LENGTH >= (length - sent)) {
- endpoint->buffer_size = length - sent;
- done = true;
- } else {
- endpoint->buffer_size = USB_INTERFACE_DESCRIPTOR_LENGTH;
- sent += USB_INTERFACE_DESCRIPTOR_LENGTH;
- // Note that an interface with zero endpoints is ok. We'll just move
- // to the next interface in the next call.
- last_endpoint = current_endpoint +
- endpoint->enumeration_data->interfaces[current_interface].number_endpoints;
- current_interface++;
- }
- }
- } else {
- // The next transfer should be a single endpoint. The
- // endpoints are actually contiguous array elements
- // but may not be packed, so they have to be transferred
- // one at a time.
- endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->endpoints[current_endpoint]);
- if ((sent + USB_ENDPOINT_DESCRIPTOR_LENGTH) >= length) {
- endpoint->buffer_size = length - sent;
- done = true;
- } else {
- endpoint->buffer_size = USB_ENDPOINT_DESCRIPTOR_LENGTH;
- current_endpoint ++;
- }
- }
-
- if (done) {
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- } else {
- req->type = (unsigned char) current_interface;
- req->value_lo = (unsigned char) current_endpoint;
- req->value_hi = (unsigned char) last_endpoint;
- req->index_hi = (unsigned char) (sent >> 8);
- req->index_lo = (unsigned char) (sent & 0x00FF);
- }
-}
-
-usbs_control_return
-usbs_handle_standard_control(usbs_control_endpoint* endpoint)
-{
- usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
- usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
- int length;
- int direction;
- int recipient;
-
- length = (req->length_hi << 8) | req->length_lo;
- direction = req->type & USB_DEVREQ_DIRECTION_MASK;
- recipient = req->type & USB_DEVREQ_RECIPIENT_MASK;
-
- if (USB_DEVREQ_CLEAR_FEATURE == req->request) {
-
- if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
- // The host should expect no data back, the device must
- // be configured, and there are no defined features to clear.
- if ((0 == length) &&
- (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
- (0 == req->value_lo)) {
-
- int interface_id = req->index_lo;
- CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
- "Higher level code should have handled this request");
-
- if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
- result = USBS_CONTROL_RETURN_HANDLED;
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
-
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
- }
-
- } else if (USB_DEVREQ_GET_CONFIGURATION == req->request) {
-
- // Return a single byte 0 if the device is not currently
- // configured. Otherwise assume a single configuration
- // in the enumeration data and return its id.
- if ((1 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
-
- if (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) {
- CYG_ASSERT( 1 == endpoint->enumeration_data->device.number_configurations, \
- "Higher level code should have handled this request");
- endpoint->control_buffer[0] = endpoint->enumeration_data->configurations[0].configuration_id;
- } else {
- endpoint->control_buffer[0] = 0;
- }
- endpoint->buffer = endpoint->control_buffer;
- endpoint->buffer_size = 1;
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
- result = USBS_CONTROL_RETURN_HANDLED;
-
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
-
- } else if (USB_DEVREQ_GET_DESCRIPTOR == req->request) {
-
- // The descriptor type is in value_hi. The descriptor index
- // is in value_lo.
- // The hsot must expect at least one byte of data.
- if ((0 == length) || (USB_DEVREQ_DIRECTION_IN != direction)) {
-
- result = USBS_CONTROL_RETURN_STALL;
-
- } else if (USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE == req->value_hi) {
-
- // The device descriptor is easy, it is a single field in the
- // enumeration data.
- endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->device);
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
- if (length < USB_DEVICE_DESCRIPTOR_LENGTH) {
- endpoint->buffer_size = length;
- } else {
- endpoint->buffer_size = USB_DEVICE_DESCRIPTOR_LENGTH;
- }
- result = USBS_CONTROL_RETURN_HANDLED;
-
- } else if (USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION == req->value_hi) {
-
- // This is where things get messy. We need to supply the
- // specified configuration data, followed by some number of
- // interfaces and endpoints. Plus there are length limits
- // to consider. First check that the specified index is valid.
- if (req->value_lo >= endpoint->enumeration_data->device.number_configurations) {
- result = USBS_CONTROL_RETURN_STALL;
- } else {
- // No such luck. OK, supplying the initial block is easy.
- endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->configurations[req->value_lo]);
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
-
- // How much data was actually requested. If only the
- // configuration itself is of interest then there is
- // no need to worry about the rest.
- if (length <= USB_CONFIGURATION_DESCRIPTOR_LENGTH) {
- endpoint->buffer_size = length;
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- } else {
- int i, j;
- int start_interface;
- int start_endpoint;
- endpoint->buffer_size = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
- endpoint->fill_buffer_fn = &usbs_configuration_descriptor_refill;
-
- // The descriptor refill_fn needs to know what next to transfer.
- // The desired interfaces and endpoints will be contiguous so
- // we need to keep track of the following:
- // 1) the current interface index being transferred.
- // 2) the last interface that should be transferred.
- // 3) the current endpoint index that should be transferred.
- // 4) the last endpoint index. This marks interface/endpoint transitions.
- // 5) how much has been transferred to date.
- // This information can be held in the control_buffer,
- // with the length field being preserved.
- start_interface = 0;
- start_endpoint = 0;
- // For all configurations up to the desired one.
- for (i = 0; i < req->value_lo; i++) {
- int config_interfaces = endpoint->enumeration_data->configurations[i].number_interfaces;
-
- // For all interfaces in this configuration.
- for (j = 0; j < config_interfaces; j++) {
- // Add the number of endpoints in this interface to the current count.
- CYG_ASSERT( (j + start_interface) < endpoint->enumeration_data->total_number_interfaces, \
- "Valid interface count in enumeration data");
- start_endpoint += endpoint->enumeration_data->interfaces[j + start_interface].number_endpoints;
- }
- // And update the index for the starting interface.
- start_interface += config_interfaces;
- }
- CYG_ASSERT( start_interface < endpoint->enumeration_data->total_number_interfaces, \
- "Valid interface count in enumeration data");
- CYG_ASSERT( ((0 == endpoint->enumeration_data->total_number_endpoints) && (0 == start_endpoint)) || \
- (start_endpoint < endpoint->enumeration_data->total_number_endpoints), \
- "Valid endpoint count in enumeration data");
-
- req->type = (unsigned char) start_interface;
- req->request = (unsigned char) (start_interface +
- endpoint->enumeration_data->configurations[req->value_lo].number_interfaces
- );
- req->value_lo = (unsigned char) start_endpoint;
- req->value_hi = (unsigned char) start_endpoint;
- req->index_lo = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
- req->index_hi = 0;
- }
- result = USBS_CONTROL_RETURN_HANDLED;
- }
-
-
- } else if (USB_DEVREQ_DESCRIPTOR_TYPE_STRING == req->value_hi) {
-
- // As long as the index is valid, the rest is easy since
- // the strings are just held in a simple array.
- // NOTE: if multiple languages have to be supported
- // then things get more difficult.
- if (req->value_lo >= endpoint->enumeration_data->total_number_strings) {
- result = USBS_CONTROL_RETURN_STALL;
- } else {
- endpoint->buffer = (unsigned char*) endpoint->enumeration_data->strings[req->value_lo];
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
-
- if (length < endpoint->buffer[0]) {
- endpoint->buffer_size = length;
- } else {
- endpoint->buffer_size = endpoint->buffer[0];
- }
- result = USBS_CONTROL_RETURN_HANDLED;
- }
-
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
-
- } else if (USB_DEVREQ_GET_INTERFACE == req->request) {
-
- if ((1 != length) ||
- (USB_DEVREQ_DIRECTION_IN != direction) ||
- (USBS_STATE_CONFIGURED != (endpoint->state & USBS_STATE_MASK))) {
-
- result = USBS_CONTROL_RETURN_STALL;
-
- } else {
- int interface_id;
-
- CYG_ASSERT( (1 == endpoint->enumeration_data->device.number_configurations) && \
- (1 == endpoint->enumeration_data->total_number_interfaces), \
- "Higher level code should have handled this request");
-
- interface_id = (req->index_hi << 8) | req->index_lo;
- if (interface_id != endpoint->enumeration_data->interfaces[0].interface_id) {
- result = USBS_CONTROL_RETURN_STALL;
- } else {
- endpoint->control_buffer[0] = endpoint->enumeration_data->interfaces[0].alternate_setting;
- endpoint->buffer = endpoint->control_buffer;
- endpoint->buffer_size = 1;
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
- result = USBS_CONTROL_RETURN_HANDLED;
- }
- }
-
- } else if (USB_DEVREQ_GET_STATUS == req->request) {
-
- if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
- // The host should expect two bytes back, the device must
- // be configured, the interface number must be valid.
- // The host should expect no data back, the device must
- // be configured, and there are no defined features to clear.
- if ((2 == length) &&
- (USB_DEVREQ_DIRECTION_IN == direction) &&
- (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK))) {
-
- int interface_id = req->index_lo;
- CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
- "Higher level code should have handled this request");
-
- if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
-
- // The request is legit, but there are no defined features for an interface...
- endpoint->control_buffer[0] = 0;
- endpoint->control_buffer[1] = 0;
- endpoint->buffer = endpoint->control_buffer;
- endpoint->buffer_size = 2;
- endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
- endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
- result = USBS_CONTROL_RETURN_HANDLED;
-
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
- }
-
- } else if (USB_DEVREQ_SET_CONFIGURATION == req->request) {
-
- // Changing to configuration 0 means a state change from
- // configured to addressed. Changing to anything else means a
- // state change to configured. Both involve invoking the
- // state change callback. If there are multiple configurations
- // to choose from then this request has to be handled at
- // a higher level.
- int old_state = endpoint->state;
- if (0 == req->value_lo) {
- endpoint->state = USBS_STATE_ADDRESSED;
- if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
- (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
- USBS_STATE_CHANGE_DECONFIGURED, old_state);
- }
- result = USBS_CONTROL_RETURN_HANDLED;
-
- } else {
- CYG_ASSERT(1 == endpoint->enumeration_data->device.number_configurations, \
- "Higher level code should have handled this request");
- if (req->value_lo == endpoint->enumeration_data->configurations[0].configuration_id) {
- endpoint->state = USBS_STATE_CONFIGURED;
- if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
- (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
- USBS_STATE_CHANGE_CONFIGURED, old_state);
- }
- result = USBS_CONTROL_RETURN_HANDLED;
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
- }
-
- } else if (USB_DEVREQ_SET_FEATURE == req->request) {
-
- if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
- // The host should expect no data back, the device must
- // be configured, and there are no defined features to clear.
- if ((0 == length) &&
- (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
- (0 == req->value_lo)) {
-
- int interface_id = req->index_lo;
- CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
- "Higher level code should have handled this request");
-
- if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
- result = USBS_CONTROL_RETURN_HANDLED;
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
-
- } else {
- result = USBS_CONTROL_RETURN_STALL;
- }
- }
-
- }
-
- return result;
-}
Index: slave/v2_0/host/configure
===================================================================
--- slave/v2_0/host/configure (revision 174)
+++ slave/v2_0/host/configure (nonexistent)
@@ -1,2233 +0,0 @@
-#! /bin/sh
-
-# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-
-# Defaults:
-ac_help=
-ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
- --enable-maintainer-mode enable make rules and dependencies not useful
- (and sometimes confusing) to the casual installer"
-ac_help="$ac_help
- --enable-debug do a debug rather than a release build"
-ac_help="$ac_help
- --enable-ansi do an ANSI rather than a unicode build"
-ac_help="$ac_help
- --with-tcl= location of Tcl header and libraries"
-ac_help="$ac_help
- --with-tcl-version= version of Tcl to be used"
-ac_help="$ac_help
- --with-tcl-header= location of Tcl header"
-ac_help="$ac_help
- --with-tcl-lib= location of Tcl libraries"
-
-# Initialize some variables set by options.
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
-exec_prefix=NONE
-host=NONE
-no_create=
-nonopt=NONE
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-target=NONE
-verbose=
-x_includes=NONE
-x_libraries=NONE
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
-ac_prev=
-for ac_option
-do
-
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case "$ac_option" in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
-
- -disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
-
- -with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "with_${ac_package}='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
-
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
- ;;
-
- *)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>./config.log
-
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
-
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
-do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
- esac
-done
-
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=usbhost.c
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
- else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
- fi
-fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
-
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
-else
- echo "creating cache $cache_file"
- > $cache_file
-fi
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-
-
-ac_aux_dir=
-for ac_dir in ../../../../../../acsupport $srcdir/../../../../../../acsupport; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in ../../../../../../acsupport $srcdir/../../../../../../acsupport" 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-
-
- echo $ac_n "checking that a separate build tree is being used""... $ac_c" 1>&6
-echo "configure:563: checking that a separate build tree is being used" >&5
- ecos_cwd=`/bin/pwd`
- if test "${srcdir}" = "." ; then
- srcdir=${ecos_cwd}
- fi
- if test "${ecos_cwd}" = "${srcdir}" ; then
- echo "$ac_t""no" 1>&6
- { echo "configure: error: This configure script should not be run inside the source tree. Instead please use a separate build tree" 1>&2; exit 1; }
- else
- echo "$ac_t""yes" 1>&6
- fi
-
-
-# Make sure we can run config.sub.
-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:582: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:614: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
-fi
-echo "$ac_t""$INSTALL" 1>&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:667: checking whether build environment is sane" >&5
-# Just in case
-sleep 1
-echo timestamp > conftestfile
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
- if test "$*" = "X"; then
- # -L didn't work.
- set X `ls -t $srcdir/configure conftestfile`
- fi
- if test "$*" != "X $srcdir/configure conftestfile" \
- && test "$*" != "X conftestfile $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
-alias in your environment" 1>&2; exit 1; }
- fi
-
- test "$2" = conftestfile
- )
-then
- # Ok.
- :
-else
- { echo "configure: error: newly created file is older than distributed files!
-Check your system clock" 1>&2; exit 1; }
-fi
-rm -f conftest*
-echo "$ac_t""yes" 1>&6
-if test "$program_transform_name" = s,x,x,; then
- program_transform_name=
-else
- # Double any \ or $. echo might interpret backslashes.
- cat <<\EOF_SED > conftestsed
-s,\\,\\\\,g; s,\$,$$,g
-EOF_SED
- program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
- rm -f conftestsed
-fi
-test "$program_prefix" != NONE &&
- program_transform_name="s,^,${program_prefix},; $program_transform_name"
-# Use a double $ so make ignores it.
-test "$program_suffix" != NONE &&
- program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
-
-# sed with no file args requires a program.
-test "$program_transform_name" = "" && program_transform_name="s,x,x,"
-
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:724: checking whether ${MAKE-make} sets \${MAKE}" >&5
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftestmake <<\EOF
-all:
- @echo 'ac_maketemp="${MAKE}"'
-EOF
-# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
-if test -n "$ac_maketemp"; then
- eval ac_cv_prog_make_${ac_make}_set=yes
-else
- eval ac_cv_prog_make_${ac_make}_set=no
-fi
-rm -f conftestmake
-fi
-if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- SET_MAKE=
-else
- echo "$ac_t""no" 1>&6
- SET_MAKE="MAKE=${MAKE-make}"
-fi
-
-
-PACKAGE=usbhost
-
-VERSION=0.1
-
-if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
- { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
-fi
-
-
-
-missing_dir=`cd $ac_aux_dir && pwd`
-echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:763: checking for working aclocal" >&5
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if (aclocal --version) < /dev/null > /dev/null 2>&1; then
- ACLOCAL=aclocal
- echo "$ac_t""found" 1>&6
-else
- ACLOCAL="$missing_dir/missing aclocal"
- echo "$ac_t""missing" 1>&6
-fi
-
-echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:776: checking for working autoconf" >&5
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if (autoconf --version) < /dev/null > /dev/null 2>&1; then
- AUTOCONF=autoconf
- echo "$ac_t""found" 1>&6
-else
- AUTOCONF="$missing_dir/missing autoconf"
- echo "$ac_t""missing" 1>&6
-fi
-
-echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:789: checking for working automake" >&5
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if (automake --version) < /dev/null > /dev/null 2>&1; then
- AUTOMAKE=automake
- echo "$ac_t""found" 1>&6
-else
- AUTOMAKE="$missing_dir/missing automake"
- echo "$ac_t""missing" 1>&6
-fi
-
-echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:802: checking for working autoheader" >&5
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if (autoheader --version) < /dev/null > /dev/null 2>&1; then
- AUTOHEADER=autoheader
- echo "$ac_t""found" 1>&6
-else
- AUTOHEADER="$missing_dir/missing autoheader"
- echo "$ac_t""missing" 1>&6
-fi
-
-echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:815: checking for working makeinfo" >&5
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
- MAKEINFO=makeinfo
- echo "$ac_t""found" 1>&6
-else
- MAKEINFO="$missing_dir/missing makeinfo"
- echo "$ac_t""missing" 1>&6
-fi
-
-
-echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
-echo "configure:829: checking whether to enable maintainer-specific portions of Makefiles" >&5
- # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
-if test "${enable_maintainer_mode+set}" = set; then
- enableval="$enable_maintainer_mode"
- USE_MAINTAINER_MODE=$enableval
-else
- USE_MAINTAINER_MODE=no
-fi
-
- echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
-
-
-if test $USE_MAINTAINER_MODE = yes; then
- MAINTAINER_MODE_TRUE=
- MAINTAINER_MODE_FALSE='#'
-else
- MAINTAINER_MODE_TRUE='#'
- MAINTAINER_MODE_FALSE=
-fi
- MAINT=$MAINTAINER_MODE_TRUE
-
-
-
-case "${host}" in
- *-*-linux-gnu* ) SUPPORTED="yes";;
- * ) SUPPORTED="no"
-esac
-
-if test "${SUPPORTED}" = "no" ; then
- echo "configure: warning: USB testing is only supported on Linux hosts" 1>&2
-else
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:863: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:893: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
- fi
-fi
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:944: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
- ;;
- esac
- fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:976: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 987 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:992: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
- else
- ac_cv_prog_cc_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:1018: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:1023: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
-else
- ac_cv_prog_gcc=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
-else
- GCC=
-fi
-
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1051: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
-else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-
- for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
-do
-# Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1087: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CXX"; then
- ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CXX="$ac_prog"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CXX="$ac_cv_prog_CXX"
-if test -n "$CXX"; then
- echo "$ac_t""$CXX" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-test -n "$CXX" && break
-done
-test -n "$CXX" || CXX="gcc"
-
-
-echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:1119: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
-
-ac_ext=C
-# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cxx_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 1130 "configure"
-#include "confdefs.h"
-
-int main(){return(0);}
-EOF
-if { (eval echo configure:1135: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cxx_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cxx_cross=no
- else
- ac_cv_prog_cxx_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cxx_works=no
-fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
-if test $ac_cv_prog_cxx_works = no; then
- { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:1161: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
-cross_compiling=$ac_cv_prog_cxx_cross
-
-echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
-echo "configure:1166: checking whether we are using GNU C++" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gxx=yes
-else
- ac_cv_prog_gxx=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gxx" 1>&6
-
-if test $ac_cv_prog_gxx = yes; then
- GXX=yes
-else
- GXX=
-fi
-
-ac_test_CXXFLAGS="${CXXFLAGS+set}"
-ac_save_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS=
-echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
-echo "configure:1194: checking whether ${CXX-g++} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.cc
-if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
- ac_cv_prog_cxx_g=yes
-else
- ac_cv_prog_cxx_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
-if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS="$ac_save_CXXFLAGS"
-elif test $ac_cv_prog_cxx_g = yes; then
- if test "$GXX" = yes; then
- CXXFLAGS="-g -O2"
- else
- CXXFLAGS="-g"
- fi
-else
- if test "$GXX" = yes; then
- CXXFLAGS="-O2"
- else
- CXXFLAGS=
- fi
-fi
-
-for ac_declaration in \
- ''\
- '#include ' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat > conftest.$ac_ext <
-$ac_declaration
-int main() {
-exit (42);
-; return 0; }
-EOF
-if { (eval echo configure:1243: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- :
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- continue
-fi
-rm -f conftest*
- cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- break
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-done
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-
-
- echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:1277: checking whether ln -s works" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- rm -f conftestdata
-if ln -s X conftestdata 2>/dev/null
-then
- rm -f conftestdata
- ac_cv_prog_LN_S="ln -s"
-else
- ac_cv_prog_LN_S=ln
-fi
-fi
-LN_S="$ac_cv_prog_LN_S"
-if test "$ac_cv_prog_LN_S" = "ln -s"; then
- echo "$ac_t""yes" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- echo $ac_n "checking for object suffix""... $ac_c" 1>&6
-echo "configure:1298: checking for object suffix" >&5
-if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- rm -f conftest*
-echo 'int i = 1;' > conftest.$ac_ext
-if { (eval echo configure:1304: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- for ac_file in conftest.*; do
- case $ac_file in
- *.c) ;;
- *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
-else
- { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_objext" 1>&6
-OBJEXT=$ac_cv_objext
-ac_objext=$ac_cv_objext
-
- echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
-echo "configure:1322: checking for Cygwin environment" >&5
-if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_cygwin=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_cygwin=no
-fi
-rm -f conftest*
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_cygwin" 1>&6
-CYGWIN=
-test "$ac_cv_cygwin" = yes && CYGWIN=yes
-echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
-echo "configure:1355: checking for mingw32 environment" >&5
-if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_mingw32=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_mingw32=no
-fi
-rm -f conftest*
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_mingw32" 1>&6
-MINGW32=
-test "$ac_cv_mingw32" = yes && MINGW32=yes
-
-
-echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
-echo "configure:1386: checking for executable suffix" >&5
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
- ac_cv_exeext=.exe
-else
- rm -f conftest*
- echo 'int main () { return 0; }' > conftest.$ac_ext
- ac_cv_exeext=
- if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
- for file in conftest.*; do
- case $file in
- *.c | *.o | *.obj) ;;
- *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
- esac
- done
- else
- { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
- fi
- rm -f conftest*
- test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
-fi
-fi
-
-EXEEXT=""
-test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
-echo "$ac_t""${ac_cv_exeext}" 1>&6
-ac_exeext=$EXEEXT
-
-
- ecos_CFLAGS=""
- ecos_CXXFLAGS=""
- ecos_LDADD=""
- ecos_INCLUDES=""
- ecos_LIBS=""
-
-
-
-
-
-
-
-
-
-
-
- echo $ac_n "checking "for Visual C++"""... $ac_c" 1>&6
-echo "configure:1434: checking "for Visual C++"" >&5
- MSVC="no";
- if test "${CC}" = "cl" ; then
- MSVC="yes"
- CXX="cl"
- MSVC_SRCDIR=${srcdir}
-
-
-
- if test "${MSVC}" = "yes" ; then
- MSVC_SRCDIR=`cygpath -w ${MSVC_SRCDIR} | tr \\\\\\\\ /`
- fi
-
-
- ecos_INCLUDES="${ecos_INCLUDES} \"-I${MSVC_SRCDIR}\""
- ecos_LDADD="-link"
- ecos_LIBS="advapi32.lib"
- fi
-
-
-if test "${MSVC}" = "yes"; then
- MSVC_TRUE=
- MSVC_FALSE='#'
-else
- MSVC_TRUE='#'
- MSVC_FALSE=
-fi
- if test "${MSVC}" = "yes" ; then
- echo "$ac_t""unfortunately yes" 1>&6
- else
- echo "$ac_t""no" 1>&6
- fi
-
-
-
-
-
-
-
- echo $ac_n "checking "the default compiler flags"""... $ac_c" 1>&6
-echo "configure:1474: checking "the default compiler flags"" >&5
-
- ecosflags_enable_debug="no"
- # Check whether --enable-debug or --disable-debug was given.
-if test "${enable_debug+set}" = set; then
- enableval="$enable_debug"
- case "${enableval}" in
- yes) ecosflags_enable_debug="yes" ;;
- *) ecosflags_enable_debug="no" ;;
- esac
-fi
-
-
- ecosflags_enable_ansi="no"
- if test "${MSVC}" = "yes" ; then
- # Check whether --enable-ansi or --disable-ansi was given.
-if test "${enable_ansi+set}" = set; then
- enableval="$enable_ansi"
- case "${enableval}" in
- yes) ecosflags_enable_ansi="yes" ;;
- *) ecosflags_enable_ansi="no" ;;
- esac
-fi
-
- fi
-
- if test "${GCC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -pipe -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -pipe -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual"
- elif test "${MSVC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -nologo -W3"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -nologo -W3 -GR -GX"
- else
- { echo "configure: error: "default flags for ${CC} are not known"" 1>&2; exit 1; }
- fi
-
- if test "${ecosflags_enable_debug}" = "yes" ; then
- if test "${GCC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -g -O0"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -g -O0"
- elif test "${MSVC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -MDd -Zi"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -MDd -Zi"
- fi
- else
- if test "${GCC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -O0"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -O0"
- elif test "${MSVC}" = "yes" ; then
- ecos_CFLAGS="${ecos_CFLAGS} -MD -O2"
- ecos_CXXFLAGS="${ecos_CXXFLAGS} -MD -O2"
- fi
- fi
-
- CFLAGS="${ac_save_CFLAGS}"
- CXXFLAGS="${ac_save_CXXFLAGS}"
-
- echo "$ac_t""done" 1>&6
-
-
-
- package_dir=`cd ${srcdir} && /bin/pwd`
- PACKAGE_VERSION=`dirname ${package_dir}`
- PACKAGE_VERSION=`basename ${PACKAGE_VERSION}`
-
- package_dir=`dirname ${package_dir}`
- package_dir=`dirname ${package_dir}`
-
- possibles="${package_dir}/.. ${package_dir}/../.. ${package_dir}/../../.. ${package_dir}/../../../.."
- possibles="${possibles} ${package_dir}/../../../../.. ${package_dir}/../../../../../.."
-
- repository_root=""
- for i in ${possibles}; do
- if test -d "$i/"acsupport""; then
- repository_root=$i
- break
- fi
- done
-
- if test "${repository_root}" = "" ; then
- { echo "configure: error: Failed to identify this package's position within the eCos repository" 1>&2; exit 1; }
- fi
- ECOS_REPOSITORY=`cd "${repository_root}/packages/pkgconf/.." && /bin/pwd`
-
- PACKAGE_DIR=`echo ${package_dir} | sed -e "s:${ECOS_REPOSITORY}/::"`
-
- PACKAGE_INSTALL="${PACKAGE_DIR}/${PACKAGE_VERSION}"
-
-
-
-
-
-
-
-
-
-
-
-
- ecos_tk_libs=""
- ecos_tk_libdir=""
-
- echo $ac_n "checking for Tcl installation""... $ac_c" 1>&6
-echo "configure:1577: checking for Tcl installation" >&5
- # Check whether --with-tcl or --without-tcl was given.
-if test "${with_tcl+set}" = set; then
- withval="$with_tcl"
- :
-fi
-
- # Check whether --with-tcl-version or --without-tcl-version was given.
-if test "${with_tcl_version+set}" = set; then
- withval="$with_tcl_version"
- :
-fi
-
-
- if test "${MSVC}" = "yes" ; then
- # Check whether --with-tcl-header or --without-tcl-header was given.
-if test "${with_tcl_header+set}" = set; then
- withval="$with_tcl_header"
- :
-fi
-
- # Check whether --with-tcl-lib or --without-tcl-lib was given.
-if test "${with_tcl_lib+set}" = set; then
- withval="$with_tcl_lib"
- :
-fi
-
- ecos_tcl_incdir=""
- ecos_tcl_libdir=""
- if test "${with_tcl_version+set}" != set ; then
- { echo "configure: error: You must specify a Tcl version using --with-tcl-version=" 1>&2; exit 1; }
- fi
- if test "${with_tcl_header+set}" = set ; then
- ecos_tcl_incdir=${with_tcl_header}
- elif test "${with_tcl+set}" = set ; then
- ecos_tcl_incdir="${with_tcl}/include"
- else
- { echo "configure: error: You must specify a Tcl installation with either --with-tcl= or --with-tcl-header=" 1>&2; exit 1; }
- fi
- if test "${with_tcl_lib+set}" = set; then
- ecos_tcl_libdir=${with_tcl_lib}
- elif test "${with_tcl+set}" = set; then
- ecos_tcl_libdir="${with_tcl}/lib"
- else
- { echo "configure: error: You must specify a Tcl installation with either --with-tcl= or --with-tcl-lib=" 1>&2; exit 1; }
- fi
-
- if test \! -r "${ecos_tcl_incdir}/tcl.h" ; then
- { echo "configure: error: unable to locate Tcl header file tcl.h" 1>&2; exit 1; }
- fi
-
-
-
-
- if test "${MSVC}" = "yes" ; then
- ecos_tcl_incdir=`cygpath -w ${ecos_tcl_incdir} | tr \\\\\\\\ /`
- fi
-
-
-
-
- if test "${MSVC}" = "yes" ; then
- ecos_tcl_libdir=`cygpath -w ${ecos_tcl_libdir} | tr \\\\\\\\ /`
- fi
-
- ecos_INCLUDES="${ecos_INCLUDES} \"-I${ecos_tcl_incdir}\""
- ecos_LIBS="${ecos_LIBS} tcl${with_tcl_version}.lib"
- ecos_LDADD="${ecos_LDADD} \"-libpath=${ecos_tcl_libdir}\""
-
- ecos_tk_libs=""
-
- else
- possibles=""
- if test "${with_tcl+set}" = set ; then
- possibles="${with_tcl}/lib"
- if test "${with_tcl_version+set}" = set ; then
- possibles="${possibles} ${with_tcl}/lib/tcl${with_tcl_version}"
- fi
- fi
- possibles="${possibles} ${prefix}/lib"
- if test "${with_tcl_version+set}" = set ; then
- possibles="${possibles} ${prefix}/lib/tcl${with_tcl_version}"
- fi
- possibles="${possibles} /usr/lib"
- if test "${with_tcl_version+set}" = set ; then
- possibles="${possibles} /usr/lib/tcl${with_tcl_version}"
- fi
-
- tclconfig=""
- for i in ${possibles}; do
- if test -r "$i/"tclConfig.sh""; then
- tclconfig=$i
- break
- fi
- done
-
- if test \! -r "${tclconfig}/tclConfig.sh" ; then
- { echo "configure: error: unable to locate Tcl configuration file tclConfig.sh" 1>&2; exit 1; }
- else
- . ${tclconfig}/tclConfig.sh
-
- if test -z "${TCL_INC_DIR}" ; then
- ecos_tcl_incdir="${TCL_PREFIX}/include"
- else
- ecos_tcl_incdir="${TCL_INC_DIR}"
- fi
- if test \! -r "${ecos_tcl_incdir}/tcl.h" ; then
- { echo "configure: error: unable to locate Tcl header file tcl.h" 1>&2; exit 1; }
- else
- if test "${ecos_tcl_incdir}" != "/usr/include" ; then
- ecos_INCLUDES="${ecos_INCLUDES} -I${ecos_tcl_incdir}"
- fi
- fi
-
- if test -z "${TCL_LIB_SPEC}" -a "${with_tcl_version+set}" = set ; then
-
- libtcl=""
- for i in ${possibles}; do
- if test -r "$i/"libtcl${with_tcl_version}.a""; then
- libtcl=$i
- break
- fi
- done
-
- if test -r "${libtcl}/libtcl${with_tcl_version}.a" ; then
- TCL_LIB_SPEC="-L${libtcl} -ltcl${with_tcl_version}"
- fi
- fi
- if test -z "${TCL_LIB_SPEC}" ; then
-
- libtcl=""
- for i in ${possibles}; do
- if test -r "$i/"libtcl.a""; then
- libtcl=$i
- break
- fi
- done
-
- if test -r "${libtcl}/libtcl.a" ; then
- TCL_LIB_SPEC="-L${libtcl} -ltcl"
- fi
- fi
- if test -z "${TCL_LIB_SPEC}" ; then
- { echo "configure: error: ${tclconfig}/tclConfig.sh does not define TCL_LIB_SPEC" 1>&2; exit 1; }
- fi
- ecos_LIBS="${ecos_LIBS} ${TCL_LIB_SPEC}"
-
- possibles=`echo ${possibles} | sed -e 's,tcl,tk,g'`
-
- tkconfig=""
- for i in ${possibles}; do
- if test -r "$i/"tkConfig.sh""; then
- tkconfig=$i
- break
- fi
- done
-
- if test \! -r "${tkconfig}/tkConfig.sh" ; then
- { echo "configure: error: unable to locate Tk config file tkConfig.sh" 1>&2; exit 1; }
- else
- . ${tkconfig}/tkConfig.sh
- if test -z "${TK_INC_DIR}" ; then
- if test "${TK_PREFIX}" = "/usr" ; then
- ecos_tk_includes="${TK_XINCLUDES}"
- else
- ecos_tk_includes="-I${TK_PREFIX}/include ${TK_XINCLUDES}"
- fi
- else
- ecos_tk_includes="-I${TK_INC_DIR} ${TK_XINCLUDES}"
- fi
-
- if test -z "${TK_LIB_SPEC}" -a "${with_tcl_version+set}" = set ; then
-
- libtk=""
- for i in ${possibles}; do
- if test -r "$i/"libtk${with_tcl_version}.a""; then
- libtk=$i
- break
- fi
- done
-
- if test -r "${libtk}/libtk${with_tcl_version}.a" ; then
- TK_LIB_SPEC="-L${libtk} -ltk${with_tcl_version}"
- fi
- fi
- if test -z "${TK_LIB_SPEC}" ; then
-
- libtk=""
- for i in ${possibles}; do
- if test -r "$i/"libtk.a""; then
- libtk=$i
- break
- fi
- done
-
- if test -r "${libtk}/libtk.a" ; then
- TK_LIB_SPEC="-L${libtk} -ltk"
- fi
- fi
- if test -z "${TK_LIB_SPEC}" ; then
- { echo "configure: error: ${tkconfig}/tkConfig.sh does not define TK_LIB_SPEC" 1>&2; exit 1; }
- fi
- ecos_tk_libs="${TK_LIB_SPEC} ${TK_LIBS}"
- fi
- fi
- fi
-
- echo "$ac_t""-I${ecos_tcl_incdir} ${TCL_LIB_SPEC}" 1>&6
-
-
-
- if test "${TK_MAJOR_VERSION}" = "8" ; then
- if test ${TK_MINOR_VERSION} -lt 2 ; then
- echo "configure: warning: Version 8.2 or greater of Tcl/Tk is required" 1>&2
- SUPPORTED="no"
- fi
- fi
- if test "${SUPPORTED}" = "yes" ; then
- echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1796: checking how to run the C preprocessor" >&5
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1817: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1834: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1851: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
-fi
-rm -f conftest*
-fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
-fi
- CPP="$ac_cv_prog_CPP"
-else
- ac_cv_prog_CPP="$CPP"
-fi
-echo "$ac_t""$CPP" 1>&6
-
-for ac_hdr in "linux/usb.h" "linux/usbdevice_fs.h"
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1879: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1889: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <&6
-SUPPORTED="no"
-fi
-done
-
- if test "${SUPPORTED}" = "no" ; then
- echo "configure: warning: Required Linux kernel functionality does not appear to be available" 1>&2
- fi
- fi
-fi
-
-if test "${SUPPORTED}" = "no" ; then
- echo "configure: warning: The USB testing support cannot be built on this platform." 1>&2
-fi
-
-
-
-if test "${SUPPORTED}" = "yes"; then
- SUPPORTED_TRUE=
- SUPPORTED_FALSE='#'
-else
- SUPPORTED_TRUE='#'
- SUPPORTED_FALSE=
-fi
-
-
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
-fi
-
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
-
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS </dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
-do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
-
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-
-trap 'rm -fr `echo "Makefile:Makefile.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@host@%$host%g
-s%@host_alias@%$host_alias%g
-s%@host_cpu@%$host_cpu%g
-s%@host_vendor@%$host_vendor%g
-s%@host_os@%$host_os%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@PACKAGE@%$PACKAGE%g
-s%@VERSION@%$VERSION%g
-s%@ACLOCAL@%$ACLOCAL%g
-s%@AUTOCONF@%$AUTOCONF%g
-s%@AUTOMAKE@%$AUTOMAKE%g
-s%@AUTOHEADER@%$AUTOHEADER%g
-s%@MAKEINFO@%$MAKEINFO%g
-s%@SET_MAKE@%$SET_MAKE%g
-s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
-s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
-s%@MAINT@%$MAINT%g
-s%@CC@%$CC%g
-s%@CXX@%$CXX%g
-s%@LN_S@%$LN_S%g
-s%@OBJEXT@%$OBJEXT%g
-s%@EXEEXT@%$EXEEXT%g
-s%@ecos_CFLAGS@%$ecos_CFLAGS%g
-s%@ecos_CXXFLAGS@%$ecos_CXXFLAGS%g
-s%@ecos_LDADD@%$ecos_LDADD%g
-s%@ecos_INCLUDES@%$ecos_INCLUDES%g
-s%@ecos_LIBS@%$ecos_LIBS%g
-s%@MSVC_SRCDIR@%$MSVC_SRCDIR%g
-s%@MSVC_TRUE@%$MSVC_TRUE%g
-s%@MSVC_FALSE@%$MSVC_FALSE%g
-s%@ECOS_REPOSITORY@%$ECOS_REPOSITORY%g
-s%@PACKAGE_DIR@%$PACKAGE_DIR%g
-s%@PACKAGE_VERSION@%$PACKAGE_VERSION%g
-s%@PACKAGE_INSTALL@%$PACKAGE_INSTALL%g
-s%@ecos_tk_includes@%$ecos_tk_includes%g
-s%@ecos_tk_libs@%$ecos_tk_libs%g
-s%@CPP@%$CPP%g
-s%@SUPPORTED_TRUE@%$SUPPORTED_TRUE%g
-s%@SUPPORTED_FALSE@%$SUPPORTED_FALSE%g
-
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
- fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
- fi
-
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
-
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
-
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
-
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-EOF
-cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF
-
-exit 0
-EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
Index: slave/v2_0/host/Makefile.in
===================================================================
--- slave/v2_0/host/Makefile.in (revision 174)
+++ slave/v2_0/host/Makefile.in (nonexistent)
@@ -1,462 +0,0 @@
-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-
-# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-#####ECOSGPLCOPYRIGHTBEGIN####
-#####ECOSGPLCOPYRIGHTEND####
-#######DESCRIPTIONBEGIN####
-######DESCRIPTIONEND####
-
-
-SHELL = @SHELL@
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
-
-DESTDIR =
-
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-
-top_builddir = .
-
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-transform = @program_transform_name@
-
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-host_alias = @host_alias@
-host_triplet = @host@
-CC = @CC@
-CXX = @CXX@
-ECOS_REPOSITORY = @ECOS_REPOSITORY@
-EXEEXT = @EXEEXT@
-LN_S = @LN_S@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MSVC_SRCDIR = @MSVC_SRCDIR@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_DIR = @PACKAGE_DIR@
-PACKAGE_INSTALL = @PACKAGE_INSTALL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-VERSION = @VERSION@
-ecos_CFLAGS = @ecos_CFLAGS@
-ecos_CXXFLAGS = @ecos_CXXFLAGS@
-ecos_INCLUDES = @ecos_INCLUDES@
-ecos_LDADD = @ecos_LDADD@
-ecos_LIBS = @ecos_LIBS@
-ecos_infra_incdir = @ecos_infra_incdir@
-ecos_infra_libdir = @ecos_infra_libdir@
-ecos_libcdl_incdir = @ecos_libcdl_incdir@
-ecos_libcdl_libdir = @ecos_libcdl_libdir@
-ecos_tk_includes = @ecos_tk_includes@
-ecos_tk_libs = @ecos_tk_libs@
-
-AUTOMAKE_OPTIONS = 1.3 foreign
-
-@SUPPORTED_TRUE@AM_CFLAGS = @SUPPORTED_TRUE@@ecos_CFLAGS@ -DUSBHOST_VERSION=\"@VERSION@\" -DPKGVERSION=\"@PACKAGE_VERSION@\" -DUSBAUXDIR=\"$(libexecdir)/ecos/@PACKAGE_INSTALL@\"
-@SUPPORTED_TRUE@AM_CXXFLAGS = @SUPPORTED_TRUE@@ecos_CXXFLAGS@
-@SUPPORTED_TRUE@INCLUDES = @SUPPORTED_TRUE@@ecos_INCLUDES@
-@SUPPORTED_TRUE@LIBS = @SUPPORTED_TRUE@@ecos_LIBS@ @ecos_LDADD@
-
-@SUPPORTED_TRUE@noinst_PROGRAMS = @SUPPORTED_TRUE@usbhost
-@SUPPORTED_TRUE@usbhost_SOURCES = @SUPPORTED_TRUE@usbhost.c
-@SUPPORTED_TRUE@usbhost_DEPENDENCIES = @SUPPORTED_TRUE@../tests/protocol.h ../tests/common.c
-@SUPPORTED_TRUE@usbhost_LDADD = @SUPPORTED_TRUE@-lpthread
-
-@SUPPORTED_TRUE@usbauxdir = @SUPPORTED_TRUE@$(libexecdir)/ecos/@PACKAGE_INSTALL@
-@SUPPORTED_TRUE@usbaux_PROGRAMS = @SUPPORTED_TRUE@usbchmod
-@SUPPORTED_TRUE@usbaux_DATA = @SUPPORTED_TRUE@usbhost.tcl list.tcl verbose.tcl
-@SUPPORTED_TRUE@usbchmod_SOURCES = @SUPPORTED_TRUE@usbchmod.c
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../../../acsupport/mkinstalldirs
-CONFIG_CLEAN_FILES =
-@SUPPORTED_TRUE@noinst_PROGRAMS = usbhost$(EXEEXT)
-@SUPPORTED_TRUE@usbaux_PROGRAMS = usbchmod$(EXEEXT)
-PROGRAMS = $(noinst_PROGRAMS) $(usbaux_PROGRAMS)
-
-
-DEFS = @DEFS@ -I. -I$(srcdir)
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-@SUPPORTED_TRUE@usbhost_OBJECTS = usbhost.$(OBJEXT)
-usbhost_LDFLAGS =
-@SUPPORTED_TRUE@usbchmod_OBJECTS = usbchmod.$(OBJEXT)
-usbchmod_LDADD = $(LDADD)
-usbchmod_DEPENDENCIES =
-usbchmod_LDFLAGS =
-CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
-DATA = $(usbaux_DATA)
-
-DIST_COMMON = Makefile.am Makefile.in acinclude.m4 aclocal.m4 configure \
-configure.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = gtar
-GZIP_ENV = --best
-DEP_FILES = .deps/usbchmod.P .deps/usbhost.P
-SOURCES = $(usbhost_SOURCES) $(usbchmod_SOURCES)
-OBJECTS = $(usbhost_OBJECTS) $(usbchmod_OBJECTS)
-
-all: all-redirect
-.SUFFIXES:
-.SUFFIXES: .S .c .o .obj .s
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
- cd $(top_builddir) \
- && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4
- cd $(srcdir) && $(ACLOCAL)
-
-config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- $(SHELL) ./config.status --recheck
-$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
- cd $(srcdir) && $(AUTOCONF)
-
-mostlyclean-noinstPROGRAMS:
-
-clean-noinstPROGRAMS:
- -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
-
-distclean-noinstPROGRAMS:
-
-maintainer-clean-noinstPROGRAMS:
-
-mostlyclean-usbauxPROGRAMS:
-
-clean-usbauxPROGRAMS:
- -test -z "$(usbaux_PROGRAMS)" || rm -f $(usbaux_PROGRAMS)
-
-distclean-usbauxPROGRAMS:
-
-maintainer-clean-usbauxPROGRAMS:
-
-install-usbauxPROGRAMS: $(usbaux_PROGRAMS)
- @$(NORMAL_INSTALL)
- $(mkinstalldirs) $(DESTDIR)$(usbauxdir)
- @list='$(usbaux_PROGRAMS)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(usbauxdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(usbauxdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
- else :; fi; \
- done
-
-uninstall-usbauxPROGRAMS:
- @$(NORMAL_UNINSTALL)
- list='$(usbaux_PROGRAMS)'; for p in $$list; do \
- rm -f $(DESTDIR)$(usbauxdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
- done
-
-# FIXME: We should only use cygpath when building on Windows,
-# and only if it is available.
-.c.obj:
- $(COMPILE) -c `cygpath -w $<`
-
-.s.o:
- $(COMPILE) -c $<
-
-.S.o:
- $(COMPILE) -c $<
-
-mostlyclean-compile:
- -rm -f *.o core *.core
- -rm -f *.$(OBJEXT)
-
-clean-compile:
-
-distclean-compile:
- -rm -f *.tab.c
-
-maintainer-clean-compile:
-
-usbhost$(EXEEXT): $(usbhost_OBJECTS) $(usbhost_DEPENDENCIES)
- @rm -f usbhost$(EXEEXT)
- $(LINK) $(usbhost_LDFLAGS) $(usbhost_OBJECTS) $(usbhost_LDADD) $(LIBS)
-
-usbchmod$(EXEEXT): $(usbchmod_OBJECTS) $(usbchmod_DEPENDENCIES)
- @rm -f usbchmod$(EXEEXT)
- $(LINK) $(usbchmod_LDFLAGS) $(usbchmod_OBJECTS) $(usbchmod_LDADD) $(LIBS)
-
-install-usbauxDATA: $(usbaux_DATA)
- @$(NORMAL_INSTALL)
- $(mkinstalldirs) $(DESTDIR)$(usbauxdir)
- @list='$(usbaux_DATA)'; for p in $$list; do \
- if test -f $(srcdir)/$$p; then \
- echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(usbauxdir)/$$p"; \
- $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(usbauxdir)/$$p; \
- else if test -f $$p; then \
- echo " $(INSTALL_DATA) $$p $(DESTDIR)$(usbauxdir)/$$p"; \
- $(INSTALL_DATA) $$p $(DESTDIR)$(usbauxdir)/$$p; \
- fi; fi; \
- done
-
-uninstall-usbauxDATA:
- @$(NORMAL_UNINSTALL)
- list='$(usbaux_DATA)'; for p in $$list; do \
- rm -f $(DESTDIR)$(usbauxdir)/$$p; \
- done
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
-
-clean-tags:
-
-distclean-tags:
- -rm -f TAGS ID
-
-maintainer-clean-tags:
-
-distdir = $(PACKAGE)-$(VERSION)
-top_distdir = $(distdir)
-
-# This target untars the dist file and tries a VPATH configuration. Then
-# it guarantees that the distribution is self-contained by making another
-# tarfile.
-distcheck: dist
- -rm -rf $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
- mkdir $(distdir)/=build
- mkdir $(distdir)/=inst
- dc_install_base=`cd $(distdir)/=inst && pwd`; \
- cd $(distdir)/=build \
- && ../configure --srcdir=.. --prefix=$$dc_install_base \
- && $(MAKE) $(AM_MAKEFLAGS) \
- && $(MAKE) $(AM_MAKEFLAGS) dvi \
- && $(MAKE) $(AM_MAKEFLAGS) check \
- && $(MAKE) $(AM_MAKEFLAGS) install \
- && $(MAKE) $(AM_MAKEFLAGS) installcheck \
- && $(MAKE) $(AM_MAKEFLAGS) dist
- -rm -rf $(distdir)
- @banner="$(distdir).tar.gz is ready for distribution"; \
- dashes=`echo "$$banner" | sed s/./=/g`; \
- echo "$$dashes"; \
- echo "$$banner"; \
- echo "$$dashes"
-dist: distdir
- -chmod -R a+r $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
- -rm -rf $(distdir)
-dist-all: distdir
- -chmod -R a+r $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
- -rm -rf $(distdir)
-distdir: $(DISTFILES)
- -rm -rf $(distdir)
- mkdir $(distdir)
- -chmod 777 $(distdir)
- here=`cd $(top_builddir) && pwd`; \
- top_distdir=`cd $(distdir) && pwd`; \
- distdir=`cd $(distdir) && pwd`; \
- cd $(top_srcdir) \
- && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile
- @for file in $(DISTFILES); do \
- d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
- done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
- -rm -rf .deps
-
-maintainer-clean-depend:
-
-%.o: %.c
- @echo '$(COMPILE) -c $<'; \
- $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-cp .deps/$(*F).pp .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm .deps/$(*F).pp
-
-%.lo: %.c
- @echo '$(LTCOMPILE) -c $<'; \
- $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
- < .deps/$(*F).pp > .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm -f .deps/$(*F).pp
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
- @$(NORMAL_INSTALL)
- $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
-install-exec: install-exec-am
-
-install-data-am: install-usbauxPROGRAMS install-usbauxDATA
- @$(NORMAL_INSTALL)
- $(MAKE) $(AM_MAKEFLAGS) install-data-hook
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am: uninstall-usbauxPROGRAMS uninstall-usbauxDATA
-uninstall: uninstall-am
-all-am: Makefile $(PROGRAMS) $(DATA)
-all-redirect: all-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(usbauxdir) $(DESTDIR)$(usbauxdir)
-
-
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
- -rm -f config.cache config.log stamp-h stamp-h[0-9]*
-
-maintainer-clean-generic:
-mostlyclean-am: mostlyclean-noinstPROGRAMS mostlyclean-usbauxPROGRAMS \
- mostlyclean-compile mostlyclean-tags mostlyclean-depend \
- mostlyclean-generic
-
-mostlyclean: mostlyclean-am
-
-clean-am: clean-noinstPROGRAMS clean-usbauxPROGRAMS clean-compile \
- clean-tags clean-depend clean-generic mostlyclean-am
-
-clean: clean-am
-
-distclean-am: distclean-noinstPROGRAMS distclean-usbauxPROGRAMS \
- distclean-compile distclean-tags distclean-depend \
- distclean-generic clean-am
-
-distclean: distclean-am
- -rm -f config.status
-
-maintainer-clean-am: maintainer-clean-noinstPROGRAMS \
- maintainer-clean-usbauxPROGRAMS \
- maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-depend maintainer-clean-generic \
- distclean-am
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
-
-maintainer-clean: maintainer-clean-am
- -rm -f config.status
-
-.PHONY: mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
-clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
-mostlyclean-usbauxPROGRAMS distclean-usbauxPROGRAMS \
-clean-usbauxPROGRAMS maintainer-clean-usbauxPROGRAMS \
-uninstall-usbauxPROGRAMS install-usbauxPROGRAMS mostlyclean-compile \
-distclean-compile clean-compile maintainer-clean-compile \
-uninstall-usbauxDATA install-usbauxDATA tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
-maintainer-clean-depend info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
-
-
-@SUPPORTED_TRUE@install-exec-hook:
-@SUPPORTED_TRUE@ $(INSTALL_PROGRAM) usbhost $(bindir)/usbhost_@PACKAGE_VERSION@
-@SUPPORTED_TRUE@ rm -f $(bindir)/usbhost
-@SUPPORTED_TRUE@ $(LN_S) $(bindir)/usbhost_@PACKAGE_VERSION@ $(bindir)/usbhost
-
-@SUPPORTED_TRUE@install-data-hook:
-@SUPPORTED_TRUE@ chown root $(usbauxdir)/usbchmod
-@SUPPORTED_TRUE@ chmod u+s $(usbauxdir)/usbchmod
-
-@SUPPORTED_FALSE@install-exec-hook:
-@SUPPORTED_FALSE@ echo Nothing to be done for this platform
-
-@SUPPORTED_FALSE@install-data-hook:
-@SUPPORTED_FALSE@ echo Nothing to be done for this platform
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
Index: slave/v2_0/host/usbchmod.c
===================================================================
--- slave/v2_0/host/usbchmod.c (revision 174)
+++ slave/v2_0/host/usbchmod.c (nonexistent)
@@ -1,180 +0,0 @@
-//=================================================================
-//
-// usb_chmod.c
-//
-// A utility to manipulate /proc/bus/usb access rights
-//
-//==========================================================================
-//####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####
-//
-// The Linux kernel allows raw access to USB devices via /proc/bus/usb.
-// However, such access requires root privileges: this makes perfect
-// sense for typical USB devices, but gets in the way of eCos USB
-// testing. This utility runs suid and can be used to change the access
-// rights to a specific and validated USB device.
-//
-// Author(s): bartv
-// Date: 2001-07-18
-//####DESCRIPTIONEND####
-//==========================================================================
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-// Note: this code is duplicated in usbhost.c. Any changes here
-// should be propagated. For now the routine is too small to warrant
-// a separate source file.
-#define USB_ROOT "/proc/bus/usb/"
-#define PRODUCT_STRING "Red Hat eCos USB test"
-
-static int
-usb_scan_devices(int* bus, int* dev)
-{
- FILE* devs_file = fopen(USB_ROOT "devices", "r");
- int current_bus = -1;
- int current_dev = -1;
- int ch;
-
- if (NULL == devs_file) {
- fprintf(stderr, "Error: unable to access " USB_ROOT "devices\n");
- return 0;
- }
- ch = getc(devs_file);
- while (EOF != ch) {
- if ('T' == ch) {
- if (2 !=fscanf(devs_file, ": Bus=%d %*[^D\n]Dev#=%d", ¤t_bus, ¤t_dev)) {
- current_bus = -1;
- current_dev = -1;
- }
- } else if ('S' == ch) {
- int start = 0, end = 0;
- if (EOF != fscanf(devs_file, ": Product=%n" PRODUCT_STRING "%n", &start, &end)) {
- if (start < end) {
- *bus = current_bus;
- *dev = current_dev;
- break;
- }
- }
- }
- // Move to the end of the current line.
- do {
- ch = getc(devs_file);
- } while ((EOF != ch) && ('\n' != ch));
- if (EOF != ch) {
- ch = getc(devs_file);
- }
- }
-
- fclose(devs_file);
- if ((-1 != *bus) && (-1 != *dev)) {
- return 1;
- }
- fprintf(stderr, "Error: failed to find a USB device \"" PRODUCT_STRING "\"\n");
- return 0;
-}
-
-int
-main(int argc, char** argv)
-{
- int bus, dev;
- int actual_bus, actual_dev;
- char devname[_POSIX_PATH_MAX];
- long strtol_tmp1;
- char* strtol_tmp2;
-
- if (3 != argc) {
- fprintf(stderr, "usb_chmod: wrong number of arguments\n");
- fprintf(stderr, " : usage, usb_chmod \n");
- exit(EXIT_FAILURE);
- }
- if (('\0' == argv[1][0]) || ('\0' == argv[2][0])) {
- fprintf(stderr, "usb_chmod: invalid arguments\n");
- exit(EXIT_FAILURE);
- }
-
- strtol_tmp1 = strtol(argv[1], &strtol_tmp2, 10);
- if ('\0' != *strtol_tmp2) {
- fprintf(stderr, "usbchmod: invalid first argument, not a number\n");
- exit(EXIT_FAILURE);
- }
- if (strtol_tmp1 > INT_MAX) {
- fprintf(stderr, "usbchmod: invalid first argument, number too large\n");
- exit(EXIT_FAILURE);
- }
- bus = (int) strtol_tmp1;
-
- strtol_tmp1 = strtol(argv[2], &strtol_tmp2, 10);
- if ('\0' != *strtol_tmp2) {
- fprintf(stderr, "usbchmod: invalid second argument, not a number\n");
- exit(EXIT_FAILURE);
- }
- if (strtol_tmp1 > INT_MAX) {
- fprintf(stderr, "usbchmod: invalid second argument, number too large\n");
- exit(EXIT_FAILURE);
- }
- dev = (int) strtol_tmp1;
-
- if (!usb_scan_devices(&actual_bus, &actual_dev)) {
- fprintf(stderr, "usb_chmod: failed to find eCos USB test application\n");
- exit(EXIT_FAILURE);
- }
- if ((bus != actual_bus) || (dev != actual_dev)) {
- fprintf(stderr, "usbchmod: mismatch between specified and actual USB identifiers.\n");
- fprintf(stderr, " : eCos test application is at %03d/%03d, not %03d/%03d\n",
- actual_bus, actual_dev, bus, dev);
- exit(EXIT_FAILURE);
- }
-
- if (_POSIX_PATH_MAX == snprintf(devname, _POSIX_PATH_MAX, "/proc/bus/usb/" "%03d/%03d", actual_bus, actual_dev)) {
- fprintf(stderr, "usbchmod: internal error, buffer overflow\n");
- exit(EXIT_FAILURE);
- }
-
- if (0 != chmod(devname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
- int old_errno = errno;
- fprintf(stderr, "usbchmod: failed to modify access rights on %s\n", devname);
- if ((old_errno >= 0) && (old_errno < sys_nerr)) {
- fprintf(stderr, " : %s\n", sys_errlist[old_errno]);
- }
- exit(EXIT_FAILURE);
- }
-
- return EXIT_SUCCESS;
-}
Index: slave/v2_0/host/acinclude.m4
===================================================================
--- slave/v2_0/host/acinclude.m4 (revision 174)
+++ slave/v2_0/host/acinclude.m4 (nonexistent)
@@ -1,54 +0,0 @@
-dnl Process this file with aclocal to get an aclocal.m4 file. Then
-dnl process that with autoconf.
-dnl ====================================================================
-dnl
-dnl acinclude.m4
-dnl
-dnl ====================================================================
-dnl ####ECOSGPLCOPYRIGHTBEGIN####
-dnl -------------------------------------------
-dnl This file is part of eCos, the Embedded Configurable Operating System.
-dnl Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-dnl
-dnl eCos is free software; you can redistribute it and/or modify it under
-dnl the terms of the GNU General Public License as published by the Free
-dnl Software Foundation; either version 2 or (at your option) any later version.
-dnl
-dnl eCos is distributed in the hope that it will be useful, but WITHOUT ANY
-dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
-dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-dnl for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License along
-dnl with eCos; if not, write to the Free Software Foundation, Inc.,
-dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-dnl
-dnl As a special exception, if other files instantiate templates or use macros
-dnl or inline functions from this file, or you compile this file and link it
-dnl with other works to produce a work based on this file, this file does not
-dnl by itself cause the resulting work to be covered by the GNU General Public
-dnl License. However the source code for this file must still be made available
-dnl in accordance with section (3) of the GNU General Public License.
-dnl
-dnl This exception does not invalidate any other reasons why a work based on
-dnl this file might be covered by the GNU General Public License.
-dnl
-dnl Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-dnl at http://sources.redhat.com/ecos/ecos-license/
-dnl -------------------------------------------
-dnl ####ECOSGPLCOPYRIGHTEND####
-dnl ====================================================================
-dnl#####DESCRIPTIONBEGIN####
-dnl
-dnl Author(s): bartv
-dnl Contact(s): bartv
-dnl Date: 2002/01/10
-dnl Version: 0.01
-dnl
-dnl####DESCRIPTIONEND####
-dnl ====================================================================
-
-dnl Access shared macros.
-dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not
-dnl incorporate the macro into aclocal.m4
-sinclude(../../../../../../acsupport/acinclude.m4)
Index: slave/v2_0/host/configure.in
===================================================================
--- slave/v2_0/host/configure.in (revision 174)
+++ slave/v2_0/host/configure.in (nonexistent)
@@ -1,115 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-dnl ====================================================================
-dnl
-dnl configure.in
-dnl
-dnl configure script for eCos USB host-side support
-dnl
-dnl ====================================================================
-dnl ####ECOSGPLCOPYRIGHTBEGIN####
-dnl -------------------------------------------
-dnl This file is part of eCos, the Embedded Configurable Operating System.
-dnl Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-dnl
-dnl eCos is free software; you can redistribute it and/or modify it under
-dnl the terms of the GNU General Public License as published by the Free
-dnl Software Foundation; either version 2 or (at your option) any later version.
-dnl
-dnl eCos is distributed in the hope that it will be useful, but WITHOUT ANY
-dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
-dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-dnl for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License along
-dnl with eCos; if not, write to the Free Software Foundation, Inc.,
-dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-dnl
-dnl As a special exception, if other files instantiate templates or use macros
-dnl or inline functions from this file, or you compile this file and link it
-dnl with other works to produce a work based on this file, this file does not
-dnl by itself cause the resulting work to be covered by the GNU General Public
-dnl License. However the source code for this file must still be made available
-dnl in accordance with section (3) of the GNU General Public License.
-dnl
-dnl This exception does not invalidate any other reasons why a work based on
-dnl this file might be covered by the GNU General Public License.
-dnl
-dnl Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-dnl at http://sources.redhat.com/ecos/ecos-license/
-dnl -------------------------------------------
-dnl ####ECOSGPLCOPYRIGHTEND####
-dnl ====================================================================
-dnl#####DESCRIPTIONBEGIN####
-dnl
-dnl Author(s): bartv
-dnl Contact(s): bartv
-dnl Date: 2002/01/10
-dnl Version: 0.01
-dnl
-dnl####DESCRIPTIONEND####
-dnl ====================================================================
-
-
-AC_INIT(usbhost.c)
-
-dnl Pick up the support files from the top-level acsupport directory.
-AC_CONFIG_AUX_DIR(../../../../../../acsupport)
-
-ECOS_CHECK_BUILD_ne_SRC
-AC_CANONICAL_HOST
-AM_INIT_AUTOMAKE(usbhost,0.1,0)
-AM_MAINTAINER_MODE
-
-dnl The current version of the USB testing support depends on
-dnl functionality provided only by Linux platforms, and has only been
-dnl tested on x86 machines, so a test is appropriate here. However
-dnl it is not a good idea for the configure script to report an error:
-dnl that would prevent any top-level configury working for other
-dnl platforms. Instead an automake conditional is used to suppress adding
-dnl targets to the build.
-case "${host}" in
- *-*-linux-gnu* ) SUPPORTED="yes";;
- * ) SUPPORTED="no"
-esac
-
-if test "${SUPPORTED}" = "no" ; then
- AC_MSG_WARN([USB testing is only supported on Linux hosts])
-else
- AC_PROG_CC
- AC_PROG_CXX
- AC_PROG_LN_S
- AC_OBJEXT
- AC_EXEEXT
- ECOS_PROG_MSVC
- ECOS_PROG_STANDARD_COMPILER_FLAGS
- ECOS_PACKAGE_DIRS
-
- ECOS_PATH_TCL
- dnl Check that the version of tcl is sufficiently recent.
- dnl e.g. "end" only became a valid index for the
- dnl string commands after 8.1
- if test "${TK_MAJOR_VERSION}" = "8" ; then
- if test ${TK_MINOR_VERSION} -lt 2 ; then
- AC_MSG_WARN([Version 8.2 or greater of Tcl/Tk is required])
- SUPPORTED="no"
- fi
- fi
- if test "${SUPPORTED}" = "yes" ; then
- AC_CHECK_HEADERS("linux/usb.h" "linux/usbdevice_fs.h",,SUPPORTED="no")
- if test "${SUPPORTED}" = "no" ; then
- AC_MSG_WARN([Required Linux kernel functionality does not appear to be available])
- fi
- fi
-fi
-
-if test "${SUPPORTED}" = "no" ; then
- AC_MSG_WARN([The USB testing support cannot be built on this platform.])
-fi
-
-AM_CONDITIONAL(SUPPORTED, test "${SUPPORTED}" = "yes")
-
-dnl There is no real need for a config.h file at this time, since the code
-dnl is specific to Linux. This may change in future.
-dnl AM_CONFIG_HEADER(config.h:config.h.in)
-
-AC_OUTPUT(Makefile:Makefile.in)
Index: slave/v2_0/host/verbose.tcl
===================================================================
--- slave/v2_0/host/verbose.tcl (revision 174)
+++ slave/v2_0/host/verbose.tcl (nonexistent)
@@ -1,71 +0,0 @@
-# {{{ Banner
-
-#===============================================================================
-#
-# verbose.tcl
-#
-# Support for USB testing
-#
-#===============================================================================
-#####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####
-#
-# Author(s): bartv
-# Date: 2002-01-16
-# Purpose: Set the target-side verbosity level
-#
-#####DESCRIPTIONEND####
-#===============================================================================
-#
-
-# }}}
-
-if { 1 == $argc } {
- puts "The desired verbosity level must be specified on the command line."
- puts "This should be a small integer. A value of 0 suppresses run-time"
- puts "logging within the target."
- exit 1
-}
-set level [lindex $argv 0]
-
-if { ![string is integer -strict $level ] } {
- puts "Invalid verbosity level \"$level\""
- puts "This should be a small integer. A value of 0 suppresses run-time"
- puts "logging within the target."
- exit 1
-}
-
-usbtest::target_verbose $level
-
Index: slave/v2_0/host/usbhost.c
===================================================================
--- slave/v2_0/host/usbhost.c (revision 174)
+++ slave/v2_0/host/usbhost.c (nonexistent)
@@ -1,1898 +0,0 @@
-/*{{{ Banner */
-
-//=================================================================
-//
-// host.c
-//
-// USB testing - host-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####
-//
-// Author(s): bartv
-// Date: 2001-07-04
-//####DESCRIPTIONEND####
-//==========================================================================
-
-// The overall architecture is as follows.
-//
-// The target hardware runs a special application which provides a
-// particular type of USB application, "Red Hat eCos USB testing".
-// This will not be recognised by any device driver, so the Linux
-// kernel will pretty much ignore the device (other host OS's are not
-// considered at this time).
-//
-// This program is the only supported way to interact with that service.
-// It acts as an extended Tcl interpreter, providing a number of new
-// Tcl commands for interacting with the target. All test cases can
-// then be written as Tcl scripts which invoke a series of these commands.
-// These Tcl commands operate essentially though the LINUX usb devfs
-// service which allows ordinary application code to perform USB operations
-// via ioctl()'s.
-
-/*}}}*/
-/*{{{ #include's */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-// Avoid compatibility problems with Tcl 8.4 vs. earlier
-#define USE_NON_CONST
-#include
-#include
-#include
-#include "../tests/protocol.h"
-
-/*}}}*/
-
-/*{{{ Statics */
-
-// ----------------------------------------------------------------------------
-// Statics.
-
-// Has the current batch of tests actually terminated? 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;
-
-// The next local thread to be allocated for testing. This variable can also
-// be used to find out how many threads are involved in the current test.
-// This counter should always be reset to 0 at the end of every test run.
-static int local_thread_count = 0;
-
-// A similar counter for remote threads.
-static int remote_thread_count = 0;
-
-// A file handle for manipulating the USB device at a low level
-static int usb_master_fd = -1;
-
-/*}}}*/
-/*{{{ Logging */
-
-// ----------------------------------------------------------------------------
-// The user can provide one or more -V/--verbose arguments to increase
-// the amount of output generated.
-
-static int verbose = 0;
-
-#define VERBOSE(_level_, _format_, _args_...) \
- do { \
- if (verbose >= _level_) { \
- printf(_format_, ## _args_); \
- } \
- } while (0);
-
-/*}}}*/
-/*{{{ Low-level USB access */
-
-// ----------------------------------------------------------------------------
-// Low-level access to a USB device.
-//
-// The various ioctl() calls require a file handle which corresponds to one
-// of the /proc/bus/usb// entries. is a bus number,
-// typically 001 or 001, and is a device number on that bus,
-// e.g. 003. Figuring out and requires scanning
-// /proc/bus/usb/devices, which is a somewhat complicated text file.
-//
-// This is all somewhat vulnerable to incompatible changes in the
-// Linux kernel, specifically the implementation of the /proc/bus/usb.
-// An alternative approach would be to write a new Linux device driver
-// and interact with that, but that approach is vulnerable to any
-// internal kernel API changes affecting USB device drivers.
-
-// How to access USB devices from userland
-#define USB_ROOT "/proc/bus/usb/"
-
-// How to identify the eCos test case
-#define PRODUCT_STRING "Red Hat eCos USB test"
-
-// Scan through /proc/bus/usb/devices looking for an entry that
-// matches what we are after, specifically a line
-// S: Product=Red Hat eCos USB testcase
-// The required information can then be obtained from the previous
-// line:
-// T: Bus= ... Dev#= ...
-//
-// Of course the T: line is going to come first, so it is necessary
-// to keep track of the current bus and device numbers.
-//
-// Note: this code is duplicated in usbchmod.c. Any changes here
-// should be propagated. For now the routine is too small to warrant
-// a separate source file.
-
-static int
-usb_scan_devices(int* bus, int* dev)
-{
- FILE* devs_file;
- int current_bus = -1;
- int current_dev = -1;
- int ch;
-
- *bus = -1;
- *dev = -1;
-
- VERBOSE(1, "Searching " USB_ROOT "devices for the eCos USB test code\n");
-
- devs_file = fopen(USB_ROOT "devices", "r");
- if (NULL == devs_file) {
- fprintf(stderr, "usbhost: error, unable to access " USB_ROOT "devices\n");
- return 0;
- }
- ch = getc(devs_file);
- while (EOF != ch) {
- if ('T' == ch) {
- if (2 !=fscanf(devs_file, ": Bus=%d %*[^D\n]Dev#=%d", ¤t_bus, ¤t_dev)) {
- current_bus = -1;
- current_dev = -1;
- }
- } else if ('S' == ch) {
- int start = 0, end = 0;
- if (EOF != fscanf(devs_file, ": Product=%n" PRODUCT_STRING "%n", &start, &end)) {
- if (start < end) {
- *bus = current_bus;
- *dev = current_dev;
- break;
- }
- }
- }
- // Move to the end of the current line.
- do {
- ch = getc(devs_file);
- } while ((EOF != ch) && ('\n' != ch));
- if (EOF != ch) {
- ch = getc(devs_file);
- }
- }
-
- fclose(devs_file);
- if ((-1 != *bus) && (-1 != *dev)) {
- VERBOSE(1, "Found eCos USB test code on bus %d, device %d\n", *bus, *dev);
- return 1;
- }
- fprintf(stderr, "usbhost: error, failed to find a USB device \"" PRODUCT_STRING "\"\n");
- return 0;
-}
-
-// Actually open the USB device, allowing subsequent ioctl() operations.
-//
-// Typically /proc/bus/usb/... will not allow ordinary applications
-// to perform ioctl()'s. Instead root privileges are required. To work
-// around this there is a little utility usbchmod, installed suid,
-// which can be used to get access to the raw device.
-static int
-usb_open_device(void)
-{
- char devname[_POSIX_PATH_MAX];
- static int bus = -1;
- static int dev = -1;
- int result;
-
- if ((-1 == bus) || (-1 == dev)) {
- if (!usb_scan_devices(&bus, &dev)) {
- return -1;
- }
- }
-
- if (_POSIX_PATH_MAX == snprintf(devname, _POSIX_PATH_MAX, USB_ROOT "%03d/%03d", bus, dev)) {
- fprintf(stderr, "usbhost: internal error, buffer overflow\n");
- exit(EXIT_FAILURE);
- }
-
- VERBOSE(1, "Attempting to access USB target via %s\n", devname);
-
- result = open(devname, O_RDWR);
- if (-1 == result) {
- // Check for access right problems. If so, try to work around them
- // by invoking usbchmod. Always look for this in the install tree,
- // since it is only that version which is likely to have been
- // chown'ed and chmod'ed to be suid root.
- if (EACCES == errno) {
- char command_name[_POSIX_PATH_MAX];
-
- VERBOSE(1, "Insufficient access to USB target, running usbchmod\n");
- if (_POSIX_PATH_MAX == snprintf(command_name, _POSIX_PATH_MAX, "%s/usbchmod %d %d", USBAUXDIR, bus, dev)) {
- fprintf(stderr, "usbhost: internal error, buffer overflow\n");
- exit(EXIT_FAILURE);
- }
- (void) system(command_name);
- result = open(devname, O_RDWR);
- }
- }
- if (-1 == result) {
- fprintf(stderr, "usbhost: error, failed to open \"%s\", errno %d\n", devname, errno);
- }
-
- VERBOSE(1, "USB device now accessible via file descriptor %d\n", result);
-
- // Also perform a set-configuration call, to avoid warnings from
- // the Linux kernel. Target-side testing is always configuration 1
- // because only a single configuration is supported.
- (void) ioctl(result, USBDEVFS_SETCONFIGURATION, 1);
- return result;
-}
-
-// Exchange a control message with the host. The return value should
-// be 0, or a small positive number indicating the actual number of
-// bytes received which may be less than requested.
-//
-// There appear to be problems with some hosts, manifesting itself as
-// an inability to send control messages that involve additional data
-// from host->target. These problems are not yet well-understood. For
-// now the workaround is to send multiple packets, each with up to
-// four bytes encoded in the index and length fields.
-static int
-usb_control_message(int fd, int request_type, int request, int value, int index, int length, void* data)
-{
- struct usbdevfs_ctrltransfer transfer;
- int result = 0;
-
- VERBOSE(3, "usb_control_message, request %02x, len %d\n", request, length);
-
- if (length > USBTEST_MAX_CONTROL_DATA) {
- fprintf(stderr, "usbhost: internal error, control message involves too much data.\n");
- exit(EXIT_FAILURE);
- }
-
-#if 1
- // Workaround - send additional data in the index and length fields.
- if ((length > 0) && (USB_DIR_OUT == (USB_ENDPOINT_DIR_MASK & request_type))) {
- int i;
- unsigned char* buf = (unsigned char*) data;
-
- for (i = 0; i < length; i+= 4) {
- int this_len = length - 1;
- int ioctl_result;
-
- transfer.requesttype = USB_TYPE_CLASS | USB_RECIP_DEVICE;
- if (this_len > 4) {
- this_len = 4;
- }
- 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 int
-usb_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 int
-usb_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 int
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-usb_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 void
-reset_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 void
-run_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;
- }
-
- // 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 void
-run_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 void
-run_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 void
-run_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 void
-pool_initialize(void)
-{
- int i;
- for (i = 0; i < USBTEST_MAX_CONCURRENT_TESTS; i++) {
- pool[i].running = 0;
- pool[i].test.fd = dup(usb_master_fd);
- if (0 != sem_init(&(pool[i].wakeup), 0, 0)) {
- fprintf(stderr, "usbhost: internal error, failed to initialize all semaphores.\n");
- exit(EXIT_FAILURE);
- }
- if (0 != pthread_create(&(pool[i].thread), NULL, &pool_function, (void*) &(pool[i]))) {
- fprintf(stderr, "usbhost: internal error, failed to start all threads.\n");
- exit(EXIT_FAILURE);
- }
- }
-}
-
-// Allocate a single entry in the thread pool.
-static UsbTest*
-pool_allocate(void)
-{
- UsbTest* result = (UsbTest*) 0;
-
- if (local_thread_count == USBTEST_MAX_CONCURRENT_TESTS) {
- fprintf(stderr, "usbhost: internal error, thread resource exhausted.\n");
- exit(EXIT_FAILURE);
- }
-
- result = &(pool[local_thread_count].test);
- local_thread_count++;
- reset_usbtest(result);
- return result;
-}
-
-// Start all the threads that are supposed to be running tests.
-static void
-pool_start(void)
-{
- int i;
- for (i = 0; i < local_thread_count; i++) {
- pool[i].running = 1;
- sem_post(&(pool[i].wakeup));
- }
-}
-
-/*}}}*/
-/*{{{ Tcl routines */
-
-// ----------------------------------------------------------------------------
-// Tcl routines to provide access to the USB device from inside Tcl
-// scripts, plus some general utilities. These routines deal mostly
-// with preparing a test run. The actual work is done in C: the
-// ioctl() operations are not readily accessible from Tcl, and
-// operations like filling in buffers and calculating checksums are
-// cpu-intensive.
-
-/*{{{ pass/fail/abort */
-
-// ----------------------------------------------------------------------------
-// Some simple routines accessible from Tcl to get the target to report pass/fail or
-// to make the target abort.
-
-static int
-tcl_target_pass(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_pass \"", TCL_STATIC);
- return TCL_ERROR;
- }
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_PASS, 0, 0, strlen(argv[1]) + 1, argv[1]);
- usb_sync(usb_master_fd, -1);
- return TCL_OK;
-}
-
-static int
-tcl_target_fail(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_fail \"", TCL_STATIC);
- return TCL_ERROR;
- }
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_FAIL, 0, 0, strlen(argv[1]) + 1, argv[1]);
- usb_sync(usb_master_fd, -1);
- return TCL_OK;
-}
-
-// The next three routines cause the target to exit, so a usb_sync() is inappropriate.
-static int
-tcl_target_pass_exit(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_pass_exit \"", TCL_STATIC);
- return TCL_ERROR;
- }
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_PASS_EXIT, 0, 0,
- strlen(argv[1]) + 1, argv[1]);
- return TCL_OK;
-}
-
-
-static int
-tcl_target_fail_exit(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_fail_exit \"", TCL_STATIC);
- return TCL_ERROR;
- }
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_FAIL_EXIT, 0, 0,
- strlen(argv[1]) + 1, argv[1]);
- return TCL_OK;
-}
-
-static int
-tcl_target_abort(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv __attribute__ ((unused)) )
-{
- if (1 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_abort\"", TCL_STATIC);
- return TCL_ERROR;
- }
- usb_abort(usb_master_fd);
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ start bulk test */
-
-// ----------------------------------------------------------------------------
-// Start a bulk test. The real Tcl interface to this functionality is
-// implemented in Tcl: it takes care of figuring out sensible default
-// arguments, validating the data, etc. All that this code does is
-// allocate a thread and fill in the appropriate data, plus request
-// the target-side to do the same thing.
-
-static int
-tcl_test_bulk(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- int i;
- int tmp;
- UsbTest* test;
- unsigned char request[USBTEST_MAX_CONTROL_DATA];
- int request_index;
-
- // The data consists of 28 numbers for UsbTest_Bulk itself, and
- // another 10 numbers for the test data definition.
- if (39 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_test_bulk \"", TCL_STATIC);
- return TCL_ERROR;
- }
- for (i = 1; i < 39; i++) {
- int discard;
- if (TCL_OK != Tcl_GetInt(interp, argv[i], &discard)) {
- Tcl_SetResult(interp, "invalid argument: all arguments should be numbers", TCL_STATIC);
- return TCL_ERROR;
- }
- }
-
- test = pool_allocate();
- Tcl_GetInt(interp, argv[1], &(test->test_params.bulk.number_packets));
- Tcl_GetInt(interp, argv[2], &(test->test_params.bulk.endpoint));
- test->which_test = (USB_DIR_IN == (test->test_params.bulk.endpoint & USB_ENDPOINT_DIR_MASK))
- ? usbtest_bulk_in : usbtest_bulk_out;
- Tcl_GetInt(interp, argv[ 3], &(test->test_params.bulk.tx_size));
- Tcl_GetInt(interp, argv[ 4], &(test->test_params.bulk.tx_size_min));
- Tcl_GetInt(interp, argv[ 5], &(test->test_params.bulk.tx_size_max));
- Tcl_GetInt(interp, argv[ 6], &(test->test_params.bulk.tx_size_multiplier));
- Tcl_GetInt(interp, argv[ 7], &(test->test_params.bulk.tx_size_divisor));
- Tcl_GetInt(interp, argv[ 8], &(test->test_params.bulk.tx_size_increment));
- Tcl_GetInt(interp, argv[ 9], &(test->test_params.bulk.rx_size));
- Tcl_GetInt(interp, argv[10], &(test->test_params.bulk.rx_size_min));
- Tcl_GetInt(interp, argv[11], &(test->test_params.bulk.rx_size_max));
- Tcl_GetInt(interp, argv[12], &(test->test_params.bulk.rx_size_multiplier));
- Tcl_GetInt(interp, argv[13], &(test->test_params.bulk.rx_size_divisor));
- Tcl_GetInt(interp, argv[14], &(test->test_params.bulk.rx_size_increment));
- Tcl_GetInt(interp, argv[15], &(test->test_params.bulk.rx_padding));
- Tcl_GetInt(interp, argv[16], &(test->test_params.bulk.tx_delay));
- Tcl_GetInt(interp, argv[17], &(test->test_params.bulk.tx_delay_min));
- Tcl_GetInt(interp, argv[18], &(test->test_params.bulk.tx_delay_max));
- Tcl_GetInt(interp, argv[19], &(test->test_params.bulk.tx_delay_multiplier));
- Tcl_GetInt(interp, argv[20], &(test->test_params.bulk.tx_delay_divisor));
- Tcl_GetInt(interp, argv[21], &(test->test_params.bulk.tx_delay_increment));
- Tcl_GetInt(interp, argv[22], &(test->test_params.bulk.rx_delay));
- Tcl_GetInt(interp, argv[23], &(test->test_params.bulk.rx_delay_min));
- Tcl_GetInt(interp, argv[24], &(test->test_params.bulk.rx_delay_max));
- Tcl_GetInt(interp, argv[25], &(test->test_params.bulk.rx_delay_multiplier));
- Tcl_GetInt(interp, argv[26], &(test->test_params.bulk.rx_delay_divisor));
- Tcl_GetInt(interp, argv[27], &(test->test_params.bulk.rx_delay_increment));
- Tcl_GetInt(interp, argv[28], &tmp);
- test->test_params.bulk.io_mechanism = (usb_io_mechanism) tmp;
- Tcl_GetInt(interp, argv[29], &tmp);
- test->test_params.bulk.data.format = (usbtestdata) tmp;
- Tcl_GetInt(interp, argv[30], &(test->test_params.bulk.data.seed));
- Tcl_GetInt(interp, argv[31], &(test->test_params.bulk.data.multiplier));
- Tcl_GetInt(interp, argv[32], &(test->test_params.bulk.data.increment));
- Tcl_GetInt(interp, argv[33], &(test->test_params.bulk.data.transfer_seed_multiplier));
- Tcl_GetInt(interp, argv[34], &(test->test_params.bulk.data.transfer_seed_increment));
- Tcl_GetInt(interp, argv[35], &(test->test_params.bulk.data.transfer_multiplier_multiplier));
- Tcl_GetInt(interp, argv[36], &(test->test_params.bulk.data.transfer_multiplier_increment));
- Tcl_GetInt(interp, argv[37], &(test->test_params.bulk.data.transfer_increment_multiplier));
- Tcl_GetInt(interp, argv[38], &(test->test_params.bulk.data.transfer_increment_increment));
-
- VERBOSE(3, "Preparing USB bulk test on endpoint %d, direction %s, for %d packets\n", \
- test->test_params.bulk.endpoint, \
- (usbtest_bulk_in == test->which_test) ? "IN" : "OUT", \
- test->test_params.bulk.number_packets);
- VERBOSE(3, " I/O mechanism is %s\n", \
- (usb_io_mechanism_usb == test->test_params.bulk.io_mechanism) ? "low-level USB" : \
- (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism) ? "devtab" : "");
- VERBOSE(3, " Data format %s, data1 %d, data* %d, data+ %d, data1* %d, data1+ %d, data** %d, data*+ %d, data+* %d, data++ %d\n",\
- (usbtestdata_none == test->test_params.bulk.data.format) ? "none" : \
- (usbtestdata_bytefill == test->test_params.bulk.data.format) ? "bytefill" : \
- (usbtestdata_wordfill == test->test_params.bulk.data.format) ? "wordfill" : \
- (usbtestdata_byteseq == test->test_params.bulk.data.format) ? "byteseq" : \
- (usbtestdata_wordseq == test->test_params.bulk.data.format) ? "wordseq" : "", \
- test->test_params.bulk.data.seed, \
- test->test_params.bulk.data.multiplier, \
- test->test_params.bulk.data.increment, \
- test->test_params.bulk.data.transfer_seed_multiplier, \
- test->test_params.bulk.data.transfer_seed_increment, \
- test->test_params.bulk.data.transfer_multiplier_multiplier, \
- test->test_params.bulk.data.transfer_multiplier_increment, \
- test->test_params.bulk.data.transfer_increment_multiplier, \
- test->test_params.bulk.data.transfer_increment_increment);
- VERBOSE(3, " txsize1 %d, txsize>= %d, txsize<= %d, txsize* %d, txsize/ %d, txsize+ %d\n", \
- test->test_params.bulk.tx_size, test->test_params.bulk.tx_size_min, \
- test->test_params.bulk.tx_size_max, test->test_params.bulk.tx_size_multiplier, \
- test->test_params.bulk.tx_size_divisor, test->test_params.bulk.tx_size_increment);
- VERBOSE(3, " rxsize1 %d, rxsize>= %d, rxsize<= %d, rxsize* %d, rxsize/ %d, rxsize+ %d\n", \
- test->test_params.bulk.rx_size, test->test_params.bulk.rx_size_min, \
- test->test_params.bulk.rx_size_max, test->test_params.bulk.rx_size_multiplier, \
- test->test_params.bulk.rx_size_divisor, test->test_params.bulk.rx_size_increment);
- VERBOSE(3, " txdelay1 %d, txdelay>= %d, txdelay<= %d, txdelay* %d, txdelay/ %d, txdelay+ %d\n", \
- test->test_params.bulk.tx_delay, test->test_params.bulk.tx_delay_min, \
- test->test_params.bulk.tx_delay_max, test->test_params.bulk.tx_delay_multiplier, \
- test->test_params.bulk.tx_delay_divisor, test->test_params.bulk.tx_delay_increment);
- VERBOSE(3, " rxdelay1 %d, rxdelay>= %d, rxdelay<= %d, rxdelay* %d, rxdelay/ %d, rxdelay+ %d\n", \
- test->test_params.bulk.rx_delay, test->test_params.bulk.rx_delay_min, \
- test->test_params.bulk.rx_delay_max, test->test_params.bulk.rx_delay_multiplier, \
- test->test_params.bulk.rx_delay_divisor, test->test_params.bulk.rx_delay_increment);
-
-
- // That is all the data converted from Tcl to C, and a local thread is set up to handle this
- // request. Also set up a thread on the target.
- request_index = 0;
- pack_usbtest_bulk(&(test->test_params.bulk), request, &request_index);
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_TEST_BULK, 0, 0, request_index, request);
- remote_thread_count++;
-
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ start control-in test */
-
-// ----------------------------------------------------------------------------
-// Start a control-in test. The real Tcl interface to this
-// functionality is implemented in Tcl: it takes care of figuring out
-// sensible default arguments, validating the data, etc. All that this
-// code does is allocate a thread and fill in the appropriate data,
-// plus request the target-side to do the same thing.
-
-static int
-tcl_test_control_in(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- int i;
- int tmp;
- UsbTest* test;
- unsigned char request[USBTEST_MAX_CONTROL_DATA];
- int request_index;
-
- // The data consists of 6 numbers for UsbTest_ControlIn itself, and
- // another 10 numbers for the test data definition.
- if (17 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_test_control_in \"", TCL_STATIC);
- return TCL_ERROR;
- }
- for (i = 1; i < 17; i++) {
- int discard;
- if (TCL_OK != Tcl_GetInt(interp, argv[i], &discard)) {
- Tcl_SetResult(interp, "invalid argument: all arguments should be numbers", TCL_STATIC);
- return TCL_ERROR;
- }
- }
-
- test = pool_allocate();
- test->which_test = usbtest_control_in;
- Tcl_GetInt(interp, argv[1], &(test->test_params.control_in.number_packets));
- Tcl_GetInt(interp, argv[2], &(test->test_params.control_in.packet_size_initial));
- Tcl_GetInt(interp, argv[3], &(test->test_params.control_in.packet_size_min));
- Tcl_GetInt(interp, argv[4], &(test->test_params.control_in.packet_size_max));
- Tcl_GetInt(interp, argv[5], &(test->test_params.control_in.packet_size_multiplier));
- Tcl_GetInt(interp, argv[6], &(test->test_params.control_in.packet_size_increment));
- Tcl_GetInt(interp, argv[7], &tmp);
- test->test_params.bulk.data.format = (usbtestdata) tmp;
- Tcl_GetInt(interp, argv[ 8], &(test->test_params.control_in.data.seed));
- Tcl_GetInt(interp, argv[ 9], &(test->test_params.control_in.data.multiplier));
- Tcl_GetInt(interp, argv[10], &(test->test_params.control_in.data.increment));
- Tcl_GetInt(interp, argv[11], &(test->test_params.control_in.data.transfer_seed_multiplier));
- Tcl_GetInt(interp, argv[12], &(test->test_params.control_in.data.transfer_seed_increment));
- Tcl_GetInt(interp, argv[13], &(test->test_params.control_in.data.transfer_multiplier_multiplier));
- Tcl_GetInt(interp, argv[14], &(test->test_params.control_in.data.transfer_multiplier_increment));
- Tcl_GetInt(interp, argv[15], &(test->test_params.control_in.data.transfer_increment_multiplier));
- Tcl_GetInt(interp, argv[16], &(test->test_params.control_in.data.transfer_increment_increment));
-
- // That is all the data converted from Tcl to C, and a local thread is set up to handle this
- // request. Also set up a thread on the target.
- request_index = 0;
- pack_usbtest_control_in(&(test->test_params.control_in), request, &request_index);
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_TEST_CONTROL_IN, 0, 0,
- request_index, request);
- remote_thread_count++;
-
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ Cancel the current batch of tests */
-
-static int
-tcl_cancel(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv __attribute__ ((unused)) )
-{
- if (1 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::cancel\"", TCL_STATIC);
- return TCL_ERROR;
- }
-
- // Send the request on to the target.
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_CANCEL, 0, 0, 0, (void*)0);
-
- // Now cancel all the local tests. This can be done by resetting the counter
- // of allocated threads: no actual work will have been started yet.
- local_thread_count = 0;
-
- // And synchronise with the target
- if (!usb_sync(usb_master_fd, 30)) {
- fprintf(stderr, "usbhost: error, target has failed to process test cancel request.\n");
- exit(EXIT_FAILURE);
-
- }
- remote_thread_count = 0;
-
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ Run a batch of tests */
-
-// ----------------------------------------------------------------------------
-// This code does an awful lot of the hard work. Start with various utilities.
-
-// Has the current batch finished as far as the local threads are concerned?
-static int
-local_batch_finished(void)
-{
- int result = 1;
- int i;
-
- for (i = 0; i < local_thread_count; i++) {
- if (pool[i].running) {
- result = 0;
- break;
- }
- }
- return result;
-}
-
-// Has the current batch finished as far as remote threads are concerned?
-static int
-remote_batch_finished(void)
-{
- char buf[1];
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_FINISHED,
- 0, 0, 1, (void*) buf);
- return buf[0];
-}
-
-// Perform recovery for a thread on the target. This involves asking the
-// target for recovery information, then performing an appropriate
-// action. If no data is returned then no recovery is needed for this thread.
-static void
-recover_remote(int index)
-{
- unsigned char buffer[USBTEST_MAX_CONTROL_DATA];
- int buffer_index;
- UsbTest_Recovery recovery;
- int i;
-
- if (0 != usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN,
- USBTEST_GET_RECOVERY, 0, index, 12, buffer)) {
- // There is work to be done
- buffer_index = 0;
- unpack_usbtest_recovery(&recovery, buffer, &buffer_index);
-
- // We have an endpoint, a protocol, and a size.
- if (0 == recovery.endpoint) {
- // The target just needs a dummy reserved control message
- usb_reliable_control_message(usb_master_fd, USB_TYPE_RESERVED | USB_RECIP_DEVICE, USBTEST_RESERVED_CONTROL_IN,
- 0, 0, 0, (void*) 0);
- } else if (USB_ENDPOINT_XFER_BULK == recovery.protocol) {
- // Either we need to send some data to the target, or we need to accept some data.
- static unsigned char recovery_buffer[USBTEST_MAX_BULK_DATA + USBTEST_MAX_BULK_DATA_EXTRA];
-
- struct usbdevfs_bulktransfer transfer;
- transfer.ep = recovery.endpoint;
- transfer.timeout = 2000; // Two seconds. Should be plenty, even for a large bulk transfer.
- transfer.data = recovery_buffer;
- if (USB_DIR_IN == (recovery.endpoint & USB_ENDPOINT_DIR_MASK)) {
- transfer.len = recovery.size;
- } else {
- transfer.len = 1;
- }
- errno = 0;
- i = ioctl(usb_master_fd, USBDEVFS_BULK, &transfer);
- }
-
- // There is no recovery support yet for other protocols.
- }
-}
-
-// Perform recovery for a local thread. This involves extracting the
-// recovery information from the local thread and asking the target
-// to take appropriate action.
-static void
-recover_local(int index)
-{
- unsigned char buffer[USBTEST_MAX_CONTROL_DATA];
- int buffer_index;
-
- if (pool[index].running) {
- buffer_index = 0;
- pack_usbtest_recovery(&(pool[index].test.recovery), buffer, &buffer_index);
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_PERFORM_RECOVERY,
- 0, 0, buffer_index, (void*) buffer);
- }
-}
-
-// All done, time for a clean-up on both target and host. The latter
-// is achieved simply by resetting the thread pool, which actually
-// just means resetting the counter since all the threads are blocked
-// waiting for the next batch.
-static void
-run_done(void)
-{
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_BATCH_DONE, 0, 0, 0, (void*) NULL);
- local_thread_count = 0;
- remote_thread_count = 0;
-}
-
-// The main routine, as invoked from Tcl. This takes a single
-// argument, a timeout in seconds.
-static int
-tcl_run(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv __attribute__ ((unused)) )
-{
- struct timespec delay;
- int timeout;
- time_t start;
- time_t now;
- int i, j;
- unsigned char result_buf[USBTEST_MAX_CONTROL_DATA];
- int all_ok;
-
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_run \"", TCL_STATIC);
- return TCL_ERROR;
- }
- if (TCL_OK != Tcl_GetInt(interp, argv[1], &timeout)) {
- Tcl_SetResult(interp, "invalid argument: timeout should be numeric", TCL_STATIC);
- return TCL_ERROR;
- }
-
- VERBOSE(2, "Starting a testrun, timeout %d seconds\n", timeout);
-
- // Start the tests running on the target. The target USB hardware
- // will not actually do anything except in response to packets
- // from the host, so it is better to start the target before the
- // local threads.
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_START, 0, 0, 0, (void*) 0);
-
- // Now the local threads can get going.
- current_tests_terminated = 0;
- pool_start();
-
- // Now leave the various testing threads to do their thing until
- // either side believes that the batch has finished, or until the
- // timeout expires. Note that if one side decides that the batch
- // has finished but the other disagrees, that in itself indicates
- // a test failure of sorts.
- //
- // There is a question of polling frequency. Once a second avoids
- // excessive polling traffic on the USB bus, and should not impose
- // intolerable delays for short-duration tests.
- start = time(NULL);
- do {
- VERBOSE(3, "The tests are running, waiting for termination\n");
- delay.tv_sec = 1;
- delay.tv_nsec = 0;
- nanosleep(&delay, NULL);
- now = time(NULL);
- } while (((start + timeout) > now) && !local_batch_finished() && !remote_batch_finished());
-
- VERBOSE(2, "Termination detected, time elapsed %ld\n", (long) now - start);
-
- // If either side believes that testing is not complete, things
- // get messy. Start by setting the terminated flag. Any tests that
- // are actually still running happily but have not finished within
- // the timeout should detect this and stop.
- if (!local_batch_finished() || !remote_batch_finished()) {
- VERBOSE(2, "Testing is not yet complete, setting TERMINATED flag\n");
- current_tests_terminated = 1;
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_SET_TERMINATED, 0, 0, 0, (void*) 0);
- // And another delay, to give threads a chance to detect the
- // flag's update
- delay.tv_sec = 1;
- delay.tv_nsec = 0;
- nanosleep(&delay, NULL);
- }
-
- // If there is still are unfinished threads, recovery action
- // is needed. It is not clear whether it is better to unlock
- // the local threads first, or the remote threads. For now the
- // latter approach is taken.
- if (!remote_batch_finished()) {
- int i;
- VERBOSE(2, "Remote threads still running, performing remote recovery\n");
- for (i = 0; i < remote_thread_count; i++) {
- recover_remote(i);
- }
- // Allow the recovery actions to take effect
- delay.tv_sec = 1;
- delay.tv_nsec = 0;
- nanosleep(&delay, NULL);
- }
-
- if (!local_batch_finished()) {
- int i;
- VERBOSE(2, "Local threads still running, performing local recovery\n");
- for (i = 0; i < local_thread_count; i++) {
- recover_local(i);
- }
- // Allow the recovery actions to take effect
- delay.tv_sec = 1;
- delay.tv_nsec = 0;
- nanosleep(&delay, NULL);
- }
-
- // One last check to make sure that everything is finished. If not,
- // testing has broken down and it is necessary to abort.
- if (!local_batch_finished() || !remote_batch_finished()) {
- VERBOSE(2, "Giving local and remote threads another chance to finish.\n");
- // Allow the recovery actions to take effect
- delay.tv_sec = 5;
- delay.tv_nsec = 0;
- nanosleep(&delay, NULL);
- if (!local_batch_finished() || !remote_batch_finished()) {
- // OK, normality has not been restored.
- // It would be nice to get hold of and display any error messages.
- usb_abort(usb_master_fd);
- fprintf(stderr, "Fatal error: the host test program and the remote target are out of synch.\n");
- fprintf(stderr, " recovery has been attempted, without success.\n");
- fprintf(stderr, " USB testing cannot continue.\n");
- exit(EXIT_FAILURE);
- }
- }
-
- VERBOSE(2, "Local and remote threads are in synch, collecting results.\n");
-
- // The world is in a coherent state. Time to collect the results.
- // The return value of this function is a simple boolean. More
- // detailed results will be held in a Tcl variable as a list of
- // messages. It is desirable to keep both local and remote results
- // in order.
- for (i = 0; i < ((local_thread_count < remote_thread_count) ? local_thread_count : remote_thread_count); i++) {
- if (!pool[i].test.result_pass) {
- Tcl_SetVar(interp, "usbtest::results", pool[i].test.result_message,
- all_ok ? (TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT) : (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT));
- all_ok = 0;
- }
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_GET_RESULT,
- 0, i, USBTEST_MAX_CONTROL_DATA, (void*) result_buf);
- if (!result_buf[0]) {
- Tcl_SetVar(interp, "usbtest::results", &(result_buf[1]),
- all_ok ? TCL_GLOBAL_ONLY : (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT));
- all_ok = 0;
- }
- }
- for (j = i; j < local_thread_count; j++) {
- if (!pool[j].test.result_pass) {
- Tcl_SetVar(interp, "usbtest::results", pool[j].test.result_message,
- all_ok ? TCL_GLOBAL_ONLY : (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT));
- all_ok = 0;
- }
- }
- for (j = i; j < remote_thread_count; j++) {
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_GET_RESULT,
- 0, i, USBTEST_MAX_CONTROL_DATA, (void*) result_buf);
- if (!result_buf[0]) {
- Tcl_SetVar(interp, "usbtest::results", &(result_buf[1]),
- all_ok ? TCL_GLOBAL_ONLY : (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT));
- all_ok = 0;
- }
- }
- VERBOSE(2, "Overall test result %d\n", all_ok);
-
- Tcl_SetResult(interp, all_ok ? "1" : "0", TCL_STATIC);
-
- run_done();
-
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ Set verbosity */
-
-// ----------------------------------------------------------------------------
-// Allow Tcl scripts to control verbosity levels for both host and target
-static int
-tcl_host_verbose(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- int level;
-
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::host_verbose \"", TCL_STATIC);
- return TCL_ERROR;
- }
- if (TCL_OK != Tcl_GetInt(interp, argv[1], &level)) {
- Tcl_SetResult(interp, "invalid argument: verbosity level should be numeric", TCL_STATIC);
- return TCL_ERROR;
- }
-
- verbose = level;
- return TCL_OK;
-}
-
-static int
-tcl_target_verbose(ClientData clientData __attribute__ ((unused)),
- Tcl_Interp* interp,
- int argc,
- char** argv)
-{
- int level;
-
- if (2 != argc) {
- Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_verbose \"", TCL_STATIC);
- return TCL_ERROR;
- }
- if (TCL_OK != Tcl_GetInt(interp, argv[1], &level)) {
- Tcl_SetResult(interp, "invalid argument: verbosity level should be numeric", TCL_STATIC);
- return TCL_ERROR;
- }
-
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_VERBOSE, level, 0, 0, NULL);
- usb_sync(usb_master_fd, -1);
-
- return TCL_OK;
-}
-
-/*}}}*/
-
-/*}}}*/
-/*{{{ AppInit() */
-
-// ----------------------------------------------------------------------------
-// Application-specific initialization. We have a bare Tcl interpreter ready
-// to start executing scripts that define various test cases. However some
-// additional functions will have to be added to the interpreter, plus
-// information about the various endpoints.
-
-static int
-usbhost_appinit(Tcl_Interp* interp)
-{
- unsigned char buf[USBTEST_MAX_CONTROL_DATA];
- int number_of_endpoints;
- int i;
- char* location;
-
- // Start by creating a usbtest namespace, for use by the various functions
- // and variables.
- if (TCL_OK != Tcl_Eval(interp,
- "namespace eval usbtest {\n"
- " variable number_of_endpoints 0\n"
- " array set endpoint [list]\n"
- "}\n")) {
- fprintf(stderr, "usbhost: internal error, failed to create Tcl usbtest:: namespace\n");
- fprintf(stderr, " Please check Tcl version (8.0b1 or later required).\n");
- exit(EXIT_FAILURE);
- }
-
- // Add some information about the install path so that the
- // main Tcl script can find and execute test scripts.
- location = getenv("USBHOSTDIR");
- if (NULL == location) {
- location = USBAUXDIR;
- }
- Tcl_SetVar(interp, "usbtest::USBAUXDIR", location, TCL_GLOBAL_ONLY);
-
- // Also set the verbosity level correctly
- Tcl_SetVar2Ex(interp, "usbtest::verbose", NULL, Tcl_NewIntObj(verbose), TCL_GLOBAL_ONLY);
-
- // Next we need to know the number of endpoints, and for each
- // endpoint we want additional information such as type. The
- // results are placed in a Tcl array.
- usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN, USBTEST_ENDPOINT_COUNT,
- 0, 0, 1, buf);
- number_of_endpoints = buf[0];
- Tcl_SetVar2Ex(interp, "usbtest::endpoint_count", NULL, Tcl_NewIntObj(number_of_endpoints), TCL_GLOBAL_ONLY);
-
- for (i = 0; i < number_of_endpoints; i++) {
- char varname[256];
- int result;
- int endpoint_min_size;
- int endpoint_max_size;
- int index;
-
- memset(buf, 0, USBTEST_MAX_CONTROL_DATA);
- result = usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_DIR_IN,
- USBTEST_ENDPOINT_DETAILS, 0, i, USBTEST_MAX_CONTROL_DATA, buf);
- if (result < 13) {
- fprintf(stderr, "usbhost: error, received insufficient endpoint data back from the target.\n");
- exit(EXIT_FAILURE);
- }
-
- // See protocol.h for the encoding used.
- sprintf(varname, "usbtest::endpoint_data(%d,type)", i);
- switch(buf[0]) {
- case USB_ENDPOINT_XFER_CONTROL : Tcl_SetVar(interp, varname, "control", TCL_GLOBAL_ONLY); break;
- case USB_ENDPOINT_XFER_ISOC : Tcl_SetVar(interp, varname, "isochronous", TCL_GLOBAL_ONLY); break;
- case USB_ENDPOINT_XFER_BULK : Tcl_SetVar(interp, varname, "bulk", TCL_GLOBAL_ONLY); break;
- case USB_ENDPOINT_XFER_INT : Tcl_SetVar(interp, varname, "interrupt", TCL_GLOBAL_ONLY); break;
- }
-
- sprintf(varname, "usbtest::endpoint_data(%d,number)", i);
- Tcl_SetVar2Ex(interp, varname, NULL, Tcl_NewIntObj((int) buf[1]), TCL_GLOBAL_ONLY);
-
- sprintf(varname, "usbtest::endpoint_data(%d,direction)", i);
- if (USB_DIR_OUT == buf[2]) {
- Tcl_SetVar(interp, varname, "out", TCL_GLOBAL_ONLY);
- } else {
- Tcl_SetVar(interp, varname, "in", TCL_GLOBAL_ONLY);
- }
-
- sprintf(varname, "usbtest::endpoint_data(%d,max_in_padding)", i);
- Tcl_SetVar2Ex(interp, varname, NULL, Tcl_NewIntObj((int) buf[3]), TCL_GLOBAL_ONLY);
-
- sprintf(varname, "usbtest::endpoint_data(%d,min_size)", i);
- index = 4;
- endpoint_min_size = unpack_int(buf, &index);
- Tcl_SetVar2Ex(interp, varname, NULL, Tcl_NewIntObj(endpoint_min_size), TCL_GLOBAL_ONLY);
-
- sprintf(varname, "usbtest::endpoint_data(%d,max_size)", i);
- endpoint_max_size = unpack_int(buf, &index);
- if (USB_ENDPOINT_XFER_CONTROL == buf[0]) {
- if (endpoint_max_size > USBTEST_MAX_CONTROL_DATA) {
- endpoint_max_size = USBTEST_MAX_CONTROL_DATA;
- }
- } else {
- if ((-1 == endpoint_max_size) || (endpoint_max_size > USBTEST_MAX_BULK_DATA)) {
- endpoint_max_size = USBTEST_MAX_BULK_DATA;
- }
- }
- Tcl_SetVar2Ex(interp, varname, NULL, Tcl_NewIntObj(endpoint_max_size), TCL_GLOBAL_ONLY);
-
- sprintf(varname, "usbtest::endpoint_data(%d,devtab)", i);
- Tcl_SetVar(interp, varname, (char*) &(buf[12]), TCL_GLOBAL_ONLY);
-
- // Perform any additional endpoint-specific initialization to make
- // sure host and target can actually communicate via this endpoint.
- switch(buf[0]) {
- case USB_ENDPOINT_XFER_CONTROL :
- {
- usb_initialise_control_endpoint(endpoint_min_size, endpoint_max_size);
- break;
- }
- case USB_ENDPOINT_XFER_ISOC :
- {
- if (USB_DIR_OUT == buf[2]) {
- usb_initialise_isochronous_out_endpoint(buf[1], endpoint_min_size, endpoint_max_size);
- } else {
- usb_initialise_isochronous_in_endpoint(buf[1], endpoint_min_size, endpoint_max_size);
- }
- break;
- }
- case USB_ENDPOINT_XFER_BULK :
- {
- if (USB_DIR_OUT == buf[2]) {
- usb_initialise_bulk_out_endpoint(buf[1], endpoint_min_size, endpoint_max_size);
- } else {
- usb_initialise_bulk_in_endpoint(buf[1], endpoint_min_size, endpoint_max_size, buf[3]);
- }
-
- break;
- }
- case USB_ENDPOINT_XFER_INT :
- {
- if (USB_DIR_OUT == buf[2]) {
- usb_initialise_interrupt_out_endpoint(buf[1], endpoint_min_size, endpoint_max_size);
- } else {
- usb_initialise_interrupt_in_endpoint(buf[1], endpoint_min_size, endpoint_max_size);
- }
- break;
- }
- }
- }
-
- // Register appropriate commands with the Tcl interpreter
- Tcl_CreateCommand(interp, "usbtest::target_pass", &tcl_target_pass, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::target_pass_exit", &tcl_target_pass_exit, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::target_fail", &tcl_target_fail, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::target_fail_exit", &tcl_target_fail_exit, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::target_abort", &tcl_target_abort, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::_test_bulk", &tcl_test_bulk, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::_test_control_in", &tcl_test_control_in, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::_cancel", &tcl_cancel, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::_run", &tcl_run, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::host_verbose", &tcl_host_verbose, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
- Tcl_CreateCommand(interp, "usbtest::target_verbose", &tcl_target_verbose, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL);
-
- return TCL_OK;
-}
-
-/*}}}*/
-/*{{{ main() */
-
-// ----------------------------------------------------------------------------
-// System start-up. After argument processing this code checks that
-// there is a suitable USB target attached - if not then there is no
-// point in proceeding. Otherwise further initialization is performed
-// and then control is passed to a Tcl interpreter.
-
-static void
-usage(void)
-{
- printf("usbhost: usage, usbhost [-V|--verbose] [-v|--version] [-h|--help] [args]\n");
- printf(" -V, --verbose Make the host-side output additional information\n");
- printf(" during test runs. This argument can be repeated to\n");
- printf(" increase verbosity.\n");
- printf(" -v, --version Output version information for usbhost.\n");
- printf(" -h, --help Output this help information.\n");
- printf(" The name of a USB test case, for example list.tcl\n");
- printf(" [args] Optional additional arguments for the testcase.\n");
- exit(0);
-}
-
-static void
-version(void)
-{
- printf("usbhost: version %s\n", USBHOST_VERSION);
- printf(" : built from USB slave package version %s\n", PKGVERSION);
- printf(" : support files installed in %s\n", USBAUXDIR);
- exit(0);
-}
-
-int
-main(int argc, char** argv)
-{
- char* interpreter = argv[0];
- char** new_argv;
- char path[_POSIX_PATH_MAX];
- char* location;
- int i;
-
- // Argument processing
- for (i = 1; i < argc; i++) {
- if ((0 == strcmp("-h", argv[i])) || (0 == strcmp("-H", argv[i])) || (0 == strcmp("--help", argv[i]))) {
- usage();
- }
- if ((0 == strcmp("-v", argv[i])) || (0 == strcmp("--version", argv[i]))) {
- version();
- }
- if ((0 == strcmp("-V", argv[i])) || (0 == strcmp("--verbose", argv[i]))) {
- verbose++;
- continue;
- }
-
- // The first unrecognised argument should correspond to the test script.
- break;
- }
- argc = (argc - i) + 1;
- argv = (argv + i) - 1;
-
- if (1 == argc) {
- fprintf(stderr, "usbhost: at least one test script must be specified on the command line.\n");
- exit(EXIT_FAILURE);
- }
-
- usb_master_fd = usb_open_device();
- if (-1 == usb_master_fd) {
- return EXIT_FAILURE;
- }
-
- // There is a valid USB target. Initialize the pool of threads etc.
- pool_initialize();
-
- // Now start a Tcl interpreter. Tcl_Main() will interpret the
- // first argument as the name of a Tcl script to execute,
- // i.e. usbhost.tcl. This can be found in the install tree,
- // but during development it is inconvenient to run
- // "make install" every time the Tcl script is edited so an
- // environment variable can be used to override the location.
- new_argv = malloc((argc + 2) * sizeof(char*));
- if (NULL == new_argv) {
- fprintf(stderr, "usbhost: internal error, out of memory.\n");
- exit(EXIT_FAILURE);
- }
- new_argv[0] = interpreter;
-
- location = getenv("USBHOSTDIR");
- if (NULL == location) {
- location = USBAUXDIR;
- }
- snprintf(path, _POSIX_PATH_MAX, "%s/usbhost.tcl", location);
- if (0 != access(path, R_OK)) {
- fprintf(stderr, "usbhost: cannot find or access required Tcl script\n");
- fprintf(stderr, " : %s\n", path);
- exit(EXIT_FAILURE);
- }
- new_argv[1] = path;
-
- for (i = 1; i < argc; i++) {
- new_argv[i+1] = argv[i];
- }
- new_argv[i+1] = NULL;
-
- Tcl_Main(i+1, new_argv, &usbhost_appinit);
-
- return EXIT_SUCCESS;
-}
-
-/*}}}*/
Index: slave/v2_0/host/usbhost.tcl
===================================================================
--- slave/v2_0/host/usbhost.tcl (revision 174)
+++ slave/v2_0/host/usbhost.tcl (nonexistent)
@@ -1,531 +0,0 @@
-# {{{ Banner
-
-#===============================================================================
-#
-# usbhost.tcl
-#
-# Support for USB testing
-#
-#===============================================================================
-#####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####
-#
-# Author(s): bartv
-# Date: 2001-07-04
-# Purpose: To provide higher-level utility commands for performing
-# USB testing, and to iterate through the various test scripts
-# specified on the command line.
-#
-#####DESCRIPTIONEND####
-#===============================================================================
-#
-
-# }}}
-
-# {{{ Endpoint data
-
-# Given the raw endpoint data provided by the C code, turn
-# it something more usable from inside Tcl scripts.
-namespace eval usbtest {
- array set control {}
-
- variable bulk_in_endpoints [list]
- array set bulk_in {}
- variable bulk_out_endpoints [list]
- array set bulk_out {}
-
- variable isochronous_in_endpoints [list]
- array set isochronous_in {}
- variable isochronous_out_endpoints [list]
- array set isochronous_out {}
-
- variable interrupt_in_endpoints [list]
- array set interrupt_in {}
- variable interrupt_out_endpoints [list]
- array set interrupt_out {}
-
- for { set i 0 } { $i < $usbtest::endpoint_count } { incr i } {
- switch -- $usbtest::endpoint_data($i,type) {
- "control" {
- set usbtest::control(min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::control(max_size) $usbtest::endpoint_data($i,max_size)
- }
-
- "bulk" {
- set number $usbtest::endpoint_data($i,number)
- if { "in" == $usbtest::endpoint_data($i,direction) } {
- lappend usbtest::bulk_in_endpoints $number
- set usbtest::bulk_in($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::bulk_in($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::bulk_in($number,max_in_padding) $usbtest::endpoint_data($i,max_in_padding)
- set usbtest::bulk_in($number,devtab) $usbtest::endpoint_data($i,devtab)
- } else {
- lappend usbtest::bulk_out_endpoints $number
- set usbtest::bulk_out($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::bulk_out($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::bulk_out($number,devtab) $usbtest::endpoint_data($i,devtab)
- }
- }
-
- "isochronous" {
- set number $usbtest::endpoint_data($i,number)
- if { "in" == $usbtest::endpoint_data($i,direction) } {
- lappend usbtest::isochronous_in_endpoints $number
- set usbtest::isochronous_in($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::isochronous_in($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::isochronous_in($number,devtab) $usbtest::endpoint_data($i,devtab)
- } else {
- lappend usbtest::isochronous_out_endpoints $number
- set usbtest::isochronous_out($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::isochronous_out($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::isochronous_out($number,devtab) $usbtest::endpoint_data($i,devtab)
- }
- }
-
- "interrupt" {
- set number $usbtest::endpoint_data($i,number)
- if { "in" == $usbtest::endpoint_data($i,direction) } {
- lappend usbtest::interrupt_in_endpoints $number
- set usbtest::interrupt_in($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::interrupt_in($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::interrupt_in($number,devtab) $usbtest::endpoint_data($i,devtab)
- } else {
- lappend usbtest::interrupt_out_endpoints $number
- set usbtest::interrupt_out($number,min_size) $usbtest::endpoint_data($i,min_size)
- set usbtest::interrupt_out($number,max_size) $usbtest::endpoint_data($i,max_size)
- set usbtest::interrupt_out($number,devtab) $usbtest::endpoint_data($i,devtab)
- }
- }
-
- default {
- puts stderr "Internal error: invalid endpoint type $usbtest::endpoint_data($i,type)"
- exit 1
- }
- }
- }
-}
-
-# }}}
-# {{{ Constants
-
-# The C code expects to receive certain data as simple numbers,
-# corresponding to #define's in common.c and elsewhere. Strictly
-# speaking it would be better to pass strings to the C code and
-# have it do the translation, thus ensuring that these constants
-# exist in only one place.
-
-namespace eval usbtest {
-
- variable _USB_DIR_IN 0x0080
- variable _DATA_NONE 0
- variable _DATA_BYTE_FILL 1
- variable _DATA_WORD_FILL 2
- variable _DATA_BYTE_GEN 3
- variable _DATA_WORD_GEN 4
- variable _IO_MECHANISM_USB 1
- variable _IO_MECHANISM_DEV 2
-}
-
-# It is also desirable to have some constants corresponding
-# to common random number generators.
-namespace eval usbtest {
- variable MULTIPLIER 1103515245
- variable INCREMENT 12345
-}
-
-# }}}
-# {{{ Argument processing
-
-# ----------------------------------------------------------------------------
-# Given a list of arguments of the form "xyzzy=123" or "xyzzy 123", and
-# an array arguments containing entries such as arguments(xyzzy) and
-# already filled in with default values, update the array using the
-# actual arguments
-namespace eval usbtest {
-
- proc process_arguments { list array_ref } {
- upvar $array_ref array
- array set defined_args [list]
-
- set listlen [llength $list]
- for { set index 0 } { $index < $listlen } { incr index } {
- set arg [lindex $list $index]
- set found 0
- foreach name [array names array] {
- set len [string length $name]
- if { [string equal -length $len $name $arg] } {
- # Partial match found.
- if { [string equal $name $arg] } {
- # Exact match found, The value must be the next arg.
- if { [info exists defined_args($name)] } {
- error "Argument $name should be specified only once"
- }
- incr index
- if { $index >= $listlen } {
- error "Missing value after argument $name"
- }
- set array($name) [lindex $list $index]
- set found 1
- break
- }
-
- # Not an exact match. Try looking for x=y
- incr len
- if { [string equal -length $len "$name=" $arg] } {
- if { [info exists defined_args($name)] } {
- error "Argument $name should be specified only once"
- }
- set array($name) [string range $arg $len end]
- set found 1
- break
- }
- }
- }
- if { ! $found } {
- error "Invalid argument $arg"
- }
- }
- }
-}
-
-# }}}
-# {{{ Starting and ending tests
-
-# This section deals with starting tests, or cleaning up when the
-# tests cannot actually proceed. Also there is some validation,
-# for example to make sure that no endpoint number is used for
-# multiple tests.
-
-namespace eval usbtest {
- variable results
- variable _tests_submitted 0
- variable _control_endpoint_in_use 0
- variable _in_endpoints_in_use [list]
- variable _out_endpoints_in_use [list]
-
- proc reset { } {
- if { 0 != $usbtest::_tests_submitted } {
- usbtest::_cancel
- set usbtest::_tests_submitted 0
-
- }
- set usbtest::_in_endpoints_in_use [list]
- set usbtest::_out_endpoints_in_use [list]
- }
-
- proc use_endpoint { endpoint direction } {
- if { 0 == $endpoint } {
- if { $usbtest::_control_endpoint_in_use } {
- error "Attempt to run multiple tests on the control endpoint"
- }
- set usbtest::_control_endpoint_in_use 1
- } else {
- switch -- $direction {
- "in" {
- if { -1 != [lsearch -exact $usbtest::_in_endpoints_in_use $endpoint] } {
- error "Attempt to run multiple IN tests on endpoint $endpoint"
- }
- lappend usbtest::_in_endpoints_in_use $endpoint
- }
-
- "out" {
- if { -1 != [lsearch -exact $usbtest::_out_endpoints_in_use $endpoint] } {
- error "Attempt to run multiple OUT tests on endpoint $endpoint"
- }
- lappend usbtest::_out_endpoints_in_use $endpoint
- }
-
- default {
- error "Invalid direction passed to usbtest::use_endpoint"
- }
- }
- }
- }
-
- proc test_submitted { } {
- incr usbtest::_tests_submitted
- }
-
- proc start { timeout } {
- set result 0
- if { 0 == $usbtest::_tests_submitted } {
- error "Attempt to start tests when no tests are scheduled to run."
- } elseif { ! [string is integer -strict $timeout] } {
- error "Invalid timeout specified, it should be a simple number."
- } else {
- set usbtest::results [list]
- set result [usbtest::_run $timeout]
- set usbtest::_tests_submitted 0
- set usbtest::_control_endpoint_in_use 0
- array unset _in_endpoints_in_use
- array unset _out_endpoints_in_use
- }
- return $result
- }
-}
-
-# }}}
-# {{{ Bulk tests
-
-# Prepare to run a bulk test.
-#
-# This test requires rather a lot of parameters, many of which
-# will have sensible defaults.
-
-namespace eval usbtest {
-
- proc bulktest { endpoint direction number_packets args } {
-
-
- # Parameters to be passed to the C code. Most are
- # held in an array indexed by the option name,
- # facilitating command-line parsing.
- set arguments(format) "none"
- set arguments(data1) 0
- set arguments(data*) 1
- set arguments(data+) 0
- set arguments(data1*) 1
- set arguments(data1+) 0
- set arguments(data**) 1
- set arguments(data*+) 0
- set arguments(data+*) 1
- set arguments(data++) 0
- set arguments(mechanism) "usb"
- set arguments(txsize1) 32
- set arguments(txsize>=) 0
- set arguments(txsize<=) -1
- set arguments(txsize*) 1
- set arguments(txsize/) 1
- set arguments(txsize+) 0
- set arguments(rxsize1) 0
- set arguments(rxsize>=) 0
- set arguments(rxsize<=) -1
- set arguments(rxsize*) 1
- set arguments(rxsize/) 1
- set arguments(rxsize+) 0
- set arguments(txdelay1) 0
- set arguments(txdelay>=) 0
- set arguments(txdelay<=) 1000000000
- set arguments(txdelay*) 1
- set arguments(txdelay/) 1
- set arguments(txdelay+) 0
- set arguments(rxdelay1) 0
- set arguments(rxdelay>=) 0
- set arguments(rxdelay<=) 1000000000
- set arguments(rxdelay*) 1
- set arguments(rxdelay/) 1
- set arguments(rxdelay+) 0
-
- set endpoint_param ""
-
- # Target limits
- set target_min_size 0
- set target_max_size 0
- set target_padding 0
- set target_devtab ""
-
- # Start by validating the endpoint and direction arguments.
- # Also check that the specified endpoint is not yet in use.
- if { ![string is integer -strict $endpoint] } {
- error "Invalid endpoint argument \"$endpoint\": should be a number"
- }
- if { ($endpoint < 1) || ($endpoint > 15) } {
- error "Invalid bulk endpoint argument \"$endpoint\": should be between 1 and 15"
- }
- switch -- $direction {
- "in" -
- "In" -
- "IN" {
- set direction "in"
- if { -1 == [lsearch -exact $usbtest::bulk_in_endpoints $endpoint] } {
- error "Invalid bulk endpoint argument \"$endpoint\": the target does not list that as a bulk IN endpoint"
- }
- set target_min_size $usbtest::bulk_in($endpoint,min_size)
- set target_max_size $usbtest::bulk_in($endpoint,max_size)
- set target_padding $usbtest::bulk_in($endpoint,max_in_padding)
- set target_devtab $usbtest::bulk_in($endpoint,devtab);
- set endpoint_param [expr $endpoint | $usbtest::_USB_DIR_IN]
- }
-
- "out" -
- "Out" -
- "OUT" {
- set direction "out"
- if { -1 == [lsearch -exact $usbtest::bulk_out_endpoints $endpoint] } {
- error "Invalid bulk endpoint argument \"$endpoint\": the target does not list that as a bulk OUT endpoint"
- }
- set target_min_size $usbtest::bulk_out($endpoint,min_size)
- set target_max_size $usbtest::bulk_out($endpoint,max_size)
- set target_devtab $usbtest::bulk_out($endpoint,devtab);
- set target_padding 0; # Not applicable
- set endpoint_param $endpoint
- }
-
- default {
- error "Invalid direction argument \"$direction\": should be \"in\" or \"out\""
- }
- }
-
- # Now parse any remaining arguments
- usbtest::process_arguments $args arguments
-
- # Convert two of the arguments from strings to numbers, for the
- # convenience of the C code
- switch -- $arguments(format) {
- "none" { set arguments(format) $usbtest::_DATA_NONE }
- "bytefill" { set arguments(format) $usbtest::_DATA_BYTE_FILL }
- "wordfill" { set arguments(format) $usbtest::_DATA_WORD_FILL }
- "byteseq" { set arguments(format) $usbtest::_DATA_BYTE_GEN }
- "wordseq" { set arguments(format) $usbtest::_DATA_WORD_GEN }
-
- default {
- error "Invalid data format argument \"$arguments(data)\"\n \
- Should be \"none\", \"bytefill\", \"wordfill\", \"byteseq\" or \"wordseq\""
- }
- }
- switch -- $arguments(mechanism) {
- "usb" { set arguments(mechanism) $usbtest::_IO_MECHANISM_USB }
- "devtab" { set arguments(mechanism) $usbtest::_IO_MECHANISM_DEV }
-
- default {
- error "Invalid mechanism argument \"$arguments(mechanism)\"\n \
- Should be \"usb\" or \"devtab\""
- }
- }
-
- puts "validating fields"
- # Validate the remaining fields
- foreach field [list data1 data* data+ data1* data1+ data** data*+ data+* data++ \
- txsize1 txsize>= txsize<= txsize* txsize/ txsize+ \
- rxsize1 rxsize>= rxsize<= rxsize* rxsize/ rxsize+ \
- txdelay1 txdelay>= txdelay<= txdelay* txdelay/ txdelay+ \
- rxdelay1 rxdelay>= rxdelay<= rxdelay* rxdelay/ rxdelay+] {
- if { ![string is integer -strict $arguments($field)] } {
- error "Invalid value \"$arguments($field)\" for argument $field, should be an integer."
- }
- }
-
- if { $arguments(txsize>=) < $target_min_size } {
- set arguments(txsize>=) $target_min_size
- }
- if { (-1 == $arguments(txsize<=) ) || ($arguments(txsize<=) > $target_max_size) } {
- set arguments(txsize<=) $target_max_size
- }
- if { $arguments(rxsize<=) == -1 } {
- set arguments(rxsize<=) $target_max_size
- }
- if { $arguments(txsize1) < $arguments(txsize>=) } {
- set arguments(txsize1) $arguments(txsize>=)
- }
- # Make sure the endpoint is not already in use
- usbtest::use_endpoint $endpoint $direction
-
- puts "Submitting test"
- # Now submit the test. This is handled by C code.
- usbtest::_test_bulk \
- $number_packets \
- $endpoint_param \
- $arguments(txsize1) \
- $arguments(txsize>=) \
- $arguments(txsize<=) \
- $arguments(txsize*) \
- $arguments(txsize/) \
- $arguments(txsize+) \
- $arguments(rxsize1) \
- $arguments(rxsize>=) \
- $arguments(rxsize<=) \
- $arguments(rxsize*) \
- $arguments(rxsize/) \
- $arguments(rxsize+) \
- $target_padding \
- $arguments(txdelay1) \
- $arguments(txdelay>=) \
- $arguments(txdelay<=) \
- $arguments(txdelay*) \
- $arguments(txdelay/) \
- $arguments(txdelay+) \
- $arguments(rxdelay1) \
- $arguments(rxdelay>=) \
- $arguments(rxdelay<=) \
- $arguments(rxdelay*) \
- $arguments(rxdelay/) \
- $arguments(rxdelay+) \
- $arguments(mechanism) \
- $arguments(format) \
- $arguments(data1) \
- $arguments(data*) \
- $arguments(data+) \
- $arguments(data1*) \
- $arguments(data1+) \
- $arguments(data**) \
- $arguments(data*+) \
- $arguments(data+*) \
- $arguments(data++)
-
- test_submitted
- }
-}
-
-# }}}
-# {{{ Execute the specified test script
-
-# Interpret the arguments as a test script plus auxiliary data.
-set script [lindex $::argv 0]
-set ::argv [lrange $::argv 1 end]
-
-set result [catch {
- set path [file join [pwd] $script]
- if { ![file exists $path] } {
- set path "$path.tcl"
- if { ![file exists $path] } {
- set path [file join $usbtest::USBAUXDIR $script]
- if { ![file exists $path] } {
- set path "$path.tcl"
- if { ![file exists $path] } {
- error "Error: unknown test script $script"
- }
- }
- }
- }
-
- source $path
-
-} message]
-
-if { 0 != $result } {
- puts $message
-}
-
-# }}}
Index: slave/v2_0/host/Makefile.am
===================================================================
--- slave/v2_0/host/Makefile.am (revision 174)
+++ slave/v2_0/host/Makefile.am (nonexistent)
@@ -1,114 +0,0 @@
-## Process this file with automake to produce Makefile.in
-## =====================================================================
-##
-## Makefile.am
-##
-## Build support for the eCos USB host-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####
-##
-## Author(s): bartv
-## Contact(s): bartv
-## Date: 2002/01/10
-## Version: 0.01
-##
-######DESCRIPTIONEND####
-## =====================================================================
-
-AUTOMAKE_OPTIONS = 1.3 foreign
-
-## Only some platforms are supported. Having the configure script throw
-## an error when attempting to configure on an unsupported platform
-## would be a mistake, since that would prevent any configury from
-## the toplevel on unsupported platforms. Instead an automake conditional
-## is used, leading to null makefiles on unsupported platforms.
-
-if SUPPORTED
-
-AM_CFLAGS = @ecos_CFLAGS@ -DUSBHOST_VERSION=\"@VERSION@\" -DPKGVERSION=\"@PACKAGE_VERSION@\" -DUSBAUXDIR=\"$(libexecdir)/ecos/@PACKAGE_INSTALL@\"
-AM_CXXFLAGS = @ecos_CXXFLAGS@
-INCLUDES = @ecos_INCLUDES@
-LIBS = @ecos_LIBS@ @ecos_LDADD@
-
-## The USB testing support consists of two programs, usbhost and
-## usbchmod, and a number of Tcl scripts. usbhost is executable by the
-## user so it should get installed in bindir, appropriately prefixed
-## and with a symbolic link installed as per e.g. tclsh (it is known
-## that this code is Linux-specific so the use of symbolic links is
-## not a problem). usbchmod is not directly executable so it should
-## get installed in or below libexec. The Tcl scripts are architecture
-## independent so should probably be installed below $(datadir), but
-## for now putting them in the same directory as usbchmod will do
-## fine.
-
-noinst_PROGRAMS = usbhost
-usbhost_SOURCES = usbhost.c
-usbhost_DEPENDENCIES = ../tests/protocol.h ../tests/common.c
-usbhost_LDADD = -lpthread
-
-usbauxdir = $(libexecdir)/ecos/@PACKAGE_INSTALL@
-usbaux_PROGRAMS = usbchmod
-usbaux_DATA = usbhost.tcl list.tcl verbose.tcl
-usbchmod_SOURCES = usbchmod.c
-
-## Two special operations are required during installation.
-## 1) usbhost needs to be installed suitably versioned, e.g. as
-## usbhost_current, and with a symbolic link from usbhost to
-## the new executable.
-## 2) usbchmod needs to be suid root
-install-exec-hook:
- $(INSTALL_PROGRAM) usbhost $(bindir)/usbhost_@PACKAGE_VERSION@
- rm -f $(bindir)/usbhost
- $(LN_S) $(bindir)/usbhost_@PACKAGE_VERSION@ $(bindir)/usbhost
-
-install-data-hook:
- chown root $(usbauxdir)/usbchmod
- chmod u+s $(usbauxdir)/usbchmod
-
-else
-
-## When automake scans for hooks it does not take conditionals fully
-## into account. If the conditional is not satisfied the generated
-## makefile will still try to invoke the hook, so dummy hooks are needed.
-install-exec-hook:
- echo Nothing to be done for this platform
-
-install-data-hook:
- echo Nothing to be done for this platform
-
-endif
Index: slave/v2_0/host/list.tcl
===================================================================
--- slave/v2_0/host/list.tcl (revision 174)
+++ slave/v2_0/host/list.tcl (nonexistent)
@@ -1,130 +0,0 @@
-# {{{ Banner
-
-#===============================================================================
-#
-# list.tcl
-#
-# Support for USB testing
-#
-#===============================================================================
-#####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####
-#
-# Author(s): bartv
-# Date: 2001-08-21
-# Purpose: Provide details of the available endpoints
-#
-#####DESCRIPTIONEND####
-#===============================================================================
-#
-
-# }}}
-
-puts "Control endpoint: valid packet sizes are $usbtest::control(min_size) to $usbtest::control(max_size)"
-
-if { 0 != [llength $usbtest::bulk_in_endpoints] } {
- puts "Bulk IN endpoints: $usbtest::bulk_in_endpoints"
- foreach ep $usbtest::bulk_in_endpoints {
- puts [format " %2d: packet sizes %d to %d, padding %d" $ep \
- $usbtest::bulk_in($ep,min_size) $usbtest::bulk_in($ep,max_size) $usbtest::bulk_in($ep,max_in_padding)]
- if { "" == $usbtest::bulk_in($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::bulk_in($ep,devtab)"
- }
- }
-}
-if { 0 != [llength $usbtest::bulk_out_endpoints] } {
- puts "Bulk OUT endpoints: $usbtest::bulk_out_endpoints"
- foreach ep $usbtest::bulk_out_endpoints {
- puts [format " %2d: packet sizes %d to %d" $ep \
- $usbtest::bulk_out($ep,min_size) $usbtest::bulk_out($ep,max_size)]
- if { "" == $usbtest::bulk_out($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::bulk_out($ep,devtab)"
- }
- }
-}
-
-if { 0 != [llength $usbtest::isochronous_in_endpoints] } {
- puts "Isochronous IN endpoints: $usbtest::isochronous_in_endpoints"
- foreach ep $usbtest::isochronous_in_endpoints {
- puts [format " %2d: packet sizes %d to %d" $ep \
- $usbtest::isochronous_in($ep,min_size) $usbtest::isochronous_in($ep,max_size)]
- if { "" == $usbtest::isochronous_in($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::isochronous_in($ep,devtab)"
- }
- }
-}
-if { 0 != [llength $usbtest::isochronous_out_endpoints] } {
- puts "Isochronous OUT endpoints: $usbtest::isochronous_out_endpoints"
- foreach ep $usbtest::isochronous_out_endpoints {
- puts [format " %2d: packet sizes %d to %d" $ep \
- $usbtest::isochronous_out($ep,min_size) $usbtest::isochronous_out($ep,max_size)]
- if { "" == $usbtest::isochronous_out($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::isochronous_out($ep,devtab)"
- }
- }
-}
-
-if { 0 != [llength $usbtest::interrupt_in_endpoints] } {
- puts "Interrupt IN endpoints: $usbtest::interrupt_in_endpoints"
- foreach ep $usbtest::interrupt_in_endpoints {
- puts [format " %2d: packet sizes %d to %d" $ep \
- $usbtest::interrupt_in($ep,min_size) $usbtest::interrupt_in($ep,max_size)]
- if { "" == $usbtest::interrupt_in($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::interrupt_in($ep,devtab)"
- }
- }
-}
-if { 0 != [llength $usbtest::interrupt_out_endpoints] } {
- puts "Interrupt OUT endpoints: $usbtest::interrupt_out_endpoints"
- foreach ep $usbtest::interrupt_out_endpoints {
- puts [format " %2d: packet sizes %d to %d" $ep \
- $usbtest::interrupt_out($ep,min_size) $usbtest::interrupt_out($ep,max_size)]
- if { "" == $usbtest::interrupt_out($ep,devtab) } {
- puts " no devtab entry"
- } else {
- puts " devtab entry $usbtest::interrupt_out($ep,devtab)"
- }
- }
-}
Index: slave/v2_0/host/aclocal.m4
===================================================================
--- slave/v2_0/host/aclocal.m4 (revision 174)
+++ slave/v2_0/host/aclocal.m4 (nonexistent)
@@ -1,192 +0,0 @@
-dnl aclocal.m4 generated automatically by aclocal 1.4-p5
-
-dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl This program is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-dnl PARTICULAR PURPOSE.
-
-dnl Process this file with aclocal to get an aclocal.m4 file. Then
-dnl process that with autoconf.
-dnl ====================================================================
-dnl
-dnl acinclude.m4
-dnl
-dnl ====================================================================
-dnl ####ECOSGPLCOPYRIGHTBEGIN####
-dnl -------------------------------------------
-dnl This file is part of eCos, the Embedded Configurable Operating System.
-dnl Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-dnl
-dnl eCos is free software; you can redistribute it and/or modify it under
-dnl the terms of the GNU General Public License as published by the Free
-dnl Software Foundation; either version 2 or (at your option) any later version.
-dnl
-dnl eCos is distributed in the hope that it will be useful, but WITHOUT ANY
-dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
-dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-dnl for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License along
-dnl with eCos; if not, write to the Free Software Foundation, Inc.,
-dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-dnl
-dnl As a special exception, if other files instantiate templates or use macros
-dnl or inline functions from this file, or you compile this file and link it
-dnl with other works to produce a work based on this file, this file does not
-dnl by itself cause the resulting work to be covered by the GNU General Public
-dnl License. However the source code for this file must still be made available
-dnl in accordance with section (3) of the GNU General Public License.
-dnl
-dnl This exception does not invalidate any other reasons why a work based on
-dnl this file might be covered by the GNU General Public License.
-dnl
-dnl Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-dnl at http://sources.redhat.com/ecos/ecos-license/
-dnl -------------------------------------------
-dnl ####ECOSGPLCOPYRIGHTEND####
-dnl ====================================================================
-dnl#####DESCRIPTIONBEGIN####
-dnl
-dnl Author(s): bartv
-dnl Contact(s): bartv
-dnl Date: 2002/01/10
-dnl Version: 0.01
-dnl
-dnl####DESCRIPTIONEND####
-dnl ====================================================================
-
-dnl Access shared macros.
-dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not
-dnl incorporate the macro into aclocal.m4
-sinclude(../../../../../../acsupport/acinclude.m4)
-
-# Define a conditional.
-
-AC_DEFUN([AM_CONDITIONAL],
-[AC_SUBST($1_TRUE)
-AC_SUBST($1_FALSE)
-if $2; then
- $1_TRUE=
- $1_FALSE='#'
-else
- $1_TRUE='#'
- $1_FALSE=
-fi])
-
-# Do all the work for Automake. This macro actually does too much --
-# some checks are only needed if your package does certain things.
-# But this isn't really a big deal.
-
-# serial 1
-
-dnl Usage:
-dnl AM_INIT_AUTOMAKE(package,version, [no-define])
-
-AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_REQUIRE([AC_PROG_INSTALL])
-PACKAGE=[$1]
-AC_SUBST(PACKAGE)
-VERSION=[$2]
-AC_SUBST(VERSION)
-dnl test to see if srcdir already configured
-if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
- AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
-fi
-ifelse([$3],,
-AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
-AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
-AC_REQUIRE([AM_SANITY_CHECK])
-AC_REQUIRE([AC_ARG_PROGRAM])
-dnl FIXME This is truly gross.
-missing_dir=`cd $ac_aux_dir && pwd`
-AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
-AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
-AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
-AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
-AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
-AC_REQUIRE([AC_PROG_MAKE_SET])])
-
-#
-# Check to make sure that the build environment is sane.
-#
-
-AC_DEFUN([AM_SANITY_CHECK],
-[AC_MSG_CHECKING([whether build environment is sane])
-# Just in case
-sleep 1
-echo timestamp > conftestfile
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
- if test "[$]*" = "X"; then
- # -L didn't work.
- set X `ls -t $srcdir/configure conftestfile`
- fi
- if test "[$]*" != "X $srcdir/configure conftestfile" \
- && test "[$]*" != "X conftestfile $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
-alias in your environment])
- fi
-
- test "[$]2" = conftestfile
- )
-then
- # Ok.
- :
-else
- AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-rm -f conftest*
-AC_MSG_RESULT(yes)])
-
-dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
-dnl The program must properly implement --version.
-AC_DEFUN([AM_MISSING_PROG],
-[AC_MSG_CHECKING(for working $2)
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf. Sigh.
-if ($2 --version) < /dev/null > /dev/null 2>&1; then
- $1=$2
- AC_MSG_RESULT(found)
-else
- $1="$3/missing $2"
- AC_MSG_RESULT(missing)
-fi
-AC_SUBST($1)])
-
-# Add --enable-maintainer-mode option to configure.
-# From Jim Meyering
-
-# serial 1
-
-AC_DEFUN([AM_MAINTAINER_MODE],
-[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
- dnl maintainer-mode is disabled by default
- AC_ARG_ENABLE(maintainer-mode,
-[ --enable-maintainer-mode enable make rules and dependencies not useful
- (and sometimes confusing) to the casual installer],
- USE_MAINTAINER_MODE=$enableval,
- USE_MAINTAINER_MODE=no)
- AC_MSG_RESULT($USE_MAINTAINER_MODE)
- AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
- MAINT=$MAINTAINER_MODE_TRUE
- AC_SUBST(MAINT)dnl
-]
-)
-