mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-18 04:43:34 +08:00
Resync new repository with old repo r5166
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
menu "Device Controller Driver Options"
|
||||
|
||||
config USBDEV_ISOCHRONOUS
|
||||
bool "Enable isochronous"
|
||||
default n
|
||||
---help---
|
||||
Build in extra support for isochronous endpoints
|
||||
|
||||
config USBDEV_DUALSPEED
|
||||
bool "Enable high and full speed"
|
||||
default n
|
||||
---help---
|
||||
Hardware handles high and full speed operation (USB 2.0)
|
||||
|
||||
choice USBDEV_POWERED
|
||||
prompt "Select USB device powered"
|
||||
default USBDEV_SELFPOWERED
|
||||
|
||||
config USBDEV_SELFPOWERED
|
||||
bool "Self powered"
|
||||
---help---
|
||||
Will cause USB features to indicate that the device is self-powered
|
||||
|
||||
config USBDEV_BUSPOWERED
|
||||
bool "Bus powered"
|
||||
---help---
|
||||
Will cause USB features to indicate that the device is self-powered
|
||||
|
||||
endchoice
|
||||
|
||||
config USBDEV_MAXPOWER
|
||||
int "Maximum power consumption in mA"
|
||||
default 100
|
||||
depends on USBDEV_BUSPOWERED
|
||||
---help---
|
||||
Maximum power consumption in mA
|
||||
|
||||
config USBDEV_DMA
|
||||
bool "Enable DMA methods"
|
||||
default n
|
||||
---help---
|
||||
Select this enable DMA-related methods in USB device controller driver
|
||||
interface. These methods include the DMA buffer allocation methods:
|
||||
allobuffer() and freebuffer().
|
||||
|
||||
The USB class driver allocates packet I/O buffers for data transfer by
|
||||
calling the driver allocbuffer() and freebuffer() methods. Those methods
|
||||
are only available if USBDEV_DMA is defined in the system configuration.
|
||||
|
||||
config USBDEV_DMAMEMORY
|
||||
bool "Board DMA Allocation Hooks"
|
||||
default n
|
||||
depends on USBDEV_DMA
|
||||
---help---
|
||||
The USB class driver allocates packet I/O buffers for data transfer by
|
||||
calling the driver allocbuffer() and freebuffer() methods. Those methods
|
||||
are only available if USBDEV_DMA is defined in the system configuration.
|
||||
|
||||
If USBDEV_DMAMEMORY is also defined in the NuttX configuration, then
|
||||
the driver implementations of the allocbuffer() and freebuffer()
|
||||
methods may use board-specific usbdev_dma_alloc() and usbdev_dma_free().
|
||||
If USBDEV_DMA and USBDEV_DMAMEMORY are both defined, then the board-
|
||||
specific logic must provide the functions usbdev_dma_alloc() and
|
||||
usbdev_dma_free(): usbdev_dma_alloc() will allocate DMA-capable
|
||||
memory of the specified size; usbdev_dma_free() is the corresponding
|
||||
function that will be called to free the DMA-capable memory.
|
||||
|
||||
config USBDEV_TRACE
|
||||
bool "Enable USB tracing for debug"
|
||||
default n
|
||||
---help---
|
||||
Enables USB tracing for debug
|
||||
|
||||
config USBDEV_TRACE_NRECORDS
|
||||
int "Number of trace entries to remember"
|
||||
default 32
|
||||
depends on USBDEV_TRACE
|
||||
---help---
|
||||
Number of trace entries to remember
|
||||
|
||||
endmenu
|
||||
|
||||
menuconfig USBDEV_COMPOSITE
|
||||
bool "USB composite device support"
|
||||
default n
|
||||
---help---
|
||||
Enables USB composite device support
|
||||
|
||||
if USBDEV_COMPOSITE
|
||||
|
||||
#config COMPOSITE_IAD
|
||||
# bool ""
|
||||
# default n
|
||||
# ---help---
|
||||
# If one of the members of the composite has multiple interfaces
|
||||
# (such as CDC/ACM), then an Interface Association Descriptor (IAD)
|
||||
# will be necessary. Default: IAD will be used automatically if
|
||||
# needed. It should not be necessary to set this.
|
||||
|
||||
config COMPOSITE_EP0MAXPACKET
|
||||
int "Max packet size for endpoint 0"
|
||||
default 64
|
||||
---help---
|
||||
Max packet size for endpoint 0
|
||||
|
||||
config COMPOSITE_VENDORID
|
||||
hex "Composite vendor ID"
|
||||
default 0
|
||||
|
||||
config COMPOSITE_VENDORSTR
|
||||
string "Composite vendor ID"
|
||||
default "Nuttx"
|
||||
---help---
|
||||
The vendor ID code/string
|
||||
|
||||
config COMPOSITE_PRODUCTID
|
||||
hex "Composite product id"
|
||||
default 0
|
||||
|
||||
config COMPOSITE_PRODUCTSTR
|
||||
string "Composite product string"
|
||||
default "Composite device"
|
||||
---help---
|
||||
The product ID code/string
|
||||
|
||||
config COMPOSITE_SERIALSTR
|
||||
string "Composite serial string"
|
||||
default "001"
|
||||
---help---
|
||||
Device serial number string
|
||||
|
||||
config COMPOSITE_CONFIGSTR
|
||||
string "Configuration string"
|
||||
default "Nuttx COMPOSITE config"
|
||||
---help---
|
||||
Configuration string
|
||||
|
||||
config COMPOSITE_VERSIONNO
|
||||
string "Composite version number"
|
||||
default ""
|
||||
---help---
|
||||
Interface version number.
|
||||
endif
|
||||
|
||||
menuconfig PL2303
|
||||
bool "Emulates the Prolific PL2303 serial/USB converter"
|
||||
default n
|
||||
---help---
|
||||
This logic emulates the Prolific PL2303 serial/USB converter
|
||||
|
||||
if PL2303
|
||||
config PL2303_EPINTIN
|
||||
int "Logical endpoint numbers"
|
||||
default 1
|
||||
|
||||
config PL2303_EPBULKOUT
|
||||
int "Endpoint Bulkout"
|
||||
default 2
|
||||
|
||||
config PL2303_EPBULKIN
|
||||
int "Endpoint Bulkin"
|
||||
default 3
|
||||
|
||||
config PL2303_EP0MAXPACKET
|
||||
int "Packet and request buffer sizes"
|
||||
default 64
|
||||
|
||||
config PL2303_NWRREQS
|
||||
int "Number of read requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of read requests that can be in flight
|
||||
|
||||
config PL2303_NRDREQS
|
||||
int "Number of write requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of write/read requests that can be in flight
|
||||
|
||||
config PL2303_RXBUFSIZE
|
||||
int "Receive buffer size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the serial receive/transmit buffers
|
||||
|
||||
config PL2303_TXBUFSIZE
|
||||
int "Transmit buffer size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the serial receive/transmit buffers
|
||||
|
||||
config PL2303_VENDORID
|
||||
hex "Vendor ID"
|
||||
default 0x067b
|
||||
|
||||
config PL2303_PRODUCTID
|
||||
hex "Product ID"
|
||||
default 0x2303
|
||||
|
||||
config PL2303_VENDORSTR
|
||||
string "Vendor string"
|
||||
default "NuttX"
|
||||
|
||||
config PL2303_PRODUCTSTR
|
||||
string "Product string"
|
||||
default "USBdev Serial"
|
||||
endif
|
||||
|
||||
menuconfig CDCACM
|
||||
bool "USB Modem (CDC ACM) support"
|
||||
default n
|
||||
---help---
|
||||
Enables USB Modem (CDC ACM) support
|
||||
|
||||
if CDCACM
|
||||
config CDCACM_COMPOSITE
|
||||
bool "CDCACM composite support"
|
||||
default n
|
||||
depends on USBDEV_COMPOSITE
|
||||
---help---
|
||||
Configure the CDC serial driver as part of a composite driver
|
||||
(only if CONFIG_USBDEV_COMPOSITE is also defined)
|
||||
|
||||
config CDCACM_IFNOBASE
|
||||
int "Offset the CDC/ACM interface numbers"
|
||||
default 0
|
||||
depends on CDCACM_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the CDC/ACM interface numbers so that they are
|
||||
unique and contiguous. When used with the Mass Storage driver, the
|
||||
correct value for this offset is zero.
|
||||
|
||||
config CDCACM_STRBASE
|
||||
int "Offset the CDC/ACM string numbers"
|
||||
default 0
|
||||
depends on CDCACM_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the CDC/ACM string numbers so that they are
|
||||
unique and contiguous. When used with the Mass Storage driver, the
|
||||
correct value for this offset is four (this value actuallly only needs
|
||||
to be defined if names are provided for the Notification interface,
|
||||
config CDCACM_NOTIFSTR, or the data interface, CONFIG_CDCACM_DATAIFSTR).
|
||||
|
||||
config CDCACM_EP0MAXPACKET
|
||||
int "Endpoint 0 max packet size"
|
||||
default 64
|
||||
---help---
|
||||
Endpoint 0 max packet size. Default 64.
|
||||
|
||||
config CDCACM_EPINTIN
|
||||
int "Hardware endpoint that supports interrupt IN operation"
|
||||
default 2
|
||||
---help---
|
||||
The logical 7-bit address of a hardware endpoint that supports
|
||||
interrupt IN operation. Default 2.
|
||||
|
||||
config CDCACM_EPINTIN_FSSIZE
|
||||
int "Endpoint in full speed size"
|
||||
default 64
|
||||
---help---
|
||||
Max package size for the interrupt IN endpoint if full speed mode.
|
||||
Default 64.
|
||||
|
||||
config CDCACM_EPINTIN_HSSIZE
|
||||
int "Endpoint in high speed size"
|
||||
default 64
|
||||
---help---
|
||||
Max package size for the interrupt IN endpoint if high speed mode.
|
||||
Default 64.
|
||||
|
||||
config CDCACM_EPBULKOUT
|
||||
int "Endpoint bulk out"
|
||||
default 0
|
||||
---help---
|
||||
The logical 7-bit address of a hardware endpoint that supports
|
||||
bulk OUT operation
|
||||
|
||||
config CDCACM_EPBULKOUT_FSSIZE
|
||||
int "Endpoint bulk out full speed size"
|
||||
default 64
|
||||
---help---
|
||||
Max package size for the bulk OUT endpoint if full speed mode.
|
||||
Default 64.
|
||||
|
||||
config CDCACM_EPBULKOUT_HSSIZE
|
||||
int "Endpoint bulk out high speed size"
|
||||
default 512
|
||||
---help---
|
||||
Max package size for the bulk OUT endpoint if high speed mode.
|
||||
Default 512.
|
||||
|
||||
config CDCACM_EPBULKIN
|
||||
int "Endpoint bulk in"
|
||||
default 0
|
||||
---help---
|
||||
The logical 7-bit address of a hardware endpoint that supports
|
||||
bulk IN operation
|
||||
|
||||
config CDCACM_EPBULKIN_FSSIZE
|
||||
int "Endpoint bulk in full speed size"
|
||||
default 64
|
||||
---help---
|
||||
Max package size for the bulk IN endpoint if full speed mode.
|
||||
Default 64.
|
||||
|
||||
config CDCACM_EPBULKIN_HSSIZE
|
||||
int "Endpoint bulk in high speed size"
|
||||
default 512
|
||||
---help---
|
||||
Max package size for the bulk IN endpoint if high speed mode.
|
||||
Default 512.
|
||||
|
||||
config CDCACM_NWRREQS
|
||||
int "Number of read requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of read requests that can be in flight
|
||||
|
||||
config CDCACM_NRDREQS
|
||||
int "Number of write requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of write/read requests that can be in flight
|
||||
|
||||
config CDCACM_RXBUFSIZE
|
||||
int "Receive buffer size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the serial receive/transmit buffers
|
||||
|
||||
config CDCACM_TXBUFSIZE
|
||||
bool "Transmit buffer size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the serial receive/transmit buffers
|
||||
|
||||
config CDCACM_VENDORID
|
||||
hex "Vendor ID"
|
||||
default 0x0525
|
||||
---help---
|
||||
The vendor ID code/string. Default 0x0525 and "NuttX"
|
||||
0x0525 is the Netchip vendor and should not be used in any
|
||||
products. This default VID was selected for compatibility with
|
||||
the Linux CDC ACM default VID.
|
||||
|
||||
config CDCACM_PRODUCTID
|
||||
hex "Product ID"
|
||||
default 0xa4a7
|
||||
---help---
|
||||
The product ID code/string. Default 0xa4a7 and "CDC/ACM Serial"
|
||||
0xa4a7 was selected for compatibility with the Linux CDC ACM
|
||||
default PID.
|
||||
|
||||
config CDCACM_VENDORSTR
|
||||
string "Vendor string"
|
||||
default "NuttX"
|
||||
|
||||
config CDCACM_PRODUCTSTR
|
||||
string "Product string"
|
||||
default "USBdev Serial"
|
||||
endif
|
||||
|
||||
menuconfig USBMSC
|
||||
bool "USB Mass storage class device"
|
||||
default n
|
||||
---help---
|
||||
References:
|
||||
"Universal Serial Bus Mass Storage Class, Specification Overview,"
|
||||
Revision 1.2, USB Implementer's Forum, June 23, 2003.
|
||||
|
||||
"Universal Serial Bus Mass Storage Class, Bulk-Only Transport,"
|
||||
Revision 1.0, USB Implementer's Forum, September 31, 1999.
|
||||
|
||||
"SCSI Primary Commands - 3 (SPC-3)," American National Standard
|
||||
for Information Technology, May 4, 2005
|
||||
|
||||
"SCSI Primary Commands - 4 (SPC-4)," American National Standard
|
||||
for Information Technology, July 19, 2008
|
||||
|
||||
"SCSI Block Commands -2 (SBC-2)," American National Standard
|
||||
for Information Technology, November 13, 2004
|
||||
|
||||
"SCSI Multimedia Commands - 3 (MMC-3)," American National Standard
|
||||
for Information Technology, November 12, 2001
|
||||
|
||||
if USBMSC
|
||||
config USBMSC_COMPOSITE
|
||||
bool "Mass storage composite support"
|
||||
default n
|
||||
depends on USBDEV_COMPOSITE
|
||||
---help---
|
||||
Configure the mass storage driver as part of a composite driver
|
||||
(only if CONFIG_USBDEV_COMPOSITE is also defined)
|
||||
|
||||
config USBMSC_IFNOBASE
|
||||
int "Offset the mass storage interface number"
|
||||
default 2
|
||||
depends on USBMSC_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the mass storage interface number so that it is
|
||||
unique and contiguous. When used with the CDC/ACM driver, the
|
||||
correct value for this offset is two (because of the two CDC/ACM
|
||||
interfaces that will precede it).
|
||||
|
||||
config USBMSC_STRBASE
|
||||
int "Offset the mass storage string numbers"
|
||||
default 2
|
||||
depends on USBMSC_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the mass storage string numbers so that they are
|
||||
unique and contiguous. When used with the CDC/ACM driver, the
|
||||
correct value for this offset is four (or perhaps 5 or 6, depending
|
||||
on if CONFIG_CDCACM_NOTIFSTR or CONFIG_CDCACM_DATAIFSTR are defined).
|
||||
|
||||
config USBMSC_EP0MAXPACKET
|
||||
int "Max packet size for endpoint 0"
|
||||
default 64
|
||||
---help---
|
||||
Max packet size for endpoint 0
|
||||
|
||||
config USBMSC_EPBULKOUT
|
||||
int "Endpoint bulk out"
|
||||
default 0
|
||||
---help---
|
||||
The logical 7-bit address of a hardware endpoints that support
|
||||
bulk OUT and IN operations
|
||||
|
||||
config USBMSC_EPBULKIN
|
||||
int "Endpoint bulk in"
|
||||
default 0
|
||||
---help---
|
||||
The logical 7-bit address of a hardware endpoints that support
|
||||
bulk OUT and IN operations
|
||||
|
||||
config USBMSC_NWRREQS
|
||||
int "The number of write requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of write/read requests that can be in flight
|
||||
config USBMSC_NRDREQS
|
||||
int "The number of read requests that can be in flight"
|
||||
default 4
|
||||
---help---
|
||||
The number of write/read requests that can be in flight
|
||||
|
||||
config USBMSC_BULKINREQLEN
|
||||
int "Bulk in request size"
|
||||
default 512
|
||||
|
||||
config USBMSC_BULKOUTREQLEN
|
||||
int "Bulk out request size"
|
||||
default 512
|
||||
---help---
|
||||
The size of the buffer in each write/read request. This
|
||||
value needs to be at least as large as the endpoint
|
||||
maxpacket and ideally as large as a block device sector.
|
||||
|
||||
config USBMSC_VENDORID
|
||||
hex "Mass stroage Vendor ID"
|
||||
default 0x00
|
||||
|
||||
config USBMSC_VENDORSTR
|
||||
string "Mass stroage vendor string"
|
||||
default "Nuttx"
|
||||
---help---
|
||||
The vendor ID code/string
|
||||
|
||||
config USBMSC_PRODUCTID
|
||||
hex "Mass stroage Product ID"
|
||||
default 0x00
|
||||
|
||||
config USBMSC_PRODUCTSTR
|
||||
string "Mass stroage product string"
|
||||
default "Mass stroage"
|
||||
|
||||
config USBMSC_VERSIONNO
|
||||
hex "USB MSC Version Number"
|
||||
default "0x399"
|
||||
|
||||
config USBMSC_REMOVABLE
|
||||
bool "Mass stroage remove able"
|
||||
default n
|
||||
---help---
|
||||
Select if the media is removable
|
||||
USB Composite Device Configuration
|
||||
endif
|
||||
@@ -0,0 +1,63 @@
|
||||
############################################################################
|
||||
# drivers/usbdev/Make.defs
|
||||
#
|
||||
# Copyright (C) 2008, 2010-2012 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_USBDEV),y)
|
||||
|
||||
# Include USB device drivers
|
||||
|
||||
ifeq ($(CONFIG_PL2303),y)
|
||||
CSRCS += pl2303.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CDCACM),y)
|
||||
CSRCS += cdcacm.c cdcacm_desc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBMSC),y)
|
||||
CSRCS += usbmsc.c usbmsc_desc.c usbmsc_scsi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
|
||||
CSRCS += composite.c composite_desc.c
|
||||
endif
|
||||
|
||||
CSRCS += usbdev_trace.c usbdev_trprintf.c
|
||||
|
||||
# Include USB device build support
|
||||
|
||||
DEPPATH += --dep-path usbdev
|
||||
VPATH += :usbdev
|
||||
CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/usbdev}
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,350 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/cdcacm.h
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_USBDEV_CDCACM_H
|
||||
#define __DRIVERS_USBDEV_CDCACM_H 1
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdc.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* If the serial device is configured as part of a composite device than both
|
||||
* CONFIG_USBDEV_COMPOSITE and CONFIG_CDCACM_COMPOSITE must be defined.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBDEV_COMPOSITE
|
||||
# undef CONFIG_CDCACM_COMPOSITE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(CONFIG_CDCACM_STRBASE)
|
||||
# define CONFIG_CDCACM_STRBASE (4)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(CONFIG_COMPOSITE_IAD)
|
||||
# warning "CONFIG_COMPOSITE_IAD may be needed"
|
||||
#endif
|
||||
|
||||
/* Packet and request buffer sizes */
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# ifndef CONFIG_CDCACM_EP0MAXPACKET
|
||||
# define CONFIG_CDCACM_EP0MAXPACKET 64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Interface IDs. If the serial driver is built as a component of a composite
|
||||
* device, then the interface IDs may need to be offset.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# undef CONFIG_CDCACM_IFNOBASE
|
||||
# define CONFIG_CDCACM_IFNOBASE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CDCACM_IFNOBASE
|
||||
# define CONFIG_CDCACM_IFNOBASE 0
|
||||
#endif
|
||||
|
||||
/* Descriptors **************************************************************/
|
||||
/* These settings are not modifiable via the NuttX configuration */
|
||||
|
||||
#define CDC_VERSIONNO 0x0110 /* CDC version number 1.10 (BCD) */
|
||||
#define CDCACM_CONFIGIDNONE (0) /* Config ID means to return to address mode */
|
||||
|
||||
/* Interface IDs:
|
||||
*
|
||||
* CDCACM_NINTERFACES Two interfaces
|
||||
* CDCACM_NOTIFID ID of the notifier interface
|
||||
* CDCACM_NOTALTIFID No alternate for the notifier interface
|
||||
* CDCACM_DATAIFID ID of the data interface
|
||||
* CDCACM_DATAALTIFID No alternate for the data interface
|
||||
*/
|
||||
|
||||
#define CDCACM_NINTERFACES (2) /* Number of interfaces in the configuration */
|
||||
#define CDCACM_NOTIFID (CONFIG_CDCACM_IFNOBASE+0)
|
||||
#define CDCACM_NOTALTIFID (0)
|
||||
#define CDCACM_DATAIFID (CONFIG_CDCACM_IFNOBASE+1)
|
||||
#define CDCACM_DATAALTIFID (0)
|
||||
|
||||
/* Configuration descriptor values */
|
||||
|
||||
#define CDCACM_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* Buffer big enough for any of our descriptors (the config descriptor is the
|
||||
* biggest).
|
||||
*/
|
||||
|
||||
#define CDCACM_MXDESCLEN (64)
|
||||
|
||||
/* Device descriptor values */
|
||||
|
||||
#define CDCACM_VERSIONNO (0x0101) /* Device version number 1.1 (BCD) */
|
||||
#define CDCACM_NCONFIGS (1) /* Number of configurations supported */
|
||||
|
||||
/* String language */
|
||||
|
||||
#define CDCACM_STR_LANGUAGE (0x0409) /* en-us */
|
||||
|
||||
/* Descriptor strings. If there serial device is part of a composite device
|
||||
* then the manufacturer, product, and serial number strings will be provided
|
||||
* by the composite logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# define CDCACM_MANUFACTURERSTRID (1)
|
||||
# define CDCACM_PRODUCTSTRID (2)
|
||||
# define CDCACM_SERIALSTRID (3)
|
||||
# define CDCACM_CONFIGSTRID (4)
|
||||
|
||||
# define CDCACM_LASTBASESTRID (4)
|
||||
# undef CONFIG_CDCACM_STRBASE
|
||||
# define CONFIG_CDCACM_STRBASE (0)
|
||||
#else
|
||||
# define CDCACM_LASTBASESTRID CONFIG_CDCACM_STRBASE
|
||||
#endif
|
||||
|
||||
/* These string IDs only exist if a user-defined string is provided */
|
||||
|
||||
#ifdef CONFIG_CDCACM_NOTIFSTR
|
||||
# define CDCACM_NOTIFSTRID (CDCACM_LASTBASESTRID+1)
|
||||
#else
|
||||
# define CDCACM_NOTIFSTRID CDCACM_LASTBASESTRID
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CDCACM_DATAIFSTR
|
||||
# define CDCACM_DATAIFSTRID (CDCACM_NOTIFSTRID+1)
|
||||
#else
|
||||
# define CDCACM_DATAIFSTRID CDCACM_NOTIFSTRID
|
||||
#endif
|
||||
|
||||
#define CDCACM_LASTSTRID CDCACM_DATAIFSTRID
|
||||
#define CDCACM_NSTRIDS (CDCACM_LASTSTRID - CONFIG_CDCACM_STRBASE)
|
||||
|
||||
/* Configuration descriptor size */
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE)
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* Configuration descriptor + (2) interface descriptors + (3) endpoint
|
||||
* descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (9)
|
||||
|
||||
/* The size of the config descriptor: (9 + 2*9 + 3*7 + 4 + 5 + 5) = 62 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(USB_SIZEOF_CFGDESC + 2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \
|
||||
SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
|
||||
#elif defined(CONFIG_COMPOSITE_IAD)
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) interface association descriptor + (2) interface descriptors +
|
||||
* (3) endpoint descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (9)
|
||||
|
||||
/* The size of the config descriptor: (8 + 2*9 + 3*7 + 4 + 5 + 5) = 61 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(USB_SIZEOF_IADDESC +2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \
|
||||
SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
|
||||
#else
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (2) interface descriptors + (3) endpoint descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (8)
|
||||
|
||||
/* The size of the config descriptor: (2*9 + 3*7 + 4 + 5 + 5) = 53 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + SIZEOF_ACM_FUNCDESC + \
|
||||
SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
#endif
|
||||
|
||||
/* Endpoint configuration ****************************************************/
|
||||
|
||||
#define CDCACM_EPINTIN_ADDR (USB_DIR_IN|CONFIG_CDCACM_EPINTIN)
|
||||
#define CDCACM_EPINTIN_ATTR (USB_EP_ATTR_XFER_INT)
|
||||
|
||||
#define CDCACM_EPOUTBULK_ADDR (CONFIG_CDCACM_EPBULKOUT)
|
||||
#define CDCACM_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define CDCACM_EPINBULK_ADDR (USB_DIR_IN|CONFIG_CDCACM_EPBULKIN)
|
||||
#define CDCACM_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
/* Device driver definitions ************************************************/
|
||||
/* A CDC/ACM device is specific by a minor number in the range of 0-255.
|
||||
* This maps to a character device at /dev/ttyACMx, x=0..255.
|
||||
*/
|
||||
|
||||
#define CDCACM_DEVNAME_FORMAT "/dev/ttyACM%d"
|
||||
#define CDCACM_DEVNAME_SIZE 16
|
||||
|
||||
/* Misc Macros **************************************************************/
|
||||
/* MIN/MAX macros */
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
/* Trace values *************************************************************/
|
||||
|
||||
#define CDCACM_CLASSAPI_SETUP TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SETUP)
|
||||
#define CDCACM_CLASSAPI_SHUTDOWN TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SHUTDOWN)
|
||||
#define CDCACM_CLASSAPI_ATTACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_ATTACH)
|
||||
#define CDCACM_CLASSAPI_DETACH TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_DETACH)
|
||||
#define CDCACM_CLASSAPI_IOCTL TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_IOCTL)
|
||||
#define CDCACM_CLASSAPI_RECEIVE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RECEIVE)
|
||||
#define CDCACM_CLASSAPI_RXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXINT)
|
||||
#define CDCACM_CLASSAPI_RXAVAILABLE TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_RXAVAILABLE)
|
||||
#define CDCACM_CLASSAPI_SEND TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_SEND)
|
||||
#define CDCACM_CLASSAPI_TXINT TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXINT)
|
||||
#define CDCACM_CLASSAPI_TXREADY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXREADY)
|
||||
#define CDCACM_CLASSAPI_TXEMPTY TRACE_EVENT(TRACE_CLASSAPI_ID, USBSER_TRACECLASSAPI_TXEMPTY)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
enum cdcacm_epdesc_e
|
||||
{
|
||||
CDCACM_EPINTIN = 0, /* Interrupt IN endpoint descriptor */
|
||||
CDCACM_EPBULKOUT, /* Bulk OUT endpoint descriptor */
|
||||
CDCACM_EPBULKIN /* Bulk IN endpoint descriptor */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring
|
||||
* endpoints)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkepdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the endpoint descriptor using the correct max packet size.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid,
|
||||
uint16_t mxpacket, FAR struct usb_epdesc_s *outdesc);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void);
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVERS_USBDEV_CDCACM_H */
|
||||
@@ -0,0 +1,613 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/cdcacm_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/cdc.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#include "cdcacm.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Describes one description in the group of descriptors forming the
|
||||
* total configuration descriptor.
|
||||
*/
|
||||
|
||||
struct cfgdecsc_group_s
|
||||
{
|
||||
uint16_t descsize; /* Size of the descriptor in bytes */
|
||||
uint16_t hsepsize; /* High speed max packet size */
|
||||
FAR void *desc; /* A pointer to the descriptor */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* USB descriptor templates these will be copied and modified **************/
|
||||
/* Device Descriptor. If the USB serial device is configured as part of
|
||||
* composite device, then the device descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
static const struct usb_devdesc_s g_devdesc =
|
||||
{
|
||||
USB_SIZEOF_DEVDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICE, /* type */
|
||||
{ /* usb */
|
||||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
USB_CLASS_CDC, /* class */
|
||||
CDC_SUBCLASS_NONE, /* subclass */
|
||||
CDC_PROTO_NONE, /* protocol */
|
||||
CONFIG_CDCACM_EP0MAXPACKET, /* maxpacketsize */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_VENDORID), /* vendor */
|
||||
MSBYTE(CONFIG_CDCACM_VENDORID)
|
||||
},
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_PRODUCTID), /* product */
|
||||
MSBYTE(CONFIG_CDCACM_PRODUCTID)
|
||||
},
|
||||
{
|
||||
LSBYTE(CDCACM_VERSIONNO), /* device */
|
||||
MSBYTE(CDCACM_VERSIONNO)
|
||||
},
|
||||
CDCACM_MANUFACTURERSTRID, /* imfgr */
|
||||
CDCACM_PRODUCTSTRID, /* iproduct */
|
||||
CDCACM_SERIALSTRID, /* serno */
|
||||
CDCACM_NCONFIGS /* nconfigs */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor. If the USB serial device is configured as part of
|
||||
* composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{
|
||||
LSBYTE(SIZEOF_CDCACM_CFGDESC), /* LS totallen */
|
||||
MSBYTE(SIZEOF_CDCACM_CFGDESC) /* MS totallen */
|
||||
},
|
||||
CDCACM_NINTERFACES, /* ninterfaces */
|
||||
CDCACM_CONFIGID, /* cfgvalue */
|
||||
CDCACM_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Interface association descriptor */
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_COMPOSITE_IAD)
|
||||
static const struct usb_iaddesc_s g_iaddesc =
|
||||
{
|
||||
USB_SIZEOF_IADDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACEASSOCIATION, /* type */
|
||||
CONFIG_CDCACM_IFNOBASE, /* firstif */
|
||||
CDCACM_NINTERFACES, /* nifs */
|
||||
USB_CLASS_CDC, /* class */
|
||||
CDC_SUBCLASS_ACM, /* subclass */
|
||||
CDC_PROTO_NONE, /* protocol */
|
||||
0 /* ifunction */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Notification interface */
|
||||
|
||||
static const struct usb_ifdesc_s g_notifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
CDCACM_NOTIFID, /* ifno */
|
||||
CDCACM_NOTALTIFID, /* alt */
|
||||
1, /* neps */
|
||||
USB_CLASS_CDC, /* class */
|
||||
CDC_SUBCLASS_ACM, /* subclass */
|
||||
CDC_PROTO_ATM, /* proto */
|
||||
#ifdef CONFIG_CDCACM_NOTIFSTR
|
||||
CDCACM_NOTIFSTRID /* iif */
|
||||
#else
|
||||
0 /* iif */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Header functional descriptor */
|
||||
|
||||
static const struct cdc_hdr_funcdesc_s g_funchdr =
|
||||
{
|
||||
SIZEOF_HDR_FUNCDESC, /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_HDR, /* subtype */
|
||||
{
|
||||
LSBYTE(CDC_VERSIONNO), /* LS cdc */
|
||||
MSBYTE(CDC_VERSIONNO) /* MS cdc */
|
||||
}
|
||||
};
|
||||
|
||||
/* ACM functional descriptor */
|
||||
|
||||
static const struct cdc_acm_funcdesc_s g_acmfunc =
|
||||
{
|
||||
SIZEOF_ACM_FUNCDESC, /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_ACM, /* subtype */
|
||||
0x06 /* caps */
|
||||
};
|
||||
|
||||
/* Union functional descriptor */
|
||||
|
||||
static const struct cdc_union_funcdesc_s g_unionfunc =
|
||||
{
|
||||
SIZEOF_UNION_FUNCDESC(1), /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_UNION, /* subtype */
|
||||
0, /* master */
|
||||
{1} /* slave[0] */
|
||||
};
|
||||
|
||||
/* Interrupt IN endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epintindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPINTIN_ADDR, /* addr */
|
||||
CDCACM_EPINTIN_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE)
|
||||
},
|
||||
0xff /* interval */
|
||||
};
|
||||
|
||||
/* Data interface descriptor */
|
||||
|
||||
static const struct usb_ifdesc_s g_dataifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
CDCACM_DATAIFID, /* ifno */
|
||||
CDCACM_DATAALTIFID, /* alt */
|
||||
2, /* neps */
|
||||
USB_CLASS_CDC_DATA, /* class */
|
||||
CDC_DATA_SUBCLASS_NONE, /* subclass */
|
||||
CDC_DATA_PROTO_NONE, /* proto */
|
||||
#ifdef CONFIG_CDCACM_DATAIFSTR
|
||||
CDCACM_DATAIFSTRID /* iif */
|
||||
#else
|
||||
0 /* iif */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Bulk OUT endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPOUTBULK_ADDR, /* addr */
|
||||
CDCACM_EPOUTBULK_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE)
|
||||
},
|
||||
1 /* interval */
|
||||
};
|
||||
|
||||
/* Bulk IN endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPINBULK_ADDR, /* addr */
|
||||
CDCACM_EPINBULK_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE)
|
||||
},
|
||||
1 /* interval */
|
||||
};
|
||||
|
||||
/* The components of the the configuration descriptor are maintained as
|
||||
* a collection of separate descriptor structure coordinated by the
|
||||
* following array. These descriptors could have been combined into
|
||||
* one larger "super" configuration descriptor structure. However, I
|
||||
* have concerns about compiler-dependent alignment and packing. Since
|
||||
* the individual structures consist only of byte types, alignment and
|
||||
* packing is not an issue. And since the are concatentated at run time
|
||||
* instead of compile time, there should no issues there either.
|
||||
*/
|
||||
|
||||
static const struct cfgdecsc_group_s g_cfggroup[CDCACM_CFGGROUP_SIZE] =
|
||||
{
|
||||
/* Configuration Descriptor. If the serial device is used in as part
|
||||
* or a composite device, then the configuration descriptor is
|
||||
* provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE)
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* 1. Configuration descriptor */
|
||||
0,
|
||||
(FAR void *)&g_cfgdesc
|
||||
},
|
||||
|
||||
/* If the serial device is part of a composite device, then it should
|
||||
* begin with an interface association descriptor (IAD) because the
|
||||
* CDC/ACM device consists of more than one interface. The IAD associates
|
||||
* the two CDC/ACM interfaces with the same CDC/ACM device.
|
||||
*/
|
||||
|
||||
#elif defined(CONFIG_COMPOSITE_IAD)
|
||||
{
|
||||
USB_SIZEOF_IADDESC, /* 1. Interface association descriptor */
|
||||
0,
|
||||
(FAR void *)&g_iaddesc
|
||||
},
|
||||
#endif
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* 2. Notification interface */
|
||||
0,
|
||||
(FAR void *)&g_notifdesc
|
||||
},
|
||||
{
|
||||
SIZEOF_HDR_FUNCDESC, /* 3. Header functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_funchdr
|
||||
},
|
||||
{
|
||||
SIZEOF_ACM_FUNCDESC, /* 4. ACM functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_acmfunc
|
||||
},
|
||||
{
|
||||
SIZEOF_UNION_FUNCDESC(1), /* 5. Union functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_unionfunc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 6. Interrupt IN endpoint descriptor */
|
||||
CONFIG_CDCACM_EPINTIN_HSSIZE,
|
||||
(FAR void *)&g_epintindesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* 7. Data interface descriptor */
|
||||
0,
|
||||
(FAR void *)&g_dataifdesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 8. Bulk OUT endpoint descriptor */
|
||||
CONFIG_CDCACM_EPBULKOUT_HSSIZE,
|
||||
(FAR void *)&g_epbulkoutdesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 9. Bulk OUT endpoint descriptor */
|
||||
CONFIG_CDCACM_EPBULKIN_HSSIZE,
|
||||
(FAR void *)&g_epbulkindesc
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
static const struct usb_qualdesc_s g_qualdesc =
|
||||
{
|
||||
USB_SIZEOF_QUALDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICEQUALIFIER, /* type */
|
||||
{ /* usb */
|
||||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
USB_CLASS_VENDOR_SPEC, /* class */
|
||||
0, /* subclass */
|
||||
0, /* protocol */
|
||||
CONFIG_CDCACM_EP0MAXPACKET, /* mxpacketsize */
|
||||
CDCACM_NCONFIGS, /* nconfigs */
|
||||
0, /* reserved */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc)
|
||||
{
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) || defined(CONFIG_CDCACM_NOTIFSTR) || \
|
||||
defined(CONFIG_CDCACM_DATAIFSTR)
|
||||
|
||||
const char *str;
|
||||
int len;
|
||||
int ndata;
|
||||
int i;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
case 0:
|
||||
{
|
||||
/* Descriptor 0 is the language id */
|
||||
|
||||
strdesc->len = 4;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
strdesc->data[0] = LSBYTE(CDCACM_STR_LANGUAGE);
|
||||
strdesc->data[1] = MSBYTE(CDCACM_STR_LANGUAGE);
|
||||
return 4;
|
||||
}
|
||||
|
||||
case CDCACM_MANUFACTURERSTRID:
|
||||
str = CONFIG_CDCACM_VENDORSTR;
|
||||
break;
|
||||
|
||||
case CDCACM_PRODUCTSTRID:
|
||||
str = CONFIG_CDCACM_PRODUCTSTR;
|
||||
break;
|
||||
|
||||
case CDCACM_SERIALSTRID:
|
||||
str = CONFIG_CDCACM_SERIALSTR;
|
||||
break;
|
||||
|
||||
case CDCACM_CONFIGSTRID:
|
||||
str = CONFIG_CDCACM_CONFIGSTR;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CDCACM_NOTIFSTR
|
||||
case CDCACM_NOTIFSTRID:
|
||||
str = CONFIG_CDCACM_NOTIFSTR;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CDCACM_DATAIFSTR
|
||||
case CDCACM_DATAIFSTRID:
|
||||
str = CONFIG_CDCACM_DATAIFSTR;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The string is utf16-le. The poor man's utf-8 to utf16-le
|
||||
* conversion below will only handle 7-bit en-us ascii
|
||||
*/
|
||||
|
||||
len = strlen(str);
|
||||
for (i = 0, ndata = 0; i < len; i++, ndata += 2)
|
||||
{
|
||||
strdesc->data[ndata] = str[i];
|
||||
strdesc->data[ndata+1] = 0;
|
||||
}
|
||||
|
||||
strdesc->len = ndata+2;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
return strdesc->len;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void)
|
||||
{
|
||||
return &g_devdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint struct (used for configuring
|
||||
* endpoints)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid)
|
||||
{
|
||||
switch (epid)
|
||||
{
|
||||
case CDCACM_EPINTIN: /* Interrupt IN endpoint */
|
||||
return &g_epintindesc;
|
||||
|
||||
case CDCACM_EPBULKOUT: /* Bulk OUT endpoint */
|
||||
return &g_epbulkoutdesc;
|
||||
|
||||
case CDCACM_EPBULKIN: /* Bulk IN endpoint */
|
||||
return &g_epbulkindesc;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkepdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the endpoint descriptor using the correct max packet size.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
void cdcacm_mkepdesc(num cdcacm_epdesc_e epid, uint16_t mxpacket,
|
||||
FAR struct usb_epdesc_s *outdesc)
|
||||
{
|
||||
FAR const struct usb_epdesc_s *indesc;
|
||||
|
||||
/* Copy the "canned" descriptor */
|
||||
|
||||
indesc = cdcacm_getepdesc(epid)
|
||||
memcpy(outdesc, indesc, USB_SIZEOF_EPDESC);
|
||||
|
||||
/* Then add the correct max packet size */
|
||||
|
||||
outdesc->mxpacketsize[0] = LSBYTE(mxpacket);
|
||||
outdesc->mxpacketsize[1] = MSBYTE(mxpacket);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf)
|
||||
#endif
|
||||
{
|
||||
FAR const struct cfgdecsc_group_s *group;
|
||||
FAR uint8_t *dest = buf;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
bool hispeed = (speed == USB_SPEED_HIGH);
|
||||
|
||||
/* Check for switches between high and full speed */
|
||||
|
||||
if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
|
||||
{
|
||||
hispeed = !hispeed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy all of the descriptors in the group */
|
||||
|
||||
for (i = 0, dest = buf; i < CDCACM_CFGGROUP_SIZE; i++)
|
||||
{
|
||||
group = &g_cfggroup[i];
|
||||
|
||||
/* The "canned" descriptors all have full speed endpoint maxpacket
|
||||
* sizes. If high speed is selected, we will have to change the
|
||||
* endpoint maxpacket size.
|
||||
*
|
||||
* Is there a alternative high speed maxpacket size in the table?
|
||||
* If so, that is sufficient proof that the descriptor that we
|
||||
* just copied is an endpoint descriptor and needs the fixup
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (highspeed && group->hsepsize != 0)
|
||||
{
|
||||
cdcacm_mkepdesc(group->desc, group->hsepsize,
|
||||
(FAR struct usb_epdesc_s*)dest);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* Copy the "canned" descriptor with the full speed max packet
|
||||
* size
|
||||
*/
|
||||
|
||||
{
|
||||
memcpy(dest, group->desc, group->descsize);
|
||||
}
|
||||
|
||||
/* Advance to the destination location for the next descriptor */
|
||||
|
||||
dest += group->descsize;
|
||||
}
|
||||
|
||||
return SIZEOF_CDCACM_CFGDESC;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void)
|
||||
{
|
||||
return &g_qualdesc;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,933 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/composite.c
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#include "composite.h"
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes the internal state of the driver */
|
||||
|
||||
struct composite_dev_s
|
||||
{
|
||||
FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
|
||||
uint8_t config; /* Configuration number */
|
||||
FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */
|
||||
struct usbdevclass_driver_s *dev1; /* Device 1 class object */
|
||||
struct usbdevclass_driver_s *dev2; /* Device 2 class object */
|
||||
};
|
||||
|
||||
/* The internal version of the class driver */
|
||||
|
||||
struct composite_driver_s
|
||||
{
|
||||
struct usbdevclass_driver_s drvr;
|
||||
FAR struct composite_dev_s *dev;
|
||||
};
|
||||
|
||||
/* This is what is allocated */
|
||||
|
||||
struct composite_alloc_s
|
||||
{
|
||||
struct composite_dev_s dev;
|
||||
struct composite_driver_s drvr;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
/* USB helps ****************************************************************/
|
||||
|
||||
static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req);
|
||||
static int composite_classsetup(FAR struct composite_dev_s *priv,
|
||||
FAR struct usbdev_s *dev,
|
||||
FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout,
|
||||
size_t outlen);
|
||||
static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep,
|
||||
uint16_t len);
|
||||
static void composite_freereq(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req);
|
||||
|
||||
/* USB class device ********************************************************/
|
||||
|
||||
static int composite_bind(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev);
|
||||
static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev);
|
||||
static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev,
|
||||
FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout,
|
||||
size_t outlen);
|
||||
static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev);
|
||||
static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev);
|
||||
static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* USB class device *********************************************************/
|
||||
|
||||
static const struct usbdevclass_driverops_s g_driverops =
|
||||
{
|
||||
composite_bind, /* bind */
|
||||
composite_unbind, /* unbind */
|
||||
composite_setup, /* setup */
|
||||
composite_disconnect, /* disconnect */
|
||||
composite_suspend, /* suspend */
|
||||
composite_resume, /* resume */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const char g_compvendorstr[] = CONFIG_COMPOSITE_VENDORSTR;
|
||||
const char g_compproductstr[] = CONFIG_COMPOSITE_PRODUCTSTR;
|
||||
const char g_compserialstr[] = CONFIG_COMPOSITE_SERIALSTR;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Helpers
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_ep0incomplete
|
||||
*
|
||||
* Description:
|
||||
* Handle completion of the composite driver's EP0 control operations
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req)
|
||||
{
|
||||
/* Just check the result of the transfer */
|
||||
|
||||
if (req->result || req->xfrd != req->len)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT), (uint16_t)-req->result);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_classsetup
|
||||
*
|
||||
* Description:
|
||||
* Forward a setup command to the appropriate component device
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int composite_classsetup(FAR struct composite_dev_s *priv,
|
||||
FAR struct usbdev_s *dev,
|
||||
FAR const struct usb_ctrlreq_s *ctrl,
|
||||
FAR uint8_t *dataout, size_t outlen)
|
||||
{
|
||||
uint16_t index;
|
||||
uint8_t interface;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
index = GETUINT16(ctrl->index);
|
||||
interface = (uint8_t)(index & 0xff);
|
||||
|
||||
if (interface >= DEV1_FIRSTINTERFACE && interface < (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES))
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen);
|
||||
}
|
||||
else if (interface >= DEV2_FIRSTINTERFACE && interface < (DEV2_FIRSTINTERFACE + DEV2_NINTERFACES))
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_allocreq
|
||||
*
|
||||
* Description:
|
||||
* Allocate a request instance along with its buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep,
|
||||
uint16_t len)
|
||||
{
|
||||
FAR struct usbdev_req_s *req;
|
||||
|
||||
req = EP_ALLOCREQ(ep);
|
||||
if (req != NULL)
|
||||
{
|
||||
req->len = len;
|
||||
req->buf = EP_ALLOCBUFFER(ep, len);
|
||||
if (!req->buf)
|
||||
{
|
||||
EP_FREEREQ(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_freereq
|
||||
*
|
||||
* Description:
|
||||
* Free a request instance along with its buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_freereq(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req)
|
||||
{
|
||||
if (ep != NULL && req != NULL)
|
||||
{
|
||||
if (req->buf != NULL)
|
||||
{
|
||||
EP_FREEBUFFER(ep, req->buf);
|
||||
}
|
||||
EP_FREEREQ(ep, req);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* USB Class Driver Methods
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_bind
|
||||
*
|
||||
* Description:
|
||||
* Invoked when the driver is bound to a USB device driver
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int composite_bind(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
int ret;
|
||||
|
||||
usbtrace(TRACE_CLASSBIND, 0);
|
||||
|
||||
/* Bind the structures */
|
||||
|
||||
priv->usbdev = dev;
|
||||
|
||||
/* Save the reference to our private data structure in EP0 so that it
|
||||
* can be recovered in ep0 completion events.
|
||||
*/
|
||||
|
||||
dev->ep0->priv = priv;
|
||||
|
||||
/* Preallocate one control request */
|
||||
|
||||
priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE);
|
||||
if (priv->ctrlreq == NULL)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCCTRLREQ), 0);
|
||||
ret = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Initialize the pre-allocated control request */
|
||||
|
||||
priv->ctrlreq->callback = composite_ep0incomplete;
|
||||
|
||||
/* Then bind each of the constituent class drivers */
|
||||
|
||||
ret = CLASS_BIND(priv->dev1, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = CLASS_BIND(priv->dev2, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Report if we are selfpowered */
|
||||
|
||||
#ifdef CONFIG_USBDEV_SELFPOWERED
|
||||
DEV_SETSELFPOWERED(dev);
|
||||
#endif
|
||||
|
||||
/* And pull-up the data line for the soft connect function */
|
||||
|
||||
DEV_CONNECT(dev);
|
||||
return OK;
|
||||
|
||||
errout:
|
||||
composite_unbind(driver, dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_unbind
|
||||
*
|
||||
* Description:
|
||||
* Invoked when the driver is unbound from a USB device driver
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
|
||||
usbtrace(TRACE_CLASSUNBIND, 0);
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!driver || !dev || !dev->ep0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract reference to private data */
|
||||
|
||||
priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!priv)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure that we are not already unbound */
|
||||
|
||||
if (priv != NULL)
|
||||
{
|
||||
/* Unbind the constituent class drivers */
|
||||
|
||||
flags = irqsave();
|
||||
CLASS_UNBIND(priv->dev1, dev);
|
||||
CLASS_UNBIND(priv->dev2, dev);
|
||||
|
||||
/* Free the pre-allocated control request */
|
||||
|
||||
priv->config = COMPOSITE_CONFIGIDNONE;
|
||||
if (priv->ctrlreq != NULL)
|
||||
{
|
||||
composite_freereq(dev->ep0, priv->ctrlreq);
|
||||
priv->ctrlreq = NULL;
|
||||
}
|
||||
irqrestore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_setup
|
||||
*
|
||||
* Description:
|
||||
* Invoked for ep0 control requests. This function probably executes
|
||||
* in the context of an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev,
|
||||
FAR const struct usb_ctrlreq_s *ctrl,
|
||||
FAR uint8_t *dataout, size_t outlen)
|
||||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
FAR struct usbdev_req_s *ctrlreq;
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint16_t len;
|
||||
bool dispatched = false;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!driver || !dev || !dev->ep0 || !ctrl)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_SETUPINVALIDARGS), 0);
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract a reference to private data */
|
||||
|
||||
usbtrace(TRACE_CLASSSETUP, ctrl->req);
|
||||
priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!priv)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EP0NOTBOUND2), 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
ctrlreq = priv->ctrlreq;
|
||||
|
||||
/* Extract the little-endian 16-bit values to host order */
|
||||
|
||||
value = GETUINT16(ctrl->value);
|
||||
index = GETUINT16(ctrl->index);
|
||||
len = GETUINT16(ctrl->len);
|
||||
|
||||
uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
|
||||
ctrl->type, ctrl->req, value, index, len);
|
||||
|
||||
if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD)
|
||||
{
|
||||
/**********************************************************************
|
||||
* Standard Requests
|
||||
**********************************************************************/
|
||||
|
||||
switch (ctrl->req)
|
||||
{
|
||||
case USB_REQ_GETDESCRIPTOR:
|
||||
{
|
||||
/* The value field specifies the descriptor type in the MS byte and the
|
||||
* descriptor index in the LS byte (order is little endian)
|
||||
*/
|
||||
|
||||
switch (ctrl->value[1])
|
||||
{
|
||||
case USB_DESC_TYPE_DEVICE:
|
||||
{
|
||||
ret = USB_SIZEOF_DEVDESC;
|
||||
memcpy(ctrlreq->buf, composite_getdevdesc(), ret);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
case USB_DESC_TYPE_DEVICEQUALIFIER:
|
||||
{
|
||||
ret = USB_SIZEOF_QUALDESC;
|
||||
memcpy(ctrlreq->buf, composite_getqualdesc(), ret);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_OTHERSPEEDCONFIG:
|
||||
#endif
|
||||
|
||||
case USB_DESC_TYPE_CONFIG:
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
ret = composite_mkcfgdesc(ctrlreq->buf, dev->speed,
|
||||
ctrl->value[1]);
|
||||
#else
|
||||
ret = composite_mkcfgdesc(ctrlreq->buf);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESC_TYPE_STRING:
|
||||
{
|
||||
/* value == string index. Zero is the language ID. */
|
||||
|
||||
uint8_t strid = ctrl->value[0];
|
||||
FAR struct usb_strdesc_s *buf = (FAR struct usb_strdesc_s *)ctrlreq->buf;
|
||||
|
||||
if (strid <= COMPOSITE_NSTRIDS)
|
||||
{
|
||||
ret = composite_mkstrdesc(strid, buf);
|
||||
}
|
||||
#if DEV1_NSTRIDS > 0
|
||||
else if (strid <= DEV1_STRIDBASE + DEV1_NSTRIDS)
|
||||
{
|
||||
ret = DEV1_MKSTRDESC(strid, buf);
|
||||
}
|
||||
#endif
|
||||
#if DEV2_NSTRIDS > 0
|
||||
else if (strid <= DEV2_STRIDBASE + DEV2_NSTRIDS)
|
||||
{
|
||||
ret = DEV2_MKSTRDESC(strid, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_GETUNKNOWNDESC), value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SETCONFIGURATION:
|
||||
{
|
||||
if (ctrl->type == 0)
|
||||
{
|
||||
/* Save the configuration and inform the constituent classes */
|
||||
|
||||
ret = CLASS_SETUP(priv->dev1, dev, ctrl);
|
||||
dispatched = true;
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev2, dev, ctrl);
|
||||
if (ret >= 0)
|
||||
{
|
||||
priv->config = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GETCONFIGURATION:
|
||||
{
|
||||
if (ctrl->type == USB_DIR_IN)
|
||||
{
|
||||
ctrlreq->buf[0] = priv->config;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SETINTERFACE:
|
||||
{
|
||||
if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE &&
|
||||
priv->config == COMPOSITE_CONFIGID)
|
||||
{
|
||||
ret = composite_classsetup(priv, dev, ctrl, dataout, outlen);
|
||||
dispatched = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GETINTERFACE:
|
||||
{
|
||||
if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
priv->config == COMPOSITE_CONFIGIDNONE)
|
||||
{
|
||||
ret = composite_classsetup(priv, dev, ctrl, dataout, outlen);
|
||||
dispatched = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t recipient;
|
||||
|
||||
/**********************************************************************
|
||||
* Non-Standard Class Requests
|
||||
**********************************************************************/
|
||||
|
||||
/* Class implementations should handle there own interface and endpoint
|
||||
* requests.
|
||||
*/
|
||||
|
||||
recipient = ctrl->type & USB_REQ_RECIPIENT_MASK;
|
||||
if (recipient == USB_REQ_RECIPIENT_INTERFACE || recipient == USB_REQ_RECIPIENT_ENDPOINT)
|
||||
{
|
||||
ret = composite_classsetup(priv, dev, ctrl, dataout, outlen);
|
||||
dispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Respond to the setup command if (1) data was returned, and (2) the request was
|
||||
* NOT successfully dispatched to the component class driver. On an error return
|
||||
* value (ret < 0), the USB driver will stall EP0.
|
||||
*/
|
||||
|
||||
if (ret >= 0 && !dispatched)
|
||||
{
|
||||
/* Setup the request */
|
||||
|
||||
ctrlreq->len = MIN(len, ret);
|
||||
ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
|
||||
|
||||
/* And submit the request to the USB controller driver */
|
||||
|
||||
ret = EP_SUBMIT(dev->ep0, ctrlreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EPRESPQ), (uint16_t)-ret);
|
||||
ctrlreq->result = OK;
|
||||
composite_ep0incomplete(dev->ep0, ctrlreq);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_disconnect
|
||||
*
|
||||
* Description:
|
||||
* Invoked after all transfers have been stopped, when the host is
|
||||
* disconnected. This function is probably called from the context of an
|
||||
* interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
|
||||
usbtrace(TRACE_CLASSDISCONNECT, 0);
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!driver || !dev)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract reference to private data */
|
||||
|
||||
priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!priv)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reset the configuration and inform the constituent class drivers of
|
||||
* the disconnection.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
priv->config = COMPOSITE_CONFIGIDNONE;
|
||||
CLASS_DISCONNECT(priv->dev1, dev);
|
||||
CLASS_DISCONNECT(priv->dev2, dev);
|
||||
irqrestore(flags);
|
||||
|
||||
/* Perform the soft connect function so that we will we can be
|
||||
* re-enumerated.
|
||||
*/
|
||||
|
||||
DEV_CONNECT(dev);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_suspend
|
||||
*
|
||||
* Description:
|
||||
* Invoked on a USB suspend event.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
|
||||
usbtrace(TRACE_CLASSSUSPEND, 0);
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!dev)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract reference to private data */
|
||||
|
||||
priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!priv)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Forward the suspend event to the constituent devices */
|
||||
|
||||
flags = irqsave();
|
||||
CLASS_SUSPEND(priv->dev1, priv->usbdev);
|
||||
CLASS_SUSPEND(priv->dev2, priv->usbdev);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_resume
|
||||
*
|
||||
* Description:
|
||||
* Invoked on a USB resume event.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv = NULL;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!dev)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract reference to private data */
|
||||
|
||||
priv = ((FAR struct composite_driver_s*)driver)->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!priv)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Forward the resume event to the constituent devices */
|
||||
|
||||
flags = irqsave();
|
||||
CLASS_RESUME(priv->dev1, priv->usbdev);
|
||||
CLASS_RESUME(priv->dev2, priv->usbdev);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Name: composite_initialize
|
||||
*
|
||||
* Description:
|
||||
* Register USB composite device as configured. This function will call
|
||||
* board-specific implementations in order to obtain the class objects for
|
||||
* each of the members of the composite (see board_mscclassobject(),
|
||||
* board_cdcclassobjec(), ...)
|
||||
*
|
||||
* Input Parameter:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL "handle" is returned on success. This handle may be used
|
||||
* later with composite_uninitialize() in order to removed the composite
|
||||
* device. This handle is the (untyped) internal representation of the
|
||||
* the class driver instance.
|
||||
*
|
||||
* NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *composite_initialize(void)
|
||||
{
|
||||
FAR struct composite_alloc_s *alloc;
|
||||
FAR struct composite_dev_s *priv;
|
||||
FAR struct composite_driver_s *drvr;
|
||||
int ret;
|
||||
|
||||
/* Allocate the structures needed */
|
||||
|
||||
alloc = (FAR struct composite_alloc_s*)kmalloc(sizeof(struct composite_alloc_s));
|
||||
if (!alloc)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCDEVSTRUCT), 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convenience pointers into the allocated blob */
|
||||
|
||||
priv = &alloc->dev;
|
||||
drvr = &alloc->drvr;
|
||||
|
||||
/* Initialize the USB composite driver structure */
|
||||
|
||||
memset(priv, 0, sizeof(struct composite_dev_s));
|
||||
|
||||
/* Get the constitueat class driver objects */
|
||||
|
||||
ret = DEV1_CLASSOBJECT(&priv->dev1);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
ret = DEV2_CLASSOBJECT(&priv->dev2);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
/* Initialize the USB class driver structure */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
drvr->drvr.speed = USB_SPEED_HIGH;
|
||||
#else
|
||||
drvr->drvr.speed = USB_SPEED_FULL;
|
||||
#endif
|
||||
drvr->drvr.ops = &g_driverops;
|
||||
drvr->dev = priv;
|
||||
|
||||
/* Register the USB composite class driver */
|
||||
|
||||
ret = usbdev_register(&drvr->drvr);
|
||||
if (ret)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_DEVREGISTER), (uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
return (FAR void *)alloc;
|
||||
|
||||
errout_with_alloc:
|
||||
kfree(alloc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_uninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB composite driver. The handle is the USB composite
|
||||
* class' device object as was returned by composite_initialize(). This
|
||||
* function will call board-specific implementations in order to free the
|
||||
* class objects for each of the members of the composite (see
|
||||
* board_mscuninitialize(), board_cdcuninitialize(), ...)
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to composite_initialize().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void composite_uninitialize(FAR void *handle)
|
||||
{
|
||||
FAR struct composite_alloc_s *alloc = (FAR struct composite_alloc_s *)handle;
|
||||
FAR struct composite_dev_s *priv;
|
||||
|
||||
DEBUGASSERT(alloc != NULL);
|
||||
|
||||
/* Uninitialize each of the member classes */
|
||||
|
||||
priv = &alloc->dev;
|
||||
if (priv->dev1)
|
||||
{
|
||||
DEV1_UNINITIALIZE(priv->dev1);
|
||||
priv->dev1 = NULL;
|
||||
}
|
||||
|
||||
if (priv->dev2)
|
||||
{
|
||||
DEV1_UNINITIALIZE(priv->dev2);
|
||||
priv->dev2 = NULL;
|
||||
}
|
||||
|
||||
/* Then unregister and destroy the composite class */
|
||||
|
||||
usbdev_unregister(&alloc->drvr.drvr);
|
||||
|
||||
/* Free any resources used by the composite driver */
|
||||
/* None */
|
||||
|
||||
/* Then free the composite driver state structure itself */
|
||||
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_ep0submit
|
||||
*
|
||||
* Description:
|
||||
* Members of the composite cannot send on EP0 directly because EP0 is
|
||||
* is "owned" by the composite device. Instead, when configured as members
|
||||
* of a composite device, those classes should call this method so that
|
||||
* the composite device can send on EP0 onbehalf of the class.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int composite_ep0submit(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev,
|
||||
FAR struct usbdev_req_s *ctrlreq)
|
||||
{
|
||||
/* This function is not really necessary in the current design. However,
|
||||
* keeping this will provide us a little flexibility in the future if
|
||||
* it becomes necessary to manage the completion callbacks.
|
||||
*/
|
||||
|
||||
return EP_SUBMIT(dev->ep0, ctrlreq);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USBDEV_COMPOSITE */
|
||||
@@ -0,0 +1,326 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/composite.h
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_USBDEV_COMPOSITE_H
|
||||
#define __DRIVERS_USBDEV_COMPOSITE_H 1
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
|
||||
#ifdef CONFIG_CDCACM_COMPOSITE
|
||||
# include <nuttx/usb/cdcacm.h>
|
||||
# include "cdcacm.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
# include "usbmsc.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* Packet sizes */
|
||||
|
||||
#ifndef CONFIG_COMPOSITE_EP0MAXPACKET
|
||||
# define CONFIG_COMPOSITE_EP0MAXPACKET 64
|
||||
#endif
|
||||
|
||||
/* Vendor and product IDs and strings */
|
||||
|
||||
#ifndef CONFIG_COMPOSITE_COMPOSITE
|
||||
# ifndef CONFIG_COMPOSITE_VENDORID
|
||||
# warning "CONFIG_COMPOSITE_VENDORID not defined"
|
||||
# define CONFIG_COMPOSITE_VENDORID 0x03eb
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_COMPOSITE_PRODUCTID
|
||||
# warning "CONFIG_COMPOSITE_PRODUCTID not defined"
|
||||
# define CONFIG_COMPOSITE_PRODUCTID 0x2022
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_COMPOSITE_VERSIONNO
|
||||
# define CONFIG_COMPOSITE_VERSIONNO (0x0101)
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_COMPOSITE_VENDORSTR
|
||||
# warning "No Vendor string specified"
|
||||
# define CONFIG_COMPOSITE_VENDORSTR "NuttX"
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_COMPOSITE_PRODUCTSTR
|
||||
# warning "No Product string specified"
|
||||
# define CONFIG_COMPOSITE_PRODUCTSTR "Composite Device"
|
||||
# endif
|
||||
|
||||
# undef CONFIG_COMPOSITE_SERIALSTR
|
||||
# define CONFIG_COMPOSITE_SERIALSTR "0101"
|
||||
#endif
|
||||
|
||||
#undef CONFIG_COMPOSITE_CONFIGSTR
|
||||
#define CONFIG_COMPOSITE_CONFIGSTR "Composite"
|
||||
|
||||
/* Constituent devices ******************************************************/
|
||||
|
||||
#undef DEV1_IS_CDCACM
|
||||
#undef DEV1_IS_USBMSC
|
||||
|
||||
#undef DEV2_IS_CDCACM
|
||||
#undef DEV2_IS_USBMSC
|
||||
|
||||
/* Pick the first device in the composite. At present, this may only be
|
||||
* the CDC serial device or the mass storage device.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE)
|
||||
# define DEV1_IS_CDCACM 1
|
||||
# define DEV1_MKCFGDESC cdcacm_mkcfgdesc
|
||||
# define DEV1_MKSTRDESC cdcacm_mkstrdesc
|
||||
# define DEV1_CLASSOBJECT board_cdcclassobject
|
||||
# define DEV1_UNINITIALIZE board_cdcuninitialize
|
||||
# define DEV1_NCONFIGS CDCACM_NCONFIGS
|
||||
# define DEV1_CONFIGID CDCACM_CONFIGID
|
||||
# define DEV1_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE
|
||||
# define DEV1_NINTERFACES CDCACM_NINTERFACES
|
||||
# define DEV1_STRIDBASE CONFIG_CDCACM_STRBASE
|
||||
# define DEV1_NSTRIDS CDCACM_NSTRIDS
|
||||
# define DEV1_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC
|
||||
#elif defined(CONFIG_CDCACM_COMPOSITE)
|
||||
# define DEV1_IS_USBMSC 1
|
||||
# define DEV1_MKCFGDESC usbmsc_mkcfgdesc
|
||||
# define DEV1_MKSTRDESC usbmsc_mkstrdesc
|
||||
# define DEV1_CLASSOBJECT board_mscclassobject
|
||||
# define DEV1_UNINITIALIZE board_mscuninitialize
|
||||
# define DEV1_NCONFIGS USBMSC_NCONFIGS
|
||||
# define DEV1_CONFIGID USBMSC_CONFIGID
|
||||
# define DEV1_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV1_NINTERFACES USBMSC_NINTERFACES
|
||||
# define DEV1_STRIDBASE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV1_NSTRIDS USBMSC_NSTRIDS
|
||||
# define DEV1_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC
|
||||
#else
|
||||
# error "No members of the composite defined"
|
||||
#endif
|
||||
|
||||
/* Pick the second device in the composite. At present, this may only be
|
||||
* the CDC serial device or the mass storage device.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(DEV1_IS_CDCACM)
|
||||
# define DEV2_IS_CDCACM 1
|
||||
# define DEV2_MKCFGDESC cdcacm_mkcfgdesc
|
||||
# define DEV2_MKSTRDESC cdcacm_mkstrdesc
|
||||
# define DEV2_CLASSOBJECT board_cdcclassobject
|
||||
# define DEV2_UNINITIALIZE board_cdcuninitialize
|
||||
# define DEV2_NCONFIGS CDCACM_NCONFIGS
|
||||
# define DEV2_CONFIGID CDCACM_CONFIGID
|
||||
# define DEV2_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE
|
||||
# define DEV2_NINTERFACES CDCACM_NINTERFACES
|
||||
# define DEV2_STRIDBASE CONFIG_CDCACM_STRBASE
|
||||
# define DEV2_NSTRIDS CDCACM_NSTRIDS
|
||||
# define DEV2_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC
|
||||
#elif defined(CONFIG_CDCACM_COMPOSITE) && !defined(DEV1_IS_USBMSC)
|
||||
# define DEV2_IS_USBMSC 1
|
||||
# define DEV2_MKCFGDESC usbmsc_mkcfgdesc
|
||||
# define DEV2_MKSTRDESC usbmsc_mkstrdesc
|
||||
# define DEV2_UNINITIALIZE board_mscuninitialize
|
||||
# define DEV2_CLASSOBJECT board_mscclassobject
|
||||
# define DEV2_NCONFIGS USBMSC_NCONFIGS
|
||||
# define DEV2_CONFIGID USBMSC_CONFIGID
|
||||
# define DEV2_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV2_NINTERFACES USBMSC_NINTERFACES
|
||||
# define DEV2_STRIDBASE CONFIG_USBMSC_STRBASE
|
||||
# define DEV2_NSTRIDS USBMSC_NSTRIDS
|
||||
# define DEV2_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC
|
||||
#else
|
||||
# error "Insufficient members of the composite defined"
|
||||
#endif
|
||||
|
||||
/* Verify interface configuration */
|
||||
|
||||
#if DEV1_FIRSTINTERFACE != 0
|
||||
# warning "The first interface number should be zero"
|
||||
#endif
|
||||
|
||||
#if (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES) != DEV2_FIRSTINTERFACE
|
||||
# warning "Interface numbers are not contiguous"
|
||||
#endif
|
||||
|
||||
/* Check if an IAD is needed */
|
||||
|
||||
#ifdef CONFIG_COMPOSITE_IAD
|
||||
# if DEV1_NINTERFACES == 1 && DEV2_NINTERFACES == 1
|
||||
# warning "CONFIG_COMPOSITE_IAD not needed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_COMPOSITE_IAD) && DEV1_NINTERFACES > 1 && DEV2_NINTERFACES > 1
|
||||
# warning "CONFIG_COMPOSITE_IAD may be needed"
|
||||
#endif
|
||||
|
||||
/* Total size of the configuration descriptor: */
|
||||
|
||||
#define COMPOSITE_CFGDESCSIZE (USB_SIZEOF_CFGDESC + DEV1_CFGDESCSIZE + DEV2_CFGDESCSIZE)
|
||||
|
||||
/* The total number of interfaces */
|
||||
|
||||
#define COMPOSITE_NINTERFACES (DEV1_NINTERFACES + DEV2_NINTERFACES)
|
||||
|
||||
/* Composite configuration ID value */
|
||||
|
||||
#if DEV1_NCONFIGS != 1 || DEV1_CONFIGID != 1
|
||||
# error "DEV1: Only a single configuration is supported"
|
||||
#endif
|
||||
|
||||
#if DEV2_NCONFIGS != 1 || DEV2_CONFIGID != 1
|
||||
# error "DEV2: Only a single configuration is supported"
|
||||
#endif
|
||||
|
||||
/* Descriptors **************************************************************/
|
||||
/* These settings are not modifiable via the NuttX configuration */
|
||||
|
||||
#define COMPOSITE_CONFIGIDNONE (0) /* Config ID = 0 means to return to address mode */
|
||||
#define COMPOSITE_NCONFIGS (1) /* The number of configurations supported */
|
||||
#define COMPOSITE_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* String language */
|
||||
|
||||
#define COMPOSITE_STR_LANGUAGE (0x0409) /* en-us */
|
||||
|
||||
/* Descriptor strings */
|
||||
|
||||
#define COMPOSITE_MANUFACTURERSTRID (1)
|
||||
#define COMPOSITE_PRODUCTSTRID (2)
|
||||
#define COMPOSITE_SERIALSTRID (3)
|
||||
#define COMPOSITE_CONFIGSTRID (4)
|
||||
#define COMPOSITE_NSTRIDS (4)
|
||||
|
||||
/* Verify string configuration */
|
||||
|
||||
#if COMPOSITE_NSTRIDS != DEV1_STRIDBASE
|
||||
# warning "The DEV1 string base should be COMPOSITE_NSTRIDS"
|
||||
#endif
|
||||
|
||||
#if (DEV1_STRIDBASE + DEV1_NSTRIDS) != DEV2_STRIDBASE
|
||||
# warning "String IDs are not contiguous"
|
||||
#endif
|
||||
|
||||
/* Everpresent MIN/MAX macros ***********************************************/
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern const char g_compvendorstr[];
|
||||
extern const char g_compproductstr[];
|
||||
extern const char g_compserialstr[];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int composite_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the composite device descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_COMPOSITE_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *composite_getdevdesc(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the composite configuration descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the composite qual descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
FAR const struct usb_qualdesc_s *composite_getqualdesc(void);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_USBDEV_COMPOSITE */
|
||||
#endif /* __DRIVERS_USBDEV_COMPOSITE_H */
|
||||
@@ -0,0 +1,291 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/composite_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#include "composite.h"
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* Device Descriptor */
|
||||
|
||||
static const struct usb_devdesc_s g_devdesc =
|
||||
{
|
||||
USB_SIZEOF_DEVDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICE, /* type */
|
||||
{ /* usb */
|
||||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
#ifdef CONFIG_COMPOSITE_IAD
|
||||
USB_CLASS_MISC, /* classid */
|
||||
2, /* subclass */
|
||||
1, /* protocol */
|
||||
#else
|
||||
USB_CLASS_PER_INTERFACE, /* classid */
|
||||
0, /* subclass */
|
||||
0, /* protocol */
|
||||
#endif
|
||||
CONFIG_COMPOSITE_EP0MAXPACKET, /* maxpacketsize */
|
||||
{
|
||||
LSBYTE(CONFIG_COMPOSITE_VENDORID), /* vendor */
|
||||
MSBYTE(CONFIG_COMPOSITE_VENDORID)
|
||||
},
|
||||
{
|
||||
LSBYTE(CONFIG_COMPOSITE_PRODUCTID), /* product */
|
||||
MSBYTE(CONFIG_COMPOSITE_PRODUCTID)
|
||||
},
|
||||
{
|
||||
LSBYTE(CONFIG_COMPOSITE_VERSIONNO), /* device */
|
||||
MSBYTE(CONFIG_COMPOSITE_VERSIONNO)
|
||||
},
|
||||
COMPOSITE_MANUFACTURERSTRID, /* imfgr */
|
||||
COMPOSITE_PRODUCTSTRID, /* iproduct */
|
||||
COMPOSITE_SERIALSTRID, /* serno */
|
||||
COMPOSITE_NCONFIGS /* nconfigs */
|
||||
};
|
||||
|
||||
/* Configuration descriptor for the composite device */
|
||||
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{
|
||||
LSBYTE(COMPOSITE_CFGDESCSIZE), /* LS totallen */
|
||||
MSBYTE(COMPOSITE_CFGDESCSIZE) /* MS totallen */
|
||||
},
|
||||
COMPOSITE_NINTERFACES, /* ninterfaces */
|
||||
COMPOSITE_CONFIGID, /* cfgvalue */
|
||||
COMPOSITE_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
static const struct usb_qualdesc_s g_qualdesc =
|
||||
{
|
||||
USB_SIZEOF_QUALDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICEQUALIFIER, /* type */
|
||||
{ /* usb */
|
||||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
USB_CLASS_VENDOR_SPEC, /* classid */
|
||||
0, /* subclass */
|
||||
0, /* protocol */
|
||||
CONFIG_COMPOSITE_EP0MAXPACKET, /* mxpacketsize */
|
||||
COMPOSITE_NCONFIGS, /* nconfigs */
|
||||
0, /* reserved */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int composite_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc)
|
||||
{
|
||||
const char *str;
|
||||
int len;
|
||||
int ndata;
|
||||
int i;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
/* Descriptor 0 is the language id */
|
||||
|
||||
strdesc->len = 4;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
strdesc->data[0] = LSBYTE(COMPOSITE_STR_LANGUAGE);
|
||||
strdesc->data[1] = MSBYTE(COMPOSITE_STR_LANGUAGE);
|
||||
return 4;
|
||||
}
|
||||
|
||||
case COMPOSITE_MANUFACTURERSTRID:
|
||||
str = g_compvendorstr;
|
||||
break;
|
||||
|
||||
case COMPOSITE_PRODUCTSTRID:
|
||||
str = g_compproductstr;
|
||||
break;
|
||||
|
||||
case COMPOSITE_SERIALSTRID:
|
||||
str = g_compserialstr;
|
||||
break;
|
||||
|
||||
case COMPOSITE_CONFIGSTRID:
|
||||
str = CONFIG_COMPOSITE_CONFIGSTR;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The string is utf16-le. The poor man's utf-8 to utf16-le
|
||||
* conversion below will only handle 7-bit en-us ascii
|
||||
*/
|
||||
|
||||
len = strlen(str);
|
||||
for (i = 0, ndata = 0; i < len; i++, ndata += 2)
|
||||
{
|
||||
strdesc->data[ndata] = str[i];
|
||||
strdesc->data[ndata+1] = 0;
|
||||
}
|
||||
|
||||
strdesc->len = ndata+2;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
return strdesc->len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_devdesc_s *composite_getdevdesc(void)
|
||||
{
|
||||
return &g_devdesc;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf)
|
||||
#endif
|
||||
{
|
||||
int16_t len;
|
||||
int16_t total;
|
||||
|
||||
/* Configuration descriptor -- Copy the canned configuration descriptor. */
|
||||
|
||||
memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC);
|
||||
total = USB_SIZEOF_CFGDESC;
|
||||
buf += USB_SIZEOF_CFGDESC;
|
||||
|
||||
/* Copy DEV1/DEV2 interface descriptors */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
len = DEV1_MKCFGDESC(buf, speed, type);
|
||||
total += len;
|
||||
buf += len;
|
||||
total += DEV2_MKCFGDESC(buf, speed, type);
|
||||
#else
|
||||
len = DEV1_MKCFGDESC(buf);
|
||||
total += len;
|
||||
buf += len;
|
||||
total += DEV2_MKCFGDESC(buf);
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(total == COMPOSITE_CFGDESCSIZE);
|
||||
return total;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
FAR const struct usb_qualdesc_s *composite_getqualdesc(void)
|
||||
{
|
||||
return &g_qualdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_USBDEV_COMPOSITE */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,233 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/usbdev_trace.c
|
||||
*
|
||||
* Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
#undef usbtrace
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_USBDEV_TRACE_NRECORDS
|
||||
# define CONFIG_USBDEV_TRACE_NRECORDS 128
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_TRACE_INITIALIDSET
|
||||
# define CONFIG_USBDEV_TRACE_INITIALIDSET 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_TRACE
|
||||
static struct usbtrace_s g_trace[CONFIG_USBDEV_TRACE_NRECORDS];
|
||||
static uint16_t g_head = 0;
|
||||
static uint16_t g_tail = 0;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB))
|
||||
static usbtrace_idset_t g_maskedidset = CONFIG_USBDEV_TRACE_INITIALIDSET;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbtrace_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable/disable tracing per trace ID. The initial state is all IDs enabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* idset - The bitset of IDs to be masked. TRACE_ALLIDS enables all IDS; zero
|
||||
* masks all IDs.
|
||||
*
|
||||
* Returned Value:
|
||||
* The previous idset value.
|
||||
*
|
||||
* Assumptions:
|
||||
* - May be called from an interrupt handler
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB))
|
||||
usbtrace_idset_t usbtrace_enable(usbtrace_idset_t idset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
usbtrace_idset_t ret;
|
||||
|
||||
/* The following read and write must be atomic */
|
||||
|
||||
flags = irqsave();
|
||||
ret = g_maskedidset;
|
||||
g_maskedidset = idset;
|
||||
irqrestore(flags);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_USBDEV_TRACE || CONFIG_DEBUG && CONFIG_DEBUG_USB */
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbtrace
|
||||
*
|
||||
* Description:
|
||||
* Record a USB event (tracing must be enabled)
|
||||
*
|
||||
* Assumptions:
|
||||
* May be called from an interrupt handler
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_TRACE) || (defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_USB))
|
||||
void usbtrace(uint16_t event, uint16_t value)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Check if tracing is enabled for this ID */
|
||||
|
||||
flags = irqsave();
|
||||
if ((g_maskedidset & TRACE_ID2BIT(event)) != 0)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_TRACE
|
||||
/* Yes... save the new trace data at the head */
|
||||
|
||||
g_trace[g_head].event = event;
|
||||
g_trace[g_head].value = value;
|
||||
|
||||
/* Increment the head and (probably) the tail index */
|
||||
|
||||
if (++g_head >= CONFIG_USBDEV_TRACE_NRECORDS)
|
||||
{
|
||||
g_head = 0;
|
||||
}
|
||||
|
||||
if (g_head == g_tail)
|
||||
{
|
||||
if (++g_tail >= CONFIG_USBDEV_TRACE_NRECORDS)
|
||||
{
|
||||
g_tail = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Just print the data using lib_lowprintf */
|
||||
|
||||
usbtrace_trprintf((trprintf_t)lib_lowprintf, event, value);
|
||||
#endif
|
||||
}
|
||||
irqrestore(flags);
|
||||
}
|
||||
#endif /* CONFIG_USBDEV_TRACE || CONFIG_DEBUG && CONFIG_DEBUG_USB */
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbtrace_enumerate
|
||||
*
|
||||
* Description:
|
||||
* Enumerate all buffer trace data (will temporarily disable tracing)
|
||||
*
|
||||
* Assumptions:
|
||||
* NEVER called from an interrupt handler
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_TRACE
|
||||
int usbtrace_enumerate(trace_callback_t callback, void *arg)
|
||||
{
|
||||
uint16_t ndx;
|
||||
uint32_t idset;
|
||||
int ret = OK;
|
||||
|
||||
/* Temporarily disable tracing */
|
||||
|
||||
idset = usbtrace_enable(0);
|
||||
|
||||
/* Visit every entry, starting with the tail */
|
||||
|
||||
for (ndx = g_tail; ndx != g_head; )
|
||||
{
|
||||
/* Call the user provided callback */
|
||||
|
||||
ret = callback(&g_trace[ndx], arg);
|
||||
if (ret != OK)
|
||||
{
|
||||
/* Abort the enumeration */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment the index */
|
||||
|
||||
if (++ndx >= CONFIG_USBDEV_TRACE_NRECORDS)
|
||||
{
|
||||
ndx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard the trace data after it has been reported */
|
||||
|
||||
g_tail = g_head;
|
||||
|
||||
/* Restore tracing state */
|
||||
|
||||
(void)usbtrace_enable(idset);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_USBDEV_TRACE */
|
||||
@@ -0,0 +1,253 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/usbdev_trprintf.c
|
||||
*
|
||||
* Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: usbtrace_trprintf
|
||||
*
|
||||
* Description:
|
||||
* Print the trace record using the supplied printing function
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
void usbtrace_trprintf(trprintf_t trprintf, uint16_t event, uint16_t value)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case TRACE_DEVINIT:
|
||||
trprintf("USB controller initialization: %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVUNINIT:
|
||||
trprintf("USB controller un-initialization: %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVREGISTER:
|
||||
trprintf("usbdev_register(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVUNREGISTER:
|
||||
trprintf("usbdev_unregister(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPCONFIGURE:
|
||||
trprintf("Endpoint configure(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPDISABLE:
|
||||
trprintf("Endpoint disable(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPALLOCREQ:
|
||||
trprintf("Endpoint allocreq(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPFREEREQ:
|
||||
trprintf("Endpoint freereq(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPALLOCBUFFER:
|
||||
trprintf("Endpoint allocbuffer(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPFREEBUFFER:
|
||||
trprintf("Endpoint freebuffer(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPSUBMIT:
|
||||
trprintf("Endpoint submit(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPCANCEL:
|
||||
trprintf("Endpoint cancel(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPSTALL:
|
||||
trprintf("Endpoint stall(true): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_EPRESUME:
|
||||
trprintf("Endpoint stall(false): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVALLOCEP:
|
||||
trprintf("Device allocep(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVFREEEP:
|
||||
trprintf("Device freeep(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVGETFRAME:
|
||||
trprintf("Device getframe(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVWAKEUP:
|
||||
trprintf("Device wakeup(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVSELFPOWERED:
|
||||
trprintf("Device selfpowered(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVPULLUP:
|
||||
trprintf("Device pullup(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSBIND:
|
||||
trprintf("Class bind(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSUNBIND:
|
||||
trprintf("Class unbind(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSDISCONNECT:
|
||||
trprintf("Class disconnect(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSSETUP:
|
||||
trprintf("Class setup(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSSUSPEND:
|
||||
trprintf("Class suspend(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSRESUME:
|
||||
trprintf("Class resume(): %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSRDCOMPLETE:
|
||||
trprintf("Class RD request complete: %04x\n", value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSWRCOMPLETE:
|
||||
trprintf("Class WR request complete: %04x\n", value);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (TRACE_ID(event))
|
||||
{
|
||||
case TRACE_CLASSAPI_ID: /* Other class driver system API calls */
|
||||
trprintf("Class API call %d: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_CLASSSTATE_ID: /* Track class driver state changes */
|
||||
trprintf("Class state %d: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_INTENTRY_ID: /* Interrupt handler entry */
|
||||
trprintf("Interrupt %d entry: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_INTDECODE_ID: /* Decoded interrupt event */
|
||||
trprintf("Interrupt decode %d: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_INTEXIT_ID: /* Interrupt handler exit */
|
||||
trprintf("Interrupt %d exit: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_OUTREQQUEUED_ID: /* Request queued for OUT endpoint */
|
||||
trprintf("EP%d OUT request queued: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_INREQQUEUED_ID: /* Request queued for IN endpoint */
|
||||
trprintf("EP%d IN request queued: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_READ_ID: /* Read (OUT) action */
|
||||
trprintf("EP%d OUT read: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_WRITE_ID: /* Write (IN) action */
|
||||
trprintf("EP%d IN write: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_COMPLETE_ID: /* Request completed */
|
||||
trprintf("EP%d request complete: %04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_DEVERROR_ID: /* USB controller driver error event */
|
||||
trprintf("Controller error: %02x:%04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
case TRACE_CLSERROR_ID: /* USB class driver error event */
|
||||
trprintf("Class error: %02x:%04x\n", TRACE_DATA(event), value);
|
||||
break;
|
||||
|
||||
default:
|
||||
trprintf("Unrecognized event: %02x:%02x:%04x\n",
|
||||
TRACE_ID(event) >> 8, TRACE_DATA(event), value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,694 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/usbmsc.h
|
||||
*
|
||||
* Copyright (C) 2008-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Mass storage class device. Bulk-only with SCSI subclass.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_USBDEV_USBMSC_H
|
||||
#define __DRIVERS_USBDEV_USBMSC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/usb/storage.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* If the USB mass storage device is configured as part of a composite device
|
||||
* then both CONFIG_USBDEV_COMPOSITE and CONFIG_USBMSC_COMPOSITE must be
|
||||
* defined.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBDEV_COMPOSITE
|
||||
# undef CONFIG_USBMSC_COMPOSITE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USBMSC_COMPOSITE) && !defined(CONFIG_USBMSC_STRBASE)
|
||||
# define CONFIG_USBMSC_STRBASE (4)
|
||||
#endif
|
||||
|
||||
/* Interface IDs. If the mass storage driver is built as a component of a
|
||||
* composite device, then the interface IDs may need to be offset.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# undef CONFIG_USBMSC_IFNOBASE
|
||||
# define CONFIG_USBMSC_IFNOBASE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBMSC_IFNOBASE
|
||||
# define CONFIG_USBMSC_IFNOBASE 0
|
||||
#endif
|
||||
|
||||
/* Number of requests in the write queue */
|
||||
|
||||
#ifndef CONFIG_USBMSC_NWRREQS
|
||||
# define CONFIG_USBMSC_NWRREQS 4
|
||||
#endif
|
||||
|
||||
/* Number of requests in the read queue */
|
||||
|
||||
#ifndef CONFIG_USBMSC_NRDREQS
|
||||
# define CONFIG_USBMSC_NRDREQS 4
|
||||
#endif
|
||||
|
||||
/* Logical endpoint numbers / max packet sizes */
|
||||
|
||||
#ifndef CONFIG_USBMSC_EPBULKOUT
|
||||
# warning "EPBULKOUT not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKOUT 2
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBMSC_EPBULKIN
|
||||
# warning "EPBULKIN not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKIN 3
|
||||
#endif
|
||||
|
||||
/* Packet and request buffer sizes */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# ifndef CONFIG_USBMSC_EP0MAXPACKET
|
||||
# define CONFIG_USBMSC_EP0MAXPACKET 64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBMSC_BULKINREQLEN
|
||||
# ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# define CONFIG_USBMSC_BULKINREQLEN 512
|
||||
# else
|
||||
# define CONFIG_USBMSC_BULKINREQLEN 64
|
||||
# endif
|
||||
#else
|
||||
# ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# if CONFIG_USBMSC_BULKINREQLEN < 512
|
||||
# warning "Bulk in buffer size smaller than max packet"
|
||||
# undef CONFIG_USBMSC_BULKINREQLEN
|
||||
# define CONFIG_USBMSC_BULKINREQLEN 512
|
||||
# endif
|
||||
# else
|
||||
# if CONFIG_USBMSC_BULKINREQLEN < 64
|
||||
# warning "Bulk in buffer size smaller than max packet"
|
||||
# undef CONFIG_USBMSC_BULKINREQLEN
|
||||
# define CONFIG_USBMSC_BULKINREQLEN 64
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBMSC_BULKOUTREQLEN
|
||||
# ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# define CONFIG_USBMSC_BULKOUTREQLEN 512
|
||||
# else
|
||||
# define CONFIG_USBMSC_BULKOUTREQLEN 64
|
||||
# endif
|
||||
#else
|
||||
# ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# if CONFIG_USBMSC_BULKOUTREQLEN < 512
|
||||
# warning "Bulk in buffer size smaller than max packet"
|
||||
# undef CONFIG_USBMSC_BULKOUTREQLEN
|
||||
# define CONFIG_USBMSC_BULKOUTREQLEN 512
|
||||
# endif
|
||||
# else
|
||||
# if CONFIG_USBMSC_BULKOUTREQLEN < 64
|
||||
# warning "Bulk in buffer size smaller than max packet"
|
||||
# undef CONFIG_USBMSC_BULKOUTREQLEN
|
||||
# define CONFIG_USBMSC_BULKOUTREQLEN 64
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Vendor and product IDs and strings */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# ifndef CONFIG_USBMSC_VENDORID
|
||||
# warning "CONFIG_USBMSC_VENDORID not defined"
|
||||
# define CONFIG_USBMSC_VENDORID 0x584e
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_USBMSC_PRODUCTID
|
||||
# warning "CONFIG_USBMSC_PRODUCTID not defined"
|
||||
# define CONFIG_USBMSC_PRODUCTID 0x5342
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_USBMSC_VERSIONNO
|
||||
# define CONFIG_USBMSC_VERSIONNO (0x0399)
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_USBMSC_VENDORSTR
|
||||
# warning "No Vendor string specified"
|
||||
# define CONFIG_USBMSC_VENDORSTR "NuttX"
|
||||
# endif
|
||||
|
||||
# ifndef CONFIG_USBMSC_PRODUCTSTR
|
||||
# warning "No Product string specified"
|
||||
# define CONFIG_USBMSC_PRODUCTSTR "USBdev Storage"
|
||||
# endif
|
||||
|
||||
# undef CONFIG_USBMSC_SERIALSTR
|
||||
# define CONFIG_USBMSC_SERIALSTR "0101"
|
||||
#endif
|
||||
|
||||
#undef CONFIG_USBMSC_CONFIGSTR
|
||||
#define CONFIG_USBMSC_CONFIGSTR "Bulk"
|
||||
|
||||
/* Debug -- must be consistent with include/debug.h */
|
||||
|
||||
#ifdef CONFIG_CPP_HAVE_VARARGS
|
||||
# ifdef CONFIG_DEBUG
|
||||
# ifdef CONFIG_ARCH_LOWPUTC
|
||||
# define dbgprintf(format, arg...) lib_lowprintf(format, ##arg)
|
||||
# else
|
||||
# define dbgprintf(format, arg...) lib_rawprintf(format, ##arg)
|
||||
# endif
|
||||
# else
|
||||
# define dbgprintf(x...)
|
||||
# endif
|
||||
#else
|
||||
# ifdef CONFIG_DEBUG
|
||||
# ifdef CONFIG_ARCH_LOWPUTC
|
||||
# define dbgprintf lib_lowprintf
|
||||
# else
|
||||
# define dbgprintf lib_rawprintf
|
||||
# endif
|
||||
# else
|
||||
# define dbgprintf (void)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Packet and request buffer sizes */
|
||||
|
||||
#ifndef CONFIG_USBMSC_EP0MAXPACKET
|
||||
# define CONFIG_USBMSC_EP0MAXPACKET 64
|
||||
#endif
|
||||
|
||||
/* USB Controller */
|
||||
|
||||
#ifndef CONFIG_USBDEV_SELFPOWERED
|
||||
# define SELFPOWERED USB_CONFIG_ATT_SELFPOWER
|
||||
#else
|
||||
# define SELFPOWERED (0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_REMOTEWAKEUP
|
||||
# define REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP
|
||||
#else
|
||||
# define REMOTEWAKEUP (0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBDEV_MAXPOWER
|
||||
# define CONFIG_USBDEV_MAXPOWER 100
|
||||
#endif
|
||||
|
||||
/* Current state of the worker thread */
|
||||
|
||||
#define USBMSC_STATE_NOTSTARTED (0) /* Thread has not yet been started */
|
||||
#define USBMSC_STATE_STARTED (1) /* Started, but is not yet initialized */
|
||||
#define USBMSC_STATE_IDLE (2) /* Started and waiting for commands */
|
||||
#define USBMSC_STATE_CMDPARSE (3) /* Processing a received command */
|
||||
#define USBMSC_STATE_CMDREAD (4) /* Processing a SCSI read command */
|
||||
#define USBMSC_STATE_CMDWRITE (5) /* Processing a SCSI write command */
|
||||
#define USBMSC_STATE_CMDFINISH (6) /* Finish command processing */
|
||||
#define USBMSC_STATE_CMDSTATUS (7) /* Processing the final status of the command */
|
||||
#define USBMSC_STATE_TERMINATED (8) /* Thread has exitted */
|
||||
|
||||
/* Event communicated to worker thread */
|
||||
|
||||
#define USBMSC_EVENT_NOEVENTS (0) /* There are no outstanding events */
|
||||
#define USBMSC_EVENT_READY (1 << 0) /* Initialization is complete */
|
||||
#define USBMSC_EVENT_RDCOMPLETE (1 << 1) /* A read has completed there is data to be processed */
|
||||
#define USBMSC_EVENT_WRCOMPLETE (1 << 2) /* A write has completed and a request is available */
|
||||
#define USBMSC_EVENT_TERMINATEREQUEST (1 << 3) /* Shutdown requested */
|
||||
#define USBMSC_EVENT_DISCONNECT (1 << 4) /* USB disconnect received */
|
||||
#define USBMSC_EVENT_RESET (1 << 5) /* USB storage setup reset received */
|
||||
#define USBMSC_EVENT_CFGCHANGE (1 << 6) /* USB setup configuration change received */
|
||||
#define USBMSC_EVENT_IFCHANGE (1 << 7) /* USB setup interface change received */
|
||||
#define USBMSC_EVENT_ABORTBULKOUT (1 << 8) /* SCSI receive failure */
|
||||
|
||||
/* SCSI command flags (passed to usbmsc_setupcmd()) */
|
||||
|
||||
#define USBMSC_FLAGS_DIRMASK (0x03) /* Bits 0-1: Data direction */
|
||||
#define USBMSC_FLAGS_DIRNONE (0x00) /* No data to send */
|
||||
#define USBMSC_FLAGS_DIRHOST2DEVICE (0x01) /* Host-to-device */
|
||||
#define USBMSC_FLAGS_DIRDEVICE2HOST (0x02) /* Device-to-host */
|
||||
#define USBMSC_FLAGS_BLOCKXFR (0x04) /* Bit 2: Command is a block transfer request */
|
||||
#define USBMSC_FLAGS_LUNNOTNEEDED (0x08) /* Bit 3: Command does not require a valid LUN */
|
||||
#define USBMSC_FLAGS_UACOKAY (0x10) /* Bit 4: Command OK if unit attention condition */
|
||||
#define USBMSC_FLAGS_RETAINSENSEDATA (0x20) /* Bit 5: Do not clear sense data */
|
||||
|
||||
/* Descriptors **************************************************************/
|
||||
|
||||
/* Big enough to hold our biggest descriptor */
|
||||
|
||||
#define USBMSC_MXDESCLEN (64)
|
||||
|
||||
/* String language */
|
||||
|
||||
#define USBMSC_STR_LANGUAGE (0x0409) /* en-us */
|
||||
|
||||
/* Descriptor strings */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# define USBMSC_MANUFACTURERSTRID (1)
|
||||
# define USBMSC_PRODUCTSTRID (2)
|
||||
# define USBMSC_SERIALSTRID (3)
|
||||
# define USBMSC_CONFIGSTRID (4)
|
||||
# define USBMSC_INTERFACESTRID USBMSC_CONFIGSTRID
|
||||
|
||||
# undef CONFIG_USBMSC_STRBASE
|
||||
# define CONFIG_USBMSC_STRBASE (0)
|
||||
#else
|
||||
# define USBMSC_INTERFACESTRID (CONFIG_USBMSC_STRBASE+1)
|
||||
#endif
|
||||
|
||||
#define USBMSC_LASTSTRID USBMSC_INTERFACESTRID
|
||||
#define USBMSC_NSTRIDS (USBMSC_LASTSTRID - CONFIG_USBMSC_STRBASE)
|
||||
|
||||
#define USBMSC_NCONFIGS (1) /* Number of configurations supported */
|
||||
|
||||
/* Configuration Descriptor */
|
||||
|
||||
#define USBMSC_NINTERFACES (1) /* Number of interfaces in the configuration */
|
||||
#define USBMSC_INTERFACEID (CONFIG_USBMSC_IFNOBASE+0)
|
||||
#define USBMSC_ALTINTERFACEID (0)
|
||||
|
||||
#define USBMSC_CONFIGIDNONE (0) /* Config ID means to return to address mode */
|
||||
#define USBMSC_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* Interface description */
|
||||
|
||||
#define USBMSC_NENDPOINTS (2) /* Number of endpoints in the interface */
|
||||
|
||||
/* Endpoint configuration */
|
||||
|
||||
#define USBMSC_EPOUTBULK_ADDR (CONFIG_USBMSC_EPBULKOUT)
|
||||
#define USBMSC_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define USBMSC_EPINBULK_ADDR (USB_DIR_IN|CONFIG_USBMSC_EPBULKIN)
|
||||
#define USBMSC_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define USBMSC_HSBULKMAXPACKET (512)
|
||||
#define USBMSC_HSBULKMXPKTSHIFT (9)
|
||||
#define USBMSC_HSBULKMXPKTMASK (0x000001ff)
|
||||
#define USBMSC_FSBULKMAXPACKET (64)
|
||||
#define USBMSC_FSBULKMXPKTSHIFT (6)
|
||||
#define USBMSC_FSBULKMXPKTMASK (0x0000003f)
|
||||
|
||||
/* Macros for dual speed vs. full speed only operation */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# define USBMSC_EPBULKINDESC(hs) \
|
||||
usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKIN : USBMSC_EPFSBULKIN)
|
||||
# define USBMSC_EPBULKOUTDESC(hs) \
|
||||
usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKOUT : USBMSC_EPFSBULKOUT)
|
||||
# define USBMSC_BULKMAXPACKET(hs) \
|
||||
((hs) ? USBMSC_HSBULKMAXPACKET : USBMSC_FSBULKMAXPACKET)
|
||||
# define USBMSC_BULKMXPKTSHIFT(d) \
|
||||
(((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTSHIFT : USBMSC_FSBULKMXPKTSHIFT)
|
||||
# define USBMSC_BULKMXPKTMASK(d) \
|
||||
(((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTMASK : USBMSC_FSBULKMXPKTMASK)
|
||||
#else
|
||||
# define USBMSC_EPBULKINDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKIN)
|
||||
# define USBMSC_EPBULKOUTDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKOUT)
|
||||
# define USBMSC_BULKMAXPACKET(hs) USBMSC_FSBULKMAXPACKET
|
||||
# define USBMSC_BULKMXPKTSHIFT(d) USBMSC_FSBULKMXPKTSHIFT
|
||||
# define USBMSC_BULKMXPKTMASK(d) USBMSC_FSBULKMXPKTMASK
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor size */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) Configuration descriptor + (1) interface descriptor + (2) interface
|
||||
* descriptors.
|
||||
*/
|
||||
|
||||
# define USBMSC_CFGGROUP_SIZE (4)
|
||||
|
||||
/* The size of the config descriptor: (9 + 9 + 2*7) = 32 */
|
||||
|
||||
# define SIZEOF_USBMSC_CFGDESC \
|
||||
(USB_SIZEOF_CFGDESC + USB_SIZEOF_IFDESC + USBMSC_NENDPOINTS * USB_SIZEOF_EPDESC)
|
||||
|
||||
#else
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) interface descriptor + (2) interface descriptors.
|
||||
*/
|
||||
|
||||
# define USBMSC_CFGGROUP_SIZE (3)
|
||||
|
||||
/* The size of the config descriptor: (9 + 2*7) = 23 */
|
||||
|
||||
# define SIZEOF_USBMSC_CFGDESC \
|
||||
(USB_SIZEOF_IFDESC + USBMSC_NENDPOINTS * USB_SIZEOF_EPDESC)
|
||||
|
||||
#endif
|
||||
|
||||
/* Block driver helpers *****************************************************/
|
||||
|
||||
#define USBMSC_DRVR_READ(l,b,s,n) ((l)->inode->u.i_bops->read((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_WRITE(l,b,s,n) ((l)->inode->u.i_bops->write((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_GEOMETRY(l,g) ((l)->inode->u.i_bops->geometry((l)->inode,g))
|
||||
|
||||
/* Everpresent MIN/MAX macros ***********************************************/
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
/* Endpoint descriptors */
|
||||
|
||||
enum usbmsc_epdesc_e
|
||||
{
|
||||
USBMSC_EPFSBULKOUT = 0, /* Full speed bulk OUT endpoint descriptor */
|
||||
USBMSC_EPFSBULKIN /* Full speed bulk IN endpoint descriptor */
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
,
|
||||
USBMSC_EPHSBULKOUT, /* High speed bulk OUT endpoint descriptor */
|
||||
USBMSC_EPHSBULKIN /* High speed bulk IN endpoint descriptor */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Container to support a list of requests */
|
||||
|
||||
struct usbmsc_req_s
|
||||
{
|
||||
FAR struct usbmsc_req_s *flink; /* Implements a singly linked list */
|
||||
FAR struct usbdev_req_s *req; /* The contained request */
|
||||
};
|
||||
|
||||
/* This structure describes one LUN: */
|
||||
|
||||
struct usbmsc_lun_s
|
||||
{
|
||||
struct inode *inode; /* Inode structure of open'ed block driver */
|
||||
uint8_t readonly:1; /* Media is read-only */
|
||||
uint8_t locked:1; /* Media removal is prevented */
|
||||
uint16_t sectorsize; /* The size of one sector */
|
||||
uint32_t sd; /* Sense data */
|
||||
uint32_t sdinfo; /* Sense data information */
|
||||
uint32_t uad; /* Unit needs attention data */
|
||||
off_t startsector; /* Sector offset to start of partition */
|
||||
size_t nsectors; /* Number of sectors in the partition */
|
||||
};
|
||||
|
||||
/* Describes the overall state of the driver */
|
||||
|
||||
struct usbmsc_dev_s
|
||||
{
|
||||
FAR struct usbdev_s *usbdev; /* usbdev driver pointer (Non-null if registered) */
|
||||
|
||||
/* Worker thread interface */
|
||||
|
||||
pthread_t thread; /* The worker thread */
|
||||
pthread_mutex_t mutex; /* Mutually exclusive access to resources*/
|
||||
pthread_cond_t cond; /* Used to signal worker thread */
|
||||
volatile uint8_t thstate; /* State of the worker thread */
|
||||
volatile uint16_t theventset; /* Set of pending events signaled to worker thread */
|
||||
volatile uint8_t thvalue; /* Value passed with the event (must persist) */
|
||||
|
||||
/* Storage class configuration and state */
|
||||
|
||||
uint8_t nluns:4; /* Number of LUNs */
|
||||
uint8_t config; /* Configuration number */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
FAR struct usbdev_ep_s *epbulkin; /* Bulk IN endpoint structure */
|
||||
FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint structure */
|
||||
FAR struct usbdev_req_s *ctrlreq; /* Control request (for ep0 setup responses) */
|
||||
|
||||
/* SCSI command processing */
|
||||
|
||||
struct usbmsc_lun_s *lun; /* Currently selected LUN */
|
||||
struct usbmsc_lun_s *luntab; /* Allocated table of all LUNs */
|
||||
uint8_t cdb[USBMSC_MAXCDBLEN]; /* Command data (cdb[]) from CBW */
|
||||
uint8_t phaseerror:1; /* Need to send phase sensing status */
|
||||
uint8_t shortpacket:1; /* Host transmission stopped unexpectedly */
|
||||
uint8_t cbwdir:2; /* Direction from CBW. See USBMSC_FLAGS_DIR* definitions */
|
||||
uint8_t cdblen; /* Length of cdb[] from CBW */
|
||||
uint8_t cbwlun; /* LUN from the CBW */
|
||||
uint16_t nsectbytes; /* Bytes buffered in iobuffer[] */
|
||||
uint16_t nreqbytes; /* Bytes buffered in head write requests */
|
||||
uint16_t iosize; /* Size of iobuffer[] */
|
||||
uint32_t cbwlen; /* Length of data from CBW */
|
||||
uint32_t cbwtag; /* Tag from the CBW */
|
||||
union
|
||||
{
|
||||
uint32_t xfrlen; /* Read/Write: Sectors remaining to be transferred */
|
||||
uint32_t alloclen; /* Other device-to-host: Host allocation length */
|
||||
} u;
|
||||
uint32_t sector; /* Current sector (relative to lun->startsector) */
|
||||
uint32_t residue; /* Untransferred amount reported in the CSW */
|
||||
uint8_t *iobuffer; /* Buffer for data transfers */
|
||||
|
||||
/* Write request list */
|
||||
|
||||
struct sq_queue_s wrreqlist; /* List of empty write request containers */
|
||||
struct sq_queue_s rdreqlist; /* List of filled read request containers */
|
||||
|
||||
/* Pre-allocated write request containers. The write requests will
|
||||
* be linked in a free list (wrreqlist), and used to send requests to
|
||||
* EPBULKIN; Read requests will be queued in the EBULKOUT.
|
||||
*/
|
||||
|
||||
struct usbmsc_req_s wrreqs[CONFIG_USBMSC_NWRREQS];
|
||||
struct usbmsc_req_s rdreqs[CONFIG_USBMSC_NRDREQS];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
# define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* String *******************************************************************/
|
||||
|
||||
/* Mass storage class vendor/product/serial number strings */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
EXTERN const char g_mscvendorstr[];
|
||||
EXTERN const char g_mscproductstr[];
|
||||
EXTERN const char g_mscserialstr[];
|
||||
|
||||
/* If we are using a composite device, then vendor/product/serial number strings
|
||||
* are provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#else
|
||||
EXTERN const char g_compvendorstr[];
|
||||
EXTERN const char g_compproductstr[];
|
||||
EXTERN const char g_compserialstr[];
|
||||
|
||||
#define g_mscvendorstr g_compvendorstr
|
||||
#define g_mscproductstr g_compproductstr
|
||||
#define g_mscserialstr g_compserialstr
|
||||
#endif
|
||||
/************************************************************************************
|
||||
* Public Function Prototypes
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
struct usb_strdesc_s;
|
||||
int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring endpoints)
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
struct usb_epdesc_s;
|
||||
FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_workerthread
|
||||
*
|
||||
* Description:
|
||||
* This is the main function of the USB storage worker thread. It loops
|
||||
* until USB-related events occur, then processes those events accordingly
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void *usbmsc_workerthread(void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_setconfig
|
||||
*
|
||||
* Description:
|
||||
* Set the device configuration by allocating and configuring endpoints and
|
||||
* by allocating and queue read and write requests.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_resetconfig
|
||||
*
|
||||
* Description:
|
||||
* Mark the device as not configured and disable all endpoints.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void usbmsc_resetconfig(FAR struct usbmsc_dev_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_wrcomplete
|
||||
*
|
||||
* Description:
|
||||
* Handle completion of write request. This function probably executes
|
||||
* in the context of an interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_rdcomplete
|
||||
*
|
||||
* Description:
|
||||
* Handle completion of read request on the bulk OUT endpoint. This
|
||||
* is handled like the receipt of serial data on the "UART"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_deferredresponse
|
||||
*
|
||||
* Description:
|
||||
* Some EP0 setup request cannot be responded to immediately becuase they
|
||||
* require some asynchronous action from the SCSI worker thread. This
|
||||
* function is provided for the SCSI thread to make that deferred response.
|
||||
* The specific requests that require this deferred response are:
|
||||
*
|
||||
* 1. USB_REQ_SETCONFIGURATION,
|
||||
* 2. USB_REQ_SETINTERFACE, or
|
||||
* 3. USBMSC_REQ_MSRESET
|
||||
*
|
||||
* In all cases, the success reponse is a zero-length packet; the failure
|
||||
* response is an EP0 stall.
|
||||
*
|
||||
* Input parameters:
|
||||
* priv - Private state structure for this USB storage instance
|
||||
* stall - true is the action failed and a stall is required
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #define __DRIVERS_USBDEV_USBMSC_H */
|
||||
@@ -0,0 +1,421 @@
|
||||
/****************************************************************************
|
||||
* drivers/usbdev/usbmsc_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#include "usbmsc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* Descriptors **************************************************************/
|
||||
/* Device descriptor. If the USB mass storage device is configured as part
|
||||
* of a composite device, then the device descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
static const struct usb_devdesc_s g_devdesc =
|
||||
{
|
||||
USB_SIZEOF_DEVDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICE, /* type */
|
||||
{LSBYTE(0x0200), MSBYTE(0x0200)}, /* usb */
|
||||
USB_CLASS_PER_INTERFACE, /* classid */
|
||||
0, /* subclass */
|
||||
0, /* protocol */
|
||||
CONFIG_USBMSC_EP0MAXPACKET, /* maxpacketsize */
|
||||
{ /* vendor */
|
||||
LSBYTE(CONFIG_USBMSC_VENDORID),
|
||||
MSBYTE(CONFIG_USBMSC_VENDORID)
|
||||
},
|
||||
{ /* product */
|
||||
LSBYTE(CONFIG_USBMSC_PRODUCTID),
|
||||
MSBYTE(CONFIG_USBMSC_PRODUCTID) },
|
||||
{ /* device */
|
||||
LSBYTE(CONFIG_USBMSC_VERSIONNO),
|
||||
MSBYTE(CONFIG_USBMSC_VERSIONNO)
|
||||
},
|
||||
USBMSC_MANUFACTURERSTRID, /* imfgr */
|
||||
USBMSC_PRODUCTSTRID, /* iproduct */
|
||||
USBMSC_SERIALSTRID, /* serno */
|
||||
USBMSC_NCONFIGS /* nconfigs */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor If the USB mass storage device is configured as part
|
||||
* of a composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{ /* totallen */
|
||||
LSBYTE(SIZEOF_USBMSC_CFGDESC),
|
||||
MSBYTE(SIZEOF_USBMSC_CFGDESC)
|
||||
},
|
||||
USBMSC_NINTERFACES, /* ninterfaces */
|
||||
USBMSC_CONFIGID, /* cfgvalue */
|
||||
USBMSC_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE|SELFPOWERED|REMOTEWAKEUP, /* attr */
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Single interface descriptor */
|
||||
|
||||
static const struct usb_ifdesc_s g_ifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
USBMSC_INTERFACEID, /* ifno */
|
||||
USBMSC_ALTINTERFACEID, /* alt */
|
||||
USBMSC_NENDPOINTS, /* neps */
|
||||
USB_CLASS_MASS_STORAGE, /* classid */
|
||||
USBMSC_SUBCLASS_SCSI, /* subclass */
|
||||
USBMSC_PROTO_BULKONLY, /* protocol */
|
||||
USBMSC_INTERFACESTRID /* iif */
|
||||
};
|
||||
|
||||
/* Endpoint descriptors */
|
||||
|
||||
static const struct usb_epdesc_s g_fsepbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPOUTBULK_ADDR, /* addr */
|
||||
USBMSC_EPOUTBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_FSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_FSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
static const struct usb_epdesc_s g_fsepbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPINBULK_ADDR, /* addr */
|
||||
USBMSC_EPINBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_FSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_FSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
static const struct usb_qualdesc_s g_qualdesc =
|
||||
{
|
||||
USB_SIZEOF_QUALDESC, /* len */
|
||||
USB_DESC_TYPE_DEVICEQUALIFIER, /* type */
|
||||
{ /* usb */
|
||||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
USB_CLASS_PER_INTERFACE, /* classid */
|
||||
0, /* subclass */
|
||||
0, /* protocol */
|
||||
CONFIG_USBMSC_EP0MAXPACKET, /* mxpacketsize */
|
||||
USBMSC_NCONFIGS, /* nconfigs */
|
||||
0, /* reserved */
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct usb_epdesc_s g_hsepbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPOUTBULK_ADDR, /* addr */
|
||||
USBMSC_EPOUTBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_HSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_HSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
static const struct usb_epdesc_s g_hsepbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPINBULK_ADDR, /* addr */
|
||||
USBMSC_EPINBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_HSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_HSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
/* Strings ******************************************************************/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
const char g_mscvendorstr[] = CONFIG_USBMSC_VENDORSTR;
|
||||
const char g_mscproductstr[] = CONFIG_USBMSC_PRODUCTSTR;
|
||||
const char g_mscserialstr[] = CONFIG_USBMSC_SERIALSTR;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc)
|
||||
{
|
||||
const char *str;
|
||||
int len;
|
||||
int ndata;
|
||||
int i;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
case 0:
|
||||
{
|
||||
/* Descriptor 0 is the language id */
|
||||
|
||||
strdesc->len = 4;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
strdesc->data[0] = LSBYTE(USBMSC_STR_LANGUAGE);
|
||||
strdesc->data[1] = MSBYTE(USBMSC_STR_LANGUAGE);
|
||||
return 4;
|
||||
}
|
||||
|
||||
case USBMSC_MANUFACTURERSTRID:
|
||||
str = g_mscvendorstr;
|
||||
break;
|
||||
|
||||
case USBMSC_PRODUCTSTRID:
|
||||
str = g_mscproductstr;
|
||||
break;
|
||||
|
||||
case USBMSC_SERIALSTRID:
|
||||
str = g_mscserialstr;
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* case USBMSC_CONFIGSTRID: */
|
||||
case USBMSC_INTERFACESTRID:
|
||||
str = CONFIG_USBMSC_CONFIGSTR;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The string is utf16-le. The poor man's utf-8 to utf16-le
|
||||
* conversion below will only handle 7-bit en-us ascii
|
||||
*/
|
||||
|
||||
len = strlen(str);
|
||||
for (i = 0, ndata = 0; i < len; i++, ndata += 2)
|
||||
{
|
||||
strdesc->data[ndata] = str[i];
|
||||
strdesc->data[ndata+1] = 0;
|
||||
}
|
||||
|
||||
strdesc->len = ndata+2;
|
||||
strdesc->type = USB_DESC_TYPE_STRING;
|
||||
return strdesc->len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void)
|
||||
{
|
||||
return &g_devdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring
|
||||
* endpoints)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid)
|
||||
{
|
||||
switch (epid)
|
||||
{
|
||||
case USBMSC_EPFSBULKOUT: /* Full speed bulk OUT endpoint descriptor */
|
||||
return &g_fsepbulkoutdesc;
|
||||
|
||||
case USBMSC_EPFSBULKIN: /* Full speed bulk IN endpoint descriptor */
|
||||
return &g_fsepbulkindesc;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
case USBMSC_EPHSBULKOUT: /* High speed bulk OUT endpoint descriptor */
|
||||
return &g_hsepbulkoutdesc;
|
||||
|
||||
case USBMSC_EPHSBULKIN: /* High speed bulk IN endpoint descriptor */
|
||||
return &g_hsepbulkindesc;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
FAR const struct usb_epdesc_s *epdesc;
|
||||
bool hispeed = (speed == USB_SPEED_HIGH);
|
||||
uint16_t bulkmxpacket;
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor. If the USB mass storage device is
|
||||
* configured as part of a composite device, then the configuration
|
||||
* descriptor will be provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC);
|
||||
buf += USB_SIZEOF_CFGDESC;
|
||||
#endif
|
||||
|
||||
/* Copy the canned interface descriptor */
|
||||
|
||||
memcpy(buf, &g_ifdesc, USB_SIZEOF_IFDESC);
|
||||
buf += USB_SIZEOF_IFDESC;
|
||||
|
||||
/* Make the two endpoint configurations */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
/* Check for switches between high and full speed */
|
||||
|
||||
hispeed = (speed == USB_SPEED_HIGH);
|
||||
if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
|
||||
{
|
||||
hispeed = !hispeed;
|
||||
}
|
||||
|
||||
bulkmxpacket = USBMSC_BULKMAXPACKET(hispeed);
|
||||
epdesc = USBMSC_EPBULKINDESC(hispeed);
|
||||
memcpy(buf, epdesc, USB_SIZEOF_EPDESC);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
|
||||
epdesc = USBMSC_EPBULKOUTDESC(hispeed);
|
||||
memcpy(buf, epdesc, USB_SIZEOF_EPDESC);
|
||||
#else
|
||||
memcpy(buf, &g_fsepbulkoutdesc, USB_SIZEOF_EPDESC);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
memcpy(buf, &g_fsepbulkindesc, USB_SIZEOF_EPDESC);
|
||||
#endif
|
||||
|
||||
return SIZEOF_USBMSC_CFGDESC;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void)
|
||||
{
|
||||
return &g_qualdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user