From 219846f408277e046bc8c971908b79939474abea Mon Sep 17 00:00:00 2001 From: c_oflynn Date: Tue, 14 Oct 2008 20:16:36 +0000 Subject: [PATCH] Addition of USB files --- cpu/avr/dev/usb/INF/AtmelRNDIS.inf | 125 +++ cpu/avr/dev/usb/INF/CompositeAtmelRNDIS.inf | 124 +++ cpu/avr/dev/usb/INF/CompositeAtmelVCP.inf | 53 ++ cpu/avr/dev/usb/compiler.h | 351 +++++++ cpu/avr/dev/usb/conf_usb.h | 148 +++ cpu/avr/dev/usb/config.h | 114 +++ cpu/avr/dev/usb/pll_drv.h | 124 +++ cpu/avr/dev/usb/rndis/ndis.h | 266 ++++++ cpu/avr/dev/usb/rndis/rndis.c | 842 +++++++++++++++++ cpu/avr/dev/usb/rndis/rndis_protocol.h | 325 +++++++ cpu/avr/dev/usb/rndis/rndis_task.c | 422 +++++++++ cpu/avr/dev/usb/rndis/rndis_task.h | 75 ++ cpu/avr/dev/usb/serial/cdc_task.c | 293 ++++++ cpu/avr/dev/usb/serial/cdc_task.h | 74 ++ cpu/avr/dev/usb/serial/uart_usb_lib.c | 197 ++++ cpu/avr/dev/usb/serial/uart_usb_lib.h | 85 ++ cpu/avr/dev/usb/storage/avr_flash.c | 515 +++++++++++ cpu/avr/dev/usb/storage/avr_flash.h | 135 +++ cpu/avr/dev/usb/storage/conf_access.h | 197 ++++ cpu/avr/dev/usb/storage/ctrl_access.c | 973 ++++++++++++++++++++ cpu/avr/dev/usb/storage/ctrl_access.h | 157 ++++ cpu/avr/dev/usb/storage/ctrl_status.h | 70 ++ cpu/avr/dev/usb/storage/scsi_decoder.c | 787 ++++++++++++++++ cpu/avr/dev/usb/storage/scsi_decoder.h | 338 +++++++ cpu/avr/dev/usb/storage/storage_task.c | 276 ++++++ cpu/avr/dev/usb/storage/storage_task.h | 69 ++ cpu/avr/dev/usb/usb_descriptors.c | 537 +++++++++++ cpu/avr/dev/usb/usb_descriptors.h | 453 +++++++++ cpu/avr/dev/usb/usb_drv.c | 333 +++++++ cpu/avr/dev/usb/usb_drv.h | 930 +++++++++++++++++++ cpu/avr/dev/usb/usb_specific_request.c | 360 ++++++++ cpu/avr/dev/usb/usb_specific_request.h | 89 ++ cpu/avr/dev/usb/usb_standard_request.c | 551 +++++++++++ cpu/avr/dev/usb/usb_standard_request.h | 88 ++ cpu/avr/dev/usb/usb_task.c | 375 ++++++++ cpu/avr/dev/usb/usb_task.h | 195 ++++ 36 files changed, 11046 insertions(+) create mode 100644 cpu/avr/dev/usb/INF/AtmelRNDIS.inf create mode 100644 cpu/avr/dev/usb/INF/CompositeAtmelRNDIS.inf create mode 100644 cpu/avr/dev/usb/INF/CompositeAtmelVCP.inf create mode 100644 cpu/avr/dev/usb/compiler.h create mode 100644 cpu/avr/dev/usb/conf_usb.h create mode 100644 cpu/avr/dev/usb/config.h create mode 100644 cpu/avr/dev/usb/pll_drv.h create mode 100644 cpu/avr/dev/usb/rndis/ndis.h create mode 100644 cpu/avr/dev/usb/rndis/rndis.c create mode 100644 cpu/avr/dev/usb/rndis/rndis_protocol.h create mode 100644 cpu/avr/dev/usb/rndis/rndis_task.c create mode 100644 cpu/avr/dev/usb/rndis/rndis_task.h create mode 100644 cpu/avr/dev/usb/serial/cdc_task.c create mode 100644 cpu/avr/dev/usb/serial/cdc_task.h create mode 100644 cpu/avr/dev/usb/serial/uart_usb_lib.c create mode 100644 cpu/avr/dev/usb/serial/uart_usb_lib.h create mode 100644 cpu/avr/dev/usb/storage/avr_flash.c create mode 100644 cpu/avr/dev/usb/storage/avr_flash.h create mode 100644 cpu/avr/dev/usb/storage/conf_access.h create mode 100644 cpu/avr/dev/usb/storage/ctrl_access.c create mode 100644 cpu/avr/dev/usb/storage/ctrl_access.h create mode 100644 cpu/avr/dev/usb/storage/ctrl_status.h create mode 100644 cpu/avr/dev/usb/storage/scsi_decoder.c create mode 100644 cpu/avr/dev/usb/storage/scsi_decoder.h create mode 100644 cpu/avr/dev/usb/storage/storage_task.c create mode 100644 cpu/avr/dev/usb/storage/storage_task.h create mode 100644 cpu/avr/dev/usb/usb_descriptors.c create mode 100644 cpu/avr/dev/usb/usb_descriptors.h create mode 100644 cpu/avr/dev/usb/usb_drv.c create mode 100644 cpu/avr/dev/usb/usb_drv.h create mode 100644 cpu/avr/dev/usb/usb_specific_request.c create mode 100644 cpu/avr/dev/usb/usb_specific_request.h create mode 100644 cpu/avr/dev/usb/usb_standard_request.c create mode 100644 cpu/avr/dev/usb/usb_standard_request.h create mode 100644 cpu/avr/dev/usb/usb_task.c create mode 100644 cpu/avr/dev/usb/usb_task.h diff --git a/cpu/avr/dev/usb/INF/AtmelRNDIS.inf b/cpu/avr/dev/usb/INF/AtmelRNDIS.inf new file mode 100644 index 000000000..c7855245d --- /dev/null +++ b/cpu/avr/dev/usb/INF/AtmelRNDIS.inf @@ -0,0 +1,125 @@ +; +; Template INF for a USB Remote NDIS Device +; Copyright (c) Microsoft Corporation +; + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %Atmel% +DriverVer = 06/20/2008,0.0.0.3 +;CatalogFile = Atmel.cat + +[Manufacturer] +%Atmel% = AtmelDevices,NT.5.1 + +[AtmelDevices] +%AtmelDevice% = RNDIS, USB\VID_03EB&PID_2019 + +[AtmelDevices.NT.5.1] +%AtmelDevice% = RNDIS.NT.5.1, USB\VID_03EB&PID_2019 + +[ControlFlags] +ExcludeFromSelect=* + +; Windows 2000 specific sections --------------------------------- + +[RNDIS.NT] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 06/20/2008,0.0.0.2 +AddReg = RNDIS_AddReg_NT, RNDIS_AddReg_WIN2K,RNDIS_AddReg_Vista +CopyFiles = RNDIS_CopyFiles_NT + +; DO NOT MODIFY THE SERVICE NAME +[RNDIS.NT.Services] +AddService = USB_RNDISY, 2, RNDIS_ServiceInst_NT, RNDIS_EventLog + +[RNDIS_CopyFiles_NT] +; no rename of files on Windows 2000, use the 'y' names as is +usb8023y.sys, , , 0 +rndismpy.sys, , , 0 + +[RNDIS_ServiceInst_NT] +DisplayName = %ServiceDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\usb8023y.sys +LoadOrderGroup = NDIS +AddReg = RNDIS_WMI_AddReg_NT + +[RNDIS_WMI_AddReg_NT] +HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismpy.sys" + +; Windows XP specific sections ----------------------------------- + +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 06/20/2008,0.0.0.2 +AddReg = RNDIS_AddReg_XP +include = netrndis.inf +needs = Usb_Rndis.ndi + +; no copyfiles - the files are already in place + +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +; Windows 2000 sections + +; DO NOT MODIFY ServiceName +[RNDIS_AddReg_NT] +HKR, Ndi, Service, 0, "USB_RNDISY" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +[RNDIS_AddReg_WIN2K] +HKR, , ReclaimRecv, 0x00010001, 1 +HKR, NDI\params\NetworkAddress, ParamDesc, 0, %NetworkAddress% +HKR, NDI\params\NetworkAddress, type, 0, "edit" +HKR, NDI\params\NetworkAddress, LimitText, 0, "12" +HKR, NDI\params\NetworkAddress, UpperCase, 0, "1" +HKR, NDI\params\NetworkAddress, default, 0, " " +HKR, NDI\params\NetworkAddress, optional, 0, "1" + +[RNDIS_EventLog] +AddReg = RNDIS_EventLog_AddReg + +[RNDIS_EventLog_AddReg] +HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll" +HKR, , TypesSupported, 0x00010001, 7 + + +[RNDIS_AddReg_XP] +HKR, NDI\params\rawmode, ParamDesc, 0, %RAWMODE% +HKR, NDI\params\rawmode, base, 0, "10" +HKR, NDI\params\rawmode, type, 0, "enum" +HKR, NDI\params\rawmode, default, 0, "0" +HKR, NDI\params\rawmode\enum, "0", 0, "Off" +HKR, NDI\params\rawmode\enum, "1", 0, "On" + + + +[SourceDisksNames] +1=%SourceDisk%,,1 + +[SourceDisksFiles] +usb8023y.sys=1 +rndismpy.sys=1 + +[DestinationDirs] +RNDIS_CopyFiles_NT = 12 + +; DO NOT CHANGE ServiceDisplayName +[Strings] +ServiceDisplayName = "USB Remote NDIS Y Network Device Driver" +NetworkAddress = "Network Address" +Atmel = "Atmel Corporation" +AtmelDevice = "Atmel RAVEN USB Stick" +SourceDisk = "Atmel USB Network Driver Install Disk" +RAWMODE = "Raw 802.15.4 Mode" + diff --git a/cpu/avr/dev/usb/INF/CompositeAtmelRNDIS.inf b/cpu/avr/dev/usb/INF/CompositeAtmelRNDIS.inf new file mode 100644 index 000000000..231f1ace7 --- /dev/null +++ b/cpu/avr/dev/usb/INF/CompositeAtmelRNDIS.inf @@ -0,0 +1,124 @@ +; +; Template INF for a USB Remote NDIS Device +; Copyright (c) Microsoft Corporation +; + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %Atmel% +DriverVer = 06/20/2008,0.0.0.3 +;CatalogFile = Atmel.cat + +[Manufacturer] +%Atmel% = AtmelDevices,NT.5.1 + +[AtmelDevices] +%AtmelDevice% = RNDIS, USB\VID_03EB&PID_2021&MI_00 + +[AtmelDevices.NT.5.1] +%AtmelDevice% = RNDIS.NT.5.1, USB\VID_03EB&PID_2021&MI_00 + +[ControlFlags] +ExcludeFromSelect=* + +; Windows 2000 specific sections --------------------------------- + +[RNDIS.NT] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 06/20/2008,0.0.0.2 +AddReg = RNDIS_AddReg_NT, RNDIS_AddReg_WIN2K,RNDIS_AddReg_Vista +CopyFiles = RNDIS_CopyFiles_NT + +; DO NOT MODIFY THE SERVICE NAME +[RNDIS.NT.Services] +AddService = USB_RNDISY, 2, RNDIS_ServiceInst_NT, RNDIS_EventLog + +[RNDIS_CopyFiles_NT] +; no rename of files on Windows 2000, use the 'y' names as is +usb8023y.sys, , , 0 +rndismpy.sys, , , 0 + +[RNDIS_ServiceInst_NT] +DisplayName = %ServiceDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\usb8023y.sys +LoadOrderGroup = NDIS +AddReg = RNDIS_WMI_AddReg_NT + +[RNDIS_WMI_AddReg_NT] +HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismpy.sys" + +; Windows XP specific sections ----------------------------------- + +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 06/20/2008,0.0.0.2 +AddReg = RNDIS_AddReg_XP +include = netrndis.inf +needs = Usb_Rndis.ndi + +; no copyfiles - the files are already in place + +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +; Windows 2000 sections + +; DO NOT MODIFY ServiceName +[RNDIS_AddReg_NT] +HKR, Ndi, Service, 0, "USB_RNDISY" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +[RNDIS_AddReg_WIN2K] +HKR, , ReclaimRecv, 0x00010001, 1 +HKR, NDI\params\NetworkAddress, ParamDesc, 0, %NetworkAddress% +HKR, NDI\params\NetworkAddress, type, 0, "edit" +HKR, NDI\params\NetworkAddress, LimitText, 0, "12" +HKR, NDI\params\NetworkAddress, UpperCase, 0, "1" +HKR, NDI\params\NetworkAddress, default, 0, " " +HKR, NDI\params\NetworkAddress, optional, 0, "1" + +[RNDIS_EventLog] +AddReg = RNDIS_EventLog_AddReg + +[RNDIS_EventLog_AddReg] +HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll" +HKR, , TypesSupported, 0x00010001, 7 + + +[RNDIS_AddReg_XP] +[RNDIS_AddReg_XP] +HKR, NDI\params\rawmode, ParamDesc, 0, %RAWMODE% +HKR, NDI\params\rawmode, base, 0, "10" +HKR, NDI\params\rawmode, type, 0, "enum" +HKR, NDI\params\rawmode, default, 0, "0" +HKR, NDI\params\rawmode\enum, "0", 0, "Off" +HKR, NDI\params\rawmode\enum, "1", 0, "On" + + +[SourceDisksNames] +1=%SourceDisk%,,1 + +[SourceDisksFiles] +usb8023y.sys=1 +rndismpy.sys=1 + +[DestinationDirs] +RNDIS_CopyFiles_NT = 12 + +; DO NOT CHANGE ServiceDisplayName +[Strings] +ServiceDisplayName = "USB Remote NDIS Y Network Device Driver" +NetworkAddress = "Network Address" +Atmel = "Atmel Corporation" +AtmelDevice = "Atmel RAVEN USB Stick" +SourceDisk = "Atmel USB Network Driver Install Disk" +RAWMODE = "Raw 802.15.4 Mode" diff --git a/cpu/avr/dev/usb/INF/CompositeAtmelVCP.inf b/cpu/avr/dev/usb/INF/CompositeAtmelVCP.inf new file mode 100644 index 000000000..91b3fc352 --- /dev/null +++ b/cpu/avr/dev/usb/INF/CompositeAtmelVCP.inf @@ -0,0 +1,53 @@ +; Windows 2000 and XP setup File for AT89C5131 demo + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} + +Provider=%ATMEL% +LayoutFile=layout.inf +DriverVer=10/15/1999,5.0.2153.1 + +[Manufacturer] +%ATMEL%=ATMEL + +[ATMEL] +%ATMEL_CDC%=Reader, USB\VID_03EB&PID_2021&MI_02 + + +[Reader_Install.NTx86] +;Windows2000 + +[DestinationDirs] +DefaultDestDir=12 +Reader.NT.Copy=12 + +[Reader.NT] +CopyFiles=Reader.NT.Copy +AddReg=Reader.NT.AddReg + +[Reader.NT.Copy] +usbser.sys + +[Reader.NT.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[Reader.NT.Services] +AddService = usbser, 0x00000002, Service_Inst + +[Service_Inst] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + +[Strings] +ATMEL = "ATMEL, Inc." +ATMEL_CDC = "Atmel Raven USB Debug Port" +Serial.SvcDesc = "USB Serial emulation driver" + diff --git a/cpu/avr/dev/usb/compiler.h b/cpu/avr/dev/usb/compiler.h new file mode 100644 index 000000000..4a398f5d2 --- /dev/null +++ b/cpu/avr/dev/usb/compiler.h @@ -0,0 +1,351 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief This file includes the correct compiler definitions for the different + * architectures. + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Name: $ + * $Revision: 1.1 $ + * $RCSfile: compiler.h,v $ + * $Date: 2008/10/14 20:16:36 $ \n + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * 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. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL ``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 EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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 _COMPILER_H_ +#define _COMPILER_H_ + +/*_____ I N C L U D E S ____________________________________________________*/ + + +/*_____ D E C L A R A T I O N S ____________________________________________*/ +#define LITTLE_ENDIAN + +#ifndef ASM_INCLUDE // define ASM_INCLUDE in your a51 source code before include of .h file +typedef float Float16; + +typedef unsigned char U8 ; +typedef unsigned short U16; +typedef unsigned long U32; +typedef signed char S8 ; +typedef signed short S16; +typedef long S32; +#if (defined __C51__) +typedef bit Bool; // Shall be used with _MEM_TYPE_BIT_ to optimize the memory. +#else +typedef unsigned char Bool; +#endif + +typedef U8 Status; +typedef Bool Status_bool; +#define PASS 0 +#define FAIL 1 + + + +#if (defined __C51__) +# define _MEM_TYPE_BIT_ bdata // Used for bit accesses +# define _MEM_TYPE_FAST_ data +# define _MEM_TYPE_MEDFAST_ idata +# define _MEM_TYPE_MEDSLOW_ pdata +# define _MEM_TYPE_SLOW_ xdata +#else +# define _MEM_TYPE_BIT_ +# define _MEM_TYPE_FAST_ +# define _MEM_TYPE_MEDFAST_ +# define _MEM_TYPE_MEDSLOW_ +# define _MEM_TYPE_SLOW_ +#endif + +typedef unsigned char Uchar; + + +typedef unsigned char Uint8; +typedef unsigned int Uint16; +typedef unsigned long int Uint32; + +typedef char Int8; +typedef int Int16; +typedef long int Int32; + +typedef unsigned char Byte; +typedef unsigned int Word; +typedef unsigned long int DWord; + +typedef union +{ + Uint32 dw; // l changed in dw (double word) because l is used for signed long... + Uint16 w[2]; + Uint8 b[4]; +} Union32; + +typedef union +{ + Uint16 w; + Uint8 b[2]; +} Union16; + +#ifdef __IAR_SYSTEMS_ICC__ +typedef char bit; +typedef int p_uart_ptchar; +typedef int r_uart_ptchar; +#endif +#ifdef __CODEVISIONAVR__ +typedef char bit; +typedef int p_uart_ptchar; +typedef char r_uart_ptchar; +#endif +#if !defined(__IAR_SYSTEMS_ICC__) && !defined(___ICC__) +typedef char p_uart_ptchar; +typedef char r_uart_ptchar; +#endif + +#endif + +/**********************************************************************************/ +/* codevision COMPILER (__CODEVISIONAVR__) */ +/**********************************************************************************/ +#ifdef __ICC__ +#define _ConstType_ lit +#define _MemType_ +#define _GenericType_ __generic +#define FLASH lit +#define XDATA +#define IDATA +#define DATA +#endif +/**********************************************************************************/ +/* IAR COMPILER (__IAR_SYSTEMS_ICC__) */ +/**********************************************************************************/ +#ifdef __IAR_SYSTEMS_ICC__ +#include "inavr.h" +#define _ConstType_ __flash +#define _MemType_ +#define _GenericType_ __generic +#define FLASH __flash +#define FARFLASH __farflash +#define XDATA +#define IDATA +#define DATA +#define At(x) @ x +#define PDATA +#define BDATA +// Memory Type Location +#ifndef _CONST_TYPE_ +# define _CONST_TYPE_ code +#endif + +#define Enable_interrupt() __enable_interrupt() +#define Disable_interrupt() __disable_interrupt() + +#include +#define SFR_W_EXT(a,b) SFR_W_R(b,a) +#endif + + +/* General purpose defines */ +/*#define _ConstType_ __farflash +#define _MemType_ +#define _GenericType_ __generic +#define code __farflash +#define xdata +#define idata +#define data*/ + + + + +/*_____ M A C R O S ________________________________________________________*/ +/* little-big endian management */ +#define INTEL_ALIGNMENT LITTLE_ENDIAN +#define MOTOROLA_ALIGNMENT BIG_ENDIAN + +// U16/U32 endian handlers +#ifdef LITTLE_ENDIAN // => 16bit: (LSB,MSB), 32bit: (LSW,MSW) or (LSB0,LSB1,LSB2,LSB3) or (MSB3,MSB2,MSB1,MSB0) +# define MSB(u16) (((U8* )&u16)[1]) +# define LSB(u16) (((U8* )&u16)[0]) +# define MSW(u32) (((U16*)&u32)[1]) +# define LSW(u32) (((U16*)&u32)[0]) +# define MSB0(u32) (((U8* )&u32)[3]) +# define MSB1(u32) (((U8* )&u32)[2]) +# define MSB2(u32) (((U8* )&u32)[1]) +# define MSB3(u32) (((U8* )&u32)[0]) +# define LSB0(u32) MSB3(u32) +# define LSB1(u32) MSB2(u32) +# define LSB2(u32) MSB1(u32) +# define LSB3(u32) MSB0(u32) +#else // BIG_ENDIAN => 16bit: (MSB,LSB), 32bit: (MSW,LSW) or (LSB3,LSB2,LSB1,LSB0) or (MSB0,MSB1,MSB2,MSB3) +# define MSB(u16) (((U8* )&u16)[0]) +# define LSB(u16) (((U8* )&u16)[1]) +# define MSW(u32) (((U16*)&u32)[0]) +# define LSW(u32) (((U16*)&u32)[1]) +# define MSB0(u32) (((U8* )&u32)[0]) +# define MSB1(u32) (((U8* )&u32)[1]) +# define MSB2(u32) (((U8* )&u32)[2]) +# define MSB3(u32) (((U8* )&u32)[3]) +# define LSB0(u32) MSB3(u32) +# define LSB1(u32) MSB2(u32) +# define LSB2(u32) MSB1(u32) +# define LSB3(u32) MSB0(u32) +#endif + +// Endian converters +#define Le16(b) \ + ( ((U16)( (b) & 0xFF) << 8) \ + | ( ((U16)(b) & 0xFF00) >> 8) \ + ) +#define Le32(b) \ + ( ((U32)( (b) & 0xFF) << 24) \ + | ((U32)((U16)(b) & 0xFF00) << 8) \ + | ( ((U32)(b) & 0xFF0000) >> 8) \ + | ( ((U32)(b) & 0xFF000000) >> 24) \ + ) + +// host to network conversion: used for Intel HEX format, TCP/IP, ... +// Convert a 16-bit value from host-byte order to network-byte order +// Standard Unix, POSIX 1003.1g (draft) + +/* +#ifdef LITTLE_ENDIAN +# define htons(a) Le16(a) +#define ntohs(a) htons(a) +# define htonl(a) Le32(a) +#define ntohl(a) htonl(a) +#else +#define htons(a) (a) +#define ntohs(a) (a) +#define htonl(a) (a) +#define ntohl(a) (a) +#endif +*/ + +// Constants +#define ENABLE 1 +#define ENABLED 1 +#define DISABLED 0 +#define DISABLE 0 +#define FALSE (0==1) +#define TRUE (1==1) + +#define KO 0 +#define OK 1 +#define OFF 0 +#define ON 1 +#ifndef NULL +#define NULL 0 +#endif +#ifndef ASM_INCLUDE // define ASM_INCLUDE in your a51 source code before include of .h file +#define CLR 0 +#define SET 1 +#endif + +/* Bit and bytes manipulations */ +#define LOW(U16) ((Uchar)U16) +#define HIGH(U16) ((Uchar)(U16>>8)) +#define TST_BIT_X(addrx,mask) (*addrx & mask) +#define SET_BIT_X(addrx,mask) (*addrx = (*addrx | mask)) +#define CLR_BIT_X(addrx,mask) (*addrx = (*addrx & ~mask)) +#define OUT_X(addrx,value) (*addrx = value) +#define IN_X(addrx) (*addrx) + +# define Max(a, b) ( (a)>(b) ? (a) : (b) ) // Take the max between a and b +# define Min(a, b) ( (a)<(b) ? (a) : (b) ) // Take the min between a and b + +// Align on the upper value on a boundary +// i.e. Upper(0, 4)= 4 +// Upper(1, 4)= 4 +// Upper(2, 4)= 4 +// Upper(3, 4)= 4 +// Upper(4, 4)= 8 +// ../.. +# define Upper(val, n) ( ((val)+(n)) & ~((n)-1) ) + +// Align up on a boundary +// i.e. Align_up(0, 4)= 0 +// Align_up(1, 4)= 4 +// Align_up(2, 4)= 4 +// Align_up(3, 4)= 4 +// Align_up(4, 4)= 4 +// ../.. +# define Align_up(val, n) ( ((val)+(n)-1) & ~((n)-1) ) + +// Align down on a boundary +// i.e. Align_down(0, 4)= 0 +// Align_down(1, 4)= 0 +// Align_down(2, 4)= 0 +// Align_down(3, 4)= 0 +// Align_down(4, 4)= 4 +// ../.. +# define Align_down(val, n) ( (val) & ~((n)-1) ) + +/* {For Langdoc} */ + +/*********************************************************** + SET_SFR_BIT macro + parameters + sfr_reg : defined value in include file for sfr register + bit_pos : defined value B_XX in include file for particular + bit of sfr register + bit_val : CLR / SET +************************************************************/ +#define SET_SFR_BIT(sfr_reg, bit_pos, bit_val) { sfr_reg &= ~(1<<(bit_pos)); sfr_reg |= ((bit_val)<<(bit_pos));} + +#define TID_GUARD(proc) ((__TID__ & 0x7FF0) != ((90 << 8) | ((proc) << 4))) + +/******************************************************************************/ +/* GCC COMPILER */ +/******************************************************************************/ + #ifdef AVRGCC +#define _CONST_TYPE_ +#define _ConstType_ __flash +#define _MemType_ +#define _GenericType_ __generic +#define FLASH PROGMEM +#define XDATA +#define IDATA +#define DATA +#define At(x) @ x +#define PDATA +#define BDATA +#define bit U8 + //#include + #include + #include + #define Enable_interrupt() sei() + #define Disable_interrupt() cli() + + #endif +#endif /* _COMPILER_H_ */ + diff --git a/cpu/avr/dev/usb/conf_usb.h b/cpu/avr/dev/usb/conf_usb.h new file mode 100644 index 000000000..23fcbf606 --- /dev/null +++ b/cpu/avr/dev/usb/conf_usb.h @@ -0,0 +1,148 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file conf_usb.h ********************************************************** + * + * \brief + * This file contains the possible external configuration of the USB. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _CONF_USB_H_ +#define _CONF_USB_H_ + + + +/** + \ingroup usbstick + \defgroup usbconf USB Configuration + @{ +*/ + + + // _________________ USB MODE CONFIGURATION ____________________________ + //! @ingroup usbconf + //! @defgroup USB_op_mode USB operating modes configuration + //! defines to enable device or host usb operating modes + //! supported by the application + //! @{ + + //! @brief ENABLE to activate the host software library support + //! + //! Possible values ENABLE or DISABLE + #define USB_HOST_FEATURE DISABLED + + //! @brief ENABLE to activate the device software library support + //! + //! Possible values ENABLE or DISABLE + #define USB_DEVICE_FEATURE ENABLED + + //! @} + + // _________________ USB REGULATOR CONFIGURATION _______________________ + //! @ingroup usbconf + //! @defgroup USB_reg_mode USB regulator configuration + //! @{ + + //! @brief Enable the internal regulator for USB pads + //! + //! When the application voltage is lower than 3.5V, to optimize power consumption + //! the internal USB pads regulatr can be disabled. +#ifndef USE_USB_PADS_REGULATOR + #define USE_USB_PADS_REGULATOR ENABLE // Possible values ENABLE or DISABLE +#endif + //! @} + +// _________________ DEVICE MODE CONFIGURATION __________________________ + + //! @ingroup usbconf + //! @defgroup USB_device_mode_cfg USB device operating mode configuration + //! + //! @{ + +/** USB RNDIS / Virtual com port setup **/ + +#define NB_ENDPOINTS 7 //! number of endpoints in the application including control endpoint +#define VCP_RX_EP 0x06 +#define VCP_TX_EP 0x05 +#define VCP_INT_EP 0x04 +#define TX_EP 0x02 +#define RX_EP 0x03 +#define INT_EP 0x01 + +/** USB Mass Storage Setup **/ + +#define NB_ENDPOINTS_MS 3 //! number of endpoints in the application including control endpoint +#define MS_IN_EP 0x01 +#define MS_OUT_EP 0x02 + +#define USB_LOW_SPEED_DEVICE DISABLE + + +#define Usb_unicode(a) ((U16)(a)) + + //! @ingroup usbconf + //! @defgroup device_cst_actions USB device custom actions + //! + //! @{ + // write here the action to associate to each USB event + // be carefull not to waste time in order not disturbing the functions +#define Usb_sof_action() /* sof_action(); */ +#define Usb_wake_up_action() +#define Usb_resume_action() +#define Usb_suspend_action() suspend_action(); +#define Usb_reset_action() +#define Usb_vbus_on_action() +#define Usb_vbus_off_action() +#define Usb_set_configuration_action() + + +// write here the action to associate to each SCSI event +// be carefull not to waste time in order not disturbing the functions +#define Scsi_start_read_action() Led1_on() +#define Scsi_stop_read_action() Led1_off() +#define Scsi_start_write_action() Led2_on() +#define Scsi_stop_write_action() Led2_off() + + //! @} + +extern void sof_action(void); +extern void suspend_action(void); + //! @} + + +/** @} */ + +#endif // _CONF_USB_H_ diff --git a/cpu/avr/dev/usb/config.h b/cpu/avr/dev/usb/config.h new file mode 100644 index 000000000..0014b3a5c --- /dev/null +++ b/cpu/avr/dev/usb/config.h @@ -0,0 +1,114 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * This file contains the system configuration definition. + * + * \par Application note: + * AVR280: USB Host CDC Demonstration + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Name: $ + * $Revision: 1.1 $ + * $RCSfile: config.h,v $ + * $Date: 2008/10/14 20:16:36 $ \n + * $Id: config.h,v 1.1 2008/10/14 20:16:36 c_oflynn Exp $ + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _CONFIG_H_ +#define _CONFIG_H_ + +/** + @addtogroup usb + @{ +*/ + +//_____ I N C L U D E S ____________________________________________________ + + +#include "compiler.h" //!< Compiler definitions + +#include "contiki-raven.h" + +#ifdef AVRGCC + #define __AVR_AT90USBxxx__ + #include +#else + #include "lib_mcu/mcu.h" //!< Register declaration +#endif + +//#include "conf_scheduler.h" //!< Scheduler tasks declaration + +//! Enable or not the ADC usage +#undef USE_ADC + +//! CPU core frequency in kHz +#define FOSC 8000 + + +// -------- END Generic Configuration ------------------------------------- + +// UART Sample configuration, if we have one ... __________________________ + +#ifndef AVRGCC + #define uart_usb_putchar putchar +#endif +#define r_uart_ptchar int +#define p_uart_ptchar int + +#define NB_MS_BEFORE_FLUSH 50 +#define REPEAT_KEY_PRESSED 100 + +// ADC Sample configuration, if we have one ... ___________________________ + +//! ADC Prescaler value +#define ADC_PRESCALER 64 +//! Right adjust +#define ADC_RIGHT_ADJUST_RESULT 1 +//! AVCC As reference voltage (See adc_drv.h) +#define ADC_INTERNAL_VREF 2 + +//!--------- Device Mass Storage Identifiers Signature ----------------------- +#define SBC_VENDOR_ID {'A','T','M','E','L',' ',' ',' '} // 8 Bytes only +#define SBC_PRODUCT_ID {'R','Z','R','A','V','E','N','U','S','B',' ','D','O','C','S',' '} // 16 Bytes only +#define SBC_REVISION_ID {'0','.','0','0'} // 4 Bytes only + +/** @} */ + +#endif // _CONFIG_H_ + diff --git a/cpu/avr/dev/usb/pll_drv.h b/cpu/avr/dev/usb/pll_drv.h new file mode 100644 index 000000000..9677b62be --- /dev/null +++ b/cpu/avr/dev/usb/pll_drv.h @@ -0,0 +1,124 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * This file contains the low level macros and definition for the USB PLL. + * + * \par Application note: + * AVR280: USB Host CDC Demonstration + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Name: $ + * $Revision: 1.1 $ + * $RCSfile: pll_drv.h,v $ + * $Date: 2008/10/14 20:16:36 $ \n + * $Id: pll_drv.h,v 1.1 2008/10/14 20:16:36 c_oflynn Exp $ + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 PLL_DRV_H +#define PLL_DRV_H + +//_____ I N C L U D E S ____________________________________________________ + +/** + @addtogroup usb + @{ +*/ +//_____ M A C R O S ________________________________________________________ + + //! @defgroup PLL_macros PLL Macros + //! These functions allow to control the PLL + //! @{ +#define PLLx24 ( (0< + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + + +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B + +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +/* NDIS_PNP_CAPABILITIES.Flags constants */ +#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +/* +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; +*/ + +/* Required Object IDs (OIDs) */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional statistics OIDs */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 +#define OID_GEN_INIT_TIME_MS 0x00020213 +#define OID_GEN_RESET_COUNTS 0x00020214 +#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define OID_GEN_FRIENDLY_NAME 0x00020216 +#define OID_GEN_MINIPORT_INFO 0x00020217 +#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* IEEE 802.3 (Ethernet) OIDs */ +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Wireless LAN OIDs */ +//Mandatory +#define OID_802_11_BSSID 0x0D010101 /* Q S */ +#define OID_802_11_SSID 0x0D010102 /* Q S */ +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ +#define OID_802_11_RSSI 0x0D010206 /* Q I */ +#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ +#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ +#define OID_802_11_ADD_WEP 0x0D010113 /* S */ +#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ +#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ +#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ + + + +/* OID_GEN_MINIPORT_INFO constants */ +#define NDIS_MINIPORT_BUS_MASTER 0x00000001 +#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 +#define NDIS_MINIPORT_SG_LIST 0x00000004 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 +#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 +#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 +#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 +#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 +#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 +#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 +#define NDIS_MINIPORT_IS_CO 0x00000400 +#define NDIS_MINIPORT_DESERIALIZE 0x00000800 +#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 +#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 +#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 +#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 +#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 +#define NDIS_MINIPORT_HIDDEN 0x00040000 +#define NDIS_MINIPORT_SWENUM 0x00080000 +#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 +#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 +#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 +#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 +#define NDIS_MINIPORT_64BITS_DMA 0x01000000 + +#define NDIS_MEDIUM_802_3 0x00000000 +#define NDIS_MEDIUM_802_5 0x00000001 +#define NDIS_MEDIUM_FDDI 0x00000002 +#define NDIS_MEDIUM_WAN 0x00000003 +#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 +#define NDIS_MEDIUM_DIX 0x00000005 +#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 +#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 +#define NDIS_MEDIUM_ATM 0x00000008 +#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 +#define NDIS_MEDIUM_IRDA 0x0000000A +#define NDIS_MEDIUM_BPC 0x0000000B +#define NDIS_MEDIUM_CO_WAN 0x0000000C +#define NDIS_MEDIUM_1394 0x0000000D + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 +#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#endif /* _LINUX_NDIS_H */ + +/** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis.c b/cpu/avr/dev/usb/rndis/rndis.c new file mode 100644 index 000000000..87e6d15ef --- /dev/null +++ b/cpu/avr/dev/usb/rndis/rndis.c @@ -0,0 +1,842 @@ +/** + * \file rndis.c + * RNDIS Functions for mounting USB device as network interface + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ +/* Copyright (c) 2008 Colin O'Flynn + + The CDC code which this is based on is Copyright (c) Atmel Corporation 2008 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/* +RNDIS Status Information: + +802.3 Support: + More or less working + +802.11 Support: + Incomplete, would just error out if you tried probably + + +*/ + +/** + \addtogroup RNDIS + @{ + */ + + +//_____ I N C L U D E S ____________________________________________________ + +#include "radio.h" +#include "contiki.h" +#include "config.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "rndis/rndis_protocol.h" +#include "uip.h" +#include "serial/uart_usb_lib.h" +#include "sicslow_ethernet.h" +#include +#include + +//_____ M A C R O S ________________________________________________________ + +//_____ D E F I N I T I O N ________________________________________________ + +//_____ P R I V A T E D E C L A R A T I O N ______________________________ + +extern PGM_VOID_P pbuffer; +extern U8 data_to_transfer; + +//NB: If you change the OID list be sure to update this!!! +//#define OID_LIST_LENGTH 50 +#define OID_LIST_LENGTH 35 + +/** + * \brief List of supported RNDIS OID's + */ +prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = { + /* Required General */ + OID_GEN_SUPPORTED_LIST , + OID_GEN_HARDWARE_STATUS , + OID_GEN_MEDIA_SUPPORTED , + OID_GEN_MEDIA_IN_USE , + OID_GEN_MAXIMUM_FRAME_SIZE , + OID_GEN_LINK_SPEED , + OID_GEN_TRANSMIT_BLOCK_SIZE , + OID_GEN_RECEIVE_BLOCK_SIZE , + OID_GEN_VENDOR_ID , + OID_GEN_VENDOR_DESCRIPTION , + OID_GEN_CURRENT_PACKET_FILTER , + OID_GEN_MAXIMUM_TOTAL_SIZE , + OID_GEN_MEDIA_CONNECT_STATUS , + OID_GEN_VENDOR_DRIVER_VERSION , + OID_GEN_PHYSICAL_MEDIUM , + + /* Required Statistical */ + OID_GEN_XMIT_OK , + OID_GEN_RCV_OK , + OID_GEN_XMIT_ERROR , + OID_GEN_RCV_ERROR , + OID_GEN_RCV_NO_BUFFER , + + /* Please configure us */ + OID_GEN_RNDIS_CONFIG_PARAMETER , + + + /* IEEE 802.3 (Ethernet) OIDs */ + OID_802_3_PERMANENT_ADDRESS , + OID_802_3_CURRENT_ADDRESS , + OID_802_3_MULTICAST_LIST , + OID_802_3_MAXIMUM_LIST_SIZE , + OID_802_3_MAC_OPTIONS , + OID_802_3_RCV_ERROR_ALIGNMENT , + OID_802_3_XMIT_ONE_COLLISION , + OID_802_3_XMIT_MORE_COLLISIONS , + +/*802.11 OID's not fully implemented yet. Hence do not say we + support them */ +#ifdef DONOTEVERDEFINETHISORBADSTUFFHAPPENS + /* 802.11 OIDs */ + OID_802_11_BSSID , + OID_802_11_SSID , + OID_802_11_NETWORK_TYPE_IN_USE , + OID_802_11_RSSI , + OID_802_11_BSSID_LIST , + OID_802_11_BSSID_LIST_SCAN , + OID_802_11_INFRASTRUCTURE_MODE , + OID_802_11_SUPPORTED_RATES , + OID_802_11_CONFIGURATION , + OID_802_11_ADD_WEP , + OID_802_11_WEP_STATUS , + OID_802_11_REMOVE_WEP , + OID_802_11_DISASSOCIATE , + OID_802_11_AUTHENTICATION_MODE , + OID_802_11_RELOAD_DEFAULTS , +#endif + + /* Minimum power managment needed for USB */ + + OID_PNP_CAPABILITIES , + OID_PNP_QUERY_POWER , + OID_PNP_SET_POWER , + + OID_PNP_ENABLE_WAKE_UP , + OID_PNP_ADD_WAKE_UP_PATTERN , + OID_PNP_REMOVE_WAKE_UP_PATTERN + + }; + + +rndis_state_t rndis_state; + +rndis_stat_t rndis_stat; + +uint8_t schedule_interrupt = 0; + +uint64_t rndis_ethernet_addr = 0x203478928323UL; + +//_____ D E C L A R A T I O N ______________________________________________ + + +void rndis_packetFilter(uint32_t newfilter); + +/******** RNDIS ********/ + +#define ENC_BUF_SIZE (4*OID_LIST_LENGTH + 32) + +// Command buffer +U8 encapsulated_buffer[ENC_BUF_SIZE]; + +//Do we have data to send back? +U8 data_to_send = 0x00; + +/** + * \brief Handles a "SEND ENCAPSULATED COMMAND" message. + * + * \return True on success, false on failure. + */ +uint8_t send_encapsulated_command(uint16_t wLength) +{ + U8 i = 0; + + //Received setup message OK + Usb_ack_receive_setup(); + + + //Crude bounds check + if (wLength > ENC_BUF_SIZE) + wLength = ENC_BUF_SIZE; + + //For debugging: this shouldn't happen, just checked it didn't + //if (data_to_send) { + // while(1); + //} + + + //Read in all the bytes... + + uint8_t nb_counter; + + + while (wLength) { + nb_counter = EP_CONTROL_LENGTH; + + //Wait for data to come in + while (!(Is_usb_receive_out())); + + while(nb_counter && wLength) { + encapsulated_buffer[i] = Usb_read_byte(); + i++; + wLength--; + nb_counter--; + } + + Usb_ack_receive_out(); + + } + + Usb_send_control_in(); + + + switch(((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) + { + /* Requests remote intilization. Respond with complete, + eventually should probably do something */ + case REMOTE_NDIS_INITIALIZE_MSG: + { + rndis_initialize_cmplt_t * m; + m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); + + //m->MessageID is same as before + m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + m->MessageLength = sizeof(rndis_initialize_cmplt_t); + m->MajorVersion = RNDIS_MAJOR_VERSION; + m->MinorVersion = RNDIS_MAJOR_VERSION; + m->Status = RNDIS_STATUS_SUCCESS; + m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; + m->Medium = RNDIS_MEDIUM_802_3; + m->MaxPacketsPerTransfer = 1; + m->MaxTransferSize = 1338; /* Space for 1280 IP buffer, Ethernet Header, + RNDIS messages */ + m->PacketAlignmentFactor = 3; + m->AfListOffset = 0; + m->AfListSize = 0; + + rndis_state = rndis_initialized; + + data_to_send = m->MessageLength; + } + break; + case REMOTE_NDIS_HALT_MSG: + + Led0_on(); + Led1_on(); + Led2_on(); + Led3_on(); + + + Usb_send_control_in(); + + while(1); + + + break; + + case REMOTE_NDIS_QUERY_MSG: + rndis_query_process(); + break; + + case REMOTE_NDIS_SET_MSG: + { + rndis_set_process(); + } + break; + + case REMOTE_NDIS_RESET_MSG: + { + rndis_reset_cmplt_t * m; + m = ((rndis_reset_cmplt_t *)encapsulated_buffer); + + rndis_state = rndis_uninitialized; + + m->MessageType = REMOTE_NDIS_RESET_CMPLT; + m->MessageLength = sizeof(rndis_reset_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + m->AddressingReset = 1; /* Make it look like we did something */ + // m->AddressingReset = 0; //Windows halts if set to 1 for some reason + data_to_send = m->MessageLength; + } + break; + + case REMOTE_NDIS_KEEPALIVE_MSG: + { + rndis_keepalive_cmplt_t * m; + m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; + m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + m->MessageLength = sizeof(rndis_keepalive_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + + //We have data to send back + data_to_send = m->MessageLength; + break; + } + + default: + Led2_on(); + return FALSE; + break; + } + + while(!(Is_usb_read_control_enabled())); + + if (Is_usb_receive_out()) Usb_ack_receive_out(); + + rndis_send_interrupt(); + + return TRUE; +} + +/** + * \brief Send an interrupt over the interrupt endpoint to the host. + */ +void rndis_send_interrupt(void) + { + + //Schedule the interrupt to take place next + //time USB task is run + schedule_interrupt = 1; + } + +#define INFBUF ((uint32_t *)(encapsulated_buffer + sizeof(rndis_query_cmplt_t))) + +uint32_t oid_packet_filter = 0x0000000; + +uint16_t panid = 0xbaad; + +/** + * \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer + */ +void rndis_query_process(void) + { + rndis_query_msg_t * m; + rndis_query_cmplt_t * c; + rndis_Status_t status = RNDIS_STATUS_SUCCESS; + + m = (rndis_query_msg_t *)encapsulated_buffer; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + + /* We set up packet for sending one 4-byte response, which a lot of + these will do. If you need more or less just change the defaults in + the specific case */ + + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + //c->Status DO NOT SET YET - as m->Oid resides in this space. We still need it... + c->InformationBufferLength = 4; + c->InformationBufferOffset = 16; + + switch (m->Oid) { + + /**** GENERAL ****/ + case OID_GEN_SUPPORTED_LIST: + c->InformationBufferLength = 4 * OID_LIST_LENGTH; + + //Copy data to SRAM + memcpy_P(INFBUF, OIDSupportedList, 4*OID_LIST_LENGTH); + break; + + case OID_GEN_HARDWARE_STATUS: + *INFBUF = 0x00000000; /* Ready and Willing */ + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + *INFBUF = NDIS_MEDIUM_802_3; /* NDIS_MEDIUM_WIRELESS_LAN instead? */ + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + *INFBUF = (uint32_t) 1280; //1280 //102; /* Assume 25 octet header on 15.4 */ + break; + + case OID_GEN_LINK_SPEED: + *INFBUF = (uint32_t) 100; /* in 100 bytes/sec units.. this is kinda a lie */ + break; + + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + *INFBUF = (uint32_t) 102; + break; + + case OID_GEN_VENDOR_ID: + *INFBUF = 0xFFFFFF; /* No vendor ID ! */ + break; + + case OID_GEN_VENDOR_DESCRIPTION: + c->InformationBufferLength = 8; + memcpy_P(INFBUF, PSTR("Atmel\0\0\0\0"), 8); + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + *INFBUF = oid_packet_filter; + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: + *INFBUF = (uint32_t) 1300; //127; + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + *INFBUF = NDIS_MEDIA_STATE_CONNECTED; + break; + + case OID_GEN_VENDOR_DRIVER_VERSION: + *INFBUF = 0x00001000; + break; + + case OID_GEN_PHYSICAL_MEDIUM: + *INFBUF = NDIS_MEDIUM_802_3; /*NDIS_MEDIUM_WIRELESS_LAN;*/ + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + *INFBUF = (uint32_t) 1280; //102; + + /******* 802.3 (Ethernet) *******/ + + /*The address of the NIC encoded in the hardware.*/ + case OID_802_3_PERMANENT_ADDRESS: + + //Clear unused bytes + *(INFBUF + 1) = 0; + + //Set address + *((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5); + *((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4); + *((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3); + *((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2); + *((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1); + *((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0); + + + /*4+2 = 6 Bytes of eth address */ + c->InformationBufferLength += 2; + break; + + /*The address the NIC is currently using.*/ + case OID_802_3_CURRENT_ADDRESS: + //Clear unused bytes + *(INFBUF + 1) = 0; + + //Set address + *((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5); + *((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4); + *((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3); + *((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2); + *((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1); + *((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0); + + /*4+2 = 6 Bytes of eth address */ + c->InformationBufferLength += 2; + break; + + /* The multicast address list on the NIC enabled for packet reception. */ + case OID_802_3_MULTICAST_LIST: + *INFBUF = 0xE000000; + break; + + /* The maximum number of multicast addresses the NIC driver can manage. */ + case OID_802_3_MAXIMUM_LIST_SIZE: + *INFBUF = 1; + break; + + /* Features supported by the underlying driver, which could be emulating Ethernet. */ + case OID_802_3_MAC_OPTIONS: + *INFBUF = 0; + break; + + /* Frames received with alignment error */ + case OID_802_3_RCV_ERROR_ALIGNMENT: + *INFBUF = 0; + break; + + /* Frames transmitted with one collision */ + case OID_802_3_XMIT_ONE_COLLISION: + *INFBUF = 0; + break; + + /* Frames transmitted with more than one collision */ + case OID_802_3_XMIT_MORE_COLLISIONS: + *INFBUF = 0; + break; + + + /*** 802.11 OIDs ***/ + case OID_802_11_BSSID: + *INFBUF = (uint32_t)panid; + *(INFBUF + 1) = 0; + + /*4+2 = 6 Bytes of eth address */ + c->InformationBufferLength += 2; + break; + + case OID_802_11_SSID: + /* Our SSID is *always* "PANID: 0xXXXX", length = 13 */ + *INFBUF = 13; + + strncpy_P((char*)(INFBUF + 1), PSTR("PANID: 0xBAAD"), 13); + break; + + case OID_802_11_NETWORK_TYPE_IN_USE: + *INFBUF = 0; /* Ndis802_11FH - it's all lies anyway */ + break; + + case OID_802_11_RSSI: + *((int32_t *) INFBUF) = -20; //-20 dBm + break; + + case OID_802_11_BSSID_LIST: + break; + + /* todo: */ + case OID_802_11_INFRASTRUCTURE_MODE: + case OID_802_11_SUPPORTED_RATES: + case OID_802_11_CONFIGURATION: + case OID_802_11_WEP_STATUS: + case OID_802_11_AUTHENTICATION_MODE: + break; + + /*** Statistical ***/ + + /* Frames transmitted without errors */ + case OID_GEN_XMIT_OK: + *INFBUF = rndis_stat.txok; + break; + + /* Frames received without errors */ + case OID_GEN_RCV_OK: + *INFBUF = rndis_stat.rxok; + break; + + /* Frames received with errors */ + case OID_GEN_RCV_ERROR: + *INFBUF = rndis_stat.rxbad; + break; + + /* Frames transmitted with errors */ + case OID_GEN_XMIT_ERROR: + *INFBUF = rndis_stat.txbad; + break; + + /* Frames dropped due to lack of buffer space */ + case OID_GEN_RCV_NO_BUFFER: + + *INFBUF = 0; /* Lies! */ + break; + + /*** Power Managment ***/ + case OID_PNP_CAPABILITIES: + c->InformationBufferLength = sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES); + + //Sorry, I don't play ball. Power managment is for hippies + memset((char *)INFBUF, 0, sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES)); + break; + + case OID_PNP_QUERY_POWER: + c->InformationBufferLength = 0; + break; + + case OID_PNP_ENABLE_WAKE_UP: + *INFBUF = 0; /* Nothing Supported */ + break; + + default: + status = RNDIS_STATUS_FAILURE; + c->InformationBufferLength = 0; + break; + + + } + + //Set Status now that we are done with Oid + c->Status = status; + + //Calculate message size + c->MessageLength = sizeof (rndis_query_cmplt_t) + c->InformationBufferLength; + + //Check if we are sending no information buffer + if (c->InformationBufferLength == 0) { + c->InformationBufferOffset = 0; + } + + //Set it up + data_to_send = c->MessageLength; + } + + +#undef INFBUF +#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) +#define CFGBUF ((rndis_config_parameter_t *) INFBUF) +#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset) +#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset) + +#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */ + +/** + * \brief Function to deal with a RNDIS "SET" command present in the + * encapsulated_buffer + */ +void rndis_set_process(void) + { + rndis_set_cmplt_t * c; + rndis_set_msg_t * m; + + c = ((rndis_set_cmplt_t *)encapsulated_buffer); + m = ((rndis_set_msg_t *)encapsulated_buffer); + + //Never have longer parameter names than PARM_NAME_LENGTH + char parmname[PARM_NAME_LENGTH]; + + uint8_t i; + int8_t parmlength; + + /* The parameter name seems to be transmitted in uint16_t, but + we want this in uint8_t. Hence have to throw out some info... */ + if (CFGBUF->ParameterNameLength > (PARM_NAME_LENGTH*2)) { + parmlength = PARM_NAME_LENGTH * 2; + } else { + parmlength = CFGBUF->ParameterNameLength; + } + + i = 0; + while(parmlength > 0) { + //Convert from uint16_t to char array. + parmname[i] = (char)*(PARMNAME + 2*i); + parmlength -= 2; + i++; + } + + + switch(m->Oid) { + + /* Parameters set up in 'Advanced' tab */ + case OID_GEN_RNDIS_CONFIG_PARAMETER: + /* Parameter name: rawmode + Parameter desc: Enables or disable raw capture of 802.15.4 Packets + Parameter type: single octet + Parameter values: '0' = disabled, '1' = enabled + */ + if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) { + if (*PARMVALUE == '0') { + usbstick_mode.raw = 0; + } else { + usbstick_mode.raw = 1; + } + } + + + break; + + /* Mandatory general OIDs */ + case OID_GEN_CURRENT_PACKET_FILTER: + oid_packet_filter = *INFBUF; + + if (oid_packet_filter) { + + rndis_packetFilter(oid_packet_filter); + + rndis_state = rndis_data_initialized; + } else { + rndis_state = rndis_initialized; + } + + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + break; + + case OID_GEN_PROTOCOL_OPTIONS: + break; + + /* Mandatory 802_3 OIDs */ + case OID_802_3_MULTICAST_LIST: + break; + + /* Mandatory 802.11 OIDs */ + case OID_802_11_BSSID: + panid = *INFBUF; + break; + + case OID_802_11_SSID: + break; + //TODO: rest of 802.11 + + /* Power Managment: fails for now */ + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: + + default: + //c->MessageID is same as before + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_FAILURE; + data_to_send = c->MessageLength; + return; + + break; + } + + //c->MessageID is same as before + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_SUCCESS; + data_to_send = c->MessageLength; + return; + } + +/** + * \brief Handle "GET ENCAPSULATED COMMAND" + * + * \return True on success, false on failure. + * + * This function assumes the message has already set up in + * the "encapsulated_buffer" variable. This will be done by + * the "SEND ENCAPSULATED COMMAND" message, which will trigger + * and interrupt on the host so it knows data is ready. + */ +uint8_t get_encapsulated_command(void) + { + U8 nb_byte, zlp, i; + + //We assume this is already set up... + + //Received setup message OK + Usb_ack_receive_setup(); + + if ((data_to_send % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } + else { zlp = FALSE; } //!< no need of zero length packet + + + i = 0; + while((data_to_send != 0) && (!Is_usb_receive_out())) + { + while(!Is_usb_read_control_enabled()); + + nb_byte=0; + while(data_to_send != 0) //!< Send data until necessary + { + if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size + { + break; + } + Usb_write_byte(encapsulated_buffer[i]); + i++; + data_to_send--; + + } + Usb_send_control_in(); + } + + if(Is_usb_receive_out()) { Usb_ack_receive_out(); return TRUE; } //!< abort from Host + + if(zlp == TRUE) + { + while(!Is_usb_read_control_enabled()); + Usb_send_control_in(); + } + + while(!Is_usb_receive_out()); + Usb_ack_receive_out(); + + return TRUE; + } + + +/** + * \brief Send a status packet back to the host + * + * \return Sucess or Failure + * \retval 1 Success + * \retval 0 Failure + */ +uint8_t rndis_send_status(rndis_Status_t stat) + { + uint8_t i; + + if(Is_usb_read_control_enabled() && !data_to_send) { + + rndis_indicate_status_t * m; + m = (rndis_indicate_status_t *)encapsulated_buffer; + + m->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; + m->MessageLength = sizeof(rndis_indicate_status_t); + m->Status = stat; + + for(i = 0; i < sizeof(rndis_indicate_status_t); i++) { + Usb_write_byte(encapsulated_buffer[i]); + } + + Usb_send_control_in(); + while(!(Is_usb_read_control_enabled())); + + while(!Is_usb_receive_out()); + Usb_ack_receive_out(); + + return 1; + } + + + return 0; + } + + +/****************** Radio Interface ****************/ + +/** + * \brief Set the packet filter - currently distinguishes + * between promiscuous mode and normal mode + */ +void rndis_packetFilter(uint32_t newfilter) +{ + + if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) { + rxMode = RX_ON; + radio_set_trx_state(RX_ON); + } else { + rxMode = RX_AACK_ON; + radio_set_trx_state(RX_AACK_ON); + } + +} + +/** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis_protocol.h b/cpu/avr/dev/usb/rndis/rndis_protocol.h new file mode 100644 index 000000000..201521440 --- /dev/null +++ b/cpu/avr/dev/usb/rndis/rndis_protocol.h @@ -0,0 +1,325 @@ +/** + * \file rndis_protocol.h + * RNDIS Defines + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 Colin O'Flynn + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _RNDIS_H +#define _RNDIS_H + +/** + \addtogroup RNDIS + @{ + */ + +#include + +#define RNDIS_MAJOR_VERSION 1 +#define RNDIS_MINOR_VERSION 0 + +#define RNDIS_STATUS_SUCCESS 0X00000000 +#define RNDIS_STATUS_FAILURE 0XC0000001 +#define RNDIS_STATUS_INVALID_DATA 0XC0010015 +#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB +#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B +#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C + + +/* Message set for Connectionless (802.3) Devices */ +#define REMOTE_NDIS_PACKET_MSG 0x00000001 +#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 +#define REMOTE_NDIS_HALT_MSG 0X00000003 +#define REMOTE_NDIS_QUERY_MSG 0X00000004 +#define REMOTE_NDIS_SET_MSG 0X00000005 +#define REMOTE_NDIS_RESET_MSG 0X00000006 +#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 +#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 +#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 +#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 +#define REMOTE_NDIS_SET_CMPLT 0X80000005 +#define REMOTE_NDIS_RESET_CMPLT 0X80000006 +#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 + +typedef uint32_t rndis_MessageType_t; +typedef uint32_t rndis_MessageLength_t; +typedef uint32_t rndis_RequestId_t; +typedef uint32_t rndis_MajorVersion_t; +typedef uint32_t rndis_MinorVersion_t; +typedef uint32_t rndis_MaxTransferSize_t; +typedef uint32_t rndis_Status_t; + + +/* Device Flags */ +#define RNDIS_DF_CONNECTIONLESS 0x00000001 +#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +typedef uint32_t rndis_DeviceFlags_t; + +/* Mediums */ +#define RNDIS_MEDIUM_802_3 0x00000000 +typedef uint32_t rndis_Medium_t; + + +typedef uint32_t rndis_MaxPacketsPerTransfer_t; +typedef uint32_t rndis_PacketAlignmentFactor_t; +typedef uint32_t rndis_AfListOffset_t; +typedef uint32_t rndis_AfListSize_t; + +/*** Remote NDIS Generic Message type ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + } rndis_generic_msg_t; + + +/*** Remote NDIS Initialize Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_MaxTransferSize_t MaxTransferSize; + } rndis_initialize_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_DeviceFlags_t DeviceFlags; + rndis_Medium_t Medium; + rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; + rndis_MaxTransferSize_t MaxTransferSize; + rndis_PacketAlignmentFactor_t PacketAlignmentFactor; + rndis_AfListOffset_t AfListOffset; + rndis_AfListSize_t AfListSize; + } rndis_initialize_cmplt_t; + + +/*** Remote NDIS Halt Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + } rndis_halt_msg_t; + +typedef uint32_t rndis_Oid_t; +typedef uint32_t rndis_InformationBufferLength_t; +typedef uint32_t rndis_InformationBufferOffset_t; +typedef uint32_t rndis_DeviceVcHandle_t; + +/*** Remote NDIS Query Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_query_msg_t; + +/* Response: */ + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + } rndis_query_cmplt_t; + +/*** Remote NDIS Set Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_set_msg_t; + +/* Response */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_set_cmplt_t; + +/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ +typedef uint32_t rndis_ParameterNameOffset_t; +typedef uint32_t rndis_ParameterNameLength_t; +typedef uint32_t rndis_ParameterType_t; +typedef uint32_t rndis_ParameterValueOffset_t; +typedef uint32_t rndis_ParameterValueLength_t; + +#define PARAMETER_TYPE_STRING 2 +#define PARAMETER_TYPE_NUMERICAL 0 + +typedef struct{ + rndis_ParameterNameOffset_t ParameterNameOffset; + rndis_ParameterNameLength_t ParameterNameLength; + rndis_ParameterType_t ParameterType; + rndis_ParameterValueOffset_t ParameterValueOffset; + rndis_ParameterValueLength_t ParameterValueLength; + }rndis_config_parameter_t; + +typedef uint32_t rndis_Reserved_t; + +/*** Remote NDIS Soft Reset Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Reserved_t Reserved; + } rndis_reset_msg_t; + +typedef uint32_t rndis_AddressingReset_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_AddressingReset_t AddressingReset; + } rndis_reset_cmplt_t; + +/*** Remote NDIS Indicate Status Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_Status_t StatusBufferLength; + rndis_Status_t StatusBufferOffset; + } rndis_indicate_status_t; + +typedef uint32_t rndis_DiagStatus_t; +typedef uint32_t rndis_ErrorOffset_t; + +typedef struct { + rndis_DiagStatus_t DiagStatus; + rndis_ErrorOffset_t ErrorOffset; + }rndis_diagnostic_info_t; + +/*** Remote NDIS Keepalive Message */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + }rndis_keepalive_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_keepalive_cmplt_t; + +/*** Remote NDIS Data Packet ***/ + +typedef uint32_t rndis_DataOffset_t; +typedef uint32_t rndis_DataLength_t; +typedef uint32_t rndis_OOBDataOffset_t; +typedef uint32_t rndis_OOBDataLength_t; +typedef uint32_t rndis_NumOOBDataElements_t; +typedef uint32_t rndis_PerPacketInfoOffset_t; +typedef uint32_t rndis_PerPacketInfoLength_t; + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_DataOffset_t DataOffset; + rndis_DataLength_t DataLength; + rndis_OOBDataOffset_t OOBDataOffset; + rndis_OOBDataLength_t OOBDataLength; + rndis_NumOOBDataElements_t NumOOBDataElements; + rndis_PerPacketInfoOffset_t PerPacketInfoOffset; + rndis_PerPacketInfoLength_t PerPacketInfoLength; + rndis_DeviceVcHandle_t DeviceVcHandle; + rndis_Reserved_t Reserved; + }rndis_data_packet_t; + +typedef uint32_t rndis_ClassInformationOffset_t; +typedef uint32_t rndis_Size_t; +typedef uint32_t rndis_Type_t; + +typedef struct{ + rndis_Size_t Size; + rndis_Type_t Type; + rndis_ClassInformationOffset_t ClassInformationType; + }rndis_OOB_packet_t; + + + +#include "ndis.h" + + +typedef enum rnids_state_e { + rndis_uninitialized, + rndis_initialized, + rndis_data_initialized + } rndis_state_t; + +typedef struct{ + uint32_t txok; + uint32_t rxok; + uint32_t txbad; + uint32_t rxbad; + } rndis_stat_t; + +extern rndis_stat_t rndis_stat; + +extern rndis_state_t rndis_state; + +extern uint8_t schedule_interrupt; + +extern uint64_t rndis_ethernet_addr; + +uint8_t send_encapsulated_command(uint16_t wLength); +uint8_t get_encapsulated_command(void); +void rndis_send_interrupt(void); +void rndis_query_process(void); +void rndis_set_process(void); +uint8_t rndis_send_status(rndis_Status_t stat); + +#endif //_RNDIS_H + +/** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis_task.c b/cpu/avr/dev/usb/rndis/rndis_task.c new file mode 100644 index 000000000..caf5c0acc --- /dev/null +++ b/cpu/avr/dev/usb/rndis/rndis_task.c @@ -0,0 +1,422 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file rndis_task.c ********************************************************* + * + * \brief + * Manages the RNDIS Dataclass for the USB Device + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ +/** + \addtogroup RNDIS + @{ + */ + +//_____ I N C L U D E S ___________________________________________________ + + +#include "contiki.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "rndis/rndis_task.h" +#include "rndis/rndis_protocol.h" +#include "uip.h" +#include "sicslow_ethernet.h" +#include + +#include +#include + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +#define PRINTF printf +#define PRINTF_P printf_P + +//_____ M A C R O S ________________________________________________________ + + + + + +//_____ D E F I N I T I O N S ______________________________________________ + + +#define IAD_TIMEOUT_DETACH 400 +#define IAD_TIMEOUT_ATTACH 800 + +#define RNDIS_TIMEOUT_DETACH 900 +#define RNDIS_TIMEOUT_ATTACH 1000 + +#define PBUF ((rndis_data_packet_t *) data_buffer) + +//_____ D E C L A R A T I O N S ____________________________________________ + + +//! Timers for LEDs +uint8_t led1_timer, led2_timer; + +//! Temp data buffer when adding RNDIS headers +uint8_t data_buffer[64]; + +//! Usb is busy with RNDIS +char usb_busy = 0; + + +static struct etimer et; +static struct timer flood_timer; +static uint16_t iad_fail_timeout, rndis_fail_timeout; + +static uint8_t doInit = 1; + +extern uint8_t fingerPresent; + +PROCESS(rndis_process, "RNDIS process"); + +/** + * \brief RNDIS Process + * + * This is the link between USB and the "good stuff". In this routine data + * is received and processed by RNDIS + */ +PROCESS_THREAD(rndis_process, ev, data_proc) +{ + + PROCESS_BEGIN(); + uint8_t bytecounter, headercounter; + uint16_t i, dataoffset; + + while(1) { + + // turn off LED's if necessary + if (led1_timer) led1_timer--; + else Led1_off(); + if (led2_timer) led2_timer--; + else Led2_off(); + + /* Device is Enumerated but RNDIS not loading. We might + have a system that does not support IAD (winXP). If so + count the timeout then switch to just network interface. */ + if (usb_mode == rndis_debug) { + //If we have timed out, detach + if (iad_fail_timeout == IAD_TIMEOUT_DETACH) { + + //Failed - BUT we are using "reverse logic", hence we force device + //into this mode. This is used to allow Windows Vista have time to + //install the drivers + if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) { + iad_fail_timeout = 0; + } else { + stdout = NULL; + Usb_detach(); + doInit = 1; //Also mark system as needing intilizing + } + + //Then wait a few before re-attaching + } else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) { + + if (fingerPresent) { + usb_mode = mass_storage; + } else { + usb_mode = rndis_only; + } + Usb_attach(); + } + + //Increment timeout when device is not initializing, OR we have already detached, + //OR the user had their finger on the device, indicating a reverse of logic + if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) || + (iad_fail_timeout > IAD_TIMEOUT_DETACH) || + (fingerPresent) ) { + iad_fail_timeout++; + } else { + iad_fail_timeout = 0; + } + } //usb_mode == rndis_debug + + + /* Device is Enumerated but RNDIS STIL not loading. We just + have RNDIS interface, so obviously no drivers on target. + Just go ahead and mount ourselves as mass storage... */ + if (usb_mode == rndis_only) { + //If we have timed out, detach + if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) { + Usb_detach(); + //Then wait a few before re-attaching + } else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) { + usb_mode = mass_storage; + Usb_attach(); + } + + //Increment timeout when device is not initializing, OR we are already + //counting to detach + if ( ( (rndis_state != rndis_data_initialized)) || + (rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) { + rndis_fail_timeout++; + } else { + rndis_fail_timeout = 0; + } + }//usb_mode == rnids_only + + + if(rndis_state == rndis_data_initialized) //Enumeration processs OK ? + { + if (doInit) { + //start flood timer + timer_set(&flood_timer, CLOCK_SECOND / 5); + + mac_ethernetSetup(); + doInit = 0; + } + + //Connected! + Led0_on(); + + Usb_select_endpoint(RX_EP); + + //If we have data and a free buffer + if(Is_usb_receive_out() && (uip_len == 0)) { + + //TODO: Fix this some better way + //If you need a delay in RNDIS to slow down super-fast sending, insert it here + //Also mark the USB as "in use" + + //This is done as "flood control" by only allowing one IP packet per time limit + clock_time_t timediff = clock_time() - flood_timer.start; + + + //If timer not yet expired + if (timediff < flood_timer.interval) { + //Wait until timer expiers + usb_busy = 1; + etimer_set(&et, flood_timer.interval - timediff); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + //Reselect endpoint in case we lost it + Usb_select_endpoint(RX_EP); + usb_busy = 0; + } + + //Restart flood timer + timer_restart(&flood_timer); + + //Read how much (endpoint only stores up to 64 bytes anyway) + bytecounter = Usb_byte_counter_8(); + + //Try and read the header in + headercounter = sizeof(rndis_data_packet_t); + + //Hmm.. what's going on here + if (bytecounter < headercounter) { + Usb_ack_receive_out(); + break; + } + + i = 0; + while (headercounter) { + data_buffer[i] = Usb_read_byte(); + bytecounter--; + headercounter--; + i++; + } + + //This is no good. Probably lost syncronization... just drop it for now + if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) { + Usb_ack_receive_out(); + break; + } + + //Looks like we've got a live one + rx_start_led(); + + + //802.3 does not have OOB data, and we don't care about per-packet data + //so that just leave regular packet data... + if (PBUF->DataLength) { + + //Get offset + dataoffset = PBUF->DataOffset; + + //Make it offset from start of message, not DataOffset field + dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t)); + + //Subtract what we already took + dataoffset -= sizeof(rndis_data_packet_t); + + //Read to the start of data + while(dataoffset) { + Usb_read_byte(); + dataoffset--; + bytecounter--; + + //If endpoint is done + if (bytecounter == 0) { + + Usb_ack_receive_out(); + + + //Wait for new data + while (!Is_usb_receive_out()); + + + bytecounter = Usb_byte_counter_8(); + } + + } + + //Read the data itself in + uint8_t * uipdata = uip_buf; + uint16_t datalen = PBUF->DataLength; + + while(datalen) { + *uipdata++ = Usb_read_byte(); + datalen--; + bytecounter--; + + //If endpoint is done + if (bytecounter == 0) { + //Might be everything we need! + if (datalen) { + Usb_ack_receive_out(); + //Wait for new data + while (!Is_usb_receive_out()); + bytecounter = Usb_byte_counter_8(); + } + } + + } + + //Ack final data packet + Usb_ack_receive_out(); + + /*** SEND DATA TO UIP ***/ + if(BUF->type == htons(UIP_ETHTYPE_IPV6)) { + + //Send data over RF or to local stack + uip_len = PBUF->DataLength; //uip_len includes LLH_LEN + mac_ethernetToLowpan(uip_buf); + } + + } //if (PBUF->DataLength) + + + } //if(Is_usb_receive_out() && (uip_len == 0)) + + } // if (rndis_data_intialized) + + if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { + etimer_set(&et, CLOCK_SECOND/80); + } else { + etimer_set(&et, CLOCK_SECOND); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + } // while(1) + + PROCESS_END(); +} + +/** + \brief Send data over RNDIS interface, data is in uipbuf and length is uiplen + */ +uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen) +{ + + + uint16_t i; + + //Setup Header + PBUF->MessageType = REMOTE_NDIS_PACKET_MSG; + PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t); + PBUF->DataLength = sendlen; + PBUF->OOBDataLength = 0; + PBUF->OOBDataOffset = 0; + PBUF->NumOOBDataElements = 0; + PBUF->PerPacketInfoOffset = 0; + PBUF->PerPacketInfoLength = 0; + PBUF->DeviceVcHandle = 0; + PBUF->Reserved = 0; + PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength; + + //Send Data + Usb_select_endpoint(TX_EP); + Usb_send_in(); + + //Wait for ready + while(!Is_usb_write_enabled()); + + //Setup first part of transfer... + for(i = 0; i < sizeof(rndis_data_packet_t); i++) { + Usb_write_byte(data_buffer[i]); + } + + //Send packet + while(sendlen) { + Usb_write_byte(*senddata); + senddata++; + sendlen--; + + //If endpoint is full, send data in + //And then wait for data to transfer + if (!Is_usb_write_enabled()) { + Usb_send_in(); + + while(!Is_usb_write_enabled()); + } + + tx_end_led(); + } + + Usb_send_in(); + + return 1; +} + +/** + @brief This will enable the RX_START LED for a period +*/ +void rx_start_led(void) +{ + Led1_on(); + led1_timer = 10; +} + +/** + @brief This will enable the TRX_END LED for a period +*/ +void tx_end_led(void) +{ + Led2_on(); + led2_timer = 10; +} +/** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis_task.h b/cpu/avr/dev/usb/rndis/rndis_task.h new file mode 100644 index 000000000..8162f25b3 --- /dev/null +++ b/cpu/avr/dev/usb/rndis/rndis_task.h @@ -0,0 +1,75 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file rndis_task.h ********************************************************* + * + * \brief + * This file manages the RNDIS task + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _RNDIS_TASK_H_ +#define _RNDIS_TASK_H_ + +/** + \addtogroup RNDIS + @{ + */ + +//_____ I N C L U D E S ____________________________________________________ + + +#include "config.h" + +//_____ M A C R O S ________________________________________________________ + + + +//_____ D E C L A R A T I O N S ____________________________________________ + + +uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen); +void sof_action(void); +void rx_start_led(void); +void tx_end_led(void); + +extern char usb_busy; + +PROCESS_NAME(rndis_process); + +/** @} */ + +#endif /* _RNDIS_TASK_H_ */ + diff --git a/cpu/avr/dev/usb/serial/cdc_task.c b/cpu/avr/dev/usb/serial/cdc_task.c new file mode 100644 index 000000000..462453089 --- /dev/null +++ b/cpu/avr/dev/usb/serial/cdc_task.c @@ -0,0 +1,293 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file cdc_task.c ********************************************************** + * + * \brief + * Manages the CDC-ACM Virtual Serial Port Dataclass for the USB Device + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ +/** + \ingroup usbstick + \defgroup cdctask CDC Task + @{ + */ + +//_____ I N C L U D E S ___________________________________________________ + + +#include "contiki.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "serial/cdc_task.h" +#include "serial/uart_usb_lib.h" +#include "rndis/rndis_protocol.h" +#include "sicslow_ethernet.h" +#include + +#include +#include + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +#define PRINTF printf +#define PRINTF_P printf_P + +//_____ M A C R O S ________________________________________________________ + + + + + +//_____ D E F I N I T I O N S ______________________________________________ + + +#define IAD_TIMEOUT_DETACH 300 +#define IAD_TIMEOUT_ATTACH 600 +#define PBUF ((rndis_data_packet_t *) data_buffer) + +//_____ D E C L A R A T I O N S ____________________________________________ + + +void menu_print(void); +void menu_process(char c); + +extern char usb_busy; + +//! Counter for USB Serial port +extern U8 tx_counter; + +//! Timers for LEDs +uint8_t led3_timer; + + +//! Was USB device *just* enumerated? +uint8_t justenumerated = 1; + + +static uint8_t timer = 0; +static struct etimer et; + + +PROCESS(cdc_process, "CDC process"); + +/** + * \brief Communication Data Class (CDC) Process + * + * This is the link between USB and the "good stuff". In this routine data + * is received and processed by CDC-ACM Class + */ +PROCESS_THREAD(cdc_process, ev, data_proc) +{ + + PROCESS_BEGIN(); + uart_usb_init(); + + while(1) { + + + // turn off LED's if necessary + if (led3_timer) led3_timer--; + else Led3_off(); + + if(Is_device_enumerated() && (usb_mode == rndis_debug) && rndis_state && (!usb_busy)) { + + if (justenumerated) { + + //If we have serial port, set it as output + if (usb_mode == rndis_debug) { + uart_usb_set_stdout(); + menu_print(); + } + justenumerated = 0; + } + + //Flush buffer if timeout + if(timer >= 4 && tx_counter!=0 ){ + timer = 0; + uart_usb_flush(); + } else { + timer++; + } + + while (uart_usb_test_hit()){ + menu_process(uart_usb_getchar()); // See what they want + } + + + }//if (Is_device_enumerated()) + + + if (usb_mode == rndis_debug) { + etimer_set(&et, CLOCK_SECOND/80); + } else { + etimer_set(&et, CLOCK_SECOND); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + } // while(1) + + PROCESS_END(); +} + +/** + \brief Print debug menu + */ +void menu_print(void) +{ + PRINTF_P(PSTR("\n\n\r********** Jackdaw Menu ******************\n\r")); + PRINTF_P(PSTR("* *\n\r")); + PRINTF_P(PSTR("* Main Menu: *\n\r")); + PRINTF_P(PSTR("* h,? Print this menu *\n\r")); + PRINTF_P(PSTR("* m Print current mode *\n\r")); + PRINTF_P(PSTR("* s Set to sniffer mode *\n\r")); + PRINTF_P(PSTR("* n Set to network mode *\n\r")); + PRINTF_P(PSTR("* 6 Toggle 6lowpan *\n\r")); + PRINTF_P(PSTR("* r Toggle raw mode *\n\r")); + PRINTF_P(PSTR("* u Switch to mass-storage*\n\r")); + PRINTF_P(PSTR("* *\n\r")); + PRINTF_P(PSTR("* Make selection at any time by pressing *\n\r")); + PRINTF_P(PSTR("* your choice on keyboard. *\n\r")); + PRINTF_P(PSTR("******************************************\n\r")); +} + +/** + \brief Process incomming char on debug port + */ +void menu_process(char c) +{ + uint8_t i; + switch(c) { + case '\r': + case '\n': + break; + + case 'h': + case '?': + menu_print(); + break; + + case 's': + PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r")); + usbstick_mode.sendToRf = 0; + usbstick_mode.translate = 0; + break; + + case 'n': + PRINTF_P(PSTR("Jackdaw now in network mode\n\r")); + usbstick_mode.sendToRf = 1; + usbstick_mode.translate = 1; + break; + + case '6': + if (usbstick_mode.sicslowpan) { + PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r")); + usbstick_mode.sicslowpan = 0; + } else { + PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r")); + usbstick_mode.sicslowpan = 1; + } + + break; + + case 'r': + if (usbstick_mode.raw) { + PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r")); + usbstick_mode.raw = 0; + } else { + PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r")); + usbstick_mode.raw = 1; + } + break; + + + case 'm': + PRINTF_P(PSTR("Currently Jackdaw:\n\r * Will ")); + if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("send data over RF\n\r * Will ")); + if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r * Will ")); + if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("decompress 6lowpan headers\n\r * Will ")); + if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r ")); + break; + + case 'u': + + //Mass storage mode + usb_mode = mass_storage; + + //No more serial port + stdout = NULL; + + //RNDIS is over + rndis_state = rndis_uninitialized; + Leds_off(); + + //Deatch USB + Usb_detach(); + + //Wait a few seconds + for(i = 0; i < 50; i++) + _delay_ms(100); + + //Attach USB + Usb_attach(); + + + break; + + default: + PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c); + break; + } + + + return; + +} + + +/** + @brief This will enable the VCP_TRX_END LED for a period +*/ +void vcptx_end_led(void) +{ + Led3_on(); + led3_timer = 10; +} +/** @} */ + diff --git a/cpu/avr/dev/usb/serial/cdc_task.h b/cpu/avr/dev/usb/serial/cdc_task.h new file mode 100644 index 000000000..66042b49d --- /dev/null +++ b/cpu/avr/dev/usb/serial/cdc_task.h @@ -0,0 +1,74 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file cdc_task.h ************************************************************ + * + * \brief + * This file manages the CDC task for the virtual COM port. + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _CDC_TASK_H_ +#define _CDC_TASK_H_ + +/** + \addtogroup cdctask + @{ + */ + +//_____ I N C L U D E S ____________________________________________________ + + +#include "config.h" + +//_____ M A C R O S ________________________________________________________ + + + +//_____ D E C L A R A T I O N S ____________________________________________ + + +void sof_action(void); +void vcptx_end_led(void); + +void rawmode_enable(void); +void rawmode_disable(void); + +PROCESS_NAME(cdc_process); + +/** @} */ + +#endif /* _CDC_TASK_H_ */ + diff --git a/cpu/avr/dev/usb/serial/uart_usb_lib.c b/cpu/avr/dev/usb/serial/uart_usb_lib.c new file mode 100644 index 000000000..1414f8c6a --- /dev/null +++ b/cpu/avr/dev/usb/serial/uart_usb_lib.c @@ -0,0 +1,197 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file uart_usb_lib.c ********************************************************************* + * + * \brief + * This file controls the UART USB functions. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/*_____ I N C L U D E S ____________________________________________________*/ + +#include "config.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "serial/cdc_task.h" +#include "serial/uart_usb_lib.h" +#include + +/** + \addtogroup cdctask + @{ + */ + +/*_____ M A C R O S ________________________________________________________*/ + +/*_____ D E F I N I T I O N ________________________________________________*/ + +Uchar tx_counter; +Uchar rx_counter; +S_line_coding line_coding; + +/*_____ D E C L A R A T I O N ______________________________________________*/ + + +int usb_stdout_putchar(char c, FILE *stream) + { + // send to USB port + // don't send anything if USB can't accept chars + Usb_select_endpoint(TX_EP); + if (!uart_usb_tx_ready()) + return 0; + + // turn on LED + vcptx_end_led(); + + uart_usb_putchar(c); + + return 0; + } + +static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar, + NULL, + _FDEV_SETUP_WRITE); + +/** + * @brief Initializes the uart_usb library + */ +void uart_usb_init(void) +{ + tx_counter = 0; + rx_counter = 0; +} + +void uart_usb_set_stdout(void) +{ + stdout = &usb_stdout; +} + + +/** + * @brief This function checks if the USB emission buffer is ready to accept at + * at least 1 byte + * + * @retval TRUE if the firmware can write a new byte to transmit. + * @retval FALSE otherwise + */ +bit uart_usb_tx_ready(void) +{ + if (!Is_usb_write_enabled()) + { + return FALSE; + } + return TRUE; +} + +/** + * @brief This function fills the USB transmit buffer with the new data. This buffer + * is sent if complete. To flush this buffer before waiting full, launch + * the uart_usb_flush() function. + * + * @param data_to_send Data to send + * + * @return data_to_send Data that was sent + */ +int uart_usb_putchar(int data_to_send) +{ + Usb_select_endpoint(VCP_TX_EP); + + if(!uart_usb_tx_ready()) return -1; + + Usb_write_byte(data_to_send); + tx_counter++; + if(!Is_usb_write_enabled()) //If Endpoint full -> flush + { + uart_usb_flush(); + } + return data_to_send; +} + +/** + * @brief This function checks if a character has been received on the USB bus. + * + * @return bit (true if a byte is ready to be read) + */ +bit uart_usb_test_hit(void) +{ + if (!rx_counter) + { + Usb_select_endpoint(VCP_RX_EP); + if (Is_usb_receive_out()) + { + rx_counter = Usb_byte_counter(); + if (!rx_counter) + { + Usb_ack_receive_out(); + } + } + } + return (rx_counter!=0); +} + +/** + * @brief This function reads one byte from the USB bus + * + * If one byte is present in the USB fifo, this byte is returned. If no data + * is present in the USB fifo, this function waits for USB data. + * + * @return U8 byte received + */ +char uart_usb_getchar(void) +{ + register Uchar data_rx; + + Usb_select_endpoint(VCP_RX_EP); + if (!rx_counter) while (!uart_usb_test_hit()); + data_rx=Usb_read_byte(); + rx_counter--; + if (!rx_counter) Usb_ack_receive_out(); + return data_rx; +} + + +/** + * @brief This function sends the data stored in the USB transmit buffer. + * This function does nothing if there is no data in the buffer. + */ +void uart_usb_flush (void) +{ + Usb_select_endpoint(VCP_TX_EP); + Usb_send_in(); + tx_counter = 0; +} + +/** @} */ diff --git a/cpu/avr/dev/usb/serial/uart_usb_lib.h b/cpu/avr/dev/usb/serial/uart_usb_lib.h new file mode 100644 index 000000000..5097b5a27 --- /dev/null +++ b/cpu/avr/dev/usb/serial/uart_usb_lib.h @@ -0,0 +1,85 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file uart_usb_lib.c ******************************************************* + * + * \brief + * This file controls the UART USB functions. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _UART_USB_LIB_H_ +#define _UART_USB_LIB_H_ + +/** + \addtogroup cdctask + @{ + */ + +/*_____ I N C L U D E S ____________________________________________________*/ + + +/*_____ M A C R O S ________________________________________________________*/ + + +#ifdef UART_USB_DEFAULT_OUTPUT +#define uart_usb_putchar putchar +#endif + +/*_____ D E F I N I T I O N ________________________________________________*/ + +typedef struct +{ + U32 dwDTERate; + U8 bCharFormat; + U8 bParityType; + U8 bDataBits; +}S_line_coding; + + +/*_____ D E C L A R A T I O N ______________________________________________*/ + +void uart_usb_init(void); +bit uart_usb_tx_ready(void); +int uart_usb_putchar(int); +void uart_usb_flush(void); +bit uart_usb_test_hit(void); +char uart_usb_getchar(void); + +/** @} **/ + +#endif /* _UART_USB_LIB_H_ */ + + diff --git a/cpu/avr/dev/usb/storage/avr_flash.c b/cpu/avr/dev/usb/storage/avr_flash.c new file mode 100644 index 000000000..53ccb327c --- /dev/null +++ b/cpu/avr/dev/usb/storage/avr_flash.c @@ -0,0 +1,515 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file avr_flash.c ********************************************************* + * + * \brief + * This file writes/reads to/from flash memory internal to the AVR. + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + ******************************************************************************/ +/* + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +//_____ I N C L U D E S ___________________________________________________ + +#include "config.h" // system configuration +#include "storage/avr_flash.h" + +#include +#include + +#ifndef SPM_PAGESIZE +#error SPM_PAGESIZE undefined!!! +#endif + + +//_____ M A C R O S ________________________________________________________ +//_____ P R I V A T E D E C L A R A T I O N _____________________________ + + +//_____ D E F I N I T I O N ________________________________________________ + + +#define MEM_BASE_ADDRESS 0x10000UL + + +DATA U32 gl_ptr_mem; /* memory data pointer */ + + +/* Disk management */ +bit reserved_disk_space = FALSE; /* reserved space for application on disk */ + + +U32 AVRF_DISK_SIZE = 111; /* 57 KB, some room at end saved for bootloader section */ + + +void avrf_check_init( void ); + + +//_____ D E C L A R A T I O N ______________________________________________ + +//! +//! @brief This function initializes the hw/sw ressources required to drive the AVR Flash +//! +//! @warning Code:?? bytes (function code length) +//! +//!/ +void avrf_mem_init(void) +{ + ; +} + + +//! +//! @brief This function tests the state of the AVR Flash +//! +//! @warning Code:?? bytes (function code length) +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! Else -> CTRL_NO_PRESENT +//!/ +Ctrl_status avrf_test_unit_ready(void) +{ + return CTRL_GOOD; +} + + +//! +//! @brief This function gives the address of the last valid sector. +//! +//! @warning Code:?? bytes (function code length) +//! +//! @param *u32_nb_sector number of sector (sector = 512B). OUT +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//!/ +Ctrl_status avrf_read_capacity( U32 *u32_nb_sector ) +{ + *u32_nb_sector = AVRF_DISK_SIZE; + return CTRL_GOOD; +} + + +//! +//! @brief This function returns the write protected status of the memory. +//! +//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection +//! !!! The customer must unplug the memory to change this write protected status, +//! which cannot be for a DF. +//! +//! @warning Code:?? bytes (function code length) +//! +//! @return FALSE -> the memory is not write-protected (always) +//!/ +Bool avrf_wr_protect(void) +{ + return FALSE; +} + + +//! +//! @brief This function tells if the memory has been removed or not. +//! +//! @warning Code:?? bytes (function code length) +//! +//! @return FALSE -> The memory isn't removed +//!/ +Bool avrf_removal(void) +{ + return FALSE; +} + + + +//------------ STANDARD FUNCTIONS to read/write the memory -------------------- + +//! +//! @brief This function performs a read operation of n sectors from a given address on. +//! (sector = 512B) +//! +//! DATA FLOW is: AVRF => USB +//! +//! +//! @warning Code:?? bytes (function code length) +//! +//! @param addr Sector address to start the read from +//! @param nb_sector Number of sectors to transfer +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! A error occur -> CTRL_FAIL +//! +Ctrl_status avrf_read_10( U32 addr , U16 nb_sector ) +{ + avrf_read_open(addr); // wait device is not busy, then send command & address + avrf_read_sector(nb_sector); // transfer data from memory to USB + avrf_read_close(); // unselect memory + return CTRL_GOOD; +} + + +//! This fonction initialise the memory for a write operation +//! +//! DATA FLOW is: USB => DF +//! +//! +//! (sector = 512B) +//! @param addr Sector address to start write +//! @param nb_sector Number of sectors to transfer +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! A error occur -> CTRL_FAIL +//! +Ctrl_status avrf_write_10( U32 addr , U16 nb_sector ) +{ + + avrf_write_open(addr); // wait device is not busy, then send command & address + avrf_write_sector(nb_sector); // transfer data from memory to USB + avrf_write_close(); // unselect memory + return CTRL_GOOD; +} + + +//------------ AVR FLASH LOWER LEVEL ROUTIENS ----------------------------------------- + +//! +//! @brief This function opens a DF memory in read mode at a given sector address. +//! +//! NOTE: Address may not be synchronized on the beginning of a page (depending on the DF page size). +//! +//! @warning Code:?? bytes (function code length) +//! +//! @param pos Logical sector address +//! +//! @return bit +//! The open succeeded -> OK +//!/ +bit avrf_read_open (Uint32 pos) +{ + // Set the global memory ptr at a Byte address. + gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS; + + return OK; +} + + +//! +//! @brief This function unselects the current DF memory. +//! +//! @warning Code:?? bytes (function code length) +//! +//!/ +void avrf_read_close (void) +{ + ; +} + + + +//! +//! @brief This function is optimized and writes nb-sector * 512 Bytes from +//! DataFlash memory to USB controller +//! +//! DATA FLOW is: DF => USB +//! +//! +//! NOTE: +//! - First call must be preceded by a call to the df_read_open() function, +//! - The USB EPIN must have been previously selected, +//! - USB ping-pong buffers are free, +//! - As 512 is always a sub-multiple of page size, there is no need to check +//! page end for each Bytes, +//! - Interrupts are disabled during transfer to avoid timer interrupt, +//! - nb_sector always >= 1, cannot be zero. +//! +//! @warning code:?? bytes (function code length) +//! +//! @param nb_sector number of contiguous sectors to read [IN] +//! +//! @return bit +//! The read succeeded -> OK +//!/ +bit avrf_read_sector (Uint16 nb_sector) +{ + U8 i,j; + do + { + for (i = 8; i != 0; i--) + { + Disable_interrupt(); // Global disable. + + for (j = 0; j < 64; j++) { + Usb_write_byte(pgm_read_byte_far(gl_ptr_mem++)); + } + + + //# Send the USB FIFO IN content to the USB Host. + Usb_send_in(); // Send the FIFO IN content to the USB Host. + + Enable_interrupt(); // Global interrupt re-enable. + + // Wait until the tx is done so that we may write to the FIFO IN again. + while(Is_usb_write_enabled()==FALSE); + } + nb_sector--; // 1 more sector read + } + while (nb_sector != 0); + + return OK; // Read done. +} + + +//! +//! @brief This function opens a DF memory in write mode at a given sector +//! address. +//! +//! NOTE: If page buffer > 512 bytes, page content is first loaded in buffer to +//! be partially updated by write_byte or write64 functions. +//! +//! @warning Code:?? bytes (function code length) +//! +//! @param pos Sector address +//! +//! @return bit +//! The open succeeded -> OK +//!/ +bit avrf_write_open (Uint32 pos) +{ + // Set the global memory ptr at a Byte address. + gl_ptr_mem = (pos * 512) + MEM_BASE_ADDRESS; + + return OK; +} + + +//! +//! @brief This function fills the end of the logical sector (512B) and launch +//! page programming. +//! +//! @warning Code:?? bytes (function code length) +//! +//!/ +void avrf_write_close (void) +{ + ; +} + + + +/* This code can be setup to work with the DFU bootloader, which comes with the AT90USB1287. However I haven't + had time to test it with such */ +#define LAST_BOOT_ENTRY 0xFFFE + + +void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word); +void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address); +void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address); + + +/* Enable the use of the AVR DFU bootloader by defining "USE_AVRDFU_BOOTLOADER", it will +then call the low-level routines already in the bootloader. */ +#ifdef USE_AVRDFU_BOOTLOADER + +#error UNTESTED/UNSUPPORTED AT THIS TIME + +// These functions pointers are used to call functions entry points in bootloader +void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)= + (void (*)(uint16_t, uint32_t, uint16_t, uint16_t))(LAST_BOOT_ENTRY-6); + +void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= + (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-4); + +void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= + (void (*)(uint32_t, uint16_t, uint32_t))(LAST_BOOT_ENTRY-2); + +#else + +// These functions pointers are used to call functions entry points in bootloader +void (*dfu_boot_buffer_write) (uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word)= + dfuclone_boot_buffer_write; + +void (*dfu_boot_page_write) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= + dfuclone_boot_page_write; + +void (*dfu_boot_page_erase) (uint32_t dummy1, uint16_t dummy2, uint32_t address)= + dfuclone_boot_page_erase; + + + +#endif + +//! +//! @brief This function is optimized and writes nb-sector * 512 Bytes from +//! USB controller to DataFlash memory +//! +//! DATA FLOW is: USB => DF +//! +//! +//! NOTE: +//! - First call must be preceded by a call to the df_write_open() function, +//! - As 512 is always a sub-multiple of page size, there is no need to check +//! page end for each Bytes, +//! - The USB EPOUT must have been previously selected, +//! - Interrupts are disabled during transfer to avoid timer interrupt, +//! - nb_sector always >= 1, cannot be zero. +//! +//! @warning code:?? bytes (function code length) +//! +//! @param nb_sector number of contiguous sectors to write [IN] +//! +//! @return bit +//! The write succeeded -> OK +//!/ +bit avrf_write_sector (Uint16 nb_sector) +{ + Byte i, j; + U16 w; + + U16 pgindex = 0; + U16 sector_bytecounter = 0; + + + do + { + //# Write 8x64b = 512b from the USB FIFO OUT. + for (i = 8; i != 0; i--) + { + // Wait end of rx in USB EPOUT. + while(Is_usb_read_enabled()==FALSE); + + Disable_interrupt(); // Global disable. + + //If start of page, erase it! + if (pgindex == 0) { + (*dfu_boot_page_erase)(0, 0, gl_ptr_mem); + } + + //For all the data in the endpoint, write to flash temp page + for (j = 0; j < 32; j++) { + w = Usb_read_byte(); + w += Usb_read_byte() << 8; + (*dfu_boot_buffer_write)(0, gl_ptr_mem, pgindex, w); + pgindex += 2; + } + + Usb_ack_receive_out(); // USB EPOUT read acknowledgement. + + //If we have filled flash page, write that sucker to memory + if (pgindex == SPM_PAGESIZE) { + + (*dfu_boot_page_write)(0,0, gl_ptr_mem); + + Enable_interrupt(); // Global enable again + + gl_ptr_mem += SPM_PAGESIZE; // Update the memory pointer. + pgindex = 0; + + sector_bytecounter += SPM_PAGESIZE; + + if(sector_bytecounter == 512) { + nb_sector--; // 1 more sector written + sector_bytecounter = 0; + } + + } + + } // for (i = 8; i != 0; i--) + + } + while (nb_sector != 0); + + return OK; // Write done +} + + +#ifndef USE_AVRDFU_BOOTLOADER +/* Perform read/write of FLASH, using same calling convention as low-level routines in AVR DFU bootloader */ + +BOOTLOADER_SECTION void dfuclone_boot_buffer_write(uint16_t dummy, uint32_t baseaddr, uint16_t pageaddr, uint16_t word) +{ + boot_page_fill(baseaddr + pageaddr, word); + return; +} + + +BOOTLOADER_SECTION void dfuclone_boot_page_erase(uint32_t dummy1, uint16_t dummy2, uint32_t address) +{ + boot_page_erase(address); + boot_spm_busy_wait(); + boot_rww_enable(); + return; +} + +BOOTLOADER_SECTION void dfuclone_boot_page_write(uint32_t dummy1, uint16_t dummy2, uint32_t address) +{ + boot_page_write(address); + boot_spm_busy_wait(); + boot_rww_enable(); + return; +} +#endif //USE_AVRDFU_BOOTLOADER + +//------------ SPECIFIC FONCTION USB TRANSFER ----------------------------------------- + +//** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader) +// !!! In this case the driver must be know the USB access + +//! This fonction transfer the memory data (programed in scsi_read_10) directly to the usb interface +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! +Ctrl_status avrf_usb_read() +{ + return CTRL_GOOD; +} + + +//! This fonction transfer the usb data (programed in scsi_write_10) directly to the memory data +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! +Ctrl_status avrf_usb_write( void ) +{ + return CTRL_GOOD; +} + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/avr_flash.h b/cpu/avr/dev/usb/storage/avr_flash.h new file mode 100644 index 000000000..5c0c8c99e --- /dev/null +++ b/cpu/avr/dev/usb/storage/avr_flash.h @@ -0,0 +1,135 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file avr_flash.h ********************************************************* + * + * \brief + * This file writes/reads to/from flash memory internal to the AVR. + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + ******************************************************************************/ +/* + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +#ifndef _DFMEM_H_ +#define _DFMEM_H_ + +#include "conf_access.h" +#include "ctrl_status.h" + + + + +//_____ D E F I N I T I O N S ______________________________________________ + +//! FAT specification +#define ENTRY_SIZE 32 // size of entrie in byte + + + +// First sector of the disk virtual (this disk isn't partitioned, only one partion) +#define PBR_SECTOR (0) +#define FAT_SECTOR (PBR_SECTOR + VMEM_RESERVED_SIZE) +#define ROOT_SECTOR (FAT_SECTOR + (VMEM_SIZE_FAT*VMEM_NB_FATS)) +#define FILE_SECTOR (ROOT_SECTOR + ((ENTRY_SIZE*VMEM_NB_ROOT_ENTRY) / VMEM_SECTOR_SIZE)) // 1(sector) = size root dir + + +/* FAT Format Structure */ +typedef struct +{ + Uint16 nb_cylinder; + Byte nb_head; + Byte nb_sector; + Byte nb_hidden_sector; + Byte nb_sector_per_cluster; +} s_format; + +#define MEM_BSY 0 +#define MEM_OK 1 +#define MEM_KO 2 + + + + +//---- CONTROL FONCTIONS ---- + +// those fonctions are declared in df_mem.h +void avrf_mem_init(void); +Ctrl_status avrf_test_unit_ready(void); +Ctrl_status avrf_read_capacity( U32 _MEM_TYPE_SLOW_ *u32_nb_sector ); +Bool avrf_wr_protect(void); +Bool avrf_removal(void); + +//---- AVR FLASH LOW-LEVEL---- + + +bit avrf_init (void); +bit avrf_mem_check(void); +bit avrf_read_open (Uint32); +void avrf_read_close (void); +bit avrf_write_open (Uint32); +void avrf_write_close (void); + +//! Funtions to link USB DEVICE flow with data flash +bit avrf_write_sector (Uint16); +bit avrf_read_sector (Uint16); + + +s_format * avrf_format (void); + + + +//---- ACCESS DATA FONCTIONS ---- + +// Standard functions for open in read/write mode the device +Ctrl_status avrf_read_10( U32 addr , U16 nb_sector ); +Ctrl_status avrf_write_10( U32 addr , U16 nb_sector ); + + +//** If your device transfer have a specific transfer for USB (Particularity of Chejudo product, or bootloader) +#ifdef DF_VALIDATION +#include "virtual_usb.h" +#else +#include "usb_drv.h" // In this case the driver must be known for the USB access +#endif +Ctrl_status avr_usb_read( void ); +Ctrl_status avr_usb_write( void ); + + + +#endif // _DFMEM_H_ + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/conf_access.h b/cpu/avr/dev/usb/storage/conf_access.h new file mode 100644 index 000000000..afc38b814 --- /dev/null +++ b/cpu/avr/dev/usb/storage/conf_access.h @@ -0,0 +1,197 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file conf_access.h ********************************************************************* + * + * \brief + * This file contains the possible external configuration of the control access + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + + +// Active the Logical Unit +#define LUN_0 DISABLE // On-Chip flash vitual memory +#define LUN_1 DISABLE // NF 2KB +#define LUN_2 DISABLE // NF 512B +#define LUN_3 DISABLE // Data Flash +#define LUN_4 ENABLE //On-chip 32KB +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE + +// LUN 0 DEFINE +#define LUN_0_INCLUDE "lib_mem\virtual_mem\virtual_mem.h" +#define Lun_0_test_unit_ready() virtual_test_unit_ready() +#define Lun_0_read_capacity(nb_sect) virtual_read_capacity(nb_sect) +#define Lun_0_wr_protect() virtual_wr_protect() +#define Lun_0_removal() virtual_removal() +#define Lun_0_read_10(ad, sec) virtual_read_10(ad, sec) +#define Lun_0_usb_read() virtual_usb_read() +#define Lun_0_write_10(ad, sec) virtual_write_10(ad, sec) +#define Lun_0_usb_write() virtual_usb_write() +#define Lun_0_ram_2_mem(addr , ram) virtual_ram_2_mem(addr, ram) +#define Lun_0_ram_2_mem_write() virtual_ram_2_mem_write() +#define Lun_0_mem_2_ram(addr , ram) virtual_mem_2_ram(addr, ram) +#define Lun_0_mem_2_ram_read() virtual_mem_2_ram_read() +#define LUN_0_NAME "VIRTUAL_MEM_ON_CHIP" + +// LUN 1 DEFINE +#if (LUN_1 == ENABLE) +#define NF_2K_MEM ENABLE +#else +#define NF_2K_MEM DISABLE +#endif +#define LUN_1_INCLUDE "lib_mem\nf_1x_2kb\nf_mem.h" +#define Lun_1_test_unit_ready() nf_test_unit_ready() +#define Lun_1_read_capacity(nb_sect) nf_read_capacity(nb_sect) +#define Lun_1_wr_protect() nf_wr_protect() +#define Lun_1_removal() nf_removal() +#define Lun_1_read_10(ad, sec) nf_read_10(ad, sec) +#define Lun_1_usb_read() nf_usb_read() +#define Lun_1_write_10(ad, sec) nf_write_10(ad, sec) +#define Lun_1_usb_write() nf_usb_write() +#define Lun_1_ram_2_mem(addr , ram) TODO +#define Lun_1_ram_2_mem_write() TODO +#define Lun_1_mem_2_ram(addr , ram) TODO +#define Lun_1_mem_2_ram_read() TODO + +// LUN 2 DEFINE +#if (LUN_2 == ENABLE) +#define NF_512_MEM ENABLE +#else +#define NF_512_MEM DISABLE +#endif +#define LUN_2_INCLUDE "lib_mem\nf_1x_512\nf_mem.h" +#define Lun_2_test_unit_ready() nf_test_unit_ready() +#define Lun_2_read_capacity(nb_sect) nf_read_capacity(nb_sect) +#define Lun_2_wr_protect() nf_wr_protect() +#define Lun_2_removal() nf_removal() +#define Lun_2_read_10(ad, sec) nf_read_10(ad, sec) +#define Lun_2_usb_read() nf_usb_read() +#define Lun_2_write_10(ad, sec) nf_write_10(ad, sec) +#define Lun_2_usb_write() nf_usb_write() +#define Lun_2_ram_2_mem(addr , ram) TODO +#define Lun_2_ram_2_mem_write() TODO +#define Lun_2_mem_2_ram(addr , ram) TODO +#define Lun_2_mem_2_ram_read() TODO + +// LUN 3 DEFINE +#if (LUN_3 == ENABLE) +#define DF_MEM ENABLE +#else +#define DF_MEM DISABLE +#endif +#define LUN_ID_DF LUN_ID_3 +#define LUN_3_INCLUDE "lib_mem\df\df_mem.h" +#define Lun_3_test_unit_ready() df_test_unit_ready() +#define Lun_3_read_capacity(nb_sect) df_read_capacity(nb_sect) +#define Lun_3_wr_protect() df_wr_protect() +#define Lun_3_removal() df_removal() +#define Lun_3_read_10(ad, sec) df_read_10(ad, sec) +#define Lun_3_usb_read() df_usb_read() +#define Lun_3_write_10(ad, sec) df_write_10(ad, sec) +#define Lun_3_usb_write() df_usb_write() +#define Lun_3_ram_2_mem(addr , ram) df_ram_2_df(addr, ram) +#define Lun_3_ram_2_mem_write() df_ram_2_df_write() +#define Lun_3_mem_2_ram(addr , ram) df_df_2_ram(addr, ram) +#define Lun_3_mem_2_ram_read() df_df_2_ram_read() +#define LUN_3_NAME "\"On board data flash\"" + +// LUN 3 DEFINE +#if (LUN_3 == ENABLE) +#define AVR_MEM ENABLE +#else +#define AVR_MEM DISABLE +#endif +#define LUN_ID_AVRF LUN_ID_4 +#define LUN_4_INCLUDE "storage/avr_flash.h" +#define Lun_4_test_unit_ready() avrf_test_unit_ready() +#define Lun_4_read_capacity(nb_sect) avrf_read_capacity(nb_sect) +#define Lun_4_wr_protect() avrf_wr_protect() +#define Lun_4_removal() avrf_removal() +#define Lun_4_read_10(ad, sec) avrf_read_10(ad, sec) +#define Lun_4_usb_read() avrf_usb_read() +#define Lun_4_write_10(ad, sec) avrf_write_10(ad,sec) +#define Lun_4_usb_write() avrf_usb_write() +#define Lun_4_ram_2_mem(addr , ram) TODO +#define Lun_4_ram_2_mem_write() TODO +#define Lun_4_mem_2_ram(addr , ram) TODO +#define Lun_4_mem_2_ram_read() TODO +#define LUN_4_NAME "\"AVR Flash Memory\"" + + +// LUN USB DEFINE +#if (LUN_USB == ENABLE) +#define MEM_USB ENABLE +#else +#define MEM_USB DISABLE +#endif +#define LUN_USB_INCLUDE "lib_mem\host_mem\host_mem.h" +#define Lun_usb_test_unit_ready(lun) host_test_unit_ready(lun) +#define Lun_usb_read_capacity(lun,nb_sect) host_read_capacity(lun,nb_sect) +#define Lun_usb_wr_protect(lun) host_wr_protect(lun) +#define Lun_usb_removal() host_removal() +#define Lun_usb_ram_2_mem(addr , ram) host_write_10_ram(addr, ram) +#define Lun_usb_mem_2_ram(addr , ram) host_read_10_ram(addr, ram) +#define LUN_USB_NAME "\"USB Remote memory\"" + + +// ATMEL DEFINE - DO NOT MODIFY + +// Active interface fonction +#define ACCESS_USB ENABLED // USB I/O in control access +#define ACCESS_STREAM DISABLED // Stream I/O in control access +#define ACCESS_STREAM_RECORD DISABLED // Stream I/O in control access AND RECORD MODE +#define ACCESS_MEM_TO_RAM DISABLED // RAM to Mem I/O in control access +#define ACCESS_MEM_TO_MEM DISABLED // Mem to Mem I/O in control access + + + +// Specific option control access +#define GLOBAL_WR_PROTECT DISABLED // To manage a global write protection + + +#endif //! _CONF_ACCESS_H_ + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/ctrl_access.c b/cpu/avr/dev/usb/storage/ctrl_access.c new file mode 100644 index 000000000..9dd2dcb9c --- /dev/null +++ b/cpu/avr/dev/usb/storage/ctrl_access.c @@ -0,0 +1,973 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ctrl_access.c ********************************************************************* + * + * \brief + * This file contains the interface : + * - between USB <-> MEMORY + * OR + * - between USB <- Access Memory Ctrl -> Memory + * + * This interface may be controled by a "Access Memory Control" for : + * - include a management of write protect global or specific + * - include a management of access password + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + + +//_____ I N C L U D E S ____________________________________________________ + +#include "config.h" +#include "storage/ctrl_access.h" + + +//_____ D E F I N I T I O N S ______________________________________________ + +#if (ACCESS_MEM_TO_MEM == ENABLED) + #include "modules/file_system/fat.h" + U8 buf_sector[FS_SIZE_OF_SECTOR]; +#endif + + +//! Computed the maximum of static lun (don't add the lun of Mass Storage in mode USB Host) +// FYC: Memory = Logical Unit + + + + // CHECK FOR LUN DEFINE +#ifndef LUN_0 + # error LUN_0 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_1 + # error LUN_1 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_2 + # error LUN_2 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_3 + # error LUN_3 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_4 + # error LUN_4 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_5 + # error LUN_5 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_6 + # error LUN_6 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_7 + # error LUN_7 must be defined with ENABLE or DISABLE in conf_access.h +#endif +#ifndef LUN_USB + # error LUN_USB must be defined with ENABLE or DISABLE in conf_access.h +#endif + + + +#if (LUN_0 == ENABLE) + #define LUN_0_EN 1 + U8 FLASH lun0_name[]=LUN_0_NAME; + #else + #define LUN_0_EN 0 +#endif +#if (LUN_1 == ENABLE) + #define LUN_1_EN 1 + U8 FLASH lun1_name[]=LUN_1_NAME; + #else + #define LUN_1_EN 0 +#endif +#if (LUN_2 == ENABLE) + #define LUN_2_EN 1 + U8 FLASH lun2_name[]=LUN_2_NAME; + #else + #define LUN_2_EN 0 +#endif +#if (LUN_3 == ENABLE) + #define LUN_3_EN 1 + U8 FLASH lun3_name[]=LUN_3_NAME; + #else + #define LUN_3_EN 0 +#endif +#if (LUN_4 == ENABLE) + #define LUN_4_EN 1 + U8 FLASH lun4_name[]=LUN_4_NAME; + #else + #define LUN_4_EN 0 +#endif +#if (LUN_5 == ENABLE) + #define LUN_5_EN 1 + U8 FLASH lun5_name[]=LUN_5_NAME; + #else + #define LUN_5_EN 0 +#endif +#if (LUN_6 == ENABLE) + #define LUN_6_EN 1 + U8 FLASH lun6_name[]=LUN_6_NAME; + #else + #define LUN_6_EN 0 +#endif +#if (LUN_7 == ENABLE) + #define LUN_7_EN 1 + U8 FLASH lun7_name[]=LUN_7_NAME; + #else + #define LUN_7_EN 0 +#endif +#if (LUN_USB == ENABLE) + #define LUN_USB_EN 1 + U8 FLASH lunusb_name[]=LUN_USB_NAME; + #else + #define LUN_USB_EN 0 +#endif + + +#define LUN_ID_0 (0) +#define LUN_ID_1 (LUN_0_EN) +#define LUN_ID_2 (LUN_0_EN+LUN_1_EN) +#define LUN_ID_3 (LUN_0_EN+LUN_1_EN+LUN_2_EN) +#define LUN_ID_4 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN) +#define LUN_ID_5 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN) +#define LUN_ID_6 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN) +#define LUN_ID_7 (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN+LUN_6_EN) +#define MAX_LUN (LUN_0_EN+LUN_1_EN+LUN_2_EN+LUN_3_EN+LUN_4_EN+LUN_5_EN+LUN_6_EN+LUN_7_EN) +#define LUN_ID_USB (MAX_LUN) + +// Check configuration +#if (MAX_LUN == 0) + #error No memory is active in conf_access.h +#endif + +// Write protect variable +#if (GLOBAL_WR_PROTECT == ENABLED) + static U8 g_u8_wr_protect; +#endif + + +//_____ D E F I N I T I O N S __ F O N C T I O N S _________________________ + + +//! This fonction return the number of logical unit +//! +//! @return U8 number of logical unit in the system +//! +U8 get_nb_lun() +{ +#if (MEM_USB == ENABLED) + return (MAX_LUN + Host_getlun()); +#else + return MAX_LUN; +#endif +} + + +//! This fonction return the current logical unit +//! +//! @return U8 number of logical unit in the system +//! +U8 get_cur_lun() +{ + return 0; //TODO +} + + +//! This fonction test the state of memory, and start the initialisation of the memory +//! +//! MORE (see SPC-3 §5.2.4) : The TEST UNIT READY command allows an application client +//! to poll a logical unit until it is ready without the need to allocate space for returned data. +//! The TEST UNIT READY command may be used to check the media status of logical units with removable media. +//! +//! @param lun Logical unit number +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! Memory unplug -> CTRL_NO_PRESENT +//! Not initialize -> CTRL_BUSY +//! +Ctrl_status mem_test_unit_ready( U8 lun ) +{ + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + return Lun_0_test_unit_ready(); + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + return Lun_1_test_unit_ready(); + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + return Lun_2_test_unit_ready(); + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + return Lun_3_test_unit_ready(); + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + return Lun_4_test_unit_ready(); + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + return Lun_5_test_unit_ready(); + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + return Lun_6_test_unit_ready(); + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + return Lun_7_test_unit_ready(); + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_test_unit_ready(lun - LUN_ID_USB); + break; +# endif + } + return CTRL_FAIL; +} + +//! This fonction return the capacity of the memory +//! +//! @param lun Logical unit number +//! @param u32_nb_sector The sector to query +//! +//! @return *u16_nb_sector number of sector (sector = 512B) +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! Memory unplug -> CTRL_NO_PRESENT +//! +Ctrl_status mem_read_capacity( U8 lun , U32 _MEM_TYPE_SLOW_ *u32_nb_sector ) +{ + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + return Lun_0_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + return Lun_1_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + return Lun_2_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + return Lun_3_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + return Lun_4_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + return Lun_5_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + return Lun_6_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + return Lun_7_read_capacity( u32_nb_sector ); + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_read_capacity( lun - LUN_ID_USB,u32_nb_sector ); + break; +# endif + } + return CTRL_FAIL; +} + +//! This fonction return is the write protected mode +//! +//! @param lun Logical unit number +//! +//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection +//! !!! The customer must be unplug the card for change this write protected mode. +//! +//! @return TRUE -> the memory is protected +//! +Bool mem_wr_protect( U8 lun ) +{ + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + return Lun_0_wr_protect(); + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + return Lun_1_wr_protect(); + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + return Lun_2_wr_protect(); + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + return Lun_3_wr_protect(); + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + return Lun_4_wr_protect(); + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + return Lun_5_wr_protect(); + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + return Lun_6_wr_protect(); + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + return Lun_7_wr_protect(); + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_wr_protect(lun - LUN_ID_USB); + break; +# endif + } + return CTRL_FAIL; +} + + +//! This fonction inform about the memory type +//! +//! @param lun Logical unit number +//! +//! @return TRUE -> The memory is removal +//! +Bool mem_removal( U8 lun ) +{ + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + return Lun_0_removal(); + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + return Lun_1_removal(); + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + return Lun_2_removal(); + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + return Lun_3_removal(); + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + return Lun_4_removal(); + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + return Lun_5_removal(); + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + return Lun_6_removal(); + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + return Lun_7_removal(); + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_removal(); + break; +# endif + } + return CTRL_FAIL; +} + +//! This fonction returns a pointer to the LUN name +//! +//! @param lun Logical unit number +//! +//! @return pointer to code string +//! +U8 FLASH* mem_name( U8 lun ) +{ + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + return (U8 FLASH*)lun0_name; + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + return (U8 FLASH*)lun1_name; + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + return (U8 FLASH*)lun2_name; + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + return (U8 FLASH*)lun3_name; + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + return (U8 FLASH*)lun4_name; + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + return (U8 FLASH*)lun5_name; + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + return (U8 FLASH*)lun6_name; + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + return (U8 FLASH*)lun7_name; + break; +# endif +# if (LUN_USB == ENABLE) + default: + return (U8 FLASH*)lunusb_name; + break; +# endif + } + return 0; // Remove compiler warning +} + +//************************************************************************************ +//!----------- Listing of READ/WRITE interface with MODE ACCESS REGISTER ------------- +//************************************************************************************ + + +//! This fonction tranfer a data from memory to usb +//! +//! @param lun Logical unit number +//! @param addr Sector address to start read (sector = 512B) +//! @param nb_sector Number of sectors to transfer +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! A error occur -> CTRL_FAIL +//! Memory unplug -> CTRL_NO_PRESENT +//! +Ctrl_status memory_2_usb( U8 lun , U32 addr , U16 nb_sector ) +{ + Ctrl_status status; + + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + status = Lun_0_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_0_usb_read(); + } + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + status = Lun_1_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_1_usb_read(); + } + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + status = Lun_2_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_2_usb_read(); + } + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + status = Lun_3_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_3_usb_read(); + } + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + status = Lun_4_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_4_usb_read(); + } + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + status = Lun_5_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_5_usb_read(); + } + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + status = Lun_6_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_6_usb_read(); + } + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + status = Lun_7_read_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_7_usb_read(); + } + break; +# endif + } + return status; +} + +//! This fonction trabsfer a data from usb to memory +//! +//! @param lun Logical unit number +//! @param addr Sector address to start write (sector = 512B) +//! @param nb_sector Number of sectors to transfer +//! +//! @return Ctrl_status +//! It is ready -> CTRL_GOOD +//! A error occur -> CTRL_FAIL +//! Memory unplug -> CTRL_NO_PRESENT +//! +Ctrl_status usb_2_memory( U8 lun , U32 addr , U16 nb_sector ) +{ + Ctrl_status status; + + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + status = Lun_0_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_0_usb_write(); + } + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + status = Lun_1_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_1_usb_write(); + } + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + status = Lun_2_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_2_usb_write(); + } + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + status = Lun_3_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_3_usb_write(); + } + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + status = Lun_4_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_4_usb_write(); + } + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + status = Lun_5_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_5_usb_write(); + } + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + status = Lun_6_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_6_usb_write(); + } + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + status = Lun_7_write_10(addr , nb_sector); + if (CTRL_GOOD == status) + { + status = Lun_7_usb_write(); + } + break; +# endif + } + return status; +} + +//! Interface for RAM +#if (ACCESS_MEM_TO_RAM == ENABLED) + +//! This fonction tranfer one sector data from memory to ram +//! +//! @param lun Logical unit number +//! @param addr Sector address to start read (sector = 512B) +//! @param ram Adresse of ram buffer (only xdata) +//! +//! @return TRUE -> The memory is removal +//! +Ctrl_status memory_2_ram( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ *ram ) +{ + + Ctrl_status status; + + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + status = Lun_0_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_0_mem_2_ram_read(); + } + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + status = Lun_1_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_1_mem_2_ram_read(); + } + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + status = Lun_2_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_2_mem_2_ram_read(); + } + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + status = Lun_3_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_3_mem_2_ram_read(); + } + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + status = Lun_4_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_4_mem_2_ram_read(); + } + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + status = Lun_5_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_5_mem_2_ram_read(); + } + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + status = Lun_6_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_6_mem_2_ram_read(); + } + break; +# endif +# if (LUN_7 == ENABLE) + case LUN_ID_7: + status = Lun_7_mem_2_ram(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_7_mem_2_ram_read(); + } + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_mem_2_ram(*addr , ram); +# endif + } + return status; +} +#endif // ACCESS_MEM_TO_RAM == ENABLED + + + +#if (ACCESS_MEM_TO_RAM==ENABLE) + +//! This fonction trabsfer a data from ram to memory +//! +//! @param lun Logical unit number +//! @param addr Sector address to start write (sector = 512B) +//! @param ram Adresse of ram buffer (only xdata) +//! +//! @return TRUE -> The memory is removal +//! +Ctrl_status ram_2_memory( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ * ram ) +{ + Ctrl_status status; + + switch( lun ) + { +# if (LUN_0 == ENABLE) + case LUN_ID_0: + status = Lun_0_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_0_ram_2_mem_write(); + } + break; +# endif +# if (LUN_1 == ENABLE) + case LUN_ID_1: + status = Lun_1_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_1_ram_2_mem_write(); + } + break; +# endif +# if (LUN_2 == ENABLE) + case LUN_ID_2: + status = Lun_2_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_2_ram_2_mem_write(); + } + break; +# endif +# if (LUN_3 == ENABLE) + case LUN_ID_3: + status = Lun_3_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_3_ram_2_mem_write(); + } + break; +# endif +# if (LUN_4 == ENABLE) + case LUN_ID_4: + status = Lun_4_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_4_ram_2_mem_write(); + } + break; +# endif +# if (LUN_5 == ENABLE) + case LUN_ID_5: + status = Lun_5_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_5_ram_2_mem_write(); + } + break; +# endif +# if (LUN_6 == ENABLE) + case LUN_ID_6: + status = Lun_6_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_6_ram_2_mem_write(); + } + break; +# endif + # if (LUN_7 == ENABLE) + case LUN_ID_7: + status = Lun_7_ram_2_mem(*addr , ram); + if (CTRL_GOOD == status) + { + status = Lun_7_ram_2_mem_write(); + } + break; +# endif +# if (LUN_USB == ENABLE) + default: + return Lun_usb_ram_2_mem(*addr , ram); + break; +# endif + } + return status; +} +#endif // ACCESS_RAM_TO_MEM == ENABLED + + + +//! Interface for streaming interface +#if (ACCESS_STREAM == ENABLED) + + + +// Interface for transfer MEM to MEM +# if (ACCESS_MEM_TO_MEM == ENABLED) +//! This fonction copy a data from memory to other memory +//! +//! @param src_lun The LUN of the source +//! @param src_addr The address of the source +//! @param dest_lun The LUN of the destination +//! @param dest_addr The address of the destination +//! @param nb_sector Number of sectors to transfer +//! +U8 stream_mem_to_mem( U8 src_lun , U32 src_addr , U8 dest_lun , U32 dest_addr , U16 nb_sector ) +{ + while(nb_sector) + { + memory_2_ram( src_lun , &src_addr , buf_sector ); + ram_2_memory( dest_lun , &dest_addr , buf_sector ); + src_addr++; + dest_addr++; + nb_sector--; + } + return CTRL_GOOD; +} +# endif // ACCESS_MEM_TO_MEM == ENABLED + + + + +//! Returns the state on a data transfer +//! +//! @param Id transfer id +//! +//! @return the state of the transfer +//! CTRL_GOOD It is finish +//! CTRL_BUSY It is running +//! CTRL_FAIL It is fail +//! +Ctrl_status stream_state( U8 Id ) +{ + + return CTRL_GOOD; +} + +//! Stop the data transfer +//! +//! @param Id Transfer id +//! +//! @return the number of sector remainder +//! +U16 stream_stop( U8 Id ) +{ + return 0; +} + +#endif // ACCESS_STREAM == ENABLED + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/ctrl_access.h b/cpu/avr/dev/usb/storage/ctrl_access.h new file mode 100644 index 000000000..a201a5342 --- /dev/null +++ b/cpu/avr/dev/usb/storage/ctrl_access.h @@ -0,0 +1,157 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ctrl_access.h ******************************************************* + * + * \brief + * This file contains the interface : + * - between USB <-> MEMORY + * OR + * - between USB <- Access Memory Ctrl -> Memory + * + * This interface may be controled by a "Access Memory Control" for : + * - include a management of write protect global or specific + * - include a management of access password + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +#ifndef _MEM_CTRL_H_ +#define _MEM_CTRL_H_ + +#include "storage/conf_access.h" +#include "storage/ctrl_status.h" + +// FYC: Memory = Logical Unit +#if (LUN_0 == ENABLE) + #include LUN_0_INCLUDE +#endif +#if (LUN_1 == ENABLE) + #include LUN_1_INCLUDE +#endif +#if (LUN_2 == ENABLE) + #include LUN_2_INCLUDE +#endif +#if (LUN_3 == ENABLE) + #include LUN_3_INCLUDE +#endif +#if (LUN_4 == ENABLE) + #include LUN_4_INCLUDE +#endif +#if (LUN_5 == ENABLE) + #include LUN_5_INCLUDE +#endif +#if (LUN_6 == ENABLE) + #include LUN_6_INCLUDE +#endif +#if (LUN_7 == ENABLE) + #include LUN_7_INCLUDE +#endif +#if (LUN_USB == ENABLE) + #include LUN_USB_INCLUDE +#endif + + +//------- Test the configuration in conf_access.h + +// Specific option control access +#ifndef GLOBAL_WR_PROTECT +# error GLOBAL_WR_PROTECT must be defined with ENABLED or DISABLED in conf_access.h +#endif +//------- END OF Test the configuration in conf_access.h + + + +//_____ D E F I N I T I O N S ______________________________________________ + + + +//!**** Listing of commun interface **************************************** + +U8 get_nb_lun(); +U8 get_cur_lun(); +Ctrl_status mem_test_unit_ready( U8 lun ); +Ctrl_status mem_read_capacity( U8 lun , U32 _MEM_TYPE_SLOW_ *u32_nb_sector ); +Bool mem_wr_protect( U8 lun ); +Bool mem_removal( U8 lun ); +U8 FLASH* mem_name( U8 lun ); + + +//!**** Listing of READ/WRITE interface ************************************ + + +//---- Interface for USB --------------------------------------------------- + Ctrl_status memory_2_usb( U8 lun , U32 addr , U16 nb_sector ); + Ctrl_status usb_2_memory( U8 lun , U32 addr , U16 nb_sector ); +#include "usb_drv.h" +#include "conf_usb.h" +//-------------------------------------------------------------------------- + +//---- Interface for RAM to MEM -------------------------------------------- +Ctrl_status memory_2_ram( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ *ram ); +Ctrl_status ram_2_memory( U8 lun , const U32 _MEM_TYPE_SLOW_ *addr , U8 _MEM_TYPE_SLOW_ * ram ); +//-------------------------------------------------------------------------- + + +//!---- Interface for streaming interface ---------------------------------- +#if (ACCESS_STREAM == ENABLED) + +#define ID_STREAM_ERR 0xFF + + +// RLE #include "dfc_mngt.h" + +#define TYPE_STREAM_AUDIO DFC_ID_AUDIOPROC1 +#define TYPE_STREAM_AUDIO2 DFC_ID_AUDIOPROC2 +#define TYPE_STREAM_SIO DFC_ID_SIO +#define TYPE_STREAM_SPI DFC_ID_SPI +#define TYPE_STREAM_DEVNULL DFC_ID_NULL_DEV + + U8 stream_mem_to_mem ( U8 src_lun , U32 src_addr , U8 dest_lun , U32 dest_addr , U16 nb_sector ); + U8 stream_read_10_start ( U8 TypeStream , U8 lun , U32 addr , U16 nb_sector ); + U8 stream_write_10_start ( U8 TypeStream , U8 lun , U32 addr , U16 nb_sector ); + U8 stream_to_stream_start ( U8 TypeStream_src , U8 TypeStream_dest , U16 nb_sector ); + Ctrl_status stream_state( U8 Id ); + U16 stream_stop( U8 Id ); + +#endif // (ACCESS_STREAM == ENABLED) +//-------------------------------------------------------------------------- + +#endif // _MEM_CTRL_H_ +/**@}*/ diff --git a/cpu/avr/dev/usb/storage/ctrl_status.h b/cpu/avr/dev/usb/storage/ctrl_status.h new file mode 100644 index 000000000..c79ca549a --- /dev/null +++ b/cpu/avr/dev/usb/storage/ctrl_status.h @@ -0,0 +1,70 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ctrl_status.h ******************************************************** + * + * \brief + * This file contains the interface : + * - between USB <-> MEMORY + * OR + * - between USB <- Access Memory Ctrl -> Memory + * + * This interface may be controled by a "Access Memory Control" for : + * - include a management of write protect global or specific + * - include a management of access password + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +#ifndef _CTRL_STATUS_H_ +#define _CTRL_STATUS_H_ + +//_____ D E F I N I T I O N S ______________________________________________ + +//! Define control status +typedef enum +{ + CTRL_GOOD =(PASS ) // It is ready +, CTRL_FAIL =(FAIL ) // Memory fail +, CTRL_NO_PRESENT =(FAIL+1) // Memory unplug +, CTRL_BUSY =(FAIL+2) // Not initialize +} Ctrl_status; + +#endif // _CTRL_STATUS_H_ +/** @} */ diff --git a/cpu/avr/dev/usb/storage/scsi_decoder.c b/cpu/avr/dev/usb/storage/scsi_decoder.c new file mode 100644 index 000000000..f803d0cd1 --- /dev/null +++ b/cpu/avr/dev/usb/storage/scsi_decoder.c @@ -0,0 +1,787 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file scsi_decoder.c ******************************************************* + * + * \brief + * This file is the scsi decoder + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +//_____ I N C L U D E S ___________________________________________________ + +#include "config.h" +#include "storage/scsi_decoder.h" +#include "conf_usb.h" +#include "usb_drv.h" +#include "storage/ctrl_status.h" +#include "storage/ctrl_access.h" + + +//_____ M A C R O S ________________________________________________________ + + +//_____ D E F I N I T I O N S ______________________________________________ + + +U8 g_scsi_command[16]; +U8 g_scsi_status; +U32 g_scsi_data_remaining; + +FLASH U8 g_sbc_vendor_id[8] = SBC_VENDOR_ID; +FLASH U8 g_sbc_product_id[16] = SBC_PRODUCT_ID; +FLASH U8 g_sbc_revision_id[4] = SBC_REVISION_ID; + +extern U8 usb_LUN; + + s_scsi_sense g_scsi_sense; + + +FLASH struct sbc_st_std_inquiry_data sbc_std_inquiry_data = +{ + /* Byte 0 : 0x00 */ + 0x00, /* DeviceType: Direct-access device */ + 0, /* PeripheralQualifier : Currently connected */ + + /* Byte 1 : 0x80 */ + 0, /* Reserved1 */ + 1, /* RMB : Medium is removable (this bit must be at 1, else the medium isn't see on Windows) */ + + // /* Byte 2 : 0x02 */ + // 0x02, /* Version: Device compliant to ANSI X3.131:1994 */ + + /* Byte 2 : 0x00 */ + 0x00, /* Version: Device not compliant to any standard */ + + /* Byte 3 : 0x02 */ + 2, /* Response data format */ + 0, /* NormACA */ + 0, /* Obsolete0 */ + 0, /* AERC */ + + /* Byte 4 : 0x1F */ + /* Byte 5 : 0x00 */ + /* Byte 6 : 0x00 */ + /* Reserved4[3] */ + { + 0x1F, /* Additional Length (n-4) */ + 0, /* SCCS : SCC supported */ + 0 + }, + + /* Byte 7 : 0x00 */ + 0, /* SoftReset */ + 0, /* CommandQueue */ + 0, /* Reserved5 */ + 0, /* LinkedCommands */ + 0, /* Synchronous */ + 0, /* Wide16Bit */ + 0, /* Wide32Bit */ + 0, /* RelativeAddressing */ +}; + + +static void send_informational_exceptions_page (void); +static void send_read_write_error_recovery_page (U8); +static void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length ); + + +//_____ D E C L A R A T I O N S ____________________________________________ +/** + * @brief SCSI decoder function + * + * This function read the SCSI command and launches the appropriate function + * + * @warning Code:.. bytes (function FLASH length) + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +Bool scsi_decode_command(void) +{ +Bool status; + + if (g_scsi_command[0] == SBC_CMD_WRITE_10) + { + Scsi_start_write_action(); + status = sbc_write_10(); + Scsi_stop_write_action(); + return status; + } + if (g_scsi_command[0] == SBC_CMD_READ_10 ) + { + Scsi_start_read_action(); + status = sbc_read_10(); + Scsi_stop_read_action(); + return status; + } + + switch (g_scsi_command[0]) /* check other command received */ + { + case SBC_CMD_REQUEST_SENSE: /* 0x03 - Mandatory */ + return sbc_request_sense(); + break; + + case SBC_CMD_INQUIRY: /* 0x12 - Mandatory */ + return sbc_inquiry(); + break; + + case SBC_CMD_TEST_UNIT_READY: /* 0x00 - Mandatory */ + return sbc_test_unit_ready(); + break; + + case SBC_CMD_READ_CAPACITY: /* 0x25 - Mandatory */ + return sbc_read_capacity(); + break; + + case SBC_CMD_MODE_SENSE_6: /* 0x1A - Optional */ + return sbc_mode_sense( FALSE ); + break; + + case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:/* 0x1E */ + return sbc_prevent_allow_medium_removal(); + break; + + case SBC_CMD_VERIFY_10: /* 0x2F - Optional */ + sbc_lun_status_is_good(); + break; + case SBC_CMD_MODE_SENSE_10: /* 0x5A - Optional */ + return sbc_mode_sense( TRUE ); + break; + + case SBC_CMD_FORMAT_UNIT: /* 0x04 - Mandatory */ + + case SBC_CMD_MODE_SELECT_6: /* 0x15 - Optional */ + + + + + case SBC_CMD_START_STOP_UNIT: /* 0x1B - Optional */ + case SBC_CMD_SEND_DIAGNOSTIC: /* 0x1D - */ + case SBC_CMD_READ_LONG: /* 0x23 - Optional */ + case SBC_CMD_SYNCHRONIZE_CACHE: /* 0x35 - Optional */ + case SBC_CMD_WRITE_BUFFER: /* 0x3B - Optional */ + case SBC_CMD_RESERVE_10: /* 0x56 - Mandatory */ + case SBC_CMD_RELEASE_10: /* 0x57 - Mandatory - see chapter 7.16 - SPC 2 */ + default: + { /* Command not supported */ + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00); + return FALSE; + break; + } + } + return TRUE; +} + + +/** + * @brief This function manages the SCSI REQUEST SENSE command (0x03) + * + * The SCSI Sense contains the status of the last command + * This status is composed of 3 Bytes : + * - sense key (g_scsi_sense.key) + * - additional sense code (g_scsi_sense.asc) + * - additional sense code qualifier (g_scsi_sense.ascq) + * + * @warning Code:.. bytes (function code length) + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +Bool sbc_request_sense (void) +{ + U8 allocation_length, i; + U8 request_sens_output[18]; /* the maximum size of request is 17 */ + + allocation_length = g_scsi_command[4]; /* Allocation length */ + + /* Initialize the request sense data */ + request_sens_output[0] = SBC_RESPONSE_CODE_SENSE; /* 70h */ + request_sens_output[1] = 0x00; /* Obsolete */ + request_sens_output[2] = g_scsi_sense.key; + + request_sens_output[3] = 0x00; /* For direct access media, Information field */ + request_sens_output[4] = 0x00; /* give the unsigned logical block */ + request_sens_output[5] = 0x00; /* address associated with the sense key */ + request_sens_output[6] = 0x00; + + request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH; /* !! UFI device shall not adjust the Additional sense length to reflect truncation */ + request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3; + request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2; + request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1; + request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0; + + request_sens_output[12] = g_scsi_sense.asc; + request_sens_output[13] = g_scsi_sense.ascq; + + request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE; + request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2; + request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1; + request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0; + + /* Send the request data */ + for( i=0 ; i SBC_MAX_INQUIRY_DATA) + { + allocation_length = SBC_MAX_INQUIRY_DATA; + } + + // send first inquiry data (0 to 8) + ptr = (FLASH U8*) &sbc_std_inquiry_data; + + for ( i=0 ; ((i != 36) && (allocation_length > i)); i++) + { + if( 8 == i ) + { // send vendor id (8 to 16) + ptr = (FLASH U8 *) &g_sbc_vendor_id; + } + if( 16 == i ) + { // send product id (16 to 32) + ptr = (FLASH U8 *) &g_sbc_product_id; + } + if( 32 == i ) + { // send revision id (32 to 36) + ptr = (FLASH U8 *) &g_sbc_revision_id; + } +#ifndef AVRGCC + Usb_write_byte((U8)(*ptr++)); // send tab +#else // AVRGCC does not support point to PGM space +#warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory + Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++)); +#endif + + } + + // send data (36 to SBC_MAX_INQUIRY_DATA), and can be tranmitted by Bulk + // Description of next bytes (this bytes is always egal to 0) : + // VendorSpecific : 20 Bytes + // Next byte : 1 byte + // - InfoUnitSupport : 1 bit + // - QuickArbitSupport : 1 bit + // - Clocking : 2 bits + // - Reserved6 : 4 bits + // Reserved7 : 1 byte + // VersionDescriptor : 8 bytes + // Reserved8 : 22 bytes + // ... + while( allocation_length > i ) + { + if (64 == i) + { // for each 64 bytes, send USB packet + Sbc_valid_write_usb(64); + allocation_length -= 64; + i = 0; + } + Usb_write_byte(0); // write value of last bytes of inquiry data + i++; + } + // send last USB packet + Sbc_valid_write_usb(allocation_length); + sbc_lun_status_is_good(); + return TRUE; + } + else + { // (CMDT=EVPD <> 0) or (PAGE CODE <> 0x00) + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00); + return FALSE; + } +} + + +Bool sbc_test_unit_ready(void) +{ + switch ( mem_test_unit_ready(usb_LUN) ) + { + case CTRL_GOOD : + sbc_lun_status_is_good(); + break; + + case CTRL_NO_PRESENT : + sbc_lun_status_is_not_present(); + break; + + case CTRL_BUSY : + sbc_lun_status_is_busy_or_change(); + break; + + case CTRL_FAIL : + default : + sbc_lun_status_is_fail(); + break; + } + return TRUE; +} + + +Bool sbc_read_capacity (void) +{ + _MEM_TYPE_SLOW_ U32 mem_size_nb_sector; + + switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) ) + { + case CTRL_GOOD : + Usb_write_byte(MSB0(mem_size_nb_sector)); // return nb block + Usb_write_byte(MSB1(mem_size_nb_sector)); + Usb_write_byte(MSB2(mem_size_nb_sector)); + Usb_write_byte(MSB3(mem_size_nb_sector)); + Usb_write_byte( 0 ); // return block size (= 512B) + Usb_write_byte( 0 ); + Usb_write_byte( (U8)(512 >> 8) ); + Usb_write_byte( (U8)(512 & 0xFF)); + + Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH); + sbc_lun_status_is_good(); + return TRUE; + break; + + case CTRL_NO_PRESENT : + sbc_lun_status_is_not_present(); + break; + + case CTRL_BUSY : + sbc_lun_status_is_busy_or_change(); + break; + + case CTRL_FAIL : + default : + sbc_lun_status_is_fail(); + break; + } + return FALSE; +} + + +Bool sbc_read_10 (void) +{ + U32 mass_addr; // rd or wr block address + U16 mass_size; // rd or write nb of blocks + + MSB0(mass_addr) = g_scsi_command[2]; // read address + MSB1(mass_addr) = g_scsi_command[3]; + MSB2(mass_addr) = g_scsi_command[4]; + MSB3(mass_addr) = g_scsi_command[5]; + + MSB(mass_size) = g_scsi_command[7]; // read size + LSB(mass_size) = g_scsi_command[8]; + + if (mass_size != 0) + { + switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) ) + { + case CTRL_GOOD : + sbc_lun_status_is_good(); + g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size); + return TRUE; + break; + + case CTRL_NO_PRESENT : + sbc_lun_status_is_not_present(); + return FALSE; + break; + + case CTRL_BUSY : + sbc_lun_status_is_busy_or_change(); + return FALSE; + break; + + case CTRL_FAIL : + default : + sbc_lun_status_is_fail(); + return FALSE; + break; + } + } + else + { // No data to transfer + sbc_lun_status_is_good(); + } + return TRUE; +} + + +Bool sbc_write_10 (void) +{ + U32 mass_addr; // rd or wr block address + U16 mass_size; // rd or write nb of blocks + + MSB0(mass_addr) = g_scsi_command[2]; // read address + MSB1(mass_addr) = g_scsi_command[3]; + MSB2(mass_addr) = g_scsi_command[4]; + MSB3(mass_addr) = g_scsi_command[5]; + + MSB(mass_size) = g_scsi_command[7]; // read size + LSB(mass_size) = g_scsi_command[8]; + + if (mass_size != 0) + { + if( TRUE == mem_wr_protect( usb_LUN ) ) + { + sbc_lun_status_is_protected(); + return FALSE; +#warning For Win98 data must be read to avoid blocking + } + else + { + switch (usb_2_memory( usb_LUN , mass_addr, mass_size )) + { + case CTRL_GOOD : + sbc_lun_status_is_good(); + g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size); + return TRUE; + break; + + case CTRL_NO_PRESENT : + sbc_lun_status_is_not_present(); + return FALSE; + break; + + case CTRL_BUSY : + sbc_lun_status_is_busy_or_change(); + return FALSE; + break; + + case CTRL_FAIL : + default : + sbc_lun_status_is_fail(); + return FALSE; + break; + } + } + } + else + { // No data to transfer + sbc_lun_status_is_good(); + } + return TRUE; +} + + +/** + * @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10) + * + * The SCSI mode sense function returns parameters to an application client. + * It is a complementary command to the SCSI MODE SELECT command. + * + * @warning Code:.. bytes (function code length) + * + * @param b_sense_10 ( TRUE = sense 10, TRUE = sense 6) + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +Bool sbc_mode_sense( Bool b_sense_10 ) +{ + U8 allocation_length; + + if( b_sense_10 ) + allocation_length = g_scsi_command[8]; + else + allocation_length = g_scsi_command[4]; + + // switch for page code + switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE ) + { + case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */ + sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS ); + send_informational_exceptions_page(); + Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1); + break; + + case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY: + sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY ); + send_read_write_error_recovery_page(allocation_length); + Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1); + break; + + case SBC_PAGE_CODE_ALL: + sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL ); + if( b_sense_10 ) + { + if (allocation_length == 8) + { + Sbc_valid_write_usb(8); + break; + } + } + else + { + if (allocation_length == 4) + { + Sbc_valid_write_usb(4); + break; + } + } + // send page by ascending order code + send_read_write_error_recovery_page(allocation_length); // 12 bytes + if (allocation_length > 12) + { + send_informational_exceptions_page(); // 12 bytes + Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1); + } + else + { + Sbc_valid_write_usb(allocation_length); + } + break; + + default: + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00); + return FALSE; + break; + } + sbc_lun_status_is_good(); + return TRUE; +} + + +/** + * @brief This function send the header of the SCSI MODE SENSE command + * + * @param b_sense_10 TRUE = sense 10, FALSE = sense 6 + * @param u8_data_length data length in byte + * + */ +void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length ) +{ + // Send Data length + if( b_sense_10 ) + { + Usb_write_byte(0); + } + Usb_write_byte( u8_data_length ); + + // Send device type + Usb_write_byte(SBC_MEDIUM_TYPE); + + // Write protect status + if (mem_wr_protect( usb_LUN )) + { + Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT); // Device is write protected + } + else + { + Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE); // Device is write enabled + } + + if( b_sense_10 ) + { // Reserved + Usb_write_byte(0); + Usb_write_byte(0); + } + + // Send Block descriptor length + if( b_sense_10 ) + { + Usb_write_byte(0); + } + Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); +} + + +/** + * @brief This function writes informational exceptions page parameters + * + * @warning Code:.. bytes (function code length) + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +void send_informational_exceptions_page (void) +{ + Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS); /* Page Code: Informational exceptions control page */ + /* See chapter 8.3.8 on SPC-2 specification */ + Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS); /* Page Length */ + Usb_write_byte(0x00); /* ..., Test bit = 0, ... */ + Usb_write_byte(SBC_MRIE); /* MRIE = 0x05 */ + Usb_write_byte(0x00); /* Interval Timer (MSB) */ + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); /* Interval Timer (LSB) */ + Usb_write_byte(0x00); /* Report Count (MSB) */ + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x01); /* Report Count (LSB) */ +} + + +/** + * @brief This function writes error recovery page + * + * @warning Code:.. bytes (function code length) + * + * @param length The length of + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +void send_read_write_error_recovery_page (U8 length) +{ + Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY); + + Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY); /* Page Length */ + Usb_write_byte(0x80); + Usb_write_byte(SBC_READ_RETRY_COUNT); + Usb_write_byte(SBC_CORRECTION_SPAN); + Usb_write_byte(SBC_HEAD_OFFSET_COUNT); + Usb_write_byte(SBC_DATA_STROBE_OFFSET); + Usb_write_byte(0x00); /* Reserved */ + + if (length > 12) + { + Usb_write_byte(SBC_WRITE_RETRY_COUNT); + Usb_write_byte(0x00); + Usb_write_byte(SBC_RECOVERY_LIMIT_MSB); + Usb_write_byte(SBC_RECOVERY_LIMIT_LSB); + } +} + +/** + * @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL + * command (0x1E) + * + * The SCSI prevent allow medium removal command requests that the target + * enable or disable the removal of the medium in the logical unit. + * + * @warning Code:.. bytes (function code length) + * + * @return FALSE: result KO, + * TRUE: result OK + * + */ +Bool sbc_prevent_allow_medium_removal(void) +{ + sbc_lun_status_is_good(); + return TRUE; +} + + +//! This fonction send the UFI status GOOD +//! +void sbc_lun_status_is_good(void) +{ + Sbc_send_good(); + Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00); +} + +//! This fonction send the UFI status "lun not present" +//! +void sbc_lun_status_is_not_present(void) +{ + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00); +} + +//! This fonction send the UFI status busy and change +//! +void sbc_lun_status_is_busy_or_change(void) +{ + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 ); +} + +//! This fonction send the UFI status FAIL +//! +void sbc_lun_status_is_fail(void) +{ + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00); +} + +//! This fonction send the UFI status FAIL because write protection +//! +void sbc_lun_status_is_protected(void) +{ + Sbc_send_failed(); + Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00); +} + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/scsi_decoder.h b/cpu/avr/dev/usb/storage/scsi_decoder.h new file mode 100644 index 000000000..e0c90a177 --- /dev/null +++ b/cpu/avr/dev/usb/storage/scsi_decoder.h @@ -0,0 +1,338 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file scsi_decoder.h ******************************************************* + * + * \brief + * This file is the scsi decoder + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ +#ifndef _SCSI_DECODER_H_ +#define _SCSI_DECODER_H_ + +//_____ I N C L U D E S ____________________________________________________ + + +//_____ M A C R O S ________________________________________________________ + +typedef struct +{ + U8 key; + U8 asc; + U8 ascq; +} s_scsi_sense; + + +//_____ D E C L A R A T I O N S ____________________________________________ + +Bool scsi_decode_command (void); + +/****************************************************************************/ +/* Command for all SCSI device types */ +/****************************************************************************/ + +#define SBC_CMD_TEST_UNIT_READY (0x00) +#define SBC_CMD_REQUEST_SENSE (0x03) +#define SBC_CMD_FORMAT_UNIT (0x04) +#define SBC_CMD_READ_6 (0x08) +#define SBC_CMD_INQUIRY (0x12) +#define SBC_CMD_MODE_SELECT_6 (0x15) +#define SBC_CMD_MODE_SENSE_6 (0x1A) +#define SBC_CMD_START_STOP_UNIT (0x1B) +#define SBC_CMD_RECEIVE_DIAGNOSTICS (0x1C) +#define SBC_CMD_SEND_DIAGNOSTIC (0x1D) +#define SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL (0x1E) +#define SBC_CMD_READ_LONG (0x23) +#define SBC_CMD_READ_CAPACITY (0x25) +#define SBC_CMD_READ_CD_ROM_CAPACITY (0x25) +#define SBC_CMD_READ_10 (0x28) +#define SBC_CMD_WRITE_10 (0x2A) +#define SBC_CMD_VERIFY_10 (0x2F) +#define SBC_CMD_SYNCHRONIZE_CACHE (0x35) +#define SBC_CMD_WRITE_BUFFER (0x3B) +#define SBC_CMD_CHANGE_DEFINITION (0x40) +#define SBC_CMD_READ_TOC (0x43) +#define SBC_CMD_MODE_SELECT_10 (0x55) +#define SBC_CMD_RESERVE_10 (0x56) +#define SBC_CMD_RELEASE_10 (0x57) +#define SBC_CMD_MODE_SENSE_10 (0x5A) + +#define SBC_CONTROL_BYTE (0x00) +#define SBC_CMD_DIR_IN (0x80) +#define SBC_CMD_DIR_OUT (0x00) + + +/****************************************************************************/ +/* Sense Key Code */ +/****************************************************************************/ +#define SBC_SENSE_KEY_NO_SENSE (0x00) +#define SBC_SENSE_KEY_RECOVERED_ERROR (0x01) +#define SBC_SENSE_KEY_NOT_READY (0x02) +#define SBC_SENSE_KEY_MEDIUM_ERROR (0x03) +#define SBC_SENSE_KEY_HARDWARE_ERROR (0x04) +#define SBC_SENSE_KEY_ILLEGAL_REQUEST (0x05) +#define SBC_SENSE_KEY_UNIT_ATTENTION (0x06) +#define SBC_SENSE_KEY_DATA_PROTECT (0x07) +#define SBC_SENSE_KEY_BLANK_CHECK (0x08) +#define SBC_SENSE_KEY_VENDOR_SPECIFIC (0x09) +#define SBC_SENSE_KEY_COPY_ABORTED (0x0A) +#define SBC_SENSE_KEY_ABORTED_COMMAND (0x0B) +#define SBC_SENSE_KEY_VOLUME_OVERFLOW (0x0D) +#define SBC_SENSE_KEY_MISCOMPARE (0x0E) + +/****************************************************************************/ +/* ASC code assignments */ +/****************************************************************************/ +#define SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION (0x00) +#define SBC_ASC_LOGICAL_UNIT_NOT_READY (0x04) +#define SBC_ASC_INVALID_FIELD_IN_CDB (0x24) +#define SBC_ASC_WRITE_PROTECTED (0x27) +#define SBC_ASC_FORMAT_ERROR (0x31) +#define SBC_ASC_INVALID_COMMAND_OPERATION_CODE (0x20) +#define SBC_ASC_NOT_READY_TO_READY_CHANGE (0x28) +#define SBC_ASC_MEDIUM_NOT_PRESENT (0x3A) + +/****************************************************************************/ +/* ASCQ code assignments */ +/****************************************************************************/ +#define SBC_ASCQ_FORMAT_COMMAND_FAILED (0x01) +#define SBC_ASCQ_INITIALIZING_COMMAND_REQUIRED (0x02) +#define SBC_ASCQ_OPERATION_IN_PROGRESS (0x07) + + +/****************************************************************************/ +/* REQUEST SENSE PARAMETERS */ +/****************************************************************************/ +#define SBC_RESPONSE_CODE_SENSE (0x70) +#define SBC_ADDITIONAL_SENSE_LENGTH (0x0A) +#define SBC_COMMAND_SPECIFIC_INFORMATION_3 (0x00) +#define SBC_COMMAND_SPECIFIC_INFORMATION_2 (0x00) +#define SBC_COMMAND_SPECIFIC_INFORMATION_1 (0x00) +#define SBC_COMMAND_SPECIFIC_INFORMATION_0 (0x00) +#define SBC_FIELD_REPLACEABLE_UNIT_CODE (0x00) +#define SBC_SENSE_KEY_SPECIFIC_2 (0x00) +#define SBC_SENSE_KEY_SPECIFIC_1 (0x00) +#define SBC_SENSE_KEY_SPECIFIC_0 (0x00) + +/******* number of bytes of READ CAPACITY response *********/ +#define SBC_READ_CAPACITY_LENGTH (0x08) + + +/****************************************************************************/ +/*MODE SENSE and REQUEST SENSE DEFINITIONS */ +/****************************************************************************/ + +/*************** Direct access medium type ****************/ +#define SBC_DEFAULT_MEDIUM_TYPE (0x00) +#define SBC_FLEXIBLE_DISK_SINGLE_SIDED_UNSPECIFIED (0x01) +#define SBC_FLEXIBLE_DISK_DOUBLE_SIDED_UNSPECIFIED (0x02) + +#define SBC_MEDIUM_TYPE SBC_DEFAULT_MEDIUM_TYPE + +#define SBC_DEV_SPEC_PARAM_WR_ENABLE (0x00) +#define SBC_DEV_SPEC_PARAM_WR_PROTECT (0x80) +#define SBC_BLOCK_DESCRIPTOR_LENGTH (0x00) + +#define SBC_MSK_DBD (0x08) +#define SBC_MSK_PAGE_CONTROL (0xC0) +#define SBC_MSK_PAGE_CODE (0x3F) + + +/************ General Page Code paramaters *****************/ +#define SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY (0x01) +#define SBC_PAGE_CODE_FORMAT_DEVICE (0x03) +#define SBC_PAGE_CODE_FLEXIBLE_DISK (0x05) +#define SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS (0x1C) +#define SBC_PAGE_CODE_ALL (0x3F) + + +#define SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS (0x0A) +#define SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY (0x0A) +#define SBC_PAGE_LENGTH_FLEXIBLE_DISK (0x1E) +#define SBC_PAGE_LENGTH_FORMAT_DEVICE (0x16) + + + +#define SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS (SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS + 2 + 3) +#define SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY (SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY + 2 + 3 ) +#define SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK (SBC_PAGE_LENGTH_FLEXIBLE_DISK + 2 + 3 ) +#define SBC_MODE_DATA_LENGTH_FORMAT_DEVICE (SBC_PAGE_LENGTH_FORMAT_DEVICE + 2 + 3 ) +/*SBC_PAGE_LENGTH_FLEXIBLE_DISK + 2 + \*/ +#define SBC_MODE_DATA_LENGTH_CODE_ALL (SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY + 2 + \ + SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS + 2 + \ + SBC_BLOCK_DESCRIPTOR_LENGTH + \ + + 3 ) + +/* SBC_MODE_DATA_LENGTH_FORMAT_DEVICE + 2 + \*/ +/****** Information exceptions control page parameters *****/ +#define SBC_MRIE (0x05) + +/*************** Format device page parameters *************/ +#define SBC_TRACK_PER_ZONE_MSB (0x00) +#define SBC_TRACK_PER_ZONE_LSB (0x00) +#define SBC_ALTERNATE_SECTORS_PER_ZONE_MSB (0x00) +#define SBC_ALTERNATE_SECTORS_PER_ZONE_LSB (0x00) +#define SBC_ALTERNATE_TRACK_PER_ZONE_MSB (0x00) +#define SBC_ALTERNATE_TRACK_PER_ZONE_LSB (0x00) +#define SBC_ALTERNATE_TRACK_PER_LU_MSB (0x00) +#define SBC_ALTERNATE_TRACK_PER_LU_LSB (0x00) + +/************* Flexible Disk page Parameters ***************/ +#define SBC_TRANSFER_RATE_MSB (0x13) +#define SBC_TRANSFER_RATE_LSB (0x88) +/* 1388h 5 Mbit/s */ +/* 07D0h 2 Mbit/s */ +/* 03E8h 1 Mbit/s */ +/* 01F4h 500 kbit/s */ +/* 012Ch 300 kbit/s */ +/* 00FAh 250 kbit/s */ + +#define SBC_NUMBER_OF_HEAD (0x04) +#define SBC_SECTOR_PER_TRACK (0x20) +#define SBC_DATA_BYTE_PER_SECTOR_MSB (0x02) +#define SBC_DATA_BYTE_PER_SECTOR_LSB (0x00) +#define SBC_NUMBER_OF_CYLINDERS_MSB (0x01) +#define SBC_NUMBER_OF_CYLINDERS_LSB (0xE9) +#define SBC_STARTING_CYLINDER_WRITE_COMPENSATION_MSB (0x00) +#define SBC_STARTING_CYLINDER_WRITE_COMPENSATION_LSB (0x00) +#define SBC_STARTING_CYLINDER_REDUCED_WRITE_MSB (0x00) +#define SBC_STARTING_CYLINDER_REDUCED_WRITE_LSB (0x00) +#define SBC_DEVICE_STEP_RATE_MSB (0x00) +#define SBC_DEVICE_STEP_RATE_LSB (0x00) +#define SBC_DEVICE_STEP_PULSE_WIDTH (0x00) +#define SBC_HEAD_SETTLE_DELAY_MSB (0x00) +#define SBC_HEAD_SETTLE_DELAY_LSB (0x00) +#define SBC_MOTOR_ON_DELAY (0x00) +#define SBC_MOTOR_OFF_DELAY (0x00) +#define SBC_STEP_PULSE_PER_CYLINDER (0x00) +#define SBC_WRITE_COMPENSATION (0x00) +#define SBC_HEAD_LOAD_DELAY (0x00) +#define SBC_HEAD_UNLOAD_DELAY (0x00) +#define SBC_PIN34_PIN2 (0x00) +#define SBC_PIN4_PIN1 (0x00) +#define SBC_MEDIUM_ROTATION_RATE_MSB (0x00) +#define SBC_MEDIUM_ROTATION_RATE_LSB (0x00) + +/************ Read/Write Error Recovery parameters**********/ +#define SBC_READ_RETRY_COUNT (0x03) +#define SBC_WRITE_RETRY_COUNT (0x80) +#define SBC_CORRECTION_SPAN (0x00) +#define SBC_HEAD_OFFSET_COUNT (0x00) +#define SBC_DATA_STROBE_OFFSET (0x00) +#define SBC_RECOVERY_LIMIT_MSB (0x00) +#define SBC_RECOVERY_LIMIT_LSB (0x00) + + +/*_____ D E F I N I T I O N ________________________________________________*/ + +#define SBC_MAX_INQUIRY_DATA (0x60) // value ? + +struct sbc_st_std_inquiry_data +{ + Byte DeviceType : 5; + Byte PeripheralQualifier : 3; + + Byte Reserved1 : 7; + Byte RemovableMedia : 1; + + Byte Version; + + Byte Reserved3 : 5; + Byte NormACA : 1; + Byte Obsolete0 : 1; + Byte AERC : 1; + + Byte Reserved4[3]; + + Byte SoftReset : 1; + Byte CommandQueue : 1; + Byte Reserved5 : 1; + Byte LinkedCommands : 1; + Byte Synchronous : 1; + Byte Wide16Bit : 1; + Byte Wide32Bit : 1; + Byte RelativeAddressing : 1; +}; + + +//_____ D E C L A R A T I O N S ____________________________________________ + +#define Sbc_send_failed() (g_scsi_status = COMMAND_FAILED) +#define Sbc_send_check_condition() (g_scsi_status = CHECK_CONDITION) +#define Sbc_send_good() (g_scsi_status = COMMAND_PASSED) + +/*#define Sbc_valid_write_usb(length) ( Usb_set_TXRDY(), \ + dCBWDataTransferLength -= length, \ + while (!Usb_tx_complete()),\ + Usb_clear_TXCMPL() ) +*/ +#define Sbc_build_sense(skey, sasc, sascq) ( g_scsi_sense.key = skey, \ + g_scsi_sense.asc = sasc, \ + g_scsi_sense.ascq = sascq ) + +#define Sbc_valid_write_usb(length) ( Usb_send_in(), \ + g_scsi_data_remaining -= length ) + + +#define COMMAND_PASSED 0x00 +#define COMMAND_FAILED 0x01 +#define CHECK_CONDITION 0x02 +#define PHASE_ERROR 0x02 + + +Bool sbc_inquiry (void); +Bool sbc_mode_sense( Bool sense_10 ); +Bool sbc_mode_select_6 (void); +Bool sbc_request_sense (void); +Bool sbc_format (void); +Bool sbc_write_10 (void); +Bool sbc_read_10 (void); +Bool sbc_test_unit_ready(void); +Bool sbc_read_capacity(void); +Bool sbc_prevent_allow_medium_removal(void); + +void sbc_lun_status_is_good(void); +void sbc_lun_status_is_busy_or_change(void); +void sbc_lun_status_is_not_present(void); +void sbc_lun_status_is_fail(void); +void sbc_lun_status_is_protected(void); + +#endif /* _SCSI_DECODER_H_ */ +/** @} */ diff --git a/cpu/avr/dev/usb/storage/storage_task.c b/cpu/avr/dev/usb/storage/storage_task.c new file mode 100644 index 000000000..1cb88223f --- /dev/null +++ b/cpu/avr/dev/usb/storage/storage_task.c @@ -0,0 +1,276 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_task.c ********************************************************************* + * + * \brief + * This file manages the USB storage. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbstorage + @{ +*/ + +//_____ I N C L U D E S ___________________________________________________ + + + +#include "contiki.h" +#include "usb_drv.h" +#include "storage/storage_task.h" +#include "usb_descriptors.h" +#include "usb_standard_request.h" +#include "usb_specific_request.h" +#include "storage/scsi_decoder.h" +#include "storage/ctrl_access.h" + + +//_____ M A C R O S ________________________________________________________ + + + + + +//_____ D E F I N I T I O N S ______________________________________________ + + + +//_____ D E C L A R A T I O N S ____________________________________________ + + + +extern U8 usb_configuration_nb; + + +static bit ms_data_direction; +static U8 dCBWTag[4]; + +extern U8 g_scsi_status; +extern U32 g_scsi_data_remaining; +extern bit ms_multiple_drive; +extern U8 g_scsi_command[16]; + + +U8 usb_LUN; + + +void usb_mass_storage_cbw (void); +void usb_mass_storage_csw (void); + +#define Usb_set_ms_data_direction_in() (ms_data_direction = 1) +#define Usb_set_ms_data_direction_out() (ms_data_direction = 0) +#define Is_usb_ms_data_direction_in() (ms_data_direction == 1) + +static struct etimer et; + +PROCESS(storage_process, "Storage process"); + +/** + * \brief USB Mass Storage Class Process + * + * This is the link between USB and the "good stuff". In this routine data + * is received and processed by USB Storage Class + */ +PROCESS_THREAD(storage_process, ev, data_proc) +{ + PROCESS_BEGIN(); + + while(1) { + + + if (usb_mode == mass_storage) { + + if (Is_device_enumerated()) { + Usb_select_endpoint(MS_OUT_EP); + + if (Is_usb_receive_out()) { + usb_mass_storage_cbw(); + usb_mass_storage_csw(); + } + } + + } + + if (usb_mode == mass_storage) { + etimer_set(&et, CLOCK_SECOND/250 + 1); + } else { + etimer_set(&et, CLOCK_SECOND); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + } //while(1) + + PROCESS_END(); +} + + + + +//! @brief USB Command Block Wrapper (CBW) management +//! +//! This function decodes the CBW command and stores the SCSI command +//! +//! @warning Code:?? bytes (function code length) +//! +void usb_mass_storage_cbw (void) +{ + bit cbw_error; + uint8_t c; + uint8_t dummy; + + cbw_error = FALSE; + Usb_select_endpoint(MS_OUT_EP); //! check if dCBWSignature is correct + if (0x55 != Usb_read_byte()) + { cbw_error = TRUE; } //! 'U' + if (0x53 != Usb_read_byte()) + { cbw_error = TRUE; } //! 'S' + if (0x42 != Usb_read_byte()) + { cbw_error = TRUE; } //! 'B' + if (0x43 != Usb_read_byte()) + { cbw_error = TRUE; } //! 'C' + + dCBWTag[0] = Usb_read_byte(); //! Store CBW Tag to be repeated in CSW + dCBWTag[1] = Usb_read_byte(); + dCBWTag[2] = Usb_read_byte(); + dCBWTag[3] = Usb_read_byte(); + + LSB0(g_scsi_data_remaining) = Usb_read_byte(); + LSB1(g_scsi_data_remaining) = Usb_read_byte(); + LSB2(g_scsi_data_remaining) = Usb_read_byte(); + LSB3(g_scsi_data_remaining) = Usb_read_byte(); + + + if (Usb_read_byte() != 0x00) //! if (bmCBWFlags.bit7 == 1) {direction = IN} + { + Usb_set_ms_data_direction_in(); + if (cbw_error) + { + Usb_ack_receive_out(); + Usb_select_endpoint(MS_IN_EP); + Usb_enable_stall_handshake(); + return; + } + } + else + { + Usb_set_ms_data_direction_out(); + if (cbw_error) + { + Usb_enable_stall_handshake(); + Usb_ack_receive_out(); + return; + } + } + + usb_LUN = Usb_read_byte(); + + if (!ms_multiple_drive) + { + usb_LUN = get_cur_lun(); + } + + dummy = Usb_read_byte(); //! dummy CBWCBLength read + + + for (c=0; c<16; c++) // store scsi_command + { + g_scsi_command[c] = Usb_read_byte(); + } + + Usb_ack_receive_out(); + + if (Is_usb_ms_data_direction_in()) + { + Usb_select_endpoint(MS_IN_EP); + } + + if (TRUE != scsi_decode_command()) + { + if (g_scsi_data_remaining != 0) + { + Usb_enable_stall_handshake(); + } + } +} + +//! @brief USB Command Status Wrapper (CSW) management +//! +//! This function sends the status in relation with the last CBW +//! +void usb_mass_storage_csw (void) +{ + Usb_select_endpoint(MS_IN_EP); + while (Is_usb_endpoint_stall_requested()) + { + Usb_select_endpoint(EP_CONTROL); + if (Is_usb_receive_setup()) { usb_process_request(); } + Usb_select_endpoint(MS_IN_EP); + } + + Usb_select_endpoint(MS_OUT_EP); + while (Is_usb_endpoint_stall_requested()) + { + Usb_select_endpoint(EP_CONTROL); + if (Is_usb_receive_setup()) { usb_process_request(); } + Usb_select_endpoint(MS_OUT_EP); + } + + Usb_select_endpoint(MS_IN_EP); + while(!Is_usb_write_enabled()); + //! write CSW Signature + Usb_write_byte(0x55); //! 'U' + Usb_write_byte(0x53); //! 'S' + Usb_write_byte(0x42); //! 'B' + Usb_write_byte(0x53); //! 'S' + //! write stored CBW Tag + Usb_write_byte(dCBWTag[0]); + Usb_write_byte(dCBWTag[1]); + Usb_write_byte(dCBWTag[2]); + Usb_write_byte(dCBWTag[3]); + //! write data residue value + Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[3] ); + Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[2] ); + Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[1] ); + Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[0] ); + + //! write command status + Usb_write_byte(g_scsi_status); //! 0 -> PASS, 1 -> FAIL + Usb_send_in(); +} + +/** @} */ diff --git a/cpu/avr/dev/usb/storage/storage_task.h b/cpu/avr/dev/usb/storage/storage_task.h new file mode 100644 index 000000000..0e1a0250a --- /dev/null +++ b/cpu/avr/dev/usb/storage/storage_task.h @@ -0,0 +1,69 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file storage_task.c ********************************************************** + * + * \brief + * This file manages the USB storage. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* + Copyright (c) 2004 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \ingroup usbstick + \defgroup usbstorage USB Mass Storage Task + @{ +*/ +#ifndef _STORAGE_TASK_H_ +#define _STORAGE_TASK_H_ + +//_____ I N C L U D E S ____________________________________________________ + + +#include "config.h" + +//_____ M A C R O S ________________________________________________________ + + + +//_____ D E C L A R A T I O N S ____________________________________________ + + +void sof_action(void); + + +PROCESS_NAME(storage_process); + +#endif /* _STORAGE_TASK_H_ */ +/** @} */ diff --git a/cpu/avr/dev/usb/usb_descriptors.c b/cpu/avr/dev/usb/usb_descriptors.c new file mode 100644 index 000000000..dbf49a090 --- /dev/null +++ b/cpu/avr/dev/usb/usb_descriptors.c @@ -0,0 +1,537 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_descriptors.c ***************************************************** + * + * \brief + * This file contains the usb parameters that uniquely identify the + * application through descriptor tables. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbconf + @{ + */ + +//_____ I N C L U D E S ____________________________________________________ + +#include "config.h" + +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" + + +//_____ M A C R O S ________________________________________________________ + + + + +//_____ D E F I N I T I O N ________________________________________________ + +/************* COMPOSITE DEVICE DESCRIPTORS (using IAD) **********/ + +// usb_user_device_descriptor +FLASH S_usb_device_descriptor usb_dev_desc_composite = +{ + sizeof(usb_dev_desc_composite) +, DEVICE_DESCRIPTOR +, Usb_write_word_enum_struc(USB_SPECIFICATION) +, COMPOSITE_DEVICE_CLASS +, COMPOSITE_DEVICE_SUB_CLASS +, COMPOSITE_DEVICE_PROTOCOL +, EP_CONTROL_LENGTH +, Usb_write_word_enum_struc(VENDOR_ID) +, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID) +, Usb_write_word_enum_struc(RELEASE_NUMBER) +, MAN_INDEX +, PROD_INDEX +, SN_INDEX +, NB_CONFIGURATION +}; + + +// usb_user_configuration_descriptor FS +FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = { + { sizeof(S_usb_configuration_descriptor) + , CONFIGURATION_DESCRIPTOR + , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_composite)) + //, 0x0043 //TODO: Change to generic codewith sizeof + , COMPOSITE_NB_INTERFACE + , CONF_NB + , CONF_INDEX + , CONF_ATTRIBUTES + , MAX_POWER + },//9 + + // --------------------------- IAD ---------------------------- + { // Interface Association Descriptor + sizeof(S_usb_interface_association_descriptor), // bLength + DSC_TYPE_IAD, // bDescriptorType = 11 + 0x00, // bFirstInterface + 0x02, // bInterfaceCount + 0x02, // bFunctionClass (Communication Class) + 0x02, // bFunctionSubClass (Abstract Control Model) + 0xFF, // bFunctionProcotol (Vendor specific) + 0x00 // iInterface + },//8 + + /// RNDIS DEVICE + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE0_NB + , ALTERNATE0 + , NB_ENDPOINT0 + , INTERFACE0_CLASS + , INTERFACE0_SUB_CLASS + , INTERFACE0_PROTOCOL + , INTERFACE0_INDEX + } //9 +, +{ +// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x00, // bDescriptorSubtype, Header Functional Descriptor +0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) + +// Call Management Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x01, // bDescriptorSubtype, Call Management Functional Descriptor +0x00, // bmCapabilities +0x01, // bDataInterface, Interface used for call management + +// Abstract Control Management Functional Descriptor +0x04, // bDescriptorLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor +0x00, // bmCapabilities + +// Union Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x06, // bDescriptorSubtype, Union Functional Descriptor +0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) +0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) +}, +{ sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_1 + , EP_ATTRIBUTES_1 + , Usb_write_word_enum_struc(EP_SIZE_1) + , EP_INTERVAL_1 + } //7 + , + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE1_NB + , ALTERNATE1 + , NB_ENDPOINT1 + , INTERFACE1_CLASS + , INTERFACE1_SUB_CLASS + , INTERFACE1_PROTOCOL + , INTERFACE1_INDEX + }, + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_2 + , EP_ATTRIBUTES_2 + , Usb_write_word_enum_struc(EP_SIZE_2) + , EP_INTERVAL_2 + }, +{ sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_3 + , EP_ATTRIBUTES_3 + , Usb_write_word_enum_struc(EP_SIZE_3) + , EP_INTERVAL_3 + }, + +// --------------------------- IAD ---------------------------- + { // Interface Association Descriptor + sizeof(S_usb_interface_association_descriptor), // bLength + DSC_TYPE_IAD, // bDescriptorType = 11 + 0x02, // bFirstInterface + 0x02, // bInterfaceCount + 0x02, // bFunctionClass (Communication Class) + 0x02, // bFunctionSubClass (Abstract Control Model) + 0x01, // bFunctionProcotol (V.25ter, Common AT commands) + 0x00 // iInterface + },//8 + + /// SERIAL PORT DEVICE + + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE2_NB + , ALTERNATE2 + , NB_ENDPOINT2 + , INTERFACE2_CLASS + , INTERFACE2_SUB_CLASS + , INTERFACE2_PROTOCOL + , INTERFACE2_INDEX + }//9 + , + { +// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x00, // bDescriptorSubtype, Header Functional Descriptor +0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) + +// Call Management Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x01, // bDescriptorSubtype, Call Management Functional Descriptor +0x03, // bmCapabilities, can do calls on it's own +0x03, // bDataInterface, Interface used for call management + +// Abstract Control Management Functional Descriptor +0x04, // bDescriptorLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor +0x00, // bmCapabilities, support nothing!!! Deal with it + + //Old was 0x06 indicating support for the GET/SET_LINE_CODING, BREAK & SET_CONTROL_LINE_STATE (2->6) + +// Union Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x06, // bDescriptorSubtype, Union Functional Descriptor +0x02, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) +0x03, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) + +}, + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_4 + , EP_ATTRIBUTES_4 + , Usb_write_word_enum_struc(EP_SIZE_4) + , EP_INTERVAL_4 + } //7 + , + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE3_NB + , ALTERNATE3 + , NB_ENDPOINT3 + , INTERFACE3_CLASS + , INTERFACE3_SUB_CLASS + , INTERFACE3_PROTOCOL + , INTERFACE3_INDEX + } + , + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_5 + , EP_ATTRIBUTES_5 + , Usb_write_word_enum_struc(EP_SIZE_5) + , EP_INTERVAL_5 + } + , + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_6 + , EP_ATTRIBUTES_6 + , Usb_write_word_enum_struc(EP_SIZE_6) + , EP_INTERVAL_6 + } + +}; + +/****************** NETWORK-ONLY DEVICE DESCRIPTORS **************************/ + +FLASH S_usb_device_descriptor usb_dev_desc_network = +{ + sizeof(usb_dev_desc_network) +, DEVICE_DESCRIPTOR +, Usb_write_word_enum_struc(USB_SPECIFICATION) +, NETWORK_DEVICE_CLASS +, NETWORK_DEVICE_SUB_CLASS +, NETWORK_DEVICE_PROTOCOL +, EP_CONTROL_LENGTH +, Usb_write_word_enum_struc(VENDOR_ID) +, Usb_write_word_enum_struc(NETWORK_PRODUCT_ID) +, Usb_write_word_enum_struc(RELEASE_NUMBER) +, MAN_INDEX +, PROD_INDEX +, SN_INDEX +, NB_CONFIGURATION +}; + +// usb_user_configuration_descriptor FS +FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = { + { sizeof(S_usb_configuration_descriptor) + , CONFIGURATION_DESCRIPTOR + , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_network)) + //, 0x0043 //TODO: Change to generic codewith sizeof + , NETWORK_NB_INTERFACE + , CONF_NB + , CONF_INDEX + , CONF_ATTRIBUTES + , MAX_POWER + },//9 + + /// RNDIS DEVICE + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE0_NB + , ALTERNATE0 + , NB_ENDPOINT0 + , INTERFACE0_CLASS + , INTERFACE0_SUB_CLASS + , INTERFACE0_PROTOCOL + , INTERFACE0_INDEX + } //9 +, +{ +// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x00, // bDescriptorSubtype, Header Functional Descriptor +0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) + +// Call Management Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x01, // bDescriptorSubtype, Call Management Functional Descriptor +0x00, // bmCapabilities +0x01, // bDataInterface, Interface used for call management + +// Abstract Control Management Functional Descriptor +0x04, // bDescriptorLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor +0x00, // bmCapabilities + +// Union Functional Descriptor +0x05, // bFunctionLength, Descriptor size in bytes +0x24, // bDescriptorType, CS_INTERFACE +0x06, // bDescriptorSubtype, Union Functional Descriptor +0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) +0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) +}, +{ sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_1 + , EP_ATTRIBUTES_1 + , Usb_write_word_enum_struc(EP_SIZE_1) + , EP_INTERVAL_1 + } //7 + , + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , INTERFACE1_NB + , ALTERNATE1 + , NB_ENDPOINT1 + , INTERFACE1_CLASS + , INTERFACE1_SUB_CLASS + , INTERFACE1_PROTOCOL + , INTERFACE1_INDEX + }, + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_2 + , EP_ATTRIBUTES_2 + , Usb_write_word_enum_struc(EP_SIZE_2) + , EP_INTERVAL_2 + }, +{ sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , ENDPOINT_NB_3 + , EP_ATTRIBUTES_3 + , Usb_write_word_enum_struc(EP_SIZE_3) + , EP_INTERVAL_3 + } +}; + + +/****************** MASS-STORAGE DEVICE DESCRIPTORS **************************/ + +FLASH S_usb_device_descriptor usb_dev_desc_mass = +{ + sizeof(usb_dev_desc_mass) +, DEVICE_DESCRIPTOR +, Usb_write_word_enum_struc(USB_SPECIFICATION) +, MASS_DEVICE_CLASS +, MASS_DEVICE_SUB_CLASS +, MASS_DEVICE_PROTOCOL +, EP_CONTROL_LENGTH +, Usb_write_word_enum_struc(VENDOR_ID) +, Usb_write_word_enum_struc(MASS_PRODUCT_ID) +, Usb_write_word_enum_struc(RELEASE_NUMBER) +, MAN_INDEX +, PROD_INDEX +, SN_INDEX +, NB_CONFIGURATION +}; + +// usb_user_configuration_descriptor FS +FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { + { sizeof(S_usb_configuration_descriptor) + , CONFIGURATION_DESCRIPTOR + , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_mass)) + , MASS_NB_INTERFACE + , CONF_NB + , CONF_INDEX + , CONF_ATTRIBUTES + , MAX_POWER + },//9 + + /// Mass storage + { sizeof(S_usb_interface_descriptor) + , INTERFACE_DESCRIPTOR + , MS_INTERFACE_NB + , MS_ALTERNATE + , MS_NB_ENDPOINT + , MS_INTERFACE_CLASS + , MS_INTERFACE_SUB_CLASS + , MS_INTERFACE_PROTOCOL + , MS_INTERFACE_INDEX + } //9 +, +{ sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , MS_ENDPOINT_NB_1 + , MS_EP_ATTRIBUTES_1 + , Usb_write_word_enum_struc(MS_EP_SIZE_1) + , MS_EP_INTERVAL_1 + } //7 + , + { sizeof(S_usb_endpoint_descriptor) + , ENDPOINT_DESCRIPTOR + , MS_ENDPOINT_NB_2 + , MS_EP_ATTRIBUTES_2 + , Usb_write_word_enum_struc(MS_EP_SIZE_2) + , MS_EP_INTERVAL_2 + } +}; + + +/************* COMMON *****************/ + + + // usb_user_manufacturer_string_descriptor +FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor = { + sizeof(usb_user_manufacturer_string_descriptor) +, STRING_DESCRIPTOR +, USB_MANUFACTURER_NAME +}; + + + // usb_user_product_string_descriptor + +FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor = { + sizeof(usb_user_product_string_descriptor) +, STRING_DESCRIPTOR +, USB_PRODUCT_NAME +}; + + + // usb_user_serial_number + +FLASH S_usb_serial_number usb_user_serial_number = { + sizeof(usb_user_serial_number) +, STRING_DESCRIPTOR +, USB_SERIAL_NUMBER +}; + + + // usb_user_language_id + +FLASH S_usb_language_id usb_user_language_id = { + sizeof(usb_user_language_id) +, STRING_DESCRIPTOR +, Usb_write_word_enum_struc(LANGUAGE_ID) +}; + + + + + +PGM_VOID_P Usb_get_dev_desc_pointer(void) +{ + if (usb_mode == rndis_only) + return &(usb_dev_desc_network.bLength); + + if (usb_mode == rndis_debug) + return &(usb_dev_desc_composite.bLength); + + return &(usb_dev_desc_mass.bLength); +} + + +U8 Usb_get_dev_desc_length(void) +{ + + if (usb_mode == rndis_only) + return sizeof(usb_dev_desc_network); + + if (usb_mode == rndis_debug) + return sizeof(usb_dev_desc_composite); + + return sizeof(usb_dev_desc_mass); +} + + +PGM_VOID_P Usb_get_conf_desc_pointer(void) +{ + if (usb_mode == rndis_only) + return &(usb_conf_desc_network.cfg.bLength); + + if (usb_mode == rndis_debug) + return &(usb_conf_desc_composite.cfg.bLength); + + return &(usb_conf_desc_mass.cfg.bLength); +} + + +U8 Usb_get_conf_desc_length(void) +{ + + if (usb_mode == rndis_only) + return sizeof (usb_conf_desc_network); + + if (usb_mode == rndis_debug) + return sizeof(usb_conf_desc_composite); + + return sizeof(usb_conf_desc_mass); +} + +/** @} */ diff --git a/cpu/avr/dev/usb/usb_descriptors.h b/cpu/avr/dev/usb/usb_descriptors.h new file mode 100644 index 000000000..dbdb1c932 --- /dev/null +++ b/cpu/avr/dev/usb/usb_descriptors.h @@ -0,0 +1,453 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_descriptors.h *************************************************** + * + * \brief + * This file contains the usb parameters that uniquely identify the + * application through descriptor tables. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbconf + @{ + */ + +#ifndef _USB_USERCONFIG_H_ +#define _USB_USERCONFIG_H_ + +//_____ I N C L U D E S ____________________________________________________ + +#include "config.h" +#include "usb_standard_request.h" +#include "conf_usb.h" +#include + +//_____ M A C R O S ________________________________________________________ + + +//_____ U S B D E F I N E _______________________________________________ + + // USB Device descriptor +#define USB_SPECIFICATION 0x0200 + +#define COMPOSITE_DEVICE_CLASS 0xEF // Misc +#define COMPOSITE_DEVICE_SUB_CLASS 0x02 // Common +#define COMPOSITE_DEVICE_PROTOCOL 0x01 // IAD + +#define NETWORK_DEVICE_CLASS 0x02 // CDC ACM +#define NETWORK_DEVICE_SUB_CLASS 0x02 // +#define NETWORK_DEVICE_PROTOCOL 0xFF // Vendor-specific + +#define MASS_DEVICE_CLASS 0x00 // +#define MASS_DEVICE_SUB_CLASS 0x00 // +#define MASS_DEVICE_PROTOCOL 0x00 // + +#define EP_CONTROL_LENGTH 64 +#define VENDOR_ID 0x03EB // Atmel vendor ID = 03EBh +#define COMPOSITE_PRODUCT_ID 0x2021 //Product ID for composite device +#define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device +#define MASS_PRODUCT_ID 0x202F //Product ID for mass storage +#define RELEASE_NUMBER 0x1000 +#define MAN_INDEX 0x01 +#define PROD_INDEX 0x02 +#define SN_INDEX 0x03 +#define NB_CONFIGURATION 1 + +#define NETWORK_NB_INTERFACE 2 +#define COMPOSITE_NB_INTERFACE 4 +#define MASS_NB_INTERFACE 1 +#define CONF_NB 1 +#define CONF_INDEX 0 +#define CONF_ATTRIBUTES USB_CONFIG_BUSPOWERED +#define MAX_POWER 50 // 100 mA + +/*** CDC RNDIS CONFIGURATION CONFIGURATION ***/ + +// Interface 0 descriptor +#define INTERFACE0_NB 0 +#define ALTERNATE0 0 +#define NB_ENDPOINT0 1 +#define INTERFACE0_CLASS 0x02 // CDC ACM Com +#define INTERFACE0_SUB_CLASS 0x02 +#define INTERFACE0_PROTOCOL 0xFF // Vendor specific +#define INTERFACE0_INDEX 0 + +// Interface 1 descriptor +#define INTERFACE1_NB 1 +#define ALTERNATE1 0 +#define NB_ENDPOINT1 2 +#define INTERFACE1_CLASS 0x0A // CDC ACM Data +#define INTERFACE1_SUB_CLASS 0 +#define INTERFACE1_PROTOCOL 0 +#define INTERFACE1_INDEX 0 + + // USB Endpoint 1 descriptor + // Interrupt IN +#define ENDPOINT_NB_1 0x80 | INT_EP +#define EP_ATTRIBUTES_1 0x03 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_1 0x08 +#define EP_INTERVAL_1 0x01 //ms interrupt pooling from host + + // USB Endpoint 1 descriptor + // Bulk IN +#define ENDPOINT_NB_2 0x80 | TX_EP +#define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_2 0x40 //64 byte max size +#define EP_INTERVAL_2 0x00 + + // USB Endpoint 2 descriptor + //Bulk OUT RX endpoint +#define ENDPOINT_NB_3 RX_EP +#define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_3 0x40 //64 byte max size +#define EP_INTERVAL_3 0x00 + +/*** CDC Virtual Serial Port ***/ + + // Interface 2 descriptor +#define INTERFACE2_NB 2 +#define ALTERNATE2 0 +#define NB_ENDPOINT2 1 +#define INTERFACE2_CLASS 0x02 // CDC ACM Com +#define INTERFACE2_SUB_CLASS 0x02 +#define INTERFACE2_PROTOCOL 0x01 +#define INTERFACE2_INDEX 0 + + // Interface 3 descriptor +#define INTERFACE3_NB 3 +#define ALTERNATE3 0 +#define NB_ENDPOINT3 2 +#define INTERFACE3_CLASS 0x0A // CDC ACM Data +#define INTERFACE3_SUB_CLASS 0 +#define INTERFACE3_PROTOCOL 0 +#define INTERFACE3_INDEX 0 + + // USB Endpoint 4 descriptor + // Interrupt IN +#define TX_EP_SIZE 0x20 +#define ENDPOINT_NB_4 0x80 | VCP_INT_EP +#define EP_ATTRIBUTES_4 0x03 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_4 TX_EP_SIZE +#define EP_INTERVAL_4 0xFF //ms interrupt pooling from host + + // USB Endpoint 5 descriptor + // Bulk IN +#define ENDPOINT_NB_5 0x80 | VCP_TX_EP +#define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_5 0x20 +#define EP_INTERVAL_5 0x00 + + // USB Endpoint 6 descriptor + // Bulk OUT +#define ENDPOINT_NB_6 VCP_RX_EP +#define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define EP_SIZE_6 0x20 +#define EP_INTERVAL_6 0x00 + + +/*** Mass Storage ***/ + +#define MS_INTERFACE_NB 0 +#define MS_ALTERNATE 0 +#define MS_NB_ENDPOINT 2 +#define MS_INTERFACE_CLASS 0x08 // Mass Storage Class +#define MS_INTERFACE_SUB_CLASS 0x06 // SCSI transparent Command Set +#define MS_INTERFACE_PROTOCOL 0x50 // Bulk-Only Transport +#define MS_INTERFACE_INDEX 0 + +// USB Endpoint 1 descriptor FS +#define MS_ENDPOINT_NB_1 (MS_IN_EP | 0x80) +#define MS_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define MS_EP_IN_LENGTH 64 +#define MS_EP_SIZE_1 MS_EP_IN_LENGTH +#define MS_EP_INTERVAL_1 0x00 + + +// USB Endpoint 2 descriptor FS +#define MS_ENDPOINT_NB_2 MS_OUT_EP +#define MS_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 +#define MS_EP_IN_LENGTH 64 +#define MS_EP_SIZE_2 MS_EP_IN_LENGTH +#define MS_EP_INTERVAL_2 0x00 + + +#define DEVICE_STATUS 0x00 // TBD +#define INTERFACE_STATUS 0x00 // TBD + +#define LANG_ID 0x00 + + + + +#define USB_MN_LENGTH 5 +#define USB_MANUFACTURER_NAME \ +{ Usb_unicode('A') \ +, Usb_unicode('t') \ +, Usb_unicode('m') \ +, Usb_unicode('e') \ +, Usb_unicode('l') \ +} + +#define USB_PN_LENGTH 16 +#define USB_PRODUCT_NAME \ +{ Usb_unicode('R') \ + ,Usb_unicode('Z') \ + ,Usb_unicode('R') \ + ,Usb_unicode('A') \ + ,Usb_unicode('V') \ + ,Usb_unicode('E') \ + ,Usb_unicode('N') \ + ,Usb_unicode(' ') \ + ,Usb_unicode('U') \ + ,Usb_unicode('S') \ + ,Usb_unicode('B') \ + ,Usb_unicode(' ') \ + ,Usb_unicode('D') \ + ,Usb_unicode('E') \ + ,Usb_unicode('M') \ + ,Usb_unicode('O') \ +} + +#define USB_SN_LENGTH 0x05 +#define USB_SERIAL_NUMBER \ +{Usb_unicode('1') \ + ,Usb_unicode('.') \ + ,Usb_unicode('0') \ + ,Usb_unicode('.') \ + ,Usb_unicode('0') \ +} + +#define LANGUAGE_ID 0x0409 + + //! Usb Request +typedef struct +{ + U8 bmRequestType; //!< Characteristics of the request + U8 bRequest; //!< Specific request + U16 wValue; //!< field that varies according to request + U16 wIndex; //!< field that varies according to request + U16 wLength; //!< Number of bytes to transfer if Data +} S_UsbRequest; + + //! Usb Device Descriptor +typedef struct { + U8 bLength; //!< Size of this descriptor in bytes + U8 bDescriptorType; //!< DEVICE descriptor type + U16 bscUSB; //!< Binay Coded Decimal Spec. release + U8 bDeviceClass; //!< Class code assigned by the USB + U8 bDeviceSubClass; //!< Sub-class code assigned by the USB + U8 bDeviceProtocol; //!< Protocol code assigned by the USB + U8 bMaxPacketSize0; //!< Max packet size for EP0 + U16 idVendor; //!< Vendor ID. ATMEL = 0x03EB + U16 idProduct; //!< Product ID assigned by the manufacturer + U16 bcdDevice; //!< Device release number + U8 iManufacturer; //!< Index of manu. string descriptor + U8 iProduct; //!< Index of prod. string descriptor + U8 iSerialNumber; //!< Index of S.N. string descriptor + U8 bNumConfigurations; //!< Number of possible configurations +} S_usb_device_descriptor; + + + //! Usb Configuration Descriptor +typedef struct { + U8 bLength; //!< size of this descriptor in bytes + U8 bDescriptorType; //!< CONFIGURATION descriptor type + U16 wTotalLength; //!< total length of data returned + U8 bNumInterfaces; //!< number of interfaces for this conf. + U8 bConfigurationValue; //!< value for SetConfiguration resquest + U8 iConfiguration; //!< index of string descriptor + U8 bmAttibutes; //!< Configuration characteristics + U8 MaxPower; //!< maximum power consumption +} S_usb_configuration_descriptor; + + + //! Usb Interface Descriptor +typedef struct { + U8 bLength; //!< size of this descriptor in bytes + U8 bDescriptorType; //!< INTERFACE descriptor type + U8 bInterfaceNumber; //!< Number of interface + U8 bAlternateSetting; //!< value to select alternate setting + U8 bNumEndpoints; //!< Number of EP except EP 0 + U8 bInterfaceClass; //!< Class code assigned by the USB + U8 bInterfaceSubClass; //!< Sub-class code assigned by the USB + U8 bInterfaceProtocol; //!< Protocol code assigned by the USB + U8 iInterface; //!< Index of string descriptor +} S_usb_interface_descriptor; + + + //! Usb Endpoint Descriptor +typedef struct { + U8 bLength; //!< Size of this descriptor in bytes + U8 bDescriptorType; //!< ENDPOINT descriptor type + U8 bEndpointAddress; //!< Address of the endpoint + U8 bmAttributes; //!< Endpoint's attributes + U16 wMaxPacketSize; //!< Maximum packet size for this EP + U8 bInterval; //!< Interval for polling EP in ms +} S_usb_endpoint_descriptor; + + + //! Usb Device Qualifier Descriptor +typedef struct { + U8 bLength; //!< Size of this descriptor in bytes + U8 bDescriptorType; //!< Device Qualifier descriptor type + U16 bscUSB; //!< Binay Coded Decimal Spec. release + U8 bDeviceClass; //!< Class code assigned by the USB + U8 bDeviceSubClass; //!< Sub-class code assigned by the USB + U8 bDeviceProtocol; //!< Protocol code assigned by the USB + U8 bMaxPacketSize0; //!< Max packet size for EP0 + U8 bNumConfigurations; //!< Number of possible configurations + U8 bReserved; //!< Reserved for future use, must be zero +} S_usb_device_qualifier_descriptor; + + + //! Usb Language Descriptor +typedef struct { + U8 bLength; //!< size of this descriptor in bytes + U8 bDescriptorType; //!< STRING descriptor type + U16 wlangid; //!< language id +} S_usb_language_id; + + +//_____ U S B M A N U F A C T U R E R D E S C R I P T O R _______________ + + +//struct usb_st_manufacturer +typedef struct { + U8 bLength; // size of this descriptor in bytes + U8 bDescriptorType; // STRING descriptor type + U16 wstring[USB_MN_LENGTH];// unicode characters +} S_usb_manufacturer_string_descriptor; + + +//_____ U S B P R O D U C T D E S C R I P T O R _________________________ + + +//struct usb_st_product +typedef struct { + U8 bLength; // size of this descriptor in bytes + U8 bDescriptorType; // STRING descriptor type + U16 wstring[USB_PN_LENGTH];// unicode characters +} S_usb_product_string_descriptor; + + +//_____ U S B S E R I A L N U M B E R D E S C R I P T O R _____________ + + +//struct usb_st_serial_number +typedef struct { + U8 bLength; // size of this descriptor in bytes + U8 bDescriptorType; // STRING descriptor type + U16 wstring[USB_SN_LENGTH];// unicode characters +} S_usb_serial_number; + + +/*_____ U S B I A D _______________________________________________________*/ + +#define DSC_TYPE_IAD 11 + +typedef struct +{ + U8 bLength; + U8 bDescriptorType; + U8 bFirstInterface; + U8 bInterfaceCount; + U8 bFunctionClass; + U8 bFunctionSubClass; + U8 bFunctionProtocol; + U8 iInterface; +} S_usb_interface_association_descriptor; + +/*_____ U S B D E S C R I P T O R __________________________________*/ + +/* RNDIS + Serial Port */ +typedef struct +{ + S_usb_configuration_descriptor cfg; + + S_usb_interface_association_descriptor iad0; + S_usb_interface_descriptor ifc0; + U8 CS1_INTERFACE[19]; + S_usb_endpoint_descriptor ep1; + S_usb_interface_descriptor ifc1; + S_usb_endpoint_descriptor ep2; + S_usb_endpoint_descriptor ep3; + + S_usb_interface_association_descriptor iad1; + S_usb_interface_descriptor ifc2; + U8 CS2_INTERFACE[19]; + S_usb_endpoint_descriptor ep4; + S_usb_interface_descriptor ifc3; + S_usb_endpoint_descriptor ep5; + S_usb_endpoint_descriptor ep6; + +} S_usb_user_configuration_descriptor_composite; + +/* Just RNDIS */ +typedef struct +{ + S_usb_configuration_descriptor cfg; + S_usb_interface_descriptor ifc0; + U8 CS1_INTERFACE[19]; + S_usb_endpoint_descriptor ep1; + S_usb_interface_descriptor ifc1; + S_usb_endpoint_descriptor ep2; + S_usb_endpoint_descriptor ep3; + +} S_usb_user_configuration_descriptor_network; + +/* Mass Storage */ + +typedef struct +{ + S_usb_configuration_descriptor cfg; + S_usb_interface_descriptor ifc0; + S_usb_endpoint_descriptor ep1; + S_usb_endpoint_descriptor ep2; + +} S_usb_user_configuration_descriptor_mass; + + +PGM_VOID_P Usb_get_dev_desc_pointer(void); +U8 Usb_get_dev_desc_length(void); +PGM_VOID_P Usb_get_conf_desc_pointer(void) ; +U8 Usb_get_conf_desc_length(void); + +#endif // _USB_USERCONFIG_H_ + +/** @} */ diff --git a/cpu/avr/dev/usb/usb_drv.c b/cpu/avr/dev/usb/usb_drv.c new file mode 100644 index 000000000..3be5a8911 --- /dev/null +++ b/cpu/avr/dev/usb/usb_drv.c @@ -0,0 +1,333 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_drv.c************************************************************ + * + * \brief + * This file contains the USB driver routines. + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \addtogroup usbdriver + @{ + */ + +//_____ I N C L U D E S ____________________________________________________ + +#include "config.h" +#include "conf_usb.h" +#include "usb_drv.h" + +//_____ M A C R O S ________________________________________________________ + +//_____ D E C L A R A T I O N ______________________________________________ + +#if (USB_DEVICE_FEATURE==DISABLED && USB_HOST_FEATURE==DISABLED) + #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be unabled +#endif + +#if (USB_DEVICE_FEATURE == ENABLED) + +//! usb_configure_endpoint. +//! +//! This function configures an endpoint with the selected type. +//! +//! @param config0 +//! @param config1 +//! +//! @return Is_endpoint_configured(). +//! +U8 usb_config_ep(U8 config0, U8 config1) +{ + Usb_enable_endpoint(); + UECFG0X = config0; + UECFG1X = (UECFG1X & (1<> 1; + } + } + return 0; +} + +//! usb_send_packet. +//! +//! This function moves the data pointed by tbuf to the selected endpoint fifo +//! and sends it through the USB. +//! +//! +//! @param ep_num number of the addressed endpoint +//! @param tbuf address of the first data to send +//! @param data_length number of bytes to send +//! +//! @return remaining_length address of the next U8 to send. +//! +//! Example: +//! usb_send_packet(3,&first_data,0x20); // send packet on the endpoint #3 +//! while(!(Usb_tx_complete)); // wait packet ACK'ed by the Host +//! Usb_clear_tx_complete(); // acknowledge the transmit +//! +//! Note: +//! tbuf is incremented of 'data_length'. +//! +U8 usb_send_packet(U8 ep_num, U8* tbuf, U8 data_length) +{ +U8 remaining_length; + + remaining_length = data_length; + Usb_select_endpoint(ep_num); + while(Is_usb_write_enabled() && (0 != remaining_length)) + { + Usb_write_byte(*tbuf); + remaining_length--; + tbuf++; + } + return remaining_length; +} + +//! usb_read_packet. +//! +//! This function moves the data stored in the selected endpoint fifo to +//! the address specified by *rbuf. +//! +//! +//! @param ep_num number of the addressed endpoint +//! @param rbuf aaddress of the first data to write with the USB data +//! @param data_length number of bytes to read +//! +//! @return remaining_length address of the next U8 to send. +//! +//! Example: +//! while(!(Usb_rx_complete)); // wait new packet received +//! usb_read_packet(4,&first_data,usb_get_nb_byte); // read packet from ep 4 +//! Usb_clear_rx(); // acknowledge the transmit +//! +//! Note: +//! rbuf is incremented of 'data_length'. +//! +U8 usb_read_packet(U8 ep_num, U8* rbuf, U8 data_length) +{ +U8 remaining_length; + + remaining_length = data_length; + Usb_select_endpoint(ep_num); + + while(Is_usb_read_enabled() && (0 != remaining_length)) + { + *rbuf = Usb_read_byte(); + remaining_length--; + rbuf++; + } + return remaining_length; +} + +//! usb_halt_endpoint. +//! +//! This function sends a STALL handshake for the next Host request. A STALL +//! handshake will be send for each next request untill a SETUP or a Clear Halt +//! Feature occurs for this endpoint. +//! +//! @param ep_num number of the addressed endpoint +//! +void usb_halt_endpoint (U8 ep_num) +{ + Usb_select_endpoint(ep_num); + Usb_enable_stall_handshake(); +} + +//! usb_init_device. +//! +//! This function initializes the USB device controller and +//! configures the Default Control Endpoint. +//! +//! @retval FALSE if not Is_usb_id_device() returns FALSE +//! @return usb_configure_endpoint() status +//! +U8 usb_init_device (void) +{ + U8 rv = FALSE; + + Usb_select_device(); + if(Is_usb_id_device()) + { + Usb_select_endpoint(EP_CONTROL); + if(!Is_usb_endpoint_enabled()) + { +#if (USB_LOW_SPEED_DEVICE==DISABLE) + rv = usb_configure_endpoint(EP_CONTROL, \ + TYPE_CONTROL, \ + DIRECTION_OUT, \ + SIZE_64, \ + ONE_BANK, \ + NYET_DISABLED); +#else + rv = usb_configure_endpoint(EP_CONTROL, \ + TYPE_CONTROL, \ + DIRECTION_OUT, \ + SIZE_8, \ + ONE_BANK, \ + NYET_DISABLED); +#endif + + } + } + return rv; +} + +#endif + +//! --------------------------------------------------------- +//! ------------------ HOST --------------------------------- +//! --------------------------------------------------------- + +#if (USB_HOST_FEATURE == ENABLED) + +//! usb_configure_pipe. +//! +//! This function configures a pipe with the selected type. +//! +//! @param config0 +//! @param config1 +//! +//! @return Is_endpoint_configured(). +U8 host_config_pipe(U8 config0, U8 config1) +{ + Host_enable_pipe(); + UPCFG0X = config0; + UPCFG1X = config1; + Host_allocate_memory(); + return (Is_pipe_configured()); +} + +//! host_determine_pipe_size. +//! +//! This function returns the size configuration register value according +//! to the endpint size detected inthe device enumeration process. +//! +//! @retval SIZE_8 pipe size register value. +//! @retval SIZE_16 pipe size register value. +//! @retval SIZE_32 pipe size register value. +//! @retval SIZE_64 pipe size register value. +//! @retval SIZE_128 pipe size register value. +//! @retval SIZE_256 pipe size register value. +//! @retval SIZE_512 pipe size register value. +//! @retval SIZE_1024 pipe size register value. +//! +U8 host_determine_pipe_size(U16 size) +{ + if(size <= 8 ) {return (SIZE_8 );} + else if(size <= 16 ) {return (SIZE_16 );} + else if(size <= 32 ) {return (SIZE_32 );} + else if(size <= 64 ) {return (SIZE_64 );} + else if(size <= 128) {return (SIZE_128 );} + else if(size <= 256) {return (SIZE_256 );} + else if(size <= 512) {return (SIZE_512 );} + else {return (SIZE_1024);} + +} + +//! host_disable_all_pipe. +//! +//! This function disable all pipes for the host controller +//! Usefull to execute upon device disconnection. +//! +void host_disable_all_pipe(void) +{ +U8 i; + for (i=0;i<7;i++) + { + Host_reset_pipe(i); + Host_select_pipe(i); + Host_unallocate_memory(); + Host_disable_pipe(); + } +} + +//! @brief Returns the pipe number that generates a USB communication interrupt +//! +//! This function sould be called only when an interrupt has been detected. Otherwize +//! the return value is incorect +//! +//! @retval MAX_EP_NB + 1 - pipe_number +//! +U8 usb_get_nb_pipe_interrupt(void) +{ +U8 interrupt_flags; +U8 i; + + interrupt_flags = Host_get_pipe_interrupt(); + for(i=0;i< MAX_EP_NB;i++) + { + if (interrupt_flags & (1<> 8), UDPADDL = (Uchar)addr) +#define Usb_write_dpram_byte(val) (UEDATX=val) +#define Usb_read_dpram_byte() (UEDATX) + + //! requests for VBus activation +#define Usb_enable_vbus() (OTGCON |= (1<> 2) + //! returns the number of busy banks +#define Usb_nb_busy_bank() (UESTA0X & MSK_NBUSYBK) + //! tests if at least one bank is busy +#define Is_usb_one_bank_busy() ((UESTA0X & MSK_NBUSYBK) == 0 ? FALSE : TRUE) + //! tests if current endpoint is configured +#define Is_endpoint_configured() ((UESTA0X & (1<> 2) + //! returns the number of the current bank +#define Usb_current_bank() ( UESTA1X & MSK_CURRBK) + + //! clears FIFOCON bit +#define Usb_ack_fifocon() (UEINTX &= ~(1<>4)) + + //! returns the type of the current pipe +#define Host_get_pipe_type() (UPCFG0X>>6) + + //! tests if error occurs on pipe +#define Host_error_status() (UPERRX & MSK_ERROR) + //! acks all pipe error +#define Host_ack_all_errors() (UPERRX = 0x00) + + //! Enable pipe end transmission interrupt +#define Host_enable_transmit_interrupt() (UPIENX |= (1<>8)&0x00FF) \ + | (((x)<<8)&0xFF00) \ + ) + + +//! Usb_write_word_enum_struc +//! This macro help to fill the U16 fill in USB enumeration struct. +//! Depending on the CPU architecture, the macro swap or not the nibbles +//! +//! @param x (U16) the 16 bit word to be written +//! +//! @return (U16) the 16 bit word written +#if !defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN) + #error YOU MUST Define the Endian Type of target: LITTLE_ENDIAN or BIG_ENDIAN +#endif +#ifdef LITTLE_ENDIAN + #define Usb_write_word_enum_struc(x) (x) +#else //BIG_ENDIAN + #define Usb_write_word_enum_struc(x) (wSWAP(x)) +#endif + + +//_____ D E C L A R A T I O N ______________________________________________ + +U8 usb_config_ep (U8, U8); +U8 usb_select_enpoint_interrupt (void); +U8 usb_send_packet (U8 , U8*, U8); +U8 usb_read_packet (U8 , U8*, U8); +void usb_halt_endpoint (U8); +U8 usb_init_device (void); + +U8 host_config_pipe (U8, U8); +U8 host_determine_pipe_size (U16); +void host_disable_all_pipe (void); +U8 usb_get_nb_pipe_interrupt (void); + +#endif // _USB_DRV_H_ + +/** @} */ diff --git a/cpu/avr/dev/usb/usb_specific_request.c b/cpu/avr/dev/usb/usb_specific_request.c new file mode 100644 index 000000000..0f873935f --- /dev/null +++ b/cpu/avr/dev/usb/usb_specific_request.c @@ -0,0 +1,360 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * USB Protocol-Specific Requests + * + * \addtogroup usbtask + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 Colin O'Flynn + Copyright (c) Atmel Corporation 2008 + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + + +//_____ I N C L U D E S ____________________________________________________ + +#include "radio.h" +#include "contiki.h" +#include "config.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "rndis/rndis_protocol.h" +#include "serial/uart_usb_lib.h" +#include "storage/ctrl_access.h" +#include "uip.h" +#include +#include + +//_____ M A C R O S ________________________________________________________ + +//_____ D E F I N I T I O N ________________________________________________ +bit ms_multiple_drive; +//_____ P R I V A T E D E C L A R A T I O N ______________________________ + +extern PGM_VOID_P pbuffer; +extern U8 data_to_transfer; + +//_____ D E C L A R A T I O N ______________________________________________ + + + +//! This function is called by the standard usb read request function when +//! the Usb request is not supported. This function returns TRUE when the +//! request is processed. This function returns FALSE if the request is not +//! supported. In this case, a STALL handshake will be automatically +//! sent by the standard usb read request function. +//! +//! @param type Not used +//! @param request Read request type +//! +//! @retval FALSE if unknown read type +//! @retval TRUE if request type is processed +//! +Bool usb_user_read_request(U8 type, U8 request) +{ + U16 wLength; + + //Both protocols have two bytes we throw away + Usb_read_byte(); + Usb_read_byte(); + + switch(request) + { + case SEND_ENCAPSULATED_COMMAND: + Usb_read_byte();//wIndex LSB + Usb_read_byte();//wIndex MSB + + LSB(wLength) = Usb_read_byte(); + MSB(wLength) = Usb_read_byte(); + return send_encapsulated_command(wLength); + break; + + case GET_ENCAPSULATED_COMMAND: + Usb_read_byte();//wIndex LSB + Usb_read_byte();//wIndex MSB + + LSB(wLength) = Usb_read_byte(); + MSB(wLength) = Usb_read_byte(); + return get_encapsulated_command(); + break; + + + case MASS_STORAGE_RESET: + Usb_ack_receive_setup(); + Usb_send_control_in(); + return TRUE; + break; + + + case GET_MAX_LUN: + Usb_ack_receive_setup(); + Usb_write_byte( (get_nb_lun()-1) ); + Usb_send_control_in(); + ms_multiple_drive = 1; + return TRUE; + break; + + + /* We don't have a real serial port - so these aren't applicable. We + advertise that we support nothing, so shouldn't get them anyway */ + /* case GET_LINE_CODING: + cdc_get_line_coding(); + return TRUE; + break; + + case SET_LINE_CODING: + cdc_set_line_coding(); + return TRUE; + break; + + case SET_CONTROL_LINE_STATE: + cdc_set_control_line_state(); + return TRUE; + break; + */ + default: + break; + + } + + return FALSE; +} + +//! usb_user_get_descriptor. +//! +//! @brief This function returns the size and the pointer on a user information +//! structure +//! +//! @param type descriptor type +//! @param string descriptor ID +//! +//! @retval FALSE +//! +Bool usb_user_get_descriptor(U8 type, U8 string) +{ + switch(type) + { + case STRING_DESCRIPTOR: + switch (string) + { + case LANG_ID: + data_to_transfer = sizeof (usb_user_language_id); + pbuffer = &(usb_user_language_id.bLength); + return TRUE; + break; + case MAN_INDEX: + data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor); + pbuffer = &(usb_user_manufacturer_string_descriptor.bLength); + return TRUE; + break; + case PROD_INDEX: + data_to_transfer = sizeof (usb_user_product_string_descriptor); + pbuffer = &(usb_user_product_string_descriptor.bLength); + return TRUE; + break; + case SN_INDEX: + data_to_transfer = sizeof (usb_user_serial_number); + pbuffer = &(usb_user_serial_number.bLength); + return TRUE; + break; + default: + return FALSE; + } + default: + return FALSE; + } + + return FALSE; +} + +//! usb_user_endpoint_init. +//! +//! @brief This function configures the endpoints. +//! +//! @param conf_nb Not used +void usb_user_endpoint_init(U8 conf_nb) +{ + + /* If we use RNDIS endpoints */ + if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { + + usb_configure_endpoint(INT_EP, \ + TYPE_INTERRUPT, \ + DIRECTION_IN, \ + SIZE_64, \ + ONE_BANK, \ + NYET_ENABLED); + + usb_configure_endpoint(TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + + usb_configure_endpoint(RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + + } + + /* If we use virtual comm port (VCP) endpoints */ + if (usb_mode == rndis_debug) { + usb_configure_endpoint(VCP_INT_EP, \ + TYPE_INTERRUPT, \ + DIRECTION_IN, \ + SIZE_32, \ + ONE_BANK, \ + NYET_ENABLED); + + usb_configure_endpoint(VCP_TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_32, \ + TWO_BANKS, \ + NYET_ENABLED); + + usb_configure_endpoint(VCP_RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_32, \ + TWO_BANKS, \ + NYET_ENABLED); + } + + /* If we use mass storage endpoints */ + if (usb_mode == mass_storage) { + + usb_configure_endpoint(MS_IN_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_64, \ + ONE_BANK, \ + NYET_ENABLED); + + usb_configure_endpoint(MS_OUT_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_64, \ + ONE_BANK, \ + NYET_ENABLED); + } + + + + if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { + Usb_reset_endpoint(INT_EP); + Usb_reset_endpoint(TX_EP); + Usb_reset_endpoint(RX_EP); + } + + if (usb_mode == rndis_debug){ + Usb_reset_endpoint(VCP_INT_EP); + Usb_reset_endpoint(VCP_TX_EP); + Usb_reset_endpoint(VCP_RX_EP); + } + + if (usb_mode == mass_storage) { + Usb_reset_endpoint(VCP_TX_EP); + Usb_reset_endpoint(VCP_RX_EP); + } + +} + + +/******************** Virtual Serial Port ************************/ + +extern S_line_coding line_coding; + +//! cdc_get_line_coding. +//! +//! @brief This function manages reception of line coding parameters (baudrate...). +//! +void cdc_get_line_coding(void) +{ + Usb_ack_receive_setup(); + Usb_write_byte(LSB0(line_coding.dwDTERate)); + Usb_write_byte(LSB1(line_coding.dwDTERate)); + Usb_write_byte(LSB2(line_coding.dwDTERate)); + Usb_write_byte(LSB3(line_coding.dwDTERate)); + Usb_write_byte(line_coding.bCharFormat); + Usb_write_byte(line_coding.bParityType); + Usb_write_byte(line_coding.bDataBits); + + Usb_send_control_in(); + while(!(Is_usb_read_control_enabled())); + //Usb_clear_tx_complete(); + + while(!Is_usb_receive_out()); + Usb_ack_receive_out(); +} + + +//! cdc_set_line_coding. +//! +//! @brief This function manages reception of line coding parameters (baudrate...). +//! +void cdc_set_line_coding (void) +{ + Usb_ack_receive_setup(); + while (!(Is_usb_receive_out())); + LSB0(line_coding.dwDTERate) = Usb_read_byte(); + LSB1(line_coding.dwDTERate) = Usb_read_byte(); + LSB2(line_coding.dwDTERate) = Usb_read_byte(); + LSB3(line_coding.dwDTERate) = Usb_read_byte(); + line_coding.bCharFormat = Usb_read_byte(); + line_coding.bParityType = Usb_read_byte(); + line_coding.bDataBits = Usb_read_byte(); + Usb_ack_receive_out(); + + Usb_send_control_in(); // send a ZLP for STATUS phase + while(!(Is_usb_read_control_enabled())); +} + +//! cdc_set_control_line_state. +//! +//! @brief This function manages the SET_CONTROL_LINE_LINE_STATE CDC request. +//! +//! Note: Can manage hardware flow control here... +//! +void cdc_set_control_line_state (void) +{ + Usb_ack_receive_setup(); + Usb_send_control_in(); + while(!(Is_usb_read_control_enabled())); +} + diff --git a/cpu/avr/dev/usb/usb_specific_request.h b/cpu/avr/dev/usb/usb_specific_request.h new file mode 100644 index 000000000..14fdb81e5 --- /dev/null +++ b/cpu/avr/dev/usb/usb_specific_request.h @@ -0,0 +1,89 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * This file contains the user callback functions corresponding to the + * application. + * + * \addtogroup usbtask + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _USB_SPECIFIC_REQUEST_H_ +#define _USB_SPECIFIC_REQUEST_H_ + +/*_____ I N C L U D E S ____________________________________________________*/ + +#include "config.h" + +/*_____ M A C R O S ________________________________________________________*/ + + +#define SEND_ENCAPSULATED_COMMAND 0x00 +#define GET_ENCAPSULATED_COMMAND 0x01 +#define GET_LINE_CODING 0x21 +#define SET_LINE_CODING 0x20 +#define SET_CONTROL_LINE_STATE 0x22 +#define SEND_BREAK 0x23 +#define MASS_STORAGE_RESET 0xFF +#define GET_MAX_LUN 0xFE + +extern FLASH S_usb_device_descriptor usb_dev_desc_composite; +extern FLASH S_usb_device_descriptor usb_dev_desc_network; +extern FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite; +extern FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network; +extern FLASH S_usb_device_qualifier_descriptor usb_qual_desc; +extern FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor; +extern FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor; +extern FLASH S_usb_serial_number usb_user_serial_number; +extern FLASH S_usb_language_id usb_user_language_id; + + + +/*_____ D E F I N I T I O N ________________________________________________*/ +Bool usb_user_read_request(U8, U8); +Bool usb_user_get_descriptor(U8 , U8); +void usb_user_endpoint_init(U8); + +void cdc_get_line_coding(); +void cdc_set_line_coding(); +void cdc_set_control_line_state (void); + +extern usb_mode_t usb_mode; + +// ____ T Y P E D E F I N I T I O N _______________________________________ + +#endif // _USB_SPECIFIC_REQUEST_H_ + diff --git a/cpu/avr/dev/usb/usb_standard_request.c b/cpu/avr/dev/usb/usb_standard_request.c new file mode 100644 index 000000000..fee58f6f7 --- /dev/null +++ b/cpu/avr/dev/usb/usb_standard_request.c @@ -0,0 +1,551 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * This file contains the USB endpoint 0 management routines corresponding to + * the standard enumeration process (refer to chapter 9 of the USB + * specification. + * This file calls routines of the usb_specific_request.c file for non-standard + * request management. + * The enumeration parameters (descriptor tables) are contained in the + * usb_descriptors.c file. + * + * \addtogroup usbdriver + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +//_____ I N C L U D E S ____________________________________________________ + +#include "config.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" + +//_____ M A C R O S ________________________________________________________ + + +//_____ D E F I N I T I O N ________________________________________________ + +//_____ P R I V A T E D E C L A R A T I O N ______________________________ + +static void usb_get_descriptor( void); +static void usb_set_address( void); +static void usb_set_configuration(void); +static void usb_clear_feature( void); +static void usb_set_feature( void); +static void usb_get_status( void); +static void usb_get_configuration(void); +static void usb_get_interface (void); +static void usb_set_interface (void); + + +//_____ D E C L A R A T I O N ______________________________________________ + +static bit zlp; +static U8 endpoint_status[NB_ENDPOINTS]; + +#ifdef AVRGCC + PGM_VOID_P pbuffer; +#else + U8 FLASH *pbuffer; +#endif + U8 data_to_transfer; + + U16 wInterface; + +static U8 bmRequestType; + + U8 usb_configuration_nb; + + usb_mode_t usb_mode = rndis_debug; + +extern bit usb_connected; +extern FLASH S_usb_device_descriptor usb_user_device_descriptor_network; +extern FLASH S_usb_user_configuration_descriptor_network usb_user_configuration_descriptor_network; +extern FLASH S_usb_device_descriptor usb_user_device_descriptor_composite; +extern FLASH S_usb_user_configuration_descriptor_composite usb_user_configuration_descriptor_composite; + +//! usb_process_request. +//! +//! @brief This function reads the SETUP request sent to the default control endpoint +//! and calls the appropriate function. When exiting of the usb_read_request +//! function, the device is ready to manage the next request. +//! +//! @note list of supported requests: +//! GET_DESCRIPTOR +//! GET_CONFIGURATION +//! SET_ADDRESS +//! SET_CONFIGURATION +//! CLEAR_FEATURE +//! SET_FEATURE +//! GET_STATUS +//! +void usb_process_request(void) +{ + U8 bmRequest; + + bmRequestType = Usb_read_byte(); + bmRequest = Usb_read_byte(); + + switch (bmRequest) + { + case GET_DESCRIPTOR: + if (0x80 == bmRequestType) { usb_get_descriptor(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case GET_CONFIGURATION: + if (0x80 == bmRequestType) { usb_get_configuration(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case SET_ADDRESS: + if (0x00 == bmRequestType) { usb_set_address(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case SET_CONFIGURATION: + if (0x00 == bmRequestType) { usb_set_configuration(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case CLEAR_FEATURE: + if (0x02 >= bmRequestType) { usb_clear_feature(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case SET_FEATURE: + if (0x02 >= bmRequestType) { usb_set_feature(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case GET_STATUS: + if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) + { usb_get_status(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + case GET_INTERFACE: + if (bmRequestType == 0x81) { usb_get_interface(); } + else { usb_user_read_request(bmRequestType, bmRequest); } + break; + + + case SET_INTERFACE: + if (bmRequestType == 0x01) {usb_set_interface();} + break; + + case SET_DESCRIPTOR: + case SYNCH_FRAME: + default: //!< un-supported request => call to user read request + if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) + { + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + break; + } +} + +//! usb_set_address. +//! +//! This function manages the SET ADDRESS request. When complete, the device +//! will filter the requests using the new address. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_set_address(void) +{ + Usb_configure_address(Usb_read_byte()); + + Usb_ack_receive_setup(); + + Usb_send_control_in(); //!< send a ZLP for STATUS phase + while(!Is_usb_in_ready()); //!< waits for status phase done + //!< before using the new address + Usb_enable_address(); +} + +//! usb_set_configuration. +//! +//! This function manages the SET CONFIGURATION request. If the selected +//! configuration is valid, this function call the usb_user_endpoint_init() +//! function that will configure the endpoints following the configuration +//! number. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_set_configuration( void ) +{ +U8 configuration_number; + + configuration_number = Usb_read_byte(); + + if (configuration_number <= NB_CONFIGURATION) + { + Usb_ack_receive_setup(); + usb_configuration_nb = configuration_number; + } + else + { + //!< keep that order (set StallRq/clear RxSetup) or a + //!< OUT request following the SETUP may be acknowledged + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + + Usb_send_control_in(); //!< send a ZLP for STATUS phase + + usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration + Usb_set_configuration_action(); +} + +//! usb_get_descriptor. +//! +//! This function manages the GET DESCRIPTOR request. The device descriptor, +//! the configuration descriptor and the device qualifier are supported. All +//! other descriptors must be supported by the usb_user_get_descriptor +//! function. +//! Only 1 configuration is supported. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_get_descriptor(void) +{ +U8 LSBwLength, MSBwLength; +U8 descriptor_type ; +U8 string_type ; +U8 dummy; +U8 nb_byte; + + zlp = FALSE; /* no zero length packet */ + string_type = Usb_read_byte(); /* read LSB of wValue */ + descriptor_type = Usb_read_byte(); /* read MSB of wValue */ + + dummy = Usb_read_byte(); //!< don't care of wIndex field + dummy = Usb_read_byte(); + LSBwLength = Usb_read_byte(); //!< read wLength + MSBwLength = Usb_read_byte(); + + switch (descriptor_type) + { + case DEVICE_DESCRIPTOR: + data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); + pbuffer = Usb_get_dev_desc_pointer(); + break; + case CONFIGURATION_DESCRIPTOR: + data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor); + pbuffer = Usb_get_conf_desc_pointer(); + break; + default: + if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) + { + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + break; + } + + + Usb_ack_receive_setup() ; //!< clear the receive setup flag + + if ((LSBwLength > data_to_transfer) || (MSBwLength)) + { + if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } + else { zlp = FALSE; } //!< no need of zero length packet + + LSBwLength = data_to_transfer; + MSBwLength = 0x00; + } + else + { + data_to_transfer = LSBwLength; //!< send only requested number of data + } + + + while((data_to_transfer != 0) && (!Is_usb_receive_out())) + { + while(!Is_usb_read_control_enabled()); + + nb_byte=0; + while(data_to_transfer != 0) //!< Send data until necessary + { + if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size + { + break; + } + +//#ifndef AVRGCC +// Usb_write_byte(*pbuffer++); +//#else // AVRGCC does not support point to PGM space + //#warning AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory + Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); +//#endif + data_to_transfer --; + + } + Usb_send_control_in(); + } + + if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host + if(zlp == TRUE) + { + while(!Is_usb_read_control_enabled()); + Usb_send_control_in(); + } + + while(!Is_usb_receive_out()); + Usb_ack_receive_out(); +} + +//! usb_get_configuration. +//! +//! This function manages the GET CONFIGURATION request. The current +//! configuration number is returned. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_get_configuration(void) +{ + Usb_ack_receive_setup(); + + Usb_write_byte(usb_configuration_nb); + Usb_ack_in_ready(); + + while( !Is_usb_receive_out() ); + Usb_ack_receive_out(); +} + +//! usb_get_status. +//! +//! This function manages the GET STATUS request. The device, interface or +//! endpoint status is returned. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_get_status(void) +{ +U8 wIndex; +U8 dummy; + + dummy = Usb_read_byte(); //!< dummy read + dummy = Usb_read_byte(); //!< dummy read + wIndex = Usb_read_byte(); + + switch(bmRequestType) + { + case REQUEST_DEVICE_STATUS: Usb_ack_receive_setup(); + Usb_write_byte(DEVICE_STATUS); + break; + + case REQUEST_INTERFACE_STATUS: Usb_ack_receive_setup(); + Usb_write_byte(INTERFACE_STATUS); + break; + + case REQUEST_ENDPOINT_STATUS: Usb_ack_receive_setup(); + wIndex = wIndex & MSK_EP_DIR; + Usb_write_byte(endpoint_status[wIndex]); + break; + default: + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + + Usb_write_byte(0x00); + Usb_send_control_in(); + + while( !Is_usb_receive_out() ); + Usb_ack_receive_out(); +} + +//! usb_set_feature. +//! +//! This function manages the SET FEATURE request. The USB test modes are +//! supported by this function. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_set_feature(void) +{ +U8 wValue; +U8 wIndex; +U8 dummy; + + if (bmRequestType == INTERFACE_TYPE) + { + //!< keep that order (set StallRq/clear RxSetup) or a + //!< OUT request following the SETUP may be acknowledged + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + else if (bmRequestType == ENDPOINT_TYPE) + { + wValue = Usb_read_byte(); + dummy = Usb_read_byte(); //!< dummy read + + if (wValue == FEATURE_ENDPOINT_HALT) + { + wIndex = (Usb_read_byte() & MSK_EP_DIR); + + if (wIndex == EP_CONTROL) + { + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + + Usb_select_endpoint(wIndex); + if(Is_usb_endpoint_enabled()) + { + Usb_enable_stall_handshake(); + Usb_select_endpoint(EP_CONTROL); + endpoint_status[wIndex] = 0x01; + Usb_ack_receive_setup(); + Usb_send_control_in(); + } + else + { + Usb_select_endpoint(EP_CONTROL); + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + } + else + { + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + } +} + +//! usb_clear_feature. +//! +//! This function manages the SET FEATURE request. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_clear_feature(void) +{ +U8 wValue; +U8 wIndex; +U8 dummy; + + if (bmRequestType == ZERO_TYPE) + { + //!< keep that order (set StallRq/clear RxSetup) or a + //!< OUT request following the SETUP may be acknowledged + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + else if (bmRequestType == INTERFACE_TYPE) + { + //!< keep that order (set StallRq/clear RxSetup) or a + //!< OUT request following the SETUP may be acknowledged + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + else if (bmRequestType == ENDPOINT_TYPE) + { + wValue = Usb_read_byte(); + dummy = Usb_read_byte(); //!< dummy read + + if (wValue == FEATURE_ENDPOINT_HALT) + { + wIndex = (Usb_read_byte() & MSK_EP_DIR); + + Usb_select_endpoint(wIndex); + if(Is_usb_endpoint_enabled()) + { + if(wIndex != EP_CONTROL) + { + Usb_disable_stall_handshake(); + Usb_reset_endpoint(wIndex); + Usb_reset_data_toggle(); + } + Usb_select_endpoint(EP_CONTROL); + endpoint_status[wIndex] = 0x00; + Usb_ack_receive_setup(); + Usb_send_control_in(); + } + else + { + Usb_select_endpoint(EP_CONTROL); + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + } + else + { + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); + return; + } + } +} + +//! usb_get_interface. +//! +//! TThis function manages the GET_INTERFACE request. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_get_interface (void) +{ + Usb_enable_stall_handshake(); + Usb_ack_receive_setup(); +} + +//! usb_set_interface. +//! +//! TThis function manages the SET_INTERFACE request. +//! +//! @warning Code:xx bytes (function code length) +//! +void usb_set_interface (void) +{ + Usb_ack_receive_setup(); + Usb_send_control_in(); //!< send a ZLP for STATUS phase + while(!Is_usb_in_ready()); +} diff --git a/cpu/avr/dev/usb/usb_standard_request.h b/cpu/avr/dev/usb/usb_standard_request.h new file mode 100644 index 000000000..ef60a4aa3 --- /dev/null +++ b/cpu/avr/dev/usb/usb_standard_request.h @@ -0,0 +1,88 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_standard_request.h ************************************************* + * + * \brief + * This file contains the USB endpoint 0 management routines corresponding to + * the standard enumeration process (refer to chapter 9 of the USB + * specification. + * This file calls routines of the usb_specific_request.c file for non-standard + * request management. + * The enumeration parameters (descriptor tables) are contained in the + * usb_descriptors.c file. + * + * \addtogroup usbdriver + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _USB_ENUM_H_ +#define _USB_ENUM_H_ + +//_____ I N C L U D E S ____________________________________________________ + +#include "usb_task.h" +#include "usb_descriptors.h" + +//_____ M A C R O S ________________________________________________________ + +//_____ S T A N D A R D D E F I N I T I O N S ___________________________ + + // Device State +#define ATTACHED 0 +#define POWERED 1 +#define DEFAULT 2 +#define ADDRESSED 3 +#define CONFIGURED 4 +#define SUSPENDED 5 + +#define USB_CONFIG_ATTRIBUTES_RESERVED 0x80 +#define USB_CONFIG_BUSPOWERED (USB_CONFIG_ATTRIBUTES_RESERVED | 0x00) +#define USB_CONFIG_SELFPOWERED (USB_CONFIG_ATTRIBUTES_RESERVED | 0x40) +#define USB_CONFIG_REMOTEWAKEUP (USB_CONFIG_ATTRIBUTES_RESERVED | 0x20) + +//_____ D E C L A R A T I O N ______________________________________________ + + //! @brief Returns true when device connected and correctly enumerated with an host. + //! The device high level application should tests this before performing any applicative requests +#define Is_device_enumerated() ((usb_configuration_nb!=0) ? TRUE : FALSE) +#define Is_device_not_enumerated() ((usb_configuration_nb!=0) ? FALSE : TRUE) + + +void usb_process_request( void); + +extern U8 usb_configuration_nb; + + +#endif // _USB_ENUM_H_ + diff --git a/cpu/avr/dev/usb/usb_task.c b/cpu/avr/dev/usb/usb_task.c new file mode 100644 index 000000000..f3952d5e9 --- /dev/null +++ b/cpu/avr/dev/usb/usb_task.c @@ -0,0 +1,375 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file usb_task.c ********************************************************************* + * + * \brief + * This file manages the USB task either device/host or both. + * + * The USB task selects the correct USB task (usb_device task or usb_host task + * to be executed depending on the current mode available. + * + * According to USB_DEVICE_FEATURE and USB_HOST_FEATURE value (located in conf_usb.h file) + * The usb_task can be configured to support USB DEVICE mode or USB Host mode or both + * for a dual role device application. + * + * This module also contains the general USB interrupt subroutine. This subroutine is used + * to detect asynchronous USB events. + * + * Note: + * - The usb_task belongs to the scheduler, the usb_device_task and usb_host do not, they are called + * from the general usb_task + * - See conf_usb.h file for more details about the configuration of this module + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + ******************************************************************************/ +/* Copyright (c) 2008 Colin O'Flynn + Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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. +*/ + +/** + \ingroup usbstick + \defgroup usbtask USB Contiki Task + @{ +*/ + +//_____ I N C L U D E S ___________________________________________________ + +#include "contiki.h" +#include "config.h" +#include "conf_usb.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "pll_drv.h" +#include "usb_task.h" +#include "rndis/rndis_protocol.h" +#include "rndis/rndis_task.h" + +PROCESS(usb_process, "USB process"); + +#ifndef USE_USB_PADS_REGULATOR + #error "USE_USB_PADS_REGULATOR" should be defined as ENABLE or DISABLE in conf_usb.h file +#endif +#include + +//_____ M A C R O S ________________________________________________________ + +#ifndef LOG_STR_CODE +#define LOG_STR_CODE(str) +#else +U8 code log_device_disconnect[]="Device Disconnected"; +U8 code log_id_change[]="Pin Id Change"; +#endif + +#define USB_EVENT 0x2F /* Contiki event number - I just made this one up?*/ + +//_____ D E F I N I T I O N S ______________________________________________ + +//! +//! Public : U16 g_usb_event +//! usb_connected is used to store USB events detected upon +//! USB general interrupt subroutine +//! Its value is managed by the following macros (See usb_task.h file) +//! Usb_send_event(x) +//! Usb_ack_event(x) +//! Usb_clear_all_event() +//! Is_usb_event(x) +//! Is_not_usb_event(x) +volatile uint16_t g_usb_event=0; + + +//! +//! Public : (bit) usb_connected +//! usb_connected is set to TRUE when VBUS has been detected +//! usb_connected is set to FALSE otherwise +//! Used with USB_DEVICE_FEATURE == ENABLED only +//!/ +bit usb_connected; + +//! +//! Public : (U8) usb_configuration_nb +//! Store the number of the USB configuration used by the USB device +//! when its value is different from zero, it means the device mode is enumerated +//! Used with USB_DEVICE_FEATURE == ENABLED only +//!/ +extern U8 usb_configuration_nb; + + +//_____ D E C L A R A T I O N S ____________________________________________ + + + +/** + * \brief Spare function to handle sleep mode. + */ +extern void suspend_action(void) +{ + Enable_interrupt(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_mode(); +} + +/** + * \brief This function initializes the USB device controller + * + * This function enables the USB controller and init the USB interrupts. + * The aim is to allow the USB connection detection in order to send + * the appropriate USB event to the operating mode manager. + * Start device function is executed once VBUS connection has been detected + * either by the VBUS change interrupt either by the VBUS high level + */ +void usb_start_device (void) +{ + Pll_start_auto(); + Wait_pll_ready(); + Usb_unfreeze_clock(); + Usb_enable_vbus_interrupt(); + Usb_enable_reset_interrupt(); + usb_init_device(); // configure the USB controller EP0 + Usb_attach(); +} + + +/** + * \brief USB Poll Handler + * + * This routine is repetively called, and deals with things such as new SETUP transfers + * on the control endpoint + */ +static void pollhandler(void) +{ + + + //RNDIS needs a delay where this isn't called, as it will switch endpoints + //and screw up the data transfers + if (!usb_busy) { + + /* Check for setup packets */ + Usb_select_endpoint(EP_CONTROL); + if (Is_usb_receive_setup()) { + usb_process_request(); + } + + /* The previous call might have requested we send + out something to the RNDIS interrupt endpoint */ + if (schedule_interrupt) { + Usb_select_endpoint(INT_EP); + + //Linux is a bunch of lies, and won't read + //the interrupt endpoint. Hence if this isn't ready just exit + //while(!Is_usb_write_enabled()); + + if (Is_usb_write_enabled()) { + + // Only valid interrupt is: + // 0x00000001 0x00000000 + // + Usb_write_byte(0x01); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + + //Send back + Usb_send_in(); + + schedule_interrupt = 0; + } + } + + } + + + /* Continue polling */ + process_poll(&usb_process); + +} +/** + * \brief USB Process + * + * The actual USB process, deals with USB events such as resets, and being plugged in + * or unplugged. A seperate polling routine is setup, which continously checks for + * things such as SETUP packets on the control interface. They must be responded to + * very quickly, hence the need for a polling process. + */ +PROCESS_THREAD(usb_process, ev, data_proc) +{ + +PROCESS_POLLHANDLER(pollhandler()); + +PROCESS_BEGIN(); + + + /*** USB initilization ***/ + + #if (USE_USB_PADS_REGULATOR==ENABLE) // Otherwise assume USB PADs regulator is not used + Usb_enable_regulator(); + #endif + + Usb_force_device_mode(); + + /* Init USB controller */ + Enable_interrupt(); + Usb_disable(); + Usb_enable(); + Usb_select_device(); +#if (USB_LOW_SPEED_DEVICE==ENABLE) + Usb_low_speed_mode(); +#endif + Usb_enable_vbus_interrupt(); + Enable_interrupt(); + + + /* Ensure pollhandler is called to start it off */ + process_poll(&usb_process); + + + /*** Begin actual USB process ***/ + while(1) + { + + if (Is_usb_vbus_high()&& usb_connected==FALSE) + { + usb_connected = TRUE; + usb_start_device(); + Usb_vbus_on_action(); + } + + if(Is_usb_event(EVT_USB_RESET)) + { + Usb_ack_event(EVT_USB_RESET); + Usb_reset_endpoint(0); + usb_configuration_nb=0; + } + + + PROCESS_WAIT_EVENT_UNTIL(ev == USB_EVENT); + }//while(1) + +PROCESS_END(); + +} + + +//! @brief USB general interrupt subroutine +//! +//! This function is called each time a USB interrupt occurs. +//! The following USB DEVICE events are taken in charge: +//! - VBus On / Off +//! - Start Of Frame +//! - Suspend +//! - Wake-Up +//! - Resume +//! - Reset +//! - Start of frame +//! +//! For each event, the user can launch an action by completing +//! the associate define (See conf_usb.h file to add action upon events) +//! +//! Note: Only interrupts events that are enabled are processed +//! + +ISR(USB_GEN_vect) +{ + + process_post(&usb_process, USB_EVENT, NULL); + + //- VBUS state detection + if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) + { + Usb_ack_vbus_transition(); + if (Is_usb_vbus_high()) + { + usb_connected = TRUE; + Usb_vbus_on_action(); + Usb_send_event(EVT_USB_POWERED); + Usb_enable_reset_interrupt(); + usb_start_device(); + Usb_attach(); + } + else + { + Usb_vbus_off_action(); + usb_connected = FALSE; + usb_configuration_nb = 0; + Usb_send_event(EVT_USB_UNPOWERED); + } + } + // - Device start of frame received + if (Is_usb_sof() && Is_sof_interrupt_enabled()) + { + Usb_ack_sof(); + Usb_sof_action(); + } + // - Device Suspend event (no more USB activity detected) + if (Is_usb_suspend() && Is_suspend_interrupt_enabled()) + { + Usb_ack_suspend(); + Usb_enable_wake_up_interrupt(); + Usb_ack_wake_up(); // clear wake up to detect next event + Usb_freeze_clock(); + Usb_send_event(EVT_USB_SUSPEND); + Usb_suspend_action(); + } + // - Wake up event (USB activity detected): Used to resume + if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) + { + Usb_unfreeze_clock(); + Usb_ack_wake_up(); + Usb_disable_wake_up_interrupt(); + Usb_wake_up_action(); + Usb_send_event(EVT_USB_WAKE_UP); + } + // - Resume state bus detection + if (Is_usb_resume() && Is_resume_interrupt_enabled()) + { + Usb_disable_wake_up_interrupt(); + Usb_ack_resume(); + Usb_disable_resume_interrupt(); + Usb_resume_action(); + Usb_send_event(EVT_USB_RESUME); + } + // - USB bus reset detection + if (Is_usb_reset()&& Is_reset_interrupt_enabled()) + { + Usb_ack_reset(); + usb_init_device(); + Usb_reset_action(); + Usb_send_event(EVT_USB_RESET); + } + +} + +/** @} */ + diff --git a/cpu/avr/dev/usb/usb_task.h b/cpu/avr/dev/usb/usb_task.h new file mode 100644 index 000000000..8b8cfa3cb --- /dev/null +++ b/cpu/avr/dev/usb/usb_task.h @@ -0,0 +1,195 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ + + +/*! \file usb_task.h ********************************************************************* + * + * \brief + * This file manages the USB task either device/host or both. + * + * The USB task selects the correct USB task (usb_device task or usb_host task + * to be executed depending on the current mode available. + * + * According to USB_DEVICE_FEATURE and USB_HOST_FEATURE value (located in conf_usb.h file) + * The usb_task can be configured to support USB DEVICE mode or USB Host mode or both + * for a dual role device application. + * + * This module also contains the general USB interrupt subroutine. This subroutine is used + * to detect asynchronous USB events. + * + * Note: + * - The usb_task belongs to the scheduler, the usb_device_task and usb_host do not, they are called + * from the general usb_task + * - See conf_usb.h file for more details about the configuration of this module + * + * \addtogroup usbstick + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 _USB_TASK_H_ +#define _USB_TASK_H_ + +/** + \ingroup usbstick + \defgroup usbdriver USB Driver + @{ +*/ + +//_____ I N C L U D E S ____________________________________________________ + + +//_____ M A C R O S ________________________________________________________ + +//! \name USB Events +//! @{ + +//! Send event +#define Usb_send_event(x) (g_usb_event |= (1<