committed by
Scott Lahteine
149 changed files with 12940 additions and 694 deletions
@ -0,0 +1,31 @@ |
|||
==== USB HOST SHIELD 3.0 LIBRARY ==== |
|||
|
|||
The lib-uhs3/ folder contains a subset of the files from the USB Host Shield |
|||
3.0 library: |
|||
|
|||
https://github.com/felis/UHS30 |
|||
|
|||
|
|||
==== LICENSE SUMMARY ==== |
|||
|
|||
Source Path: Repository: License: |
|||
------------ ----------- -------- |
|||
usb_flashdrive/lib github.com/felis/UHS30 GPLv2 or later |
|||
|
|||
|
|||
==== MARLIN INTEGRATION WORK ==== |
|||
|
|||
All additional work done to integrate USB into Marlin was performed by |
|||
AlephObjects, Inc. and is licensed under the GPLv3. |
|||
|
|||
This version of UHS3 has been modified for better compatibility with Marlin. |
|||
The upstream version of UHS 3.0 runs a frame timer interrupt every 1 ms to |
|||
handle device polling. This timer interrupt interferes with Marlin's stepper |
|||
IRQ, so the flag USB_HOST_MANUAL_POLL has been added to move the polling to |
|||
the idle task. Additional logic was added to disable and enable the frame |
|||
IRQ. |
|||
|
|||
SKIP_PAGE3F and USB_NO_TEST_UNIT_READY were added to work around bugs with |
|||
certain devices. |
|||
|
|||
-- marcio@alephobjects.com |
@ -0,0 +1,249 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(__UHS_BULK_STORAGE_H__) |
|||
#define __UHS_BULK_STORAGE_H__ |
|||
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Define any of these options at the top of your sketch to override
|
|||
// the defaults contained herewith. Do NOT do modifications here.
|
|||
// Macro | Settings and notes | Default
|
|||
// -----------------------------------------+-----------------------+-----------
|
|||
// | 1 to 8 |
|
|||
// | Each LUN needs |
|
|||
// MASS_MAX_SUPPORTED_LUN | ~13 bytes to be able | 8
|
|||
// | to track the state of |
|
|||
// | each unit. |
|
|||
// -----------------------------------------+-----------------------+-----------
|
|||
// | Just define to use. |
|
|||
// DEBUG_PRINTF_EXTRA_HUGE_UHS_BULK_STORAGE | works only if extra |
|
|||
// | huge debug is on too. |
|
|||
// -----------------------------------------^-----------------------^-----------
|
|||
|
|||
#ifndef MASS_MAX_SUPPORTED_LUN |
|||
#define MASS_MAX_SUPPORTED_LUN 8 |
|||
#endif |
|||
|
|||
#include "UHS_SCSI.h" |
|||
|
|||
#define UHS_BULK_bmREQ_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE |
|||
#define UHS_BULK_bmREQ_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE |
|||
|
|||
// Request Codes
|
|||
#define UHS_BULK_REQ_ADSC 0x00U |
|||
#define UHS_BULK_REQ_GET 0xFCU |
|||
#define UHS_BULK_REQ_PUT 0xFDU |
|||
#define UHS_BULK_REQ_GET_MAX_LUN 0xFEU |
|||
#define UHS_BULK_REQ_BOMSR 0xFFU // Mass Storage Reset
|
|||
|
|||
#define UHS_BULK_CBW_SIGNATURE 0x43425355LU |
|||
#define UHS_BULK_CSW_SIGNATURE 0x53425355LU |
|||
|
|||
#define UHS_BULK_CMD_DIR_OUT 0x00U |
|||
#define UHS_BULK_CMD_DIR_IN 0x80U |
|||
|
|||
/* Bulk error codes */ |
|||
#define UHS_BULK_ERR_SUCCESS UHS_HOST_ERROR_NONE |
|||
#define UHS_BULK_ERR_PHASE_ERROR 0x22U |
|||
#define UHS_BULK_ERR_UNIT_NOT_READY 0x23U |
|||
#define UHS_BULK_ERR_UNIT_BUSY 0x24U |
|||
#define UHS_BULK_ERR_STALL 0x25U |
|||
#define UHS_BULK_ERR_CMD_NOT_SUPPORTED 0x26U |
|||
#define UHS_BULK_ERR_INVALID_CSW 0x27U |
|||
#define UHS_BULK_ERR_NO_MEDIA 0x28U |
|||
#define UHS_BULK_ERR_BAD_LBA 0x29U |
|||
#define UHS_BULK_ERR_MEDIA_CHANGED 0x2AU |
|||
#define UHS_BULK_ERR_DEVICE_DISCONNECTED UHS_HOST_ERROR_UNPLUGGED |
|||
#define UHS_BULK_ERR_UNABLE_TO_RECOVER 0x32U // Reset recovery error
|
|||
#define UHS_BULK_ERR_INVALID_LUN 0x33U |
|||
#define UHS_BULK_ERR_WRITE_STALL 0x34U |
|||
#define UHS_BULK_ERR_READ_NAKS 0x35U |
|||
#define UHS_BULK_ERR_WRITE_NAKS 0x36U |
|||
#define UHS_BULK_ERR_WRITE_PROTECTED 0x37U |
|||
#define UHS_BULK_ERR_NOT_IMPLEMENTED 0xFDU |
|||
#define UHS_BULK_ERR_GENERAL_SCSI_ERROR 0xF0U |
|||
#define UHS_BULK_ERR_GENERAL_USB_ERROR 0xFFU |
|||
#define UHS_BULK_ERR_USER 0xA0U // For subclasses to define their own error codes
|
|||
|
|||
#define MASS_MAX_ENDPOINTS 3 |
|||
|
|||
struct UHS_BULK_CommandBlockWrapperBase { |
|||
volatile uint32_t dCBWSignature; |
|||
volatile uint32_t dCBWTag; |
|||
volatile uint32_t dCBWDataTransferLength; |
|||
volatile uint8_t bmCBWFlags; |
|||
public: |
|||
|
|||
UHS_BULK_CommandBlockWrapperBase(void) { |
|||
} |
|||
|
|||
UHS_BULK_CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) : |
|||
dCBWSignature(UHS_BULK_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) { |
|||
} |
|||
} __attribute__((packed)); |
|||
|
|||
struct UHS_BULK_CommandBlockWrapper : public UHS_BULK_CommandBlockWrapperBase { |
|||
|
|||
struct { |
|||
uint8_t bmCBWLUN : 4; |
|||
uint8_t bmReserved1 : 4; |
|||
}; |
|||
|
|||
struct { |
|||
uint8_t bmCBWCBLength : 4; |
|||
uint8_t bmReserved2 : 4; |
|||
}; |
|||
|
|||
uint8_t CBWCB[16]; |
|||
|
|||
public: |
|||
// All zeroed.
|
|||
|
|||
UHS_BULK_CommandBlockWrapper() : |
|||
UHS_BULK_CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { |
|||
for(int i = 0; i < 16; i++) CBWCB[i] = 0; |
|||
} |
|||
|
|||
// Generic Wrap, CDB zeroed.
|
|||
|
|||
UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : |
|||
UHS_BULK_CommandBlockWrapperBase(tag, xflen, flgs), |
|||
bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { |
|||
for(int i = 0; i < 16; i++) CBWCB[i] = 0; |
|||
SCSI_CDB_BASE_t *x = reinterpret_cast<SCSI_CDB_BASE_t *>(CBWCB); |
|||
x->LUN = cmd; |
|||
} |
|||
|
|||
// Wrap for CDB of 6
|
|||
|
|||
UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, SCSI_CDB6_t *cdb, uint8_t dir) : |
|||
UHS_BULK_CommandBlockWrapperBase(tag, xflen, dir), |
|||
bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) { |
|||
memcpy(&CBWCB, cdb, 6); |
|||
} |
|||
// Wrap for CDB of 10
|
|||
|
|||
UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, SCSI_CDB10_t *cdb, uint8_t dir) : |
|||
UHS_BULK_CommandBlockWrapperBase(tag, xflen, dir), |
|||
bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) { |
|||
memcpy(&CBWCB, cdb, 10); |
|||
} |
|||
} __attribute__((packed)); |
|||
|
|||
struct UHS_BULK_CommandStatusWrapper { |
|||
uint32_t dCSWSignature; |
|||
uint32_t dCSWTag; |
|||
uint32_t dCSWDataResidue; |
|||
uint8_t bCSWStatus; |
|||
} __attribute__((packed)); |
|||
|
|||
class UHS_Bulk_Storage : public UHS_USBInterface { |
|||
protected: |
|||
static const uint8_t epDataInIndex = 1; // DataIn endpoint index
|
|||
static const uint8_t epDataOutIndex = 2; // DataOUT endpoint index
|
|||
static const uint8_t epInterruptInIndex = 3; // InterruptIN endpoint index
|
|||
|
|||
uint8_t bMaxLUN; // Max LUN
|
|||
volatile uint32_t dCBWTag; // Tag
|
|||
volatile uint8_t bTheLUN; // Active LUN
|
|||
volatile uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
|
|||
volatile uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
|
|||
volatile bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
|
|||
volatile bool WriteOk[MASS_MAX_SUPPORTED_LUN]; |
|||
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); |
|||
|
|||
public: |
|||
UHS_Bulk_Storage(UHS_USB_HOST_BASE *p); |
|||
|
|||
volatile UHS_EpInfo epInfo[MASS_MAX_ENDPOINTS]; |
|||
|
|||
uint8_t GetbMaxLUN(void) { |
|||
return bMaxLUN; // Max LUN
|
|||
} |
|||
|
|||
uint8_t GetbTheLUN(void) { |
|||
return bTheLUN; // Active LUN
|
|||
} |
|||
|
|||
bool WriteProtected(uint8_t lun); |
|||
uint8_t MediaCTL(uint8_t lun, uint8_t ctl); |
|||
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf); |
|||
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf); |
|||
uint8_t LockMedia(uint8_t lun, uint8_t lock); |
|||
|
|||
bool LUNIsGood(uint8_t lun); |
|||
uint32_t GetCapacity(uint8_t lun); |
|||
uint16_t GetSectorSize(uint8_t lun); |
|||
uint8_t SCSITransaction6(SCSI_CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); |
|||
uint8_t SCSITransaction10(SCSI_CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); |
|||
|
|||
|
|||
// Configure and internal methods, these should never be called by a user's sketch.
|
|||
uint8_t Start(void); |
|||
bool OKtoEnumerate(ENUMERATION_INFO *ei); |
|||
uint8_t SetInterface(ENUMERATION_INFO *ei); |
|||
|
|||
uint8_t GetAddress(void) { |
|||
return bAddress; |
|||
}; |
|||
|
|||
|
|||
void Poll(void); |
|||
|
|||
void DriverDefaults(void); |
|||
|
|||
|
|||
private: |
|||
void Reset(void); |
|||
void CheckMedia(void); |
|||
|
|||
bool IsValidCBW(uint8_t size, uint8_t *pcbw); |
|||
bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw); |
|||
bool IsValidCSW(UHS_BULK_CommandStatusWrapper *pcsw, UHS_BULK_CommandBlockWrapperBase *pcbw); |
|||
|
|||
bool CheckLUN(uint8_t lun); |
|||
|
|||
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); |
|||
uint8_t TestUnitReady(uint8_t lun); |
|||
uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf); |
|||
uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); |
|||
uint8_t GetMaxLUN(uint8_t *max_lun); |
|||
uint8_t SetCurLUN(uint8_t lun); |
|||
uint8_t ResetRecovery(); |
|||
uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf); |
|||
uint8_t Page3F(uint8_t lun); |
|||
uint8_t ClearEpHalt(uint8_t index); |
|||
uint8_t Transaction(UHS_BULK_CommandBlockWrapper *cbw, uint16_t bsize, void *buf); |
|||
uint8_t HandleUsbError(uint8_t error, uint8_t index); |
|||
uint8_t HandleSCSIError(uint8_t status); |
|||
|
|||
}; |
|||
|
|||
#if defined(LOAD_UHS_BULK_STORAGE) && !defined(UHS_BULK_STORAGE_LOADED) |
|||
#include "UHS_BULK_STORAGE_INLINE.h" |
|||
#endif |
|||
#endif // __MASSTORAGE_H__
|
File diff suppressed because it is too large
@ -0,0 +1,328 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#ifndef UHS_SCSI_H |
|||
#define UHS_SCSI_H |
|||
|
|||
/*
|
|||
* Reference documents from T10 (http://www.t10.org)
|
|||
* SCSI Primary Commands - 3 (SPC-3) |
|||
* SCSI Block Commands - 2 (SBC-2) |
|||
* Multi-Media Commands - 5 (MMC-5) |
|||
*/ |
|||
|
|||
/* Group 1 commands (CDB's here are should all be 6-bytes) */ |
|||
#define SCSI_CMD_TEST_UNIT_READY 0x00U |
|||
#define SCSI_CMD_REQUEST_SENSE 0x03U |
|||
#define SCSI_CMD_FORMAT_UNIT 0x04U |
|||
#define SCSI_CMD_READ_6 0x08U |
|||
#define SCSI_CMD_WRITE_6 0x0AU |
|||
#define SCSI_CMD_INQUIRY 0x12U |
|||
#define SCSI_CMD_MODE_SELECT_6 0x15U |
|||
#define SCSI_CMD_MODE_SENSE_6 0x1AU |
|||
#define SCSI_CMD_START_STOP_UNIT 0x1BU |
|||
#define SCSI_CMD_PREVENT_REMOVAL 0x1EU |
|||
/* Group 2 Commands (CDB's here are 10-bytes) */ |
|||
#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23U |
|||
#define SCSI_CMD_READ_CAPACITY_10 0x25U |
|||
#define SCSI_CMD_READ_10 0x28U |
|||
#define SCSI_CMD_WRITE_10 0x2AU |
|||
#define SCSI_CMD_SEEK_10 0x2BU |
|||
#define SCSI_CMD_ERASE_10 0x2CU |
|||
#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2EU |
|||
#define SCSI_CMD_VERIFY_10 0x2FU |
|||
#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35U |
|||
#define SCSI_CMD_WRITE_BUFFER 0x3BU |
|||
#define SCSI_CMD_READ_BUFFER 0x3CU |
|||
#define SCSI_CMD_READ_SUBCHANNEL 0x42U |
|||
#define SCSI_CMD_READ_TOC 0x43U |
|||
#define SCSI_CMD_READ_HEADER 0x44U |
|||
#define SCSI_CMD_PLAY_AUDIO_10 0x45U |
|||
#define SCSI_CMD_GET_CONFIGURATION 0x46U |
|||
#define SCSI_CMD_PLAY_AUDIO_MSF 0x47U |
|||
#define SCSI_CMD_PLAY_AUDIO_TI 0x48U |
|||
#define SCSI_CMD_PLAY_TRACK_REL_10 0x49U |
|||
#define SCSI_CMD_GET_EVENT_STATUS 0x4AU |
|||
#define SCSI_CMD_PAUSE_RESUME 0x4BU |
|||
#define SCSI_CMD_READ_DISC_INFORMATION 0x51U |
|||
#define SCSI_CMD_READ_TRACK_INFORMATION 0x52U |
|||
#define SCSI_CMD_RESERVE_TRACK 0x53U |
|||
#define SCSI_CMD_SEND_OPC_INFORMATION 0x54U |
|||
#define SCSI_CMD_MODE_SELECT_10 0x55U |
|||
#define SCSI_CMD_REPAIR_TRACK 0x58U |
|||
#define SCSI_CMD_MODE_SENSE_10 0x5AU |
|||
#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5BU |
|||
#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5CU |
|||
#define SCSI_CMD_SEND_CUE_SHEET 0x5DU |
|||
/* Group 5 Commands (CDB's here are 12-bytes) */ |
|||
#define SCSI_CMD_REPORT_LUNS 0xA0U |
|||
#define SCSI_CMD_BLANK 0xA1U |
|||
#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2U |
|||
#define SCSI_CMD_SEND_KEY 0xA3U |
|||
#define SCSI_CMD_REPORT_KEY 0xA4U |
|||
#define SCSI_CMD_PLAY_AUDIO_12 0xA5U |
|||
#define SCSI_CMD_LOAD_UNLOAD 0xA6U |
|||
#define SCSI_CMD_SET_READ_AHEAD 0xA7U |
|||
#define SCSI_CMD_READ_12 0xA8U |
|||
#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9U |
|||
#define SCSI_CMD_WRITE_12 0xAAU |
|||
#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xABU |
|||
#define SCSI_CMD_GET_PERFORMANCE 0xACU |
|||
#define SCSI_CMD_READ_DVD_STRUCTURE 0xADU |
|||
#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5U |
|||
#define SCSI_CMD_SET_STREAMING 0xB6U |
|||
#define SCSI_CMD_READ_MSF 0xB9U |
|||
#define SCSI_CMD_SET_SPEED 0xBBU |
|||
#define SCSI_CMD_MECHANISM_STATUS 0xBDU |
|||
#define SCSI_CMD_READ_CD 0xBEU |
|||
#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBFU |
|||
/* Vendor-unique Commands, included for completeness */ |
|||
#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4U /* SONY unique */ |
|||
#define SCSI_CMD_PLAYBACK_CONTROL 0xC9U /* SONY unique */ |
|||
#define SCSI_CMD_READ_CDDA 0xD8U /* Vendor unique */ |
|||
#define SCSI_CMD_READ_CDXA 0xDBU /* Vendor unique */ |
|||
#define SCSI_CMD_READ_ALL_SUBCODES 0xDFU /* Vendor unique */ |
|||
|
|||
/* SCSI error codes */ |
|||
#define SCSI_S_NOT_READY 0x02U |
|||
#define SCSI_S_MEDIUM_ERROR 0x03U |
|||
#define SCSI_S_ILLEGAL_REQUEST 0x05U |
|||
#define SCSI_S_UNIT_ATTENTION 0x06U |
|||
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21U |
|||
#define SCSI_ASC_MEDIA_CHANGED 0x28U |
|||
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3AU |
|||
|
|||
struct SCSI_Capacity { |
|||
uint8_t data[8]; |
|||
//uint32_t dwBlockAddress;
|
|||
//uint32_t dwBlockLength;
|
|||
} __attribute__((packed)); |
|||
|
|||
struct SCSI_CDB_BASE { |
|||
uint8_t Opcode; |
|||
|
|||
unsigned unused : 5; |
|||
unsigned LUN : 3; |
|||
|
|||
uint8_t info[12]; |
|||
} __attribute__((packed)); |
|||
|
|||
typedef SCSI_CDB_BASE SCSI_CDB_BASE_t; |
|||
|
|||
struct SCSI_CDB6 { |
|||
uint8_t Opcode; |
|||
|
|||
unsigned LBAMSB : 5; |
|||
unsigned LUN : 3; |
|||
|
|||
uint8_t LBAHB; |
|||
uint8_t LBALB; |
|||
uint8_t AllocationLength; |
|||
uint8_t Control; |
|||
|
|||
public: |
|||
|
|||
SCSI_CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) : |
|||
Opcode(_Opcode), LBAMSB(UHS_UINT8_BYTE2(LBA) & 0x1f), LUN(_LUN), LBAHB(UHS_UINT8_BYTE1(LBA)), LBALB(UHS_UINT8_BYTE0(LBA)), |
|||
AllocationLength(_AllocationLength), Control(_Control) { |
|||
} |
|||
|
|||
SCSI_CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) : |
|||
Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0), |
|||
AllocationLength(_AllocationLength), Control(_Control) { |
|||
} |
|||
} __attribute__((packed)); |
|||
|
|||
typedef SCSI_CDB6 SCSI_CDB6_t; |
|||
|
|||
struct SCSI_CDB10 { |
|||
uint8_t Opcode; |
|||
|
|||
unsigned Service_Action : 5; |
|||
unsigned LUN : 3; |
|||
|
|||
uint8_t LBA_L_M_MB; |
|||
uint8_t LBA_L_M_LB; |
|||
uint8_t LBA_L_L_MB; |
|||
uint8_t LBA_L_L_LB; |
|||
|
|||
uint8_t Misc2; |
|||
|
|||
uint8_t ALC_MB; |
|||
uint8_t ALC_LB; |
|||
|
|||
uint8_t Control; |
|||
public: |
|||
|
|||
SCSI_CDB10(uint8_t _Opcode, uint8_t _LUN) : |
|||
Opcode(_Opcode), Service_Action(0), LUN(_LUN), |
|||
LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0), |
|||
Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) { |
|||
} |
|||
|
|||
SCSI_CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) : |
|||
Opcode(_Opcode), Service_Action(0), LUN(_LUN), |
|||
LBA_L_M_MB(UHS_UINT8_BYTE3(_LBA)), LBA_L_M_LB(UHS_UINT8_BYTE2(_LBA)), LBA_L_L_MB(UHS_UINT8_BYTE1(_LBA)), LBA_L_L_LB(UHS_UINT8_BYTE0(_LBA)), |
|||
Misc2(0), ALC_MB(UHS_UINT8_BYTE1(xflen)), ALC_LB(UHS_UINT8_BYTE0(xflen)), Control(0) { |
|||
} |
|||
} __attribute__((packed)); |
|||
|
|||
typedef SCSI_CDB10 SCSI_CDB10_t; |
|||
|
|||
struct SCSI_CDB12 { |
|||
uint8_t Opcode; |
|||
|
|||
unsigned Service_Action : 5; |
|||
unsigned Misc : 3; |
|||
|
|||
uint8_t LBA_L_M_LB; |
|||
uint8_t LBA_L_L_MB; |
|||
uint8_t LBA_L_L_LB; |
|||
|
|||
uint8_t ALC_M_LB; |
|||
uint8_t ALC_L_MB; |
|||
uint8_t ALC_L_LB; |
|||
uint8_t Control; |
|||
} __attribute__((packed)); |
|||
|
|||
typedef SCSI_CDB12 SCSI_CDB12_t; |
|||
|
|||
struct SCSI_CDB_LBA32_16 { |
|||
uint8_t Opcode; |
|||
|
|||
unsigned Service_Action : 5; |
|||
unsigned Misc : 3; |
|||
|
|||
uint8_t LBA_L_M_MB; |
|||
uint8_t LBA_L_M_LB; |
|||
uint8_t LBA_L_L_MB; |
|||
uint8_t LBA_L_L_LB; |
|||
|
|||
uint8_t A_M_M_MB; |
|||
uint8_t A_M_M_LB; |
|||
uint8_t A_M_L_MB; |
|||
uint8_t A_M_L_LB; |
|||
|
|||
uint8_t ALC_M_MB; |
|||
uint8_t ALC_M_LB; |
|||
uint8_t ALC_L_MB; |
|||
uint8_t ALC_L_LB; |
|||
|
|||
uint8_t Misc2; |
|||
uint8_t Control; |
|||
} __attribute__((packed)); |
|||
|
|||
struct SCSI_CDB_LBA64_16 { |
|||
uint8_t Opcode; |
|||
uint8_t Misc; |
|||
|
|||
uint8_t LBA_M_M_MB; |
|||
uint8_t LBA_M_M_LB; |
|||
uint8_t LBA_M_L_MB; |
|||
uint8_t LBA_M_L_LB; |
|||
|
|||
uint8_t LBA_L_M_MB; |
|||
uint8_t LBA_L_M_LB; |
|||
uint8_t LBA_L_L_MB; |
|||
uint8_t LBA_L_L_LB; |
|||
|
|||
uint8_t ALC_M_MB; |
|||
uint8_t ALC_M_LB; |
|||
uint8_t ALC_L_MB; |
|||
uint8_t ALC_L_LB; |
|||
|
|||
uint8_t Misc2; |
|||
uint8_t Control; |
|||
} __attribute__((packed)); |
|||
|
|||
struct SCSI_Inquiry_Response { |
|||
uint8_t DeviceType : 5; |
|||
uint8_t PeripheralQualifier : 3; |
|||
|
|||
unsigned Reserved : 7; |
|||
unsigned Removable : 1; |
|||
|
|||
uint8_t Version; |
|||
|
|||
unsigned ResponseDataFormat : 4; |
|||
unsigned HISUP : 1; |
|||
unsigned NormACA : 1; |
|||
unsigned TrmTsk : 1; |
|||
unsigned AERC : 1; |
|||
|
|||
uint8_t AdditionalLength; |
|||
|
|||
unsigned PROTECT : 1; |
|||
unsigned Res : 2; |
|||
unsigned ThreePC : 1; |
|||
unsigned TPGS : 2; |
|||
unsigned ACC : 1; |
|||
unsigned SCCS : 1; |
|||
|
|||
unsigned ADDR16 : 1; |
|||
unsigned R1 : 1; |
|||
unsigned R2 : 1; |
|||
unsigned MCHNGR : 1; |
|||
unsigned MULTIP : 1; |
|||
unsigned VS : 1; |
|||
unsigned ENCSERV : 1; |
|||
unsigned BQUE : 1; |
|||
|
|||
unsigned SoftReset : 1; |
|||
unsigned CmdQue : 1; |
|||
unsigned Reserved4 : 1; |
|||
unsigned Linked : 1; |
|||
unsigned Sync : 1; |
|||
unsigned WideBus16Bit : 1; |
|||
unsigned WideBus32Bit : 1; |
|||
unsigned RelAddr : 1; |
|||
|
|||
uint8_t VendorID[8]; |
|||
uint8_t ProductID[16]; |
|||
uint8_t RevisionID[4]; |
|||
} __attribute__((packed)); |
|||
|
|||
struct SCSI_Request_Sense_Response { |
|||
uint8_t bResponseCode; |
|||
uint8_t bSegmentNumber; |
|||
|
|||
uint8_t bmSenseKey : 4; |
|||
uint8_t bmReserved : 1; |
|||
uint8_t bmILI : 1; |
|||
uint8_t bmEOM : 1; |
|||
uint8_t bmFileMark : 1; |
|||
|
|||
uint8_t Information[4]; |
|||
uint8_t bAdditionalLength; |
|||
uint8_t CmdSpecificInformation[4]; |
|||
uint8_t bAdditionalSenseCode; |
|||
uint8_t bAdditionalSenseQualifier; |
|||
uint8_t bFieldReplaceableUnitCode; |
|||
uint8_t SenseKeySpecific[3]; |
|||
} __attribute__((packed)); |
|||
|
|||
#endif /* UHS_SCSI_H */ |
|||
|
@ -0,0 +1,33 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
#ifndef _UHS_UNOFFICIAL_IDs_h |
|||
#define _UHS_UNOFFICIAL_IDs_h |
|||
|
|||
// Bogus unofficial and unregistered VIDs from cloners to be listed here.
|
|||
|
|||
#define UHS_VID_UNOFFICIAL_JOYTECH 0x162EU // For unofficial Joytech controllers
|
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,336 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(_UHS_host_h_) || defined(USBCORE_H) |
|||
#error "Never include UHS_UsbCore.h directly; include UHS_Host.h instead" |
|||
#else |
|||
#define USBCORE_H |
|||
|
|||
#ifndef UHS_HOST_MAX_INTERFACE_DRIVERS |
|||
#define UHS_HOST_MAX_INTERFACE_DRIVERS 0x10U // Default maximum number of USB interface drivers
|
|||
#endif |
|||
|
|||
#if !defined(SYSTEM_OR_SPECIAL_YIELD) |
|||
#define SYSTEM_OR_SPECIAL_YIELD(...) VOID0 |
|||
#endif |
|||
|
|||
#if !defined(SYSTEM_OR_SPECIAL_YIELD_FROM_ISR) |
|||
#define SYSTEM_OR_SPECIAL_YIELD_FROM_ISR(...) SYSTEM_OR_SPECIAL_YIELD |
|||
#endif |
|||
|
|||
// As we make extensions to a target interface add to UHS_HOST_MAX_INTERFACE_DRIVERS
|
|||
// This offset gets calculated for supporting wide subclasses, such as HID, BT, etc.
|
|||
#define UHS_HID_INDEX (UHS_HOST_MAX_INTERFACE_DRIVERS + 1) |
|||
|
|||
/* Common setup data constant combinations */ |
|||
//get descriptor request type
|
|||
#define UHS_bmREQ_GET_DESCR (USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE) |
|||
|
|||
//set request type for all but 'set feature' and 'set interface'
|
|||
#define UHS_bmREQ_SET (USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE) |
|||
|
|||
//get interface request type
|
|||
#define UHS_bmREQ_CL_GET_INTF (USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE) |
|||
|
|||
// D7 data transfer direction (0 - host-to-device, 1 - device-to-host)
|
|||
// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
|
|||
// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
|
|||
|
|||
|
|||
// TO-DO: Use the python script to generate these.
|
|||
// TO-DO: Add _all_ subclasses here.
|
|||
// USB Device Classes, Subclasses and Protocols
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Use Class Info in the Interface Descriptors
|
|||
#define UHS_USB_CLASS_USE_CLASS_INFO 0x00U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Audio
|
|||
#define UHS_USB_CLASS_AUDIO 0x01U |
|||
// Subclasses
|
|||
#define UHS_USB_SUBCLASS_AUDIOCONTROL 0x01U |
|||
#define UHS_USB_SUBCLASS_AUDIOSTREAMING 0x02U |
|||
#define UHS_USB_SUBCLASS_MIDISTREAMING 0x03U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Communications and CDC Control
|
|||
#define UHS_USB_CLASS_COM_AND_CDC_CTRL 0x02U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// HID
|
|||
#define UHS_USB_CLASS_HID 0x03U |
|||
// Subclasses
|
|||
#define UHS_HID_BOOT_SUBCLASS 0x01U |
|||
// Protocols
|
|||
#define UHS_HID_PROTOCOL_HIDBOOT_KEYBOARD 0x01U |
|||
#define UHS_HID_PROTOCOL_HIDBOOT_MOUSE 0x02U |
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Physical
|
|||
#define UHS_USB_CLASS_PHYSICAL 0x05U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Image
|
|||
#define UHS_USB_CLASS_IMAGE 0x06U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Printer
|
|||
#define UHS_USB_CLASS_PRINTER 0x07U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Mass Storage
|
|||
#define UHS_USB_CLASS_MASS_STORAGE 0x08 |
|||
// Subclasses
|
|||
#define UHS_BULK_SUBCLASS_SCSI_NOT_REPORTED 0x00U // De facto use
|
|||
#define UHS_BULK_SUBCLASS_RBC 0x01U |
|||
#define UHS_BULK_SUBCLASS_ATAPI 0x02U // MMC-5 (ATAPI)
|
|||
#define UHS_BULK_SUBCLASS_OBSOLETE1 0x03U // Was QIC-157
|
|||
#define UHS_BULK_SUBCLASS_UFI 0x04U // Specifies how to interface Floppy Disk Drives to USB
|
|||
#define UHS_BULK_SUBCLASS_OBSOLETE2 0x05U // Was SFF-8070i
|
|||
#define UHS_BULK_SUBCLASS_SCSI 0x06U // SCSI Transparent Command Set
|
|||
#define UHS_BULK_SUBCLASS_LSDFS 0x07U // Specifies how host has to negotiate access before trying SCSI
|
|||
#define UHS_BULK_SUBCLASS_IEEE1667 0x08U |
|||
// Protocols
|
|||
#define UHS_STOR_PROTO_CBI 0x00U // CBI (with command completion interrupt)
|
|||
#define UHS_STOR_PROTO_CBI_NO_INT 0x01U // CBI (without command completion interrupt)
|
|||
#define UHS_STOR_PROTO_OBSOLETE 0x02U |
|||
#define UHS_STOR_PROTO_BBB 0x50U // Bulk Only Transport
|
|||
#define UHS_STOR_PROTO_UAS 0x62U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Hub
|
|||
#define UHS_USB_CLASS_HUB 0x09U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// CDC-Data
|
|||
#define UHS_USB_CLASS_CDC_DATA 0x0AU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Smart-Card
|
|||
#define UHS_USB_CLASS_SMART_CARD 0x0BU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Content Security
|
|||
#define UHS_USB_CLASS_CONTENT_SECURITY 0x0DU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Video
|
|||
#define UHS_USB_CLASS_VIDEO 0x0EU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Personal Healthcare
|
|||
#define UHS_USB_CLASS_PERSONAL_HEALTH 0x0FU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Diagnostic Device
|
|||
#define UHS_USB_CLASS_DIAGNOSTIC_DEVICE 0xDCU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Wireless Controller
|
|||
#define UHS_USB_CLASS_WIRELESS_CTRL 0xE0U |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Miscellaneous
|
|||
#define UHS_USB_CLASS_MISC 0xEFU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Application Specific
|
|||
#define UHS_USB_CLASS_APP_SPECIFIC 0xFEU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Vendor Specific
|
|||
#define UHS_USB_CLASS_VENDOR_SPECIFIC 0xFFU |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
|
|||
/* USB state machine states */ |
|||
#define UHS_USB_HOST_STATE_MASK 0xF0U |
|||
|
|||
// Configure states, MSN == 0 --------------------------V
|
|||
#define UHS_USB_HOST_STATE_DETACHED 0x00U |
|||
#define UHS_USB_HOST_STATE_DEBOUNCE 0x01U |
|||
#define UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE 0x02U |
|||
#define UHS_USB_HOST_STATE_RESET_NOT_COMPLETE 0x03U |
|||
#define UHS_USB_HOST_STATE_WAIT_SOF 0x04U |
|||
#define UHS_USB_HOST_STATE_WAIT_BUS_READY 0x05U |
|||
#define UHS_USB_HOST_STATE_RESET_DEVICE 0x0AU |
|||
#define UHS_USB_HOST_STATE_CONFIGURING 0x0CU // Looks like "CO"nfig (backwards)
|
|||
#define UHS_USB_HOST_STATE_CONFIGURING_DONE 0x0DU // Looks like "DO"one (backwards)
|
|||
#define UHS_USB_HOST_STATE_CHECK 0x0EU |
|||
#define UHS_USB_HOST_STATE_ILLEGAL 0x0FU // Foo
|
|||
|
|||
// Run states, MSN != 0 --------------------------------V
|
|||
#define UHS_USB_HOST_STATE_RUNNING 0x60U // Looks like "GO"
|
|||
#define UHS_USB_HOST_STATE_IDLE 0x1DU // Looks like "ID"le
|
|||
#define UHS_USB_HOST_STATE_ERROR 0xF0U // Looks like "FO"o
|
|||
#define UHS_USB_HOST_STATE_INITIALIZE 0x10U // Looks like "I"nit
|
|||
|
|||
// Host SE result codes.
|
|||
// Common SE results are stored in the low nybble, all interface drivers understand these plus 0x1f.
|
|||
// Extended SE results are 0x10-0x1e. SE code only understands these internal to the hardware.
|
|||
// Values > 0x1F are driver or other internal error conditions.
|
|||
// Return these result codes from your host controller driver to match the error condition
|
|||
// ALL Non-zero values are errors.
|
|||
// Values not listed in this table are not handled in the base class, or any host driver.
|
|||
|
|||
#define UHS_HOST_ERROR_NONE 0x00U // No error
|
|||
#define UHS_HOST_ERROR_BUSY 0x01U // transfer pending
|
|||
#define UHS_HOST_ERROR_BADREQ 0x02U // Transfer Launch Request was bad
|
|||
#define UHS_HOST_ERROR_DMA 0x03U // DMA was too short, or too long
|
|||
#define UHS_HOST_ERROR_NAK 0x04U // Peripheral returned NAK
|
|||
#define UHS_HOST_ERROR_STALL 0x05U // Peripheral returned STALL
|
|||
#define UHS_HOST_ERROR_TOGERR 0x06U // Toggle error/ISO over-underrun
|
|||
#define UHS_HOST_ERROR_WRONGPID 0x07U // Received wrong Packet ID
|
|||
#define UHS_HOST_ERROR_BADBC 0x08U // Byte count is bad
|
|||
#define UHS_HOST_ERROR_PIDERR 0x09U // Received Packet ID is corrupted
|
|||
#define UHS_HOST_ERROR_BADRQ 0x0AU // Packet error. Increase max packet.
|
|||
#define UHS_HOST_ERROR_CRC 0x0BU // USB CRC was incorrect
|
|||
#define UHS_HOST_ERROR_KERR 0x0CU // K-state instead of response, usually indicates wrong speed
|
|||
#define UHS_HOST_ERROR_JERR 0x0DU // J-state instead of response, usually indicates wrong speed
|
|||
#define UHS_HOST_ERROR_TIMEOUT 0x0EU // Device did not respond in time
|
|||
#define UHS_HOST_ERROR_BABBLE 0x0FU // Line noise/unexpected data
|
|||
#define UHS_HOST_ERROR_MEM_LAT 0x10U // Error caused by memory latency.
|
|||
#define UHS_HOST_ERROR_NYET 0x11U // OUT transfer accepted with NYET
|
|||
|
|||
// Addressing error codes
|
|||
#define ADDR_ERROR_INVALID_INDEX 0xA0U |
|||
#define ADDR_ERROR_INVALID_ADDRESS 0xA1U |
|||
|
|||
// Common Interface Driver error codes
|
|||
#define UHS_HOST_ERROR_DEVICE_NOT_SUPPORTED 0xD1U // Driver doesn't support the device or interfaces
|
|||
#define UHS_HOST_ERROR_DEVICE_INIT_INCOMPLETE 0xD2U // Init partially finished, but died.
|
|||
#define UHS_HOST_ERROR_CANT_REGISTER_DEVICE_CLASS 0xD3U // There was no driver for the interface requested.
|
|||
#define UHS_HOST_ERROR_ADDRESS_POOL_FULL 0xD4U // No addresses left in the address pool.
|
|||
#define UHS_HOST_ERROR_HUB_ADDRESS_OVERFLOW 0xD5U // No hub addresses left. The maximum is 7.
|
|||
#define UHS_HOST_ERROR_NO_ADDRESS_IN_POOL 0xD6U // Address was not allocated in the pool, thus not found.
|
|||
#define UHS_HOST_ERROR_NULL_EPINFO 0xD7U // The supplied endpoint was NULL, indicates a bug or other problem.
|
|||
#define UHS_HOST_ERROR_BAD_ARGUMENT 0xD8U // Indicates a range violation bug.
|
|||
#define UHS_HOST_ERROR_DEVICE_DRIVER_BUSY 0xD9U // The interface driver is busy or out buffer is full, try again later.
|
|||
#define UHS_HOST_ERROR_BAD_MAX_PACKET_SIZE 0xDAU // The maximum packet size was exceeded. Try again with smaller size.
|
|||
#define UHS_HOST_ERROR_NO_ENDPOINT_IN_TABLE 0xDBU // The endpoint could not be found in the endpoint table.
|
|||
#define UHS_HOST_ERROR_UNPLUGGED 0xDEU // Someone removed the USB device, or Vbus was turned off.
|
|||
#define UHS_HOST_ERROR_NOMEM 0xDFU // Out Of Memory.
|
|||
|
|||
// Control request stream errors
|
|||
#define UHS_HOST_ERROR_FailGetDevDescr 0xE1U |
|||
#define UHS_HOST_ERROR_FailSetDevTblEntry 0xE2U |
|||
#define UHS_HOST_ERROR_FailGetConfDescr 0xE3U |
|||
#define UHS_HOST_ERROR_END_OF_STREAM 0xEFU |
|||
|
|||
// Host base class specific Error codes
|
|||
#define UHS_HOST_ERROR_NOT_IMPLEMENTED 0xFEU |
|||
#define UHS_HOST_ERROR_TRANSFER_TIMEOUT 0xFFU |
|||
|
|||
// SEI interaction defaults
|
|||
#define UHS_HOST_TRANSFER_MAX_MS 10000 // USB transfer timeout in ms, per section 9.2.6.1 of USB 2.0 spec
|
|||
#define UHS_HOST_TRANSFER_RETRY_MAXIMUM 3 // 3 retry limit for a transfer
|
|||
#define UHS_HOST_DEBOUNCE_DELAY_MS 500 // settle delay in milliseconds
|
|||
#define UHS_HUB_RESET_DELAY_MS 20 // hub port reset delay, 10ms recomended, but can be up to 20ms
|
|||
|
|||
//
|
|||
// We only provide the minimum needed information for enumeration.
|
|||
// Interface drivers should be able to set up what is needed with nothing more.
|
|||
// A driver needs to know the following information:
|
|||
// 1: address on the USB network, parent and port (aka UsbDeviceAddress)
|
|||
// 2: endpoints
|
|||
// 3: vid:pid, class, subclass, protocol
|
|||
//
|
|||
|
|||
struct ENDPOINT_INFO { |
|||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
|||
uint8_t bmAttributes; // Endpoint transfer type.
|
|||
uint16_t wMaxPacketSize; // Maximum packet size.
|
|||
uint8_t bInterval; // Polling interval in frames.
|
|||
} __attribute__((packed)); |
|||
|
|||
struct INTERFACE_INFO { |
|||
uint8_t bInterfaceNumber; |
|||
uint8_t bAlternateSetting; |
|||
uint8_t numep; |
|||
uint8_t klass; |
|||
uint8_t subklass; |
|||
uint8_t protocol; |
|||
ENDPOINT_INFO epInfo[16]; |
|||
} __attribute__((packed)); |
|||
|
|||
struct ENUMERATION_INFO { |
|||
uint16_t vid; |
|||
uint16_t pid; |
|||
uint16_t bcdDevice; |
|||
uint8_t klass; |
|||
uint8_t subklass; |
|||
uint8_t protocol; |
|||
uint8_t bMaxPacketSize0; |
|||
uint8_t currentconfig; |
|||
uint8_t parent; |
|||
uint8_t port; |
|||
uint8_t address; |
|||
INTERFACE_INFO interface; |
|||
} __attribute__((packed)); |
|||
|
|||
/* USB Setup Packet Structure */ |
|||
typedef struct { |
|||
// offset description
|
|||
// 0 Bit-map of request type
|
|||
union { |
|||
uint8_t bmRequestType; |
|||
|
|||
struct { |
|||
uint8_t recipient : 5; // Recipient of the request
|
|||
uint8_t type : 2; // Type of request
|
|||
uint8_t direction : 1; // Direction of data transfer
|
|||
} __attribute__((packed)); |
|||
} ReqType_u; |
|||
|
|||
// 1 Request
|
|||
uint8_t bRequest; |
|||
|
|||
// 2 Depends on bRequest
|
|||
union { |
|||
uint16_t wValue; |
|||
|
|||
struct { |
|||
uint8_t wValueLo; |
|||
uint8_t wValueHi; |
|||
} __attribute__((packed)); |
|||
} wVal_u; |
|||
// 4 Depends on bRequest
|
|||
uint16_t wIndex; |
|||
// 6 Depends on bRequest
|
|||
uint16_t wLength; |
|||
// 8 bytes total
|
|||
} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT; |
|||
|
|||
|
|||
// little endian :-) 8 8 8 8 16 16
|
|||
#define mkSETUP_PKT8(bmReqType, bRequest, wValLo, wValHi, wInd, total) ((uint64_t)(((uint64_t)(bmReqType)))|(((uint64_t)(bRequest))<<8)|(((uint64_t)(wValLo))<<16)|(((uint64_t)(wValHi))<<24)|(((uint64_t)(wInd))<<32)|(((uint64_t)(total)<<48))) |
|||
#define mkSETUP_PKT16(bmReqType, bRequest, wVal, wInd, total) ((uint64_t)(((uint64_t)(bmReqType)))|(((uint64_t)(bRequest))<<8)|(((uint64_t)(wVal ))<<16) |(((uint64_t)(wInd))<<32)|(((uint64_t)(total)<<48))) |
|||
|
|||
// Big endian -- but we aren't able to use this :-/
|
|||
//#define mkSETUP_PKT8(bmReqType, bRequest, wValLo, wValHi, wInd, total) ((uint64_t)(((uint64_t)(bmReqType))<<56)|(((uint64_t)(bRequest))<<48)|(((uint64_t)(wValLo))<<40)|(((uint64_t)(wValHi))<<32)|(((uint64_t)(wInd))<<16)|((uint64_t)(total)))
|
|||
//#define mkSETUP_PKT16(bmReqType, bRequest, wVal, wInd, total) ((uint64_t)(((uint64_t)(bmReqType))<<56)|(((uint64_t)(bRequest))<<48) |(((uint64_t)(wVal))<<32) |(((uint64_t)(wInd))<<16)|((uint64_t)(total)))
|
|||
|
|||
#endif /* USBCORE_H */ |
@ -0,0 +1,248 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(_UHS_host_h_) || defined(__ADDRESS_H__) |
|||
#error "Never include UHS_address.h directly; include UHS_Usb.h instead" |
|||
#else |
|||
#define __ADDRESS_H__ |
|||
|
|||
|
|||
|
|||
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ |
|||
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ |
|||
#define UHS_USB_NAK_MAX_POWER 14 // NAK binary order maximum value
|
|||
#define UHS_USB_NAK_DEFAULT 13 // default 16K-1 NAKs before giving up
|
|||
#define UHS_USB_NAK_NOWAIT 1 // Single NAK stops transfer
|
|||
#define UHS_USB_NAK_NONAK 0 // Do not count NAKs, stop retrying after USB Timeout. Try not to use this.
|
|||
|
|||
#define bmUSB_DEV_ADDR_PORT 0x07 |
|||
#define bmUSB_DEV_ADDR_PARENT 0x78 |
|||
#define bmUSB_DEV_ADDR_HUB 0x40 |
|||
|
|||
// TODO: embed parent?
|
|||
struct UHS_EpInfo { |
|||
uint8_t epAddr; // Endpoint address
|
|||
uint8_t bIface; |
|||
uint16_t maxPktSize; // Maximum packet size
|
|||
|
|||
union { |
|||
uint8_t epAttribs; |
|||
|
|||
struct { |
|||
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
|
|||
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
|
|||
uint8_t bmNeedPing : 1; // 1 == ping protocol needed for next out packet
|
|||
uint8_t bmNakPower : 5; // Binary order for NAK_LIMIT value
|
|||
} __attribute__((packed)); |
|||
}; |
|||
} __attribute__((packed)); |
|||
|
|||
// TODO: embed parent address and port into epinfo struct,
|
|||
// and nuke this address stupidity.
|
|||
// This is a compact scheme. Should also support full spec.
|
|||
// This produces a 7 hub limit, 49 devices + 7 hubs, 56 total.
|
|||
//
|
|||
// 7 6 5 4 3 2 1 0
|
|||
// ---------------------------------
|
|||
// | | H | P | P | P | A | A | A |
|
|||
// ---------------------------------
|
|||
//
|
|||
// H - if 1 the address is a hub address
|
|||
// P - parent hub number
|
|||
// A - port number of parent
|
|||
//
|
|||
|
|||
struct UHS_DeviceAddress { |
|||
|
|||
union { |
|||
|
|||
struct { |
|||
uint8_t bmAddress : 3; // port number
|
|||
uint8_t bmParent : 3; // parent hub address
|
|||
uint8_t bmHub : 1; // hub flag
|
|||
uint8_t bmReserved : 1; // reserved, must be zero
|
|||
} __attribute__((packed)); |
|||
uint8_t devAddress; |
|||
}; |
|||
} __attribute__((packed)); |
|||
|
|||
struct UHS_Device { |
|||
volatile UHS_EpInfo *epinfo[UHS_HOST_MAX_INTERFACE_DRIVERS]; // endpoint info pointer
|
|||
UHS_DeviceAddress address; |
|||
uint8_t epcount; // number of endpoints
|
|||
uint8_t speed; // indicates device speed
|
|||
} __attribute__((packed)); |
|||
|
|||
typedef void (*UsbDeviceHandleFunc)(UHS_Device *pdev); |
|||
|
|||
class AddressPool { |
|||
UHS_EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
|||
|
|||
// In order to avoid hub address duplication, this should use bits
|
|||
uint8_t hubCounter; // hub counter
|
|||
|
|||
UHS_Device thePool[UHS_HOST_MAX_INTERFACE_DRIVERS]; |
|||
|
|||
// Initializes address pool entry
|
|||
|
|||
void UHS_NI InitEntry(uint8_t index) { |
|||
thePool[index].address.devAddress = 0; |
|||
thePool[index].epcount = 1; |
|||
thePool[index].speed = 0; |
|||
for(uint8_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) { |
|||
thePool[index].epinfo[i] = &dev0ep; |
|||
} |
|||
}; |
|||
|
|||
// Returns thePool index for a given address
|
|||
|
|||
uint8_t UHS_NI FindAddressIndex(uint8_t address = 0) { |
|||
for(uint8_t i = 1; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) { |
|||
if(thePool[i].address.devAddress == address) |
|||
return i; |
|||
} |
|||
return 0; |
|||
}; |
|||
|
|||
// Returns thePool child index for a given parent
|
|||
|
|||
uint8_t UHS_NI FindChildIndex(UHS_DeviceAddress addr, uint8_t start = 1) { |
|||
for(uint8_t i = (start < 1 || start >= UHS_HOST_MAX_INTERFACE_DRIVERS) ? 1 : start; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) { |
|||
if(thePool[i].address.bmParent == addr.bmAddress) |
|||
return i; |
|||
} |
|||
return 0; |
|||
}; |
|||
|
|||
// Frees address entry specified by index parameter
|
|||
|
|||
void UHS_NI FreeAddressByIndex(uint8_t index) { |
|||
// Zero field is reserved and should not be affected
|
|||
if(index == 0) |
|||
return; |
|||
|
|||
UHS_DeviceAddress uda = thePool[index].address; |
|||
// If a hub was switched off all port addresses should be freed
|
|||
if(uda.bmHub == 1) { |
|||
for(uint8_t i = 1; (i = FindChildIndex(uda, i));) |
|||
FreeAddressByIndex(i); |
|||
|
|||
// FIXME: use BIT MASKS
|
|||
// If the hub had the last allocated address, hubCounter should be decremented
|
|||
if(hubCounter == uda.bmAddress) |
|||
hubCounter--; |
|||
} |
|||
InitEntry(index); |
|||
} |
|||
|
|||
void InitAllAddresses(void) { |
|||
for(uint8_t i = 1; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) InitEntry(i); |
|||
hubCounter = 0; |
|||
}; |
|||
public: |
|||
|
|||
AddressPool() { |
|||
hubCounter = 0; |
|||
// Zero address is reserved
|
|||
InitEntry(0); |
|||
|
|||
thePool[0].epinfo[0] = &dev0ep; |
|||
dev0ep.epAddr = 0; |
|||
#if UHS_DEVICE_WINDOWS_USB_SPEC_VIOLATION_DESCRIPTOR_DEVICE |
|||
dev0ep.maxPktSize = 0x40; //starting at 0x40 and work down
|
|||
#else |
|||
dev0ep.maxPktSize = 0x08; |
|||
#endif |
|||
dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
|
|||
dev0ep.bmNakPower = UHS_USB_NAK_MAX_POWER; |
|||
InitAllAddresses(); |
|||
}; |
|||
|
|||
// Returns a pointer to a specified address entry
|
|||
|
|||
UHS_Device* UHS_NI GetUsbDevicePtr(uint8_t addr) { |
|||
if(!addr) |
|||
return thePool; |
|||
|
|||
uint8_t index = FindAddressIndex(addr); |
|||
|
|||
return (!index) ? NULL : &thePool[index]; |
|||
}; |
|||
|
|||
|
|||
// Allocates new address
|
|||
|
|||
uint8_t UHS_NI AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 1) { |
|||
/* if (parent != 0 && port == 0)
|
|||
USB_HOST_SERIAL.println("PRT:0"); */ |
|||
UHS_DeviceAddress _parent; |
|||
_parent.devAddress = parent; |
|||
if(_parent.bmReserved || port > 7) |
|||
//if(parent > 127 || port > 7)
|
|||
return 0; |
|||
|
|||
// FIXME: use BIT MASKS
|
|||
if(is_hub && hubCounter == 7) |
|||
return 0; |
|||
|
|||
// finds first empty address entry starting from one
|
|||
uint8_t index = FindAddressIndex(0); |
|||
|
|||
if(!index) // if empty entry is not found
|
|||
return 0; |
|||
|
|||
UHS_DeviceAddress addr; |
|||
addr.devAddress = port; |
|||
addr.bmParent = _parent.bmAddress; |
|||
|
|||
// FIXME: use BIT MASKS
|
|||
if(is_hub) { |
|||
hubCounter++; |
|||
addr.bmHub = 1; |
|||
addr.bmAddress = hubCounter; |
|||
} |
|||
thePool[index].address = addr; |
|||
#if DEBUG_PRINTF_EXTRA_HUGE |
|||
#if defined(UHS_DEBUG_USB_ADDRESS) |
|||
printf("Address: %x (%x.%x.%x)\r\n", addr.devAddress, addr.bmHub, addr.bmParent, addr.bmAddress); |
|||
#endif |
|||
#endif |
|||
return thePool[index].address.devAddress; |
|||
}; |
|||
|
|||
void UHS_NI FreeAddress(uint8_t addr) { |
|||
// if the root hub is disconnected all the addresses should be initialized
|
|||
if(addr == 0x41) { |
|||
InitAllAddresses(); |
|||
return; |
|||
} |
|||
uint8_t index = FindAddressIndex(addr); |
|||
FreeAddressByIndex(index); |
|||
}; |
|||
|
|||
}; |
|||
|
|||
#endif // __ADDRESS_H__
|
@ -0,0 +1,70 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
#if !defined(_usb_h_) || defined(__HEXDUMP_H__) |
|||
#error "Never include UHS_hexdump.h directly; include UHS_Usb.h instead" |
|||
#else |
|||
#define __HEXDUMP_H__ |
|||
|
|||
extern int UsbDEBUGlvl; |
|||
|
|||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> |
|||
class HexDumper : public BASE_CLASS { |
|||
uint8_t byteCount; |
|||
OFFSET_TYPE byteTotal; |
|||
|
|||
public: |
|||
|
|||
HexDumper() : byteCount(0), byteTotal(0) { |
|||
}; |
|||
|
|||
void Initialize(void) { |
|||
byteCount = 0; |
|||
byteTotal = 0; |
|||
}; |
|||
|
|||
virtual void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset); |
|||
}; |
|||
|
|||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> |
|||
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { |
|||
if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
|
|||
for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { |
|||
if(!byteCount) { |
|||
PrintHex<OFFSET_TYPE > (byteTotal, 0x80); |
|||
E_Notify(PSTR(": "), 0x80); |
|||
} |
|||
PrintHex<uint8_t > (pbuf[j], 0x80); |
|||
E_Notify(PSTR(" "), 0x80); |
|||
|
|||
if(byteCount == 15) { |
|||
E_Notify(PSTR("\r\n"), 0x80); |
|||
byteCount = 0xFF; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif // __HEXDUMP_H__
|
@ -0,0 +1,111 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
/* USB functions */ |
|||
#ifndef _UHS_host_h_ |
|||
#define _UHS_host_h_ |
|||
|
|||
// WARNING: Do not change the order of includes, or stuff will break!
|
|||
#include <inttypes.h> |
|||
#include <stddef.h> |
|||
#include <stdio.h> |
|||
#include <stdint.h> |
|||
|
|||
#if DISABLED(USE_UHS3_USB) |
|||
#include <ISR_safe_memory.h> |
|||
#include <Wire.h> |
|||
#include <SPI.h> |
|||
#include <UHS_ByteBuffer.h> |
|||
#endif |
|||
#include "UHS_macros.h" |
|||
|
|||
// None of these should ever be directly included by a driver, or a user's sketch.
|
|||
#include "../dyn_SWI/dyn_SWI.h" |
|||
#include "UHS_USB_IDs.h" |
|||
#include "UHS_settings.h" |
|||
#include "UHS_usb_ch9.h" |
|||
#include "UHS_UsbCore.h" |
|||
#include "UHS_address.h" |
|||
#include "UHS_usbhost.h" |
|||
#include "UHS_printhex.h" |
|||
#include "UHS_message.h" |
|||
|
|||
// Load system components as required
|
|||
#if defined(LOAD_USB_HOST_SYSTEM) && !defined(USB_HOST_SYSTEM_LOADED) |
|||
#include "UHS_util_INLINE.h" |
|||
#include "UHS_host_INLINE.h" |
|||
#include "UHS_printf_HELPER.h" |
|||
|
|||
#if defined(LOAD_USB_HOST_SHIELD) |
|||
#include "USB_HOST_SHIELD/USB_HOST_SHIELD.h" |
|||
#endif |
|||
|
|||
#if defined(LOAD_UHS_KINETIS_FS_HOST) && !defined(UHS_KINETIS_FS_HOST_LOADED) |
|||
#include "UHS_KINETIS_FS_HOST/UHS_KINETIS_FS_HOST.h" |
|||
#endif |
|||
|
|||
#if defined(LOAD_UHS_KINETIS_EHCI) && !defined(UHS_KINETIS_EHCI_LOADED) |
|||
#include "UHS_KINETIS_EHCI/UHS_KINETIS_EHCI.h" |
|||
#endif |
|||
|
|||
// Load USB drivers and multiplexers
|
|||
|
|||
#if defined(LOAD_UHS_HUB) |
|||
#include "UHS_HUB/UHS_HUB.h" |
|||
#endif // HUB loaded
|
|||
|
|||
#if defined(LOAD_UHS_BULK_STORAGE) |
|||
#include "UHS_BULK_STORAGE/UHS_BULK_STORAGE.h" |
|||
#endif |
|||
|
|||
#if defined(LOAD_GENERIC_STORAGE) |
|||
#include "../UHS_FS/UHS_FS.h" |
|||
#endif |
|||
// Add BT and optionally HID if directed to do so
|
|||
#if defined(LOAD_UHS_BT) |
|||
#include "UHS_BT/UHS_BT.h" |
|||
#endif // BT and optionally HID loaded
|
|||
|
|||
// Add HID
|
|||
#if defined(LOAD_UHS_HID) |
|||
#include "UHS_HID/UHS_HID.h" |
|||
#endif // HID loaded
|
|||
|
|||
// Add CDC multiplexers (currently only ACM)
|
|||
#if defined(LOAD_UHS_CDC_ACM) || defined(LOAD_UHS_CDC_ACM_FTDI) || defined(LOAD_UHS_CDC_ACM_PROLIFIC) || defined(LOAD_UHS_CDC_ACM_XR21B1411) |
|||
#include "UHS_CDC/UHS_CDC.h" |
|||
#endif // CDC loaded
|
|||
|
|||
#if defined(LOAD_UHS_ADK) |
|||
#include "UHS_ADK/UHS_ADK.h" |
|||
#endif |
|||
|
|||
#if defined(LOAD_UHS_MIDI) |
|||
#include "UHS_MIDI/UHS_MIDI.h" |
|||
#endif |
|||
|
|||
#endif // System code loaded
|
|||
|
|||
#endif // _UHS_host_h_
|
File diff suppressed because it is too large
@ -0,0 +1,393 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(MACROS_H) |
|||
#define MACROS_H |
|||
#include "macro_logic.h" |
|||
/*
|
|||
* Universal Arduino(tm) "IDE" fixups. |
|||
*/ |
|||
|
|||
|
|||
// Just in case...
|
|||
#ifndef SERIAL_PORT_MONITOR |
|||
#define SERIAL_PORT_MONITOR Serial |
|||
#endif |
|||
|
|||
#ifndef INT16_MIN |
|||
#define INT16_MIN -32768 |
|||
#endif |
|||
// require 10607+
|
|||
#if defined(ARDUINO) && ARDUINO >=10607 |
|||
// nop :-)
|
|||
#else |
|||
#error "Arduino version too old, and must be at least 1.6.7" |
|||
#endif |
|||
|
|||
// Nuke screwed up macro junk from the IDE.
|
|||
#ifdef __cplusplus |
|||
#if defined(true) |
|||
#undef true |
|||
#endif |
|||
#if defined(false) |
|||
#undef false |
|||
#endif |
|||
#endif |
|||
|
|||
|
|||
#if !defined(UHS_DEVICE_WINDOWS_USB_SPEC_VIOLATION_DESCRIPTOR_DEVICE) |
|||
|
|||
#if !defined(UHS_BIG_FLASH) |
|||
|
|||
#if defined(FLASHEND) && defined(FLASHSTART) |
|||
#if (FLASHEND - FLASHSTART) > 0x0FFFFU |
|||
#define UHS_BIG_FLASH 1 |
|||
#else |
|||
#define UHS_BIG_FLASH 0 |
|||
#endif |
|||
|
|||
#elif defined(__PIC32_FLASH_SIZE) |
|||
#if __PIC32_FLASH_SIZE > 511 |
|||
#define UHS_BIG_FLASH 1 |
|||
#else |
|||
#define UHS_BIG_FLASH 0 |
|||
#endif |
|||
|
|||
#elif defined(FLASHEND) && !defined(FLASHSTART) |
|||
// Assumes flash starts at 0x00000, is this a safe assumption?
|
|||
// 192K + should be OK
|
|||
#if FLASHEND > 0x02FFFFU |
|||
#define UHS_BIG_FLASH 1 |
|||
#else |
|||
#define UHS_BIG_FLASH 0 |
|||
#endif |
|||
|
|||
#elif defined(IFLASH_SIZE) |
|||
#if IFLASH_SIZE > 0x0FFFFU |
|||
#define UHS_BIG_FLASH 1 |
|||
#else |
|||
#define UHS_BIG_FLASH 0 |
|||
#endif |
|||
|
|||
#elif defined(ESP8266) |
|||
#define UHS_BIG_FLASH 1 |
|||
#define SYSTEM_OR_SPECIAL_YIELD(...) yield() |
|||
|
|||
#elif defined(__arm__) && defined(CORE_TEENSY) |
|||
#define UHS_BIG_FLASH 1 |
|||
|
|||
#elif defined(ARDUINO_spresense_ast) |
|||
#define UHS_BIG_FLASH 1 |
|||
#else |
|||
// safe default
|
|||
#warning Small flash? |
|||
#define UHS_BIG_FLASH 0 |
|||
#endif |
|||
#endif |
|||
|
|||
#if UHS_BIG_FLASH |
|||
#define UHS_DEVICE_WINDOWS_USB_SPEC_VIOLATION_DESCRIPTOR_DEVICE 1 |
|||
#else |
|||
#define UHS_DEVICE_WINDOWS_USB_SPEC_VIOLATION_DESCRIPTOR_DEVICE 0 |
|||
#endif |
|||
#endif |
|||
|
|||
#if defined(__arm__) && defined(CORE_TEENSY) |
|||
#define UHS_PIN_WRITE(p, v) digitalWriteFast(p, v) |
|||
#define UHS_PIN_READ(p) digitalReadFast(p) |
|||
#endif |
|||
// TODO: Fast inline code for AVR and SAM based microcontrollers
|
|||
// This can be done pretty easily.
|
|||
// For now, this will just work out-of-the-box.
|
|||
#if !defined(UHS_PIN_WRITE) |
|||
#define UHS_PIN_WRITE(p, v) digitalWrite(p, v) |
|||
#endif |
|||
#if !defined(UHS_PIN_READ) |
|||
#define UHS_PIN_READ(p) digitalRead(p) |
|||
#endif |
|||
|
|||
#if defined( __PIC32MX__ ) && !defined(interrupts) // compiling with Microchip XC32 compiler
|
|||
#define interrupts() __builtin_enable_interrupts() |
|||
#edfine noInterrupts() __builtin_disable_interrupts() |
|||
#endif |
|||
|
|||
#if !defined(ARDUINO_SAMD_ZERO) |
|||
#if defined(ARDUINO_AVR_ADK) |
|||
#define UHS_GET_DPI(x) (x == 54 ? 6 : digitalPinToInterrupt(x)) |
|||
#else |
|||
#define UHS_GET_DPI(x) digitalPinToInterrupt(x) |
|||
#endif |
|||
#else |
|||
#define UHS_GET_DPI(x) (x) |
|||
#endif |
|||
|
|||
#ifndef __AVR__ |
|||
#ifndef __PGMSPACE_H_ |
|||
// This define should prevent reading the system pgmspace.h if included elsewhere
|
|||
// This is not normally needed.
|
|||
#define __PGMSPACE_H_ 1 |
|||
#endif |
|||
|
|||
#ifndef PROGMEM |
|||
#define PROGMEM |
|||
#endif |
|||
#ifndef PGM_P |
|||
#define PGM_P const char * |
|||
#endif |
|||
#ifndef PSTR |
|||
#define PSTR(str) (str) |
|||
#endif |
|||
#ifndef F |
|||
#define F(str) (str) |
|||
#endif |
|||
#ifndef _SFR_BYTE |
|||
#define _SFR_BYTE(n) (n) |
|||
#endif |
|||
#ifndef memchr_P |
|||
#define memchr_P(str, c, len) memchr((str), (c), (len)) |
|||
#endif |
|||
#ifndef memcmp_P |
|||
#define memcmp_P(a, b, n) memcmp((a), (b), (n)) |
|||
#endif |
|||
#ifndef memcpy_P |
|||
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) |
|||
#endif |
|||
#ifndef memmem_P |
|||
#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) |
|||
#endif |
|||
#ifndef memrchr_P |
|||
#define memrchr_P(str, val, len) memrchr((str), (val), (len)) |
|||
#endif |
|||
#ifndef strcat_P |
|||
#define strcat_P(dest, src) strcat((dest), (src)) |
|||
#endif |
|||
#ifndef strchr_P |
|||
#define strchr_P(str, c) strchr((str), (c)) |
|||
#endif |
|||
#ifndef strchrnul_P |
|||
#define strchrnul_P(str, c) strchrnul((str), (c)) |
|||
#endif |
|||
#ifndef strcmp_P |
|||
#define strcmp_P(a, b) strcmp((a), (b)) |
|||
#endif |
|||
#ifndef strcpy_P |
|||
#define strcpy_P(dest, src) strcpy((dest), (src)) |
|||
#endif |
|||
#ifndef strcasecmp_P |
|||
#define strcasecmp_P(a, b) strcasecmp((a), (b)) |
|||
#endif |
|||
#ifndef strcasestr_P |
|||
#define strcasestr_P(a, b) strcasestr((a), (b)) |
|||
#endif |
|||
#ifndef strlcat_P |
|||
#define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) |
|||
#endif |
|||
#ifndef strlcpy_P |
|||
#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) |
|||
#endif |
|||
#ifndef strlen_P |
|||
#define strlen_P(s) strlen((const char *)(s)) |
|||
#endif |
|||
#ifndef strnlen_P |
|||
#define strnlen_P(str, len) strnlen((str), (len)) |
|||
#endif |
|||
#ifndef strncmp_P |
|||
#define strncmp_P(a, b, n) strncmp((a), (b), (n)) |
|||
#endif |
|||
#ifndef strncasecmp_P |
|||
#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) |
|||
#endif |
|||
#ifndef strncat_P |
|||
#define strncat_P(a, b, n) strncat((a), (b), (n)) |
|||
#endif |
|||
#ifndef strncpy_P |
|||
#define strncpy_P(a, b, n) strncmp((a), (b), (n)) |
|||
#endif |
|||
#ifndef strpbrk_P |
|||
#define strpbrk_P(str, chrs) strpbrk((str), (chrs)) |
|||
#endif |
|||
#ifndef strrchr_P |
|||
#define strrchr_P(str, c) strrchr((str), (c)) |
|||
#endif |
|||
#ifndef strsep_P |
|||
#define strsep_P(strp, delim) strsep((strp), (delim)) |
|||
#endif |
|||
#ifndef strspn_P |
|||
#define strspn_P(str, chrs) strspn((str), (chrs)) |
|||
#endif |
|||
#ifndef strstr_P |
|||
#define strstr_P(a, b) strstr((a), (b)) |
|||
#endif |
|||
#ifndef sprintf_P |
|||
#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__) |
|||
#endif |
|||
#ifndef vfprintf_P |
|||
#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__) |
|||
#endif |
|||
#ifndef printf_P |
|||
#define printf_P(...) printf(__VA_ARGS__) |
|||
#endif |
|||
#ifndef snprintf_P |
|||
#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__) |
|||
#endif |
|||
#ifndef vsprintf_P |
|||
#define vsprintf_P(s, ...) ((s),__VA_ARGS__) |
|||
#endif |
|||
#ifndef vsnprintf_P |
|||
#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__) |
|||
#endif |
|||
#ifndef fprintf_P |
|||
#define fprintf_P(s, ...) ((s), __VA_ARGS__) |
|||
#endif |
|||
|
|||
#ifndef pgm_read_byte |
|||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) |
|||
#endif |
|||
#ifndef pgm_read_word |
|||
#define pgm_read_word(addr) (*(const unsigned short *)(addr)) |
|||
#endif |
|||
#ifndef pgm_read_dword |
|||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) |
|||
#endif |
|||
#ifndef pgm_read_float |
|||
#define pgm_read_float(addr) (*(const float *)(addr)) |
|||
#endif |
|||
|
|||
#ifndef pgm_read_byte_near |
|||
#define pgm_read_byte_near(addr) pgm_read_byte(addr) |
|||
#endif |
|||
#ifndef pgm_read_word_near |
|||
#define pgm_read_word_near(addr) pgm_read_word(addr) |
|||
#endif |
|||
#ifndef pgm_read_dword_near |
|||
#define pgm_read_dword_near(addr) pgm_read_dword(addr) |
|||
#endif |
|||
#ifndef pgm_read_float_near |
|||
#define pgm_read_float_near(addr) pgm_read_float(addr) |
|||
#endif |
|||
#ifndef pgm_read_byte_far |
|||
#define pgm_read_byte_far(addr) pgm_read_byte(addr) |
|||
#endif |
|||
#ifndef pgm_read_word_far |
|||
#define pgm_read_word_far(addr) pgm_read_word(addr) |
|||
#endif |
|||
#ifndef pgm_read_dword_far |
|||
#define pgm_read_dword_far(addr) pgm_read_dword(addr) |
|||
#endif |
|||
#ifndef pgm_read_float_far |
|||
#define pgm_read_float_far(addr) pgm_read_float(addr) |
|||
#endif |
|||
|
|||
#ifndef pgm_read_pointer |
|||
#define pgm_read_pointer |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// HANDY MACROS
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
// Atmoically set/clear single bits using bitbands.
|
|||
// Believe it or not, this boils down to a constant,
|
|||
// and is less code than using |= &= operators.
|
|||
// Bonus, it makes code easier to read too.
|
|||
// Bitbanding is a wonderful thing.
|
|||
#define BITNR(i) (i&0x1?0:i&0x2?1:i&0x4?2:i&0x8?3:i&0x10?4:i&0x20?5:i&0x40?6:i&0x80?7:i&0x100?8:i&0x200?9:i&0x400?10:i&0x800?11:i&0x1000?12:i&0x2000?13:i&0x4000?14:i&0x8000?15:i&0x10000?16:i&0x20000?17:i&0x40000?18:i&0x80000?19:i&0x100000?20:i&0x200000?21:i&0x400000?22:i&0x800000?23:i&0x1000000?24:i&0x2000000?25:i&0x4000000?26:i&0x8000000?27:i&0x10000000?28:i&0x20000000?29:i&0x40000000?30:i&0x80000000?31:32) |
|||
#define UHS_KIO_BITBAND_ADDR(r, i) (((uint32_t)&(r) - 0x40000000) * 32 + (i) * 4 + 0x42000000) |
|||
#define UHS_KIO_SETBIT_ATOMIC(r, m) (*(uint32_t *)UHS_KIO_BITBAND_ADDR((r), BITNR((m)))) = 1 |
|||
#define UHS_KIO_CLRBIT_ATOMIC(r, m) (*(uint32_t *)UHS_KIO_BITBAND_ADDR((r), BITNR((m)))) = 0 |
|||
|
|||
|
|||
#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h))) |
|||
#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h))) |
|||
#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el) |
|||
#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el); |
|||
|
|||
#define UHS_SWAP_VALUES(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) |
|||
#ifndef __BYTE_GRABBING_DEFINED__ |
|||
#define __BYTE_GRABBING_DEFINED__ 1 |
|||
#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN |
|||
// Note: Use this if your compiler generates horrible assembler!
|
|||
#define UHS_UINT8_BYTE0(__usi__) (((uint8_t *)&(__usi__))[0]) |
|||
#define UHS_UINT8_BYTE1(__usi__) (((uint8_t *)&(__usi__))[1]) |
|||
#define UHS_UINT8_BYTE2(__usi__) (((uint8_t *)&(__usi__))[2]) |
|||
#define UHS_UINT8_BYTE3(__usi__) (((uint8_t *)&(__usi__))[3]) |
|||
#define UHS_UINT8_BYTE4(__usi__) (((uint8_t *)&(__usi__))[4]) |
|||
#define UHS_UINT8_BYTE5(__usi__) (((uint8_t *)&(__usi__))[5]) |
|||
#define UHS_UINT8_BYTE6(__usi__) (((uint8_t *)&(__usi__))[6]) |
|||
#define UHS_UINT8_BYTE7(__usi__) (((uint8_t *)&(__usi__))[7]) |
|||
#else |
|||
// Note: The cast alone to uint8_t is actually enough.
|
|||
// GCC throws out the "& 0xff", and the size is no different.
|
|||
// Some compilers need it.
|
|||
#define UHS_UINT8_BYTE0(__usi__) ((uint8_t)((__usi__) & 0xff )) |
|||
#define UHS_UINT8_BYTE1(__usi__) ((uint8_t)(((__usi__) >> 8) & 0xff)) |
|||
#define UHS_UINT8_BYTE2(__usi__) ((uint8_t)(((__usi__) >> 16) & 0xff)) |
|||
#define UHS_UINT8_BYTE3(__usi__) ((uint8_t)(((__usi__) >> 24) & 0xff)) |
|||
#define UHS_UINT8_BYTE4(__usi__) ((uint8_t)(((__usi__) >> 32) & 0xff)) |
|||
#define UHS_UINT8_BYTE5(__usi__) ((uint8_t)(((__usi__) >> 40) & 0xff)) |
|||
#define UHS_UINT8_BYTE6(__usi__) ((uint8_t)(((__usi__) >> 48) & 0xff)) |
|||
#define UHS_UINT8_BYTE7(__usi__) ((uint8_t)(((__usi__) >> 56) & 0xff)) |
|||
#endif |
|||
#define UHS_UINT16_SET_BYTE1(__usi__) ((uint16_t)(__usi__) << 8) |
|||
#define UHS_UINT32_SET_BYTE1(__usi__) ((uint32_t)(__usi__) << 8) |
|||
#define UHS_UINT64_SET_BYTE1(__usi__) ((uint64_t)(__usi__) << 8) |
|||
#define UHS_UINT32_SET_BYTE2(__usi__) ((uint32_t)(__usi__) << 16) |
|||
#define UHS_UINT64_SET_BYTE2(__usi__) ((uint64_t)(__usi__) << 16) |
|||
#define UHS_UINT32_SET_BYTE3(__usi__) ((uint32_t)(__usi__) << 24) |
|||
#define UHS_UINT64_SET_BYTE3(__usi__) ((uint64_t)(__usi__) << 24) |
|||
#define UHS_UINT64_SET_BYTE4(__usi__) ((uint64_t)(__usi__) << 32) |
|||
#define UHS_UINT64_SET_BYTE5(__usi__) ((uint64_t)(__usi__) << 40) |
|||
#define UHS_UINT64_SET_BYTE6(__usi__) ((uint64_t)(__usi__) << 48) |
|||
#define UHS_UINT64_SET_BYTE7(__usi__) ((uint64_t)(__usi__) << 56) |
|||
|
|||
// These are the smallest and fastest ways I have found so far in pure C/C++.
|
|||
#define UHS_BYTES_TO_UINT16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)UHS_UINT16_SET_BYTE1(__usc1__))) |
|||
#define UHS_BYTES_TO_UINT32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | UHS_UINT32_SET_BYTE1(__usc1__) | UHS_UINT32_SET_BYTE2(__usc2__) | UHS_UINT32_SET_BYTE3(__usc3__))) |
|||
#define UHS_BYTES_TO_UINT64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | UHS_UINT64_SET_BYTE1(__usc1__) | UHS_UINT64_SET_BYTE2(__usc2__) | UHS_UINT64_SET_BYTE3(__usc3__) | UHS_UINT64_SET_BYTE4(__usc4__) | UHS_UINT64_SET_BYTE5(__usc5__) | UHS_UINT64_SET_BYTE6(__usc6__) | UHS_UINT64_SET_BYTE7(__usc7__))) |
|||
#endif |
|||
/*
|
|||
* Debug macros. |
|||
* Useful when porting from UHS2. |
|||
* Do not use these for any new code. |
|||
* Change to better debugging after port is completed. |
|||
* Strings are stored in progmem (flash) instead of RAM. |
|||
*/ |
|||
#define USBTRACE1(s,l) (Notify(PSTR(s), l)) |
|||
#define USBTRACE(s) (USBTRACE1((s), 0x80)); USB_HOST_SERIAL.flush() |
|||
#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l)) |
|||
#define USBTRACE3X(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l)) |
|||
#define USBTRACE2(s,r) (USBTRACE3((s),(r),0x80)); USB_HOST_SERIAL.flush() |
|||
#define USBTRACE2X(s,r) (USBTRACE3X((s),(r),0x80)); USB_HOST_SERIAL.flush() |
|||
|
|||
#define VOID0 ((void)0) |
|||
#if !defined(NOTUSED) |
|||
#define NOTUSED(...) __VA_ARGS__ __attribute__((unused)) |
|||
#endif |
|||
#endif /* MACROS_H */ |
|||
|
@ -0,0 +1,91 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
#if !defined(_UHS_host_h_) || defined(__MESSAGE_H__) |
|||
#error "Never include UHS_message.h directly; include UHS_Usb.h instead" |
|||
#else |
|||
#define __MESSAGE_H__ |
|||
|
|||
extern int UsbDEBUGlvl; |
|||
|
|||
void E_Notify(char const * msg, int lvl); |
|||
void E_Notify(uint8_t b, int lvl); |
|||
void E_NotifyStr(char const * msg, int lvl); |
|||
void E_Notifyc(char c, int lvl); |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
#define Notify E_Notify |
|||
#define NotifyStr E_NotifyStr |
|||
#define Notifyc E_Notifyc |
|||
void NotifyFailGetDevDescr(uint8_t reason); |
|||
void NotifyFailSetDevTblEntry(uint8_t reason); |
|||
void NotifyFailGetConfDescr(uint8_t reason); |
|||
void NotifyFailSetConfDescr(uint8_t reason); |
|||
void NotifyFailGetDevDescr(void); |
|||
void NotifyFailSetDevTblEntry(void); |
|||
void NotifyFailGetConfDescr(void); |
|||
void NotifyFailSetConfDescr(void); |
|||
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); |
|||
void NotifyFail(uint8_t rcode); |
|||
#else |
|||
#define Notify(...) VOID0 |
|||
#define NotifyStr(...) VOID0 |
|||
#define Notifyc(...) VOID0 |
|||
#define NotifyFailGetDevDescr(...) VOID0 |
|||
#define NotifyFailSetDevTblEntry(...) VOID0 |
|||
#define NotifyFailGetConfDescr(...) VOID0 |
|||
#define NotifyFailGetDevDescr(...) VOID0 |
|||
#define NotifyFailSetDevTblEntry(...) VOID0 |
|||
#define NotifyFailGetConfDescr(...) VOID0 |
|||
#define NotifyFailSetConfDescr(...) VOID0 |
|||
#define NotifyFailUnknownDevice(...) VOID0 |
|||
#define NotifyFail(...) VOID0 |
|||
#endif |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
template <class ERROR_TYPE> void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { |
|||
Notify(msg, level); |
|||
Notify(PSTR(": "), level); |
|||
D_PrintHex<ERROR_TYPE > (rcode, level); |
|||
Notify(PSTR("\r\n"), level); |
|||
#else |
|||
template <class ERROR_TYPE> void ErrorMessage(NOTUSED(uint8_t level), NOTUSED(char const * msg), ERROR_TYPE rcode = 0) { |
|||
(void)rcode; |
|||
#endif |
|||
} |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
template <class ERROR_TYPE> void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { |
|||
Notify(msg, 0x80); |
|||
Notify(PSTR(": "), 0x80); |
|||
D_PrintHex<ERROR_TYPE > (rcode, 0x80); |
|||
Notify(PSTR("\r\n"), 0x80); |
|||
#else |
|||
template <class ERROR_TYPE> void ErrorMessage(NOTUSED(char const * msg), ERROR_TYPE rcode = 0) { |
|||
(void)rcode; |
|||
#endif |
|||
} |
|||
|
|||
#endif // __MESSAGE_H__
|
@ -0,0 +1,201 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#ifndef UHS_PRINTF_HELPER_H |
|||
#define UHS_PRINTF_HELPER_H |
|||
|
|||
#if defined(LOAD_UHS_PRINTF_HELPER) |
|||
#include <Arduino.h> |
|||
#ifdef true |
|||
#undef true |
|||
#endif |
|||
#ifdef false |
|||
#undef false |
|||
#endif |
|||
|
|||
#if !defined(STDIO_IS_OK_TO_USE_AS_IS) |
|||
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAM_DUE) || defined(ARDUINO_spresense_ast) |
|||
// STDIO patching not required.
|
|||
#define STDIO_IS_OK_TO_USE_AS_IS |
|||
#endif |
|||
#endif |
|||
|
|||
#if !defined(STDIO_IS_OK_TO_USE_AS_IS) |
|||
// We need to patch STDIO so it can be used.
|
|||
|
|||
#ifndef SERIAL_PORT_MONITOR |
|||
// Some don't define this.
|
|||
#define SERIAL_PORT_MONITOR Serial |
|||
#endif |
|||
|
|||
#ifndef SERIAL_PORT_HARDWARE |
|||
// Some don't define this.
|
|||
#define SERIAL_PORT_HARDWARE SERIAL_PORT_MONITOR |
|||
#endif |
|||
|
|||
#ifndef USB_HOST_SERIAL |
|||
#if defined(SERIAL_PORT_USBVIRTUAL) && defined(LOAD_UHS_KINETIS_FS_HOST) |
|||
#define USB_HOST_SERIAL SERIAL_PORT_HARDWARE |
|||
#else |
|||
#define USB_HOST_SERIAL SERIAL_PORT_MONITOR |
|||
#endif |
|||
#endif |
|||
|
|||
#if !defined(NOTUSED) |
|||
#define NOTUSED(...) __VA_ARGS__ __attribute__((unused)) |
|||
#endif |
|||
|
|||
#ifndef __AVR__ |
|||
#ifndef printf_P |
|||
#define printf_P(...) printf(__VA_ARGS__) |
|||
#endif |
|||
#endif |
|||
|
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
/*
|
|||
* For printf() output with pic32 Arduino |
|||
*/ |
|||
extern "C" { |
|||
|
|||
void _mon_putc(char s) { |
|||
USB_HOST_SERIAL.write(s); |
|||
} |
|||
|
|||
int _mon_getc() { |
|||
while(!USB_HOST_SERIAL.available()); |
|||
return USB_HOST_SERIAL.read(); |
|||
} |
|||
} |
|||
|
|||
#elif defined(__AVR__) |
|||
extern "C" { |
|||
|
|||
static FILE tty_stdio; |
|||
static FILE tty_stderr; |
|||
|
|||
static int NOTUSED(tty_stderr_putc(char c, NOTUSED(FILE *t))); |
|||
static int NOTUSED(tty_stderr_flush(NOTUSED(FILE *t))); |
|||
static int NOTUSED(tty_std_putc(char c, NOTUSED(FILE *t))); |
|||
static int NOTUSED(tty_std_getc(NOTUSED(FILE *t))); |
|||
static int NOTUSED(tty_std_flush(NOTUSED(FILE *t))); |
|||
|
|||
static int tty_stderr_putc(char c, NOTUSED(FILE *t)) { |
|||
USB_HOST_SERIAL.write(c); |
|||
return 0; |
|||
} |
|||
|
|||
static int tty_stderr_flush(NOTUSED(FILE *t)) { |
|||
USB_HOST_SERIAL.flush(); |
|||
return 0; |
|||
} |
|||
|
|||
static int tty_std_putc(char c, NOTUSED(FILE *t)) { |
|||
USB_HOST_SERIAL.write(c); |
|||
return 0; |
|||
} |
|||
|
|||
static int tty_std_getc(NOTUSED(FILE *t)) { |
|||
while(!USB_HOST_SERIAL.available()); |
|||
return USB_HOST_SERIAL.read(); |
|||
} |
|||
|
|||
static int tty_std_flush(NOTUSED(FILE *t)) { |
|||
USB_HOST_SERIAL.flush(); |
|||
return 0; |
|||
} |
|||
} |
|||
#elif defined(CORE_TEENSY) |
|||
extern "C" { |
|||
|
|||
int _write(int fd, const char *ptr, int len) { |
|||
int j; |
|||
for(j = 0; j < len; j++) { |
|||
if(fd == 1) |
|||
USB_HOST_SERIAL.write(*ptr++); |
|||
else if(fd == 2) |
|||
USB_HOST_SERIAL.write(*ptr++); |
|||
} |
|||
return len; |
|||
} |
|||
|
|||
int _read(int fd, char *ptr, int len) { |
|||
if(len > 0 && fd == 0) { |
|||
while(!USB_HOST_SERIAL.available()); |
|||
*ptr = USB_HOST_SERIAL.read(); |
|||
return 1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
#include <sys/stat.h> |
|||
|
|||
int _fstat(int fd, struct stat *st) { |
|||
memset(st, 0, sizeof (*st)); |
|||
st->st_mode = S_IFCHR; |
|||
st->st_blksize = 1024; |
|||
return 0; |
|||
} |
|||
|
|||
int _isatty(int fd) { |
|||
return (fd < 3) ? 1 : 0; |
|||
} |
|||
} |
|||
#else |
|||
#error no STDIO |
|||
#endif // defined(ARDUINO_ARCH_PIC32)
|
|||
|
|||
|
|||
|
|||
#if defined(__AVR__) |
|||
// The only wierdo in the bunch...
|
|||
void UHS_AVR_printf_HELPER_init(void) { |
|||
// Set up stdio/stderr
|
|||
tty_stdio.put = tty_std_putc; |
|||
tty_stdio.get = tty_std_getc; |
|||
tty_stdio.flags = _FDEV_SETUP_RW; |
|||
tty_stdio.udata = 0; |
|||
|
|||
tty_stderr.put = tty_stderr_putc; |
|||
tty_stderr.get = NULL; |
|||
tty_stderr.flags = _FDEV_SETUP_WRITE; |
|||
tty_stderr.udata = 0; |
|||
|
|||
stdout = &tty_stdio; |
|||
stdin = &tty_stdio; |
|||
stderr = &tty_stderr; |
|||
|
|||
} |
|||
#define UHS_printf_HELPER_init() UHS_AVR_printf_HELPER_init() |
|||
#endif |
|||
|
|||
#endif /* STDIO_IS_OK_TO_USE_AS_IS */ |
|||
#endif /* load.... */ |
|||
|
|||
#if !defined(UHS_printf_HELPER_init) |
|||
#define UHS_printf_HELPER_init() (void(0)) |
|||
#endif |
|||
#endif /* UHS_PRINTF_HELPER_H */ |
|||
|
@ -0,0 +1,96 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(_UHS_host_h_) || defined(__PRINTHEX_H__) |
|||
#error "Never include UHS_printhex.h directly; include UHS_Usb.h instead" |
|||
#else |
|||
#define __PRINTHEX_H__ |
|||
|
|||
void E_Notifyc(char c, int lvl); |
|||
|
|||
template <class T> |
|||
void PrintHex(T val, int lvl) { |
|||
int num_nibbles = sizeof (T) * 2; |
|||
|
|||
do { |
|||
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); |
|||
if(v > 57) v += 7; |
|||
E_Notifyc(v, lvl); |
|||
} while(--num_nibbles); |
|||
} |
|||
|
|||
template <class T> |
|||
void PrintBin(T val, int lvl) { |
|||
for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) |
|||
if(val & mask) |
|||
E_Notifyc('1', lvl); |
|||
else |
|||
E_Notifyc('0', lvl); |
|||
} |
|||
|
|||
template <class T> |
|||
void SerialPrintHex(T val) { |
|||
int num_nibbles = sizeof (T) * 2; |
|||
|
|||
do { |
|||
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); |
|||
if(v > 57) v += 7; |
|||
USB_HOST_SERIAL.print(v); |
|||
} while(--num_nibbles); |
|||
} |
|||
|
|||
template <class T> |
|||
void PrintHex2(Print *prn, T val) { |
|||
T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2)); |
|||
|
|||
while(mask > 1) { |
|||
if(val < mask) |
|||
prn->print("0"); |
|||
|
|||
mask >>= 4; |
|||
} |
|||
prn->print((T)val, HEX); |
|||
} |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
template <class T> void D_PrintHex(T val, int lvl) { |
|||
PrintHex<T > (val, lvl); |
|||
#else |
|||
template <class T> void D_PrintHex(NOTUSED(T val), NOTUSED(int lvl)) { |
|||
#endif |
|||
} |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
template <class T> void D_PrintBin(T val, int lvl) { |
|||
PrintBin<T > (val, lvl); |
|||
#else |
|||
template <class T> void D_PrintBin(NOTUSED(T val), NOTUSED(int lvl)) { |
|||
#endif |
|||
} |
|||
|
|||
|
|||
|
|||
#endif // __PRINTHEX_H__
|
@ -0,0 +1,141 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#ifndef UHS_SETTINGS_H |
|||
#define UHS_SETTINGS_H |
|||
|
|||
// TO-DO: Move specific settings to modules which use them.
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Define any of these options at the top of your sketch to override
|
|||
// the defaults contained herewith. Do NOT do modifications here.
|
|||
// Individual Components have their own settings.
|
|||
//
|
|||
// Macro | Settings and notes | Default
|
|||
// -----------------------------+-----------------------+-----------------------
|
|||
// | Any class that does |
|
|||
// USB_HOST_SERIAL | text streaming | SERIAL_PORT_MONITOR
|
|||
// | e.g. Serial2 |
|
|||
// -----------------------------+-----------------------+-----------------------
|
|||
// ENABLE_UHS_DEBUGGING | 0 = off, 1 = on | 0
|
|||
// -----------------------------+-----------------------+-----------------------
|
|||
// | 0 = off, 1 = on |
|
|||
// | Caution! Can make |
|
|||
// DEBUG_PRINTF_EXTRA_HUGE | program too large! | 0
|
|||
// | Other modules depend |
|
|||
// | on this setting. |
|
|||
// -----------------------------+-----------------------+-----------------------
|
|||
// USE_UHS_BLACK_WIDDOW | 0 = no, 1 = yes | 0
|
|||
// -----------------------------+-----------------------+-----------------------
|
|||
// ENABLE_WII_IR_CAMERA | 0 = no, 1 = yes | 0
|
|||
// -----------------------------^-----------------------^-----------------------
|
|||
//
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// DEBUGGING
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
#ifndef USB_HOST_SERIAL |
|||
#if defined(SERIAL_PORT_USBVIRTUAL) && defined(LOAD_UHS_KINETIS_FS_HOST) |
|||
#define USB_HOST_SERIAL SERIAL_PORT_HARDWARE |
|||
#else |
|||
#define USB_HOST_SERIAL SERIAL_PORT_MONITOR |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef ENABLE_UHS_DEBUGGING |
|||
#define ENABLE_UHS_DEBUGGING 0 |
|||
#endif |
|||
|
|||
#ifndef DEBUG_PRINTF_EXTRA_HUGE |
|||
#define DEBUG_PRINTF_EXTRA_HUGE 0 |
|||
#endif |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Manual board activation
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
/* Set this to 1 if you are using a Black Widdow */ |
|||
#ifndef USE_UHS_BLACK_WIDDOW |
|||
#define USE_UHS_BLACK_WIDDOW 0 |
|||
#endif |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Wii IR camera
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
/* Set this to 1 to activate code for the Wii IR camera */ |
|||
#ifndef ENABLE_WII_IR_CAMERA |
|||
#define ENABLE_WII_IR_CAMERA 0 |
|||
#endif |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// Set to 1 to use the faster spi4teensy3 driver. (not used yet))
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
#ifndef USE_SPI4TEENSY3 |
|||
#define USE_SPI4TEENSY3 0 |
|||
#endif |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
// AUTOMATIC Settings
|
|||
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
// No user serviceable parts below this line.
|
|||
// DO NOT change anything below here unless you are a developer!
|
|||
|
|||
#if defined(__GNUC__) && defined(__AVR__) |
|||
#ifndef GCC_VERSION |
|||
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) |
|||
#endif |
|||
#if GCC_VERSION < 40602 // Test for GCC < 4.6.2
|
|||
#ifdef PROGMEM |
|||
#undef PROGMEM |
|||
#define PROGMEM __attribute__((section(".progmem.data"))) // Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734#c4
|
|||
#ifdef PSTR |
|||
#undef PSTR |
|||
#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) // Copied from pgmspace.h in avr-libc source
|
|||
#endif |
|||
#endif |
|||
#endif |
|||
#endif |
|||
|
|||
#if !defined(DEBUG_USB_HOST) && ENABLE_UHS_DEBUGGING |
|||
#define DEBUG_USB_HOST |
|||
#endif |
|||
|
|||
#if !defined(WIICAMERA) && ENABLE_WII_IR_CAMERA |
|||
#define WIICAMERA |
|||
#endif |
|||
|
|||
#define UHS_SLEEP_MS(v) pUsb->sof_delay(v) |
|||
|
|||
#ifndef UHS_NI |
|||
#define UHS_NI __attribute__((noinline)) |
|||
#endif |
|||
|
|||
#endif /* SETTINGS_H */ |
@ -0,0 +1,222 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(_UHS_host_h_) || defined(_UHS_ch9_h_) |
|||
#error "Never include UHS_usb_ch9.h directly; include UHS_Usb.h instead" |
|||
#else |
|||
|
|||
/* USB chapter 9 structures */ |
|||
#define _UHS_ch9_h_ |
|||
|
|||
/* Misc.USB constants */ |
|||
#define DEV_DESCR_LEN 18 //device descriptor length
|
|||
#define CONF_DESCR_LEN 9 //configuration descriptor length
|
|||
#define INTR_DESCR_LEN 9 //interface descriptor length
|
|||
#define EP_DESCR_LEN 7 //endpoint descriptor length
|
|||
|
|||
/* Standard Device Requests */ |
|||
#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
|
|||
#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
|
|||
#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
|
|||
#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
|
|||
#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
|
|||
#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
|
|||
#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
|
|||
#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
|
|||
#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
|
|||
#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
|
|||
#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
|
|||
|
|||
/* Wireless USB Device Requests */ |
|||
#define USB_REQ_SET_ENCRYPTION 0x0D |
|||
#define USB_REQ_GET_ENCRYPTION 0x0E |
|||
#define USB_REQ_RPIPE_ABORT 0x0E |
|||
#define USB_REQ_SET_HANDSHAKE 0x0F |
|||
#define USB_REQ_RPIPE_RESET 0x0F |
|||
#define USB_REQ_GET_HANDSHAKE 0x10 |
|||
#define USB_REQ_SET_CONNECTION 0x11 |
|||
#define USB_REQ_SET_SECURITY_DATA 0x12 |
|||
#define USB_REQ_GET_SECURITY_DATA 0x13 |
|||
#define USB_REQ_SET_WUSB_DATA 0x14 |
|||
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 |
|||
#define USB_REQ_LOOPBACK_DATA_READ 0x16 |
|||
#define USB_REQ_SET_INTERFACE_DS 0x17 |
|||
|
|||
/* USB feature flags */ |
|||
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ |
|||
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ |
|||
#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ |
|||
#define USB_DEVICE_BATTERY 2 /* (wireless) */ |
|||
#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ |
|||
#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ |
|||
#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ |
|||
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ |
|||
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ |
|||
|
|||
#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
|
|||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
|
|||
#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
|
|||
/* OTG SET FEATURE Constants */ |
|||
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
|
|||
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
|
|||
#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
|
|||
|
|||
/* Setup Data Constants */ |
|||
#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
|
|||
#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
|
|||
#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
|
|||
#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
|
|||
#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
|
|||
#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
|
|||
#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
|
|||
#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
|
|||
#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
|
|||
#define USB_SETUP_RECIPIENT_PORT 0x04 // Wireless USB 1.0
|
|||
#define USB_SETUP_RECIPIENT_RPIPE 0x05 // Wireless USB 1.0
|
|||
|
|||
|
|||
/* USB descriptors */ |
|||
#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
|
|||
#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
|
|||
#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
|
|||
#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
|
|||
#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
|
|||
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
|
|||
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
|
|||
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
|
|||
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
|
|||
#define USB_DESCRIPTOR_DEBUG 0x0a |
|||
#define USB_DESCRIPTOR_INTERFACE_ASSOCIATION 0x0b |
|||
#define USB_DESCRIPTOR_SECURITY 0x0c |
|||
#define USB_DESCRIPTOR_KEY 0x0d |
|||
#define USB_DESCRIPTOR_ENCRYPTION_TYPE 0x0e |
|||
#define USB_DESCRIPTOR_BOS 0x0f |
|||
#define USB_DESCRIPTOR_DEVICE_CAPABILITY 0x10 |
|||
#define USB_DESCRIPTOR_WIRELESS_ENDPOINT_COMP 0x11 |
|||
#define USB_DESCRIPTOR_WIRE_ADAPTER 0x21 |
|||
#define USB_DESCRIPTOR_RPIPE 0x22 |
|||
#define USB_DESCRIPTOR_CS_RADIO_CONTROL 0x23 |
|||
#define USB_DESCRIPTOR_SS_ENDPOINT_COMP 0x30 |
|||
|
|||
#define USB_HID_DESCRIPTOR 0x21 |
|||
|
|||
|
|||
// Conventional codes for class-specific descriptors. "Common Class" Spec (3.11)
|
|||
#define USB_DESCRIPTOR_CS_DEVICE 0x21 |
|||
#define USB_DESCRIPTOR_CS_CONFIG 0x22 |
|||
#define USB_DESCRIPTOR_CS_STRING 0x23 |
|||
#define USB_DESCRIPTOR_CS_INTERFACE 0x24 |
|||
#define USB_DESCRIPTOR_CS_ENDPOINT 0x25 |
|||
|
|||
|
|||
|
|||
/* USB Endpoint Transfer Types */ |
|||
#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
|
|||
#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
|
|||
#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
|
|||
#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
|
|||
#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
|
|||
#define USB_TRANSFER_DIRECTION_IN 0x80 // Indicate direction is IN
|
|||
|
|||
/* Standard Feature Selectors for CLEAR_FEATURE Requests */ |
|||
#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
|
|||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
|
|||
#define USB_FEATURE_TEST_MODE 2 // Device recipient
|
|||
|
|||
/* descriptor data structures */ |
|||
|
|||
/* Device descriptor structure */ |
|||
typedef struct { |
|||
uint8_t bLength; // Length of this descriptor.
|
|||
uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
|||
uint16_t bcdUSB; // USB Spec Release Number (BCD).
|
|||
uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
|||
uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
|||
uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
|||
uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
|||
uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
|
|||
uint16_t idProduct; // Product ID (assigned by the manufacturer).
|
|||
uint16_t bcdDevice; // Device release number (BCD).
|
|||
uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
|
|||
uint8_t iProduct; // Index of String Descriptor describing the product.
|
|||
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
|||
uint8_t bNumConfigurations; // Number of possible configurations.
|
|||
} __attribute__((packed)) USB_DEVICE_DESCRIPTOR; |
|||
|
|||
/* Configuration descriptor structure */ |
|||
typedef struct { |
|||
uint8_t bLength; // Length of this descriptor.
|
|||
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
|||
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
|||
uint8_t bNumInterfaces; // Number of interfaces in this configuration.
|
|||
uint8_t bConfigurationValue; // Value of this configuration (1 based).
|
|||
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
|||
uint8_t bmAttributes; // Configuration characteristics.
|
|||
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
|||
} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; |
|||
|
|||
/* Interface descriptor structure */ |
|||
typedef struct { |
|||
uint8_t bLength; // Length of this descriptor.
|
|||
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
|||
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
|||
uint8_t bAlternateSetting; // Value of this alternate interface setting.
|
|||
uint8_t bNumEndpoints; // Number of endpoints in this interface.
|
|||
uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
|||
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
|||
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
|||
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
|||
} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR; |
|||
|
|||
/* Endpoint descriptor structure */ |
|||
typedef struct { |
|||
uint8_t bLength; // Length of this descriptor.
|
|||
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
|||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
|||
uint8_t bmAttributes; // Endpoint transfer type.
|
|||
uint16_t wMaxPacketSize; // Maximum packet size.
|
|||
uint8_t bInterval; // Polling interval in frames.
|
|||
} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; |
|||
|
|||
/* HID descriptor */ |
|||
/*
|
|||
typedef struct { |
|||
uint8_t bLength; |
|||
uint8_t bDescriptorType; |
|||
uint16_t bcdHID; // HID class specification release
|
|||
uint8_t bCountryCode; |
|||
uint8_t bNumDescriptors; // Number of additional class specific descriptors
|
|||
uint8_t bDescrType; // Type of class descriptor
|
|||
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
|||
} __attribute__((packed)) USB_HID_DESCRIPTOR; |
|||
*/ |
|||
|
|||
typedef struct { |
|||
uint8_t bDescrType; // Type of class descriptor
|
|||
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
|||
} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; |
|||
|
|||
#endif // _ch9_h_
|
@ -0,0 +1,452 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if !defined(_UHS_host_h_) |
|||
#error "Never include UHS_usbhost.h directly; include UHS_host.h instead" |
|||
#else |
|||
#if !defined(_USBHOST_H_) |
|||
#define _USBHOST_H_ |
|||
|
|||
// Very early prototypes
|
|||
#if defined(UHS_LOAD_BT) |
|||
void UHS_BT_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei); |
|||
void UHS_BT_ScanUninitialized(UHS_USB_HOST_BASE *host); |
|||
void UHS_BT_Poll(UHS_USB_HOST_BASE *host); |
|||
#endif |
|||
#if defined(UHS_LOAD_HID) |
|||
void UHS_HID_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei); |
|||
void UHS_HID_ScanUninitialized(UHS_USB_HOST_BASE *host); |
|||
void UHS_HID_Poll(UHS_USB_HOST_BASE *host); |
|||
#endif |
|||
|
|||
//#if defined(LOAD_UHS_CDC_ACM) || defined(LOAD_UHS_CDC_ACM_FTDI) || defined(LOAD_UHS_CDC_ACM_PROLIFIC) || defined(LOAD_UHS_CDC_ACM_XR21B1411)
|
|||
//void UHS_CDC_ACM_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei);
|
|||
//void UHS_CDC_ACM_ScanUninitialized(UHS_USB_HOST_BASE *host);
|
|||
//void UHS_CDC_ACM_Poll(UHS_USB_HOST_BASE *host);
|
|||
//#endif
|
|||
|
|||
class UHS_USBInterface; // forward class declaration
|
|||
|
|||
// enumerator to turn the VBUS on/off
|
|||
|
|||
typedef enum { |
|||
vbus_on = 0, |
|||
vbus_off = 1 |
|||
} VBUS_t; |
|||
|
|||
// All host SEI use this base class
|
|||
|
|||
class UHS_USB_HOST_BASE { |
|||
public: |
|||
AddressPool addrPool; |
|||
UHS_USBInterface* devConfig[UHS_HOST_MAX_INTERFACE_DRIVERS]; |
|||
volatile uint8_t usb_error; |
|||
volatile uint8_t usb_task_state; |
|||
volatile uint8_t usb_task_polling_disabled; |
|||
volatile uint8_t usb_host_speed; |
|||
volatile uint8_t hub_present; |
|||
|
|||
UHS_USB_HOST_BASE(void) { |
|||
for(uint16_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) { |
|||
devConfig[i] = NULL; |
|||
} |
|||
usb_task_polling_disabled = 0; |
|||
usb_task_state = UHS_USB_HOST_STATE_INITIALIZE; //set up state machine
|
|||
usb_host_speed = 0; |
|||
usb_error = 0; |
|||
}; |
|||
|
|||
/////////////////////////////////////////////
|
|||
//
|
|||
// Virtual methods that interface to the SIE
|
|||
// Overriding each is mandatory.
|
|||
//
|
|||
/////////////////////////////////////////////
|
|||
|
|||
/**
|
|||
* Delay for x milliseconds |
|||
* Override if your controller provides an SOF IRQ, which may involve |
|||
* some sort of reentrant ISR or workaround with interrupts enabled. |
|||
* |
|||
* @param x how many milliseconds to delay |
|||
* @return true if delay completed without a state change, false if delay aborted |
|||
*/ |
|||
virtual bool UHS_NI sof_delay(uint16_t x) { |
|||
if(!(usb_task_state & UHS_USB_HOST_STATE_MASK)) return false; |
|||
uint8_t current_state = usb_task_state; |
|||
while(current_state == usb_task_state && x--) { |
|||
delay(1); |
|||
} |
|||
return (current_state == usb_task_state); |
|||
}; |
|||
|
|||
virtual UHS_EpInfo * UHS_NI ctrlReqOpen(NOTUSED(uint8_t addr), NOTUSED(uint64_t Request), NOTUSED(uint8_t* dataptr)) { |
|||
return NULL; |
|||
}; |
|||
|
|||
virtual void UHS_NI vbusPower(NOTUSED(VBUS_t state)) { |
|||
}; |
|||
|
|||
virtual void UHS_NI Task(void) { |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI SetAddress(NOTUSED(uint8_t addr), NOTUSED(uint8_t ep), NOTUSED(UHS_EpInfo **ppep), NOTUSED(uint16_t &nak_limit)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI OutTransfer(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t nak_limit), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *data)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI InTransfer(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t nak_limit), NOTUSED(uint16_t *nbytesptr), NOTUSED(uint8_t *data)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI ctrlReqClose(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint8_t bmReqType), NOTUSED(uint16_t left), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *dataptr)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI ctrlReqRead(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t *left), NOTUSED(uint16_t *read), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *dataptr)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI dispatchPkt(NOTUSED(uint8_t token), NOTUSED(uint8_t ep), NOTUSED(uint16_t nak_limit)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t UHS_NI init(void) { |
|||
return 0; |
|||
}; |
|||
|
|||
virtual void UHS_NI doHostReset(void) { |
|||
}; |
|||
|
|||
virtual int16_t UHS_NI Init(NOTUSED(int16_t mseconds)) { |
|||
return -1; |
|||
}; |
|||
|
|||
virtual int16_t UHS_NI Init(void) { |
|||
return Init(INT16_MIN); |
|||
}; |
|||
|
|||
virtual uint8_t hwlPowerUp(void) { |
|||
/* This is for machine specific support to enable/power up the USB HW to operate*/ |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual uint8_t hwPowerDown(void) { |
|||
/* This is for machine specific support to disable/powerdown the USB Hw */ |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
virtual bool IsHub(uint8_t klass) { |
|||
return (klass == UHS_USB_CLASS_HUB); |
|||
}; |
|||
|
|||
virtual void UHS_NI suspend_host(void) { |
|||
// Used on MCU that lack control of IRQ priority (AVR).
|
|||
// Suspends ISRs, for critical code. IRQ will be serviced after it is resumed.
|
|||
// NOTE: you must track the state yourself!
|
|||
}; |
|||
|
|||
virtual void UHS_NI resume_host(void) { |
|||
// Used on MCU that lack control of IRQ priority (AVR).
|
|||
// Resumes ISRs.
|
|||
// NOTE: you must track the state yourself!
|
|||
}; |
|||
|
|||
/////////////////////////////////////////////
|
|||
//
|
|||
// Built-ins, No need to override
|
|||
//
|
|||
/////////////////////////////////////////////
|
|||
// these two probably will go away, and won't be used, TBD
|
|||
inline void Poll_Others(void) { |
|||
#if defined(UHS_LOAD_BT) |
|||
UHS_BT_Poll(this); |
|||
#endif |
|||
#if defined(UHS_LOAD_HID) |
|||
UHS_HID_Poll(this); |
|||
#endif |
|||
} |
|||
|
|||
inline void DisablePoll(void) { |
|||
noInterrupts(); |
|||
usb_task_polling_disabled++; |
|||
DDSB(); |
|||
interrupts(); |
|||
} |
|||
|
|||
inline void EnablePoll(void) { |
|||
noInterrupts(); |
|||
usb_task_polling_disabled--; |
|||
DDSB(); |
|||
interrupts(); |
|||
} |
|||
|
|||
uint8_t UHS_NI seekInterface(ENUMERATION_INFO *ei, uint16_t inf, USB_CONFIGURATION_DESCRIPTOR *ucd); |
|||
|
|||
uint8_t UHS_NI setEpInfoEntry(uint8_t addr, uint8_t iface, uint8_t epcount, volatile UHS_EpInfo* eprecord_ptr); |
|||
|
|||
uint8_t UHS_NI EPClearHalt(uint8_t addr, uint8_t ep); |
|||
|
|||
uint8_t UHS_NI ctrlReq(uint8_t addr, uint64_t Request, uint16_t nbytes, uint8_t* dataptr); |
|||
|
|||
uint8_t UHS_NI getDevDescr(uint8_t addr, uint16_t nbytes, uint8_t* dataptr); |
|||
|
|||
uint8_t UHS_NI getConfDescr(uint8_t addr, uint16_t nbytes, uint8_t conf, uint8_t* dataptr); |
|||
|
|||
uint8_t UHS_NI setAddr(uint8_t oldaddr, uint8_t newaddr); |
|||
|
|||
uint8_t UHS_NI setConf(uint8_t addr, uint8_t conf_value); |
|||
|
|||
uint8_t UHS_NI getStrDescr(uint8_t addr, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr); |
|||
|
|||
void UHS_NI ReleaseDevice(uint8_t addr); |
|||
|
|||
uint8_t UHS_NI Configuring(uint8_t parent, uint8_t port, uint8_t speed); |
|||
|
|||
void UHS_NI DeviceDefaults(uint8_t maxep, UHS_USBInterface *device); |
|||
|
|||
UHS_EpInfo* UHS_NI getEpInfoEntry(uint8_t addr, uint8_t ep); |
|||
|
|||
inline uint8_t getUsbTaskState(void) { |
|||
return ( usb_task_state); |
|||
}; |
|||
|
|||
inline AddressPool* GetAddressPool(void) { |
|||
return &addrPool; |
|||
}; |
|||
|
|||
int UHS_NI RegisterDeviceClass(UHS_USBInterface *pdev) { |
|||
for(uint8_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) { |
|||
if(!devConfig[i]) { |
|||
devConfig[i] = pdev; |
|||
return i; |
|||
} |
|||
} |
|||
//return UHS_HOST_ERROR_CANT_REGISTER_DEVICE_CLASS;
|
|||
return -1; |
|||
}; |
|||
#if 0 |
|||
|
|||
inline void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { |
|||
addrPool.ForEachUsbDevice(pfunc); |
|||
}; |
|||
#endif |
|||
|
|||
uint8_t TestInterface(ENUMERATION_INFO *ei); |
|||
uint8_t enumerateInterface(ENUMERATION_INFO *ei); |
|||
uint8_t getNextInterface(ENUMERATION_INFO *ei, UHS_EpInfo *pep, uint8_t data[], uint16_t *left, uint16_t *read, uint8_t *offset); |
|||
uint8_t initDescrStream(ENUMERATION_INFO *ei, USB_CONFIGURATION_DESCRIPTOR *ucd, UHS_EpInfo *pep, uint8_t *data, uint16_t *left, uint16_t *read, uint8_t *offset); |
|||
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data); |
|||
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data); |
|||
uint8_t doSoftReset(uint8_t parent, uint8_t port, uint8_t address); |
|||
uint8_t getone(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint8_t *dataptr, uint8_t *offset); |
|||
uint8_t eat(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint8_t *dataptr, uint8_t *offset, uint16_t *yum); |
|||
|
|||
}; |
|||
|
|||
// All device interface drivers use this subclass
|
|||
|
|||
class UHS_USBInterface { |
|||
public: |
|||
|
|||
UHS_USB_HOST_BASE *pUsb; // Parent USB host
|
|||
volatile uint8_t bNumEP; // total number of EP in this interface
|
|||
volatile UHS_EpInfo epInfo[16]; // This is a stub, override in the driver.
|
|||
|
|||
volatile uint8_t bAddress; // address of the device
|
|||
volatile uint8_t bConfNum; // configuration number
|
|||
volatile uint8_t bIface; // interface value
|
|||
volatile bool bPollEnable; // poll enable flag, operating status
|
|||
volatile uint32_t qNextPollTime; // next poll time
|
|||
|
|||
/**
|
|||
* Resets interface driver to unused state. You should override this in |
|||
* your driver if it requires extra class variable cleanup. |
|||
*/ |
|||
virtual void DriverDefaults(void) { |
|||
printf("Default driver defaults.\r\n"); |
|||
pUsb->DeviceDefaults(bNumEP, this); |
|||
}; |
|||
|
|||
/**
|
|||
* Checks if this interface is supported. |
|||
* Executed called when new devices are connected. |
|||
* |
|||
* @param ei |
|||
* @return true if the interface is supported |
|||
*/ |
|||
virtual bool OKtoEnumerate(NOTUSED(ENUMERATION_INFO *ei)) { |
|||
return false; |
|||
}; |
|||
|
|||
/**
|
|||
* Configures any needed endpoint information for an interface. |
|||
* You must provide this in your driver. |
|||
* Executed when new devices are connected and OKtoEnumerate() |
|||
* returned true. |
|||
* |
|||
* @param ei |
|||
* @return zero on success |
|||
*/ |
|||
virtual uint8_t SetInterface(NOTUSED(ENUMERATION_INFO *ei)) { |
|||
return UHS_HOST_ERROR_NOT_IMPLEMENTED; |
|||
}; |
|||
|
|||
/**
|
|||
* Interface specific additional setup and enumeration that |
|||
* can't occur when the descriptor stream is open. |
|||
* Also used for collection of unclaimed interfaces, to link to the master. |
|||
* |
|||
* @return zero on success |
|||
*/ |
|||
virtual uint8_t Finalize(void) { |
|||
return 0; |
|||
}; |
|||
|
|||
/**
|
|||
* Executed after interface is finalized but, before polling has started. |
|||
* |
|||
* @return 0 on success |
|||
*/ |
|||
virtual uint8_t OnStart(void) { |
|||
return 0; |
|||
}; |
|||
|
|||
/**
|
|||
* Start interface polling |
|||
* @return |
|||
*/ |
|||
virtual uint8_t Start(void) { |
|||
uint8_t rcode = OnStart(); |
|||
if(!rcode) bPollEnable = true; |
|||
return rcode; |
|||
}; |
|||
|
|||
/**
|
|||
* Executed before anything else in Release(). |
|||
* |
|||
*/ |
|||
virtual void OnRelease(void) { |
|||
return; |
|||
}; |
|||
|
|||
/**
|
|||
* Release resources when device is disconnected. |
|||
* Normally this does not need to be overridden. |
|||
*/ |
|||
virtual void Release(void) { |
|||
OnRelease(); |
|||
DriverDefaults(); |
|||
return; |
|||
}; |
|||
|
|||
/**
|
|||
* Executed After driver polls. |
|||
* Can be used when there is an important change detected during polling |
|||
* and you want to handle it elsewhere. |
|||
* Examples: |
|||
* Media status change for bulk, e.g. ready, not-ready, media changed, door opened. |
|||
* Button state/joystick position/etc changes on a HID device. |
|||
* Flow control status change on a communication device, e.g. CTS on serial |
|||
*/ |
|||
virtual void OnPoll(void) { |
|||
return; |
|||
}; |
|||
|
|||
/**
|
|||
* Poll interface driver. You should override this in your driver if you |
|||
* require polling faster or slower than every 100 milliseconds, or your |
|||
* driver requires special housekeeping. |
|||
*/ |
|||
virtual void Poll() { |
|||
OnPoll(); |
|||
qNextPollTime = millis() + 100; |
|||
}; |
|||
|
|||
virtual bool UHS_NI Polling(void) { |
|||
return bPollEnable; |
|||
} |
|||
|
|||
/**
|
|||
* This is only for a hub. |
|||
* @param port |
|||
*/ |
|||
virtual void ResetHubPort(NOTUSED(uint8_t port)) { |
|||
return; |
|||
}; |
|||
|
|||
#if 0 |
|||
/**
|
|||
* |
|||
* @return true if this interface is Vendor Specific. |
|||
*/ |
|||
virtual bool IsVSI() { |
|||
return false; |
|||
} |
|||
#endif |
|||
}; |
|||
|
|||
#if 0 |
|||
/**
|
|||
* |
|||
* Vendor Specific interface class. |
|||
* This is used by a partner interface. |
|||
* It can also be used to force-enumerate an interface that |
|||
* can use this interface directly. |
|||
* You can also add an instance of this class within the interface constructor |
|||
* if you expect the interface. |
|||
* |
|||
* If this is not needed, it may be removed. Nothing I have written needs this. |
|||
* Let me know if it is not required, then IsVSI method can also be shit-canned. |
|||
* -- AJK |
|||
*/ |
|||
|
|||
class UHS_VSI : public UHS_USBInterface { |
|||
public: |
|||
volatile UHS_EpInfo epInfo[1]; |
|||
volatile ENUMERATION_INFO eInfo; |
|||
UHS_VSI(UHS_USB_HOST_BASE *p); |
|||
bool OKtoEnumerate(ENUMERATION_INFO *ei); |
|||
uint8_t SetInterface(ENUMERATION_INFO *ei); |
|||
virtual void DriverDefaults(void); |
|||
virtual void Release(void); |
|||
|
|||
uint8_t GetAddress(void) { |
|||
return bAddress; |
|||
}; |
|||
|
|||
virtual bool IsVSI() { |
|||
return true; |
|||
} |
|||
|
|||
}; |
|||
#endif |
|||
|
|||
#endif //_USBHOST_H_
|
|||
#endif |
@ -0,0 +1,129 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#if defined(LOAD_USB_HOST_SYSTEM) && !defined(USB_HOST_SYSTEM_UTIL_LOADED) |
|||
#define USB_HOST_SYSTEM_UTIL_LOADED |
|||
|
|||
// 0x80 is the default (i.e. trace) to turn off set this global to something lower.
|
|||
// this allows for 126 other debugging levels.
|
|||
// TO-DO: Allow assignment to a different serial port by software
|
|||
int UsbDEBUGlvl = 0x80; |
|||
|
|||
void E_Notifyc(char c, int lvl) { |
|||
if(UsbDEBUGlvl < lvl) return; |
|||
#if defined(ARDUINO) && ARDUINO >=100 |
|||
USB_HOST_SERIAL.print(c); |
|||
#else |
|||
USB_HOST_SERIAL.print(c, BYTE); |
|||
#endif |
|||
//USB_HOST_SERIAL.flush();
|
|||
} |
|||
|
|||
void E_Notify(char const * msg, int lvl) { |
|||
if(UsbDEBUGlvl < lvl) return; |
|||
if(!msg) return; |
|||
char c; |
|||
|
|||
while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); |
|||
} |
|||
|
|||
void E_NotifyStr(char const * msg, int lvl) { |
|||
if(UsbDEBUGlvl < lvl) return; |
|||
if(!msg) return; |
|||
char c; |
|||
|
|||
while((c = *msg++)) E_Notifyc(c, lvl); |
|||
} |
|||
|
|||
void E_Notify(uint8_t b, int lvl) { |
|||
if(UsbDEBUGlvl < lvl) return; |
|||
#if defined(ARDUINO) && ARDUINO >=100 |
|||
USB_HOST_SERIAL.print(b); |
|||
#else |
|||
USB_HOST_SERIAL.print(b, DEC); |
|||
#endif |
|||
} |
|||
|
|||
void E_Notify(double d, int lvl) { |
|||
if(UsbDEBUGlvl < lvl) return; |
|||
USB_HOST_SERIAL.print(d); |
|||
} |
|||
|
|||
#ifdef DEBUG_USB_HOST |
|||
|
|||
void NotifyFailGetDevDescr(void) { |
|||
Notify(PSTR("\r\ngetDevDescr "), 0x80); |
|||
} |
|||
|
|||
void NotifyFailSetDevTblEntry(void) { |
|||
Notify(PSTR("\r\nsetDevTblEn "), 0x80); |
|||
} |
|||
|
|||
void NotifyFailGetConfDescr(void) { |
|||
Notify(PSTR("\r\ngetConf "), 0x80); |
|||
} |
|||
|
|||
void NotifyFailSetConfDescr(void) { |
|||
Notify(PSTR("\r\nsetConf "), 0x80); |
|||
} |
|||
|
|||
void NotifyFailGetDevDescr(uint8_t reason) { |
|||
NotifyFailGetDevDescr(); |
|||
NotifyFail(reason); |
|||
} |
|||
|
|||
void NotifyFailSetDevTblEntry(uint8_t reason) { |
|||
NotifyFailSetDevTblEntry(); |
|||
NotifyFail(reason); |
|||
|
|||
} |
|||
|
|||
void NotifyFailGetConfDescr(uint8_t reason) { |
|||
NotifyFailGetConfDescr(); |
|||
NotifyFail(reason); |
|||
} |
|||
|
|||
void NotifyFailSetConfDescr(uint8_t reason) { |
|||
NotifyFailSetConfDescr(); |
|||
NotifyFail(reason); |
|||
} |
|||
|
|||
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { |
|||
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); |
|||
D_PrintHex<uint16_t > (VID, 0x80); |
|||
Notify(PSTR(" PID: "), 0x80); |
|||
D_PrintHex<uint16_t > (PID, 0x80); |
|||
} |
|||
|
|||
void NotifyFail(uint8_t rcode) { |
|||
D_PrintHex<uint8_t > (rcode, 0x80); |
|||
Notify(PSTR("\r\n"), 0x80); |
|||
} |
|||
#endif |
|||
|
|||
#else |
|||
#error "Never include UHS_util_INLINE.h, include UHS_host.h instead" |
|||
#endif |
@ -0,0 +1,226 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This software may be distributed and modified under the terms of the GNU |
|||
General Public License version 2 (GPL2) as published by the Free Software |
|||
Foundation and appearing in the file GPL2.TXT included in the packaging of |
|||
this file. Please note that GPL2 Section 2[b] requires that all works based |
|||
on this software must also be made publicly available under the terms of |
|||
the GPL2 ("Copyleft"). |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
#if !defined(USB_HOST_SHIELD_H) || defined(_max3421e_h_) |
|||
#error "Never include UHS_max3421e.h directly; include USB_HOST_SHIELD.h instead" |
|||
#else |
|||
|
|||
#define _max3421e_h_ |
|||
|
|||
/* MAX3421E register/bit names and bitmasks */ |
|||
|
|||
#define SE0 0 |
|||
#define SE1 1 |
|||
#define FSHOST 2 |
|||
#define LSHOST 3 |
|||
|
|||
/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ |
|||
|
|||
//
|
|||
// MAX3421E Registers in HOST mode.
|
|||
//
|
|||
#define rRCVFIFO 0x08 // Receive FIFO Register
|
|||
#define rSNDFIFO 0x10 // Send FIFO Register
|
|||
#define rSUDFIFO 0x20 // Set Up Data FIFO Register
|
|||
#define rRCVBC 0x30 // Receive FIFO Byte Count Register
|
|||
#define rSNDBC 0x38 // Send FIFO Byte Count Register
|
|||
|
|||
// USB Interrupt Request Status (USBIRQ)
|
|||
#define rUSBIRQ 0x68 // USB Interrupt Request Register
|
|||
#define bmVBUSIRQ 0x40 // Vbus Present Interrupt Request
|
|||
#define bmNOVBUSIRQ 0x20 // Vbus Absent Interrupt Request
|
|||
#define bmOSCOKIRQ 0x01 // Oscillator OK Interrupt Request
|
|||
|
|||
// USB Interrupt Request Control (USBIEN)
|
|||
#define rUSBIEN 0x70 // USB Interrupt Request Enable Register
|
|||
#define bmVBUSIE bmVBUSIRQ // Vbus Present Interrupt Request Enable
|
|||
#define bmNOVBUSIE bmNOVBUSIRQ // Vbus Absent Interrupt Request Enable
|
|||
#define bmOSCOKIE bmOSCOKIRQ // Oscillator OK Interrupt Request Enable
|
|||
|
|||
// (USBCTL)
|
|||
#define rUSBCTL 0x78 //15<<3
|
|||
#define bmCHIPRES 0x20 //b5
|
|||
#define bmPWRDOWN 0x10 //b4
|
|||
|
|||
// (CPUCTL)
|
|||
#define rCPUCTL 0x80 //16<<3
|
|||
#define bmPUSLEWID1 0x80 //b7
|
|||
#define bmPULSEWID0 0x40 //b6
|
|||
#define bmIE 0x01 //b0
|
|||
|
|||
// bmPUSLEWID1 bmPULSEWID0 Pulse width
|
|||
// 0 0 10.6uS
|
|||
// 0 1 5.3uS
|
|||
// 1 0 2.6uS
|
|||
// 1 1 1.3uS
|
|||
#define PUSLEWIDTH10_6 (0) |
|||
#define PUSLEWIDTH5_3 (bmPULSEWID0) |
|||
#define PUSLEWIDTH2_6 (bmPUSLEWID1) |
|||
#define PUSLEWIDTH1_3 (bmPULSEWID0 | bmPUSLEWID1) |
|||
|
|||
// (PINCTL)
|
|||
#define rPINCTL 0x88 //17<<3
|
|||
#define bmFDUPSPI 0x10 //b4
|
|||
#define bmINTLEVEL 0x08 //b3
|
|||
#define bmPOSINT 0x04 //b2
|
|||
#define bmGPXB 0x02 //b1
|
|||
#define bmGPXA 0x01 //b0
|
|||
|
|||
// GPX pin selections
|
|||
#define GPX_OPERATE 0x00 //
|
|||
#define GPX_VBDET 0x01 //
|
|||
#define GPX_BUSACT 0x02 //
|
|||
#define GPX_SOF 0x03 //
|
|||
|
|||
#define rREVISION 0x90 //18<<3
|
|||
|
|||
// (IOPINS1)
|
|||
#define rIOPINS1 0xa0 //20<<3
|
|||
#define bmGPOUT0 0x01 //
|
|||
#define bmGPOUT1 0x02 //
|
|||
#define bmGPOUT2 0x04 //
|
|||
#define bmGPOUT3 0x08 //
|
|||
#define bmGPIN0 0x10 //
|
|||
#define bmGPIN1 0x20 //
|
|||
#define bmGPIN2 0x40 //
|
|||
#define bmGPIN3 0x80 //
|
|||
|
|||
// (IOPINS2)
|
|||
#define rIOPINS2 0xa8 //21<<3
|
|||
#define bmGPOUT4 0x01 //
|
|||
#define bmGPOUT5 0x02 //
|
|||
#define bmGPOUT6 0x04 //
|
|||
#define bmGPOUT7 0x08 //
|
|||
#define bmGPIN4 0x10 //
|
|||
#define bmGPIN5 0x20 //
|
|||
#define bmGPIN6 0x40 //
|
|||
#define bmGPIN7 0x80 //
|
|||
|
|||
// (GPINIRQ)
|
|||
#define rGPINIRQ 0xb0 //22<<3
|
|||
#define bmGPINIRQ0 0x01 //
|
|||
#define bmGPINIRQ1 0x02 //
|
|||
#define bmGPINIRQ2 0x04 //
|
|||
#define bmGPINIRQ3 0x08 //
|
|||
#define bmGPINIRQ4 0x10 //
|
|||
#define bmGPINIRQ5 0x20 //
|
|||
#define bmGPINIRQ6 0x40 //
|
|||
#define bmGPINIRQ7 0x80 //
|
|||
|
|||
// (GPINIEN)
|
|||
#define rGPINIEN 0xb8 //23<<3
|
|||
#define bmGPINIEN0 0x01 //
|
|||
#define bmGPINIEN1 0x02 //
|
|||
#define bmGPINIEN2 0x04 //
|
|||
#define bmGPINIEN3 0x08 //
|
|||
#define bmGPINIEN4 0x10 //
|
|||
#define bmGPINIEN5 0x20 //
|
|||
#define bmGPINIEN6 0x40 //
|
|||
#define bmGPINIEN7 0x80 //
|
|||
|
|||
// (GPINPOL)
|
|||
#define rGPINPOL 0xc0 //24<<3
|
|||
#define bmGPINPOL0 0x01 //
|
|||
#define bmGPINPOL1 0x02 //
|
|||
#define bmGPINPOL2 0x04 //
|
|||
#define bmGPINPOL3 0x08 //
|
|||
#define bmGPINPOL4 0x10 //
|
|||
#define bmGPINPOL5 0x20 //
|
|||
#define bmGPINPOL6 0x40 //
|
|||
#define bmGPINPOL7 0x80 //
|
|||
|
|||
//
|
|||
// If any data transfer errors occur, the HXFRDNIRQ asserts, while the RCVDAVIRQ does not.
|
|||
//
|
|||
// The CPU clears the SNDBAVIRQ by writing the SNDBC register.
|
|||
// The CPU should never directly clear the SNDBAVIRQ bit.
|
|||
|
|||
// Host Interrupt Request Status (HIRQ)
|
|||
#define rHIRQ 0xc8 // Host Interrupt Request Register
|
|||
#define bmBUSEVENTIRQ 0x01 // BUS Reset Done or BUS Resume Interrupt Request
|
|||
#define bmRWUIRQ 0x02 // Remote Wakeup Interrupt Request
|
|||
#define bmRCVDAVIRQ 0x04 // Receive FIFO Data Available Interrupt Request
|
|||
#define bmSNDBAVIRQ 0x08 // Send Buffer Available Interrupt Request
|
|||
#define bmSUSDNIRQ 0x10 // Suspend operation Done Interrupt Request
|
|||
#define bmCONDETIRQ 0x20 // Peripheral Connect/Disconnect Interrupt Request
|
|||
#define bmFRAMEIRQ 0x40 // Frame Generator Interrupt Request
|
|||
#define bmHXFRDNIRQ 0x80 // Host Transfer Done Interrupt Request
|
|||
|
|||
// IRQs that are OK for the CPU to clear
|
|||
#define ICLRALLBITS (bmBUSEVENTIRQ | bmRWUIRQ | bmRCVDAVIRQ | bmSUSDNIRQ | bmCONDETIRQ | bmFRAMEIRQ | bmHXFRDNIRQ) |
|||
|
|||
// Host Interrupt Request Control (HIEN)
|
|||
#define rHIEN 0xd0 //
|
|||
#define bmBUSEVENTIE bmBUSEVENTIRQ // BUS Reset Done or BUS Resume Interrupt Request Enable
|
|||
#define bmRWUIE bmRWUIRQ // Remote Wakeup Interrupt Request Enable
|
|||
#define bmRCVDAVIE bmRCVDAVIRQ // Receive FIFO Data Available Interrupt Request Enable
|
|||
#define bmSNDBAVIE bmSNDBAVIRQ // Send Buffer Available Interrupt Request Enable
|
|||
#define bmSUSDNIE bmSUSDNIRQ // Suspend operation Done Interrupt Request Enable
|
|||
#define bmCONDETIE bmCONDETIRQ // Peripheral Connect/Disconnect Interrupt Request Enable
|
|||
#define bmFRAMEIE bmFRAMEIRQ // Frame Generator Interrupt Request Enable
|
|||
#define bmHXFRDNIE bmHXFRDNIRQ // Host Transfer Done Interrupt Request Enable
|
|||
|
|||
// (MODE))
|
|||
#define rMODE 0xd8 //27<<3
|
|||
#define bmHOST 0x01 //
|
|||
#define bmLOWSPEED 0x02 //
|
|||
#define bmHUBPRE 0x04 //
|
|||
#define bmSOFKAENAB 0x08 //
|
|||
#define bmSEPIRQ 0x10 //
|
|||
#define bmDELAYISO 0x20 //
|
|||
#define bmDMPULLDN 0x40 //
|
|||
#define bmDPPULLDN 0x80 //
|
|||
|
|||
#define rPERADDR 0xe0 //28<<3
|
|||
|
|||
// (HCTL)
|
|||
#define rHCTL 0xe8 //29<<3
|
|||
#define bmBUSRST 0x01 //
|
|||
#define bmFRMRST 0x02 //
|
|||
#define bmSAMPLEBUS 0x04 //
|
|||
#define bmSIGRSM 0x08 //
|
|||
#define bmRCVTOG0 0x10 //
|
|||
#define bmRCVTOG1 0x20 //
|
|||
#define bmSNDTOG0 0x40 //
|
|||
#define bmSNDTOG1 0x80 //
|
|||
|
|||
// Host transfer (HXFR)
|
|||
#define rHXFR 0xf0 //30<<3
|
|||
/* Host transfer token values for writing the HXFR register (R30) */ |
|||
/* OR this bit field with the endpoint number in bits 3:0 */ |
|||
#define MAX3421E_tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1
|
|||
#define MAX3421E_tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0
|
|||
#define MAX3421E_tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0
|
|||
#define MAX3421E_tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0
|
|||
#define MAX3421E_tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0
|
|||
#define MAX3421E_tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0
|
|||
#define MAX3421E_tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
|||
|
|||
// (HRSL)
|
|||
#define rHRSL 0xf8 //31<<3
|
|||
#define bmRCVTOGRD 0x10 //
|
|||
#define bmSNDTOGRD 0x20 //
|
|||
#define bmKSTATUS 0x40 //
|
|||
#define bmJSTATUS 0x80 //
|
|||
#define bmSE0 0x00 //SE0 - disconnect state
|
|||
#define bmSE1 0xc0 //SE1 - illegal state
|
|||
|
|||
#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) |
|||
#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) |
|||
|
|||
#endif //_max3421e_h_
|
@ -0,0 +1,519 @@ |
|||
/* Copyright (C) 2015-2016 Andrew J. Kroll
|
|||
and |
|||
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. |
|||
|
|||
This software may be distributed and modified under the terms of the GNU |
|||
General Public License version 2 (GPL2) as published by the Free Software |
|||
Foundation and appearing in the file GPL2.TXT included in the packaging of |
|||
this file. Please note that GPL2 Section 2[b] requires that all works based |
|||
on this software must also be made publicly available under the terms of |
|||
the GPL2 ("Copyleft"). |
|||
|
|||
Contact information |
|||
------------------- |
|||
|
|||
Circuits At Home, LTD |
|||
Web : http://www.circuitsathome.com
|
|||
e-mail : support@circuitsathome.com |
|||
*/ |
|||
|
|||
#ifndef USB_HOST_SHIELD_H |
|||
#define USB_HOST_SHIELD_H |
|||
|
|||
// uncomment to get 'printf' console debugging. NOT FOR UNO!
|
|||
//#define DEBUG_PRINTF_EXTRA_HUGE_USB_HOST_SHIELD
|
|||
|
|||
#ifdef LOAD_USB_HOST_SHIELD |
|||
#include "UHS_max3421e.h" |
|||
#include <SPI.h> |
|||
|
|||
|
|||
#if !defined(SPI_HAS_TRANSACTION) |
|||
#error "Your SPI library installation is too old." |
|||
#else |
|||
#if !defined(SPI_ATOMIC_VERSION) |
|||
#warning "Your SPI library installation lacks 'SPI_ATOMIC_VERSION'. Please complain to the maintainer." |
|||
#elif SPI_ATOMIC_VERSION < 1 |
|||
#error "Your SPI library installation is too old." |
|||
#endif |
|||
|
|||
#endif |
|||
#if DEBUG_PRINTF_EXTRA_HUGE |
|||
#ifdef DEBUG_PRINTF_EXTRA_HUGE_USB_HOST_SHIELD |
|||
#define MAX_HOST_DEBUG(...) printf_P(__VA_ARGS__) |
|||
#else |
|||
#define MAX_HOST_DEBUG(...) VOID0 |
|||
#endif |
|||
#else |
|||
#define MAX_HOST_DEBUG(...) VOID0 |
|||
#endif |
|||
|
|||
#if !defined(USB_HOST_SHIELD_USE_ISR) |
|||
#if defined(USE_MULTIPLE_APP_API) |
|||
#define USB_HOST_SHIELD_USE_ISR 0 |
|||
#else |
|||
#define USB_HOST_SHIELD_USE_ISR 1 |
|||
#endif |
|||
#else |
|||
#define USB_HOST_SHIELD_USE_ISR 1 |
|||
#endif |
|||
|
|||
|
|||
|
|||
#if !USB_HOST_SHIELD_USE_ISR |
|||
#error NOISR Polled mode _NOT SUPPORTED YET_ |
|||
|
|||
//
|
|||
// Polled defaults
|
|||
//
|
|||
#if defined(BOARD_BLACK_WIDDOW) |
|||
#define UHS_MAX3421E_SS_ 6 |
|||
#define UHS_MAX3421E_INT_ 3 |
|||
#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) |
|||
#if EXT_RAM |
|||
// Teensy++ 2.0 with XMEM2
|
|||
#define UHS_MAX3421E_SS_ 20 |
|||
#define UHS_MAX3421E_INT_ 7 |
|||
#else |
|||
#define UHS_MAX3421E_SS_ 9 |
|||
#define UHS_MAX3421E_INT_ 8 |
|||
#endif |
|||
#define UHS_MAX3421E_SPD |
|||
#elif defined(ARDUINO_AVR_ADK) |
|||
#define UHS_MAX3421E_SS_ 53 |
|||
#define UHS_MAX3421E_INT_ 54 |
|||
#elif defined(ARDUINO_AVR_BALANDUINO) |
|||
#define UHS_MAX3421E_SS_ 20 |
|||
#define UHS_MAX3421E_INT_ 19 |
|||
#else |
|||
#define UHS_MAX3421E_SS_ 10 |
|||
#define UHS_MAX3421E_INT_ 9 |
|||
#endif |
|||
|
|||
#else |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
// PIC32 only allows edge interrupts, isn't that lovely? We'll emulate it...
|
|||
#if CHANGE < 2 |
|||
#error core too old. |
|||
#endif |
|||
|
|||
#define IRQ_IS_EDGE 0 |
|||
#ifndef digitalPinToInterrupt |
|||
// great, this isn't implemented.
|
|||
#warning digitalPinToInterrupt is not defined, complain here https://github.com/chipKIT32/chipKIT-core/issues/114
|
|||
#if defined(_BOARD_UNO_) || defined(_BOARD_UC32_) |
|||
#define digitalPinToInterrupt(p) ((p) == 2 ? 1 : ((p) == 7 ? 2 : ((p) == 8 ? 3 : ((p) == 35 ? 4 : ((p) == 38 ? 0 : NOT_AN_INTERRUPT))))) |
|||
#warning digitalPinToInterrupt is now defined until this is taken care of. |
|||
#else |
|||
#error digitalPinToInterrupt not defined for your board, complain here https://github.com/chipKIT32/chipKIT-core/issues/114
|
|||
#endif |
|||
#endif |
|||
#else |
|||
#define IRQ_IS_EDGE 0 |
|||
#endif |
|||
|
|||
// More stupidity from our friends @ Sony...
|
|||
#if defined(ARDUINO_spresense_ast) |
|||
#if !defined(NOT_AN_INTERRUPT) |
|||
#define NOT_AN_INTERRUPT -1 |
|||
#endif |
|||
#endif |
|||
|
|||
// SAMD uses an enum for this instead of a define. Isn't that just dandy?
|
|||
#if !defined(NOT_AN_INTERRUPT) && !defined(ARDUINO_ARCH_SAMD) |
|||
#warning NOT_AN_INTERRUPT not defined, possible problems ahead. |
|||
#warning If NOT_AN_INTERRUPT is an enum or something else, complain to UHS30 developers on github. |
|||
#warning Otherwise complain to your board core developer/maintainer. |
|||
#define NOT_AN_INTERRUPT -1 |
|||
#endif |
|||
|
|||
//
|
|||
// Interrupt defaults. Int0 or Int1
|
|||
//
|
|||
#ifdef BOARD_BLACK_WIDDOW |
|||
#error "HELP! Please send us an email, I don't know the values for Int0 and Int1 on the Black Widow board!" |
|||
#elif defined(ARDUINO_AVR_ADK) |
|||
#define UHS_MAX3421E_SS_ 53 |
|||
#define UHS_MAX3421E_INT_ 54 |
|||
#elif defined(ARDUINO_spresense_ast) |
|||
#define UHS_MAX3421E_SS_ 21 |
|||
#define UHS_MAX3421E_INT_ 20 |
|||
#define SPIclass SPI5 |
|||
//#define UHS_MAX3421E_SPD 100000
|
|||
#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) |
|||
|
|||
// TO-DO!
|
|||
|
|||
#if EXT_RAM |
|||
// Teensy++ 2.0 with XMEM2
|
|||
#define UHS_MAX3421E_SS_ 20 |
|||
#define UHS_MAX3421E_INT_ 7 |
|||
#else |
|||
#define UHS_MAX3421E_SS_ 9 |
|||
#define UHS_MAX3421E_INT_ 8 |
|||
#endif |
|||
|
|||
#elif defined(ARDUINO_AVR_BALANDUINO) |
|||
#error "ISR mode is currently not supported on the Balanduino. Please set USB_HOST_SHIELD_USE_ISR to 0." |
|||
#else |
|||
#define UHS_MAX3421E_SS_ 10 |
|||
#ifdef __AVR__ |
|||
#if defined(__AVR_ATmega32U4__) |
|||
#define INT_FOR_PIN2 1 |
|||
#define INT_FOR_PIN3 0 |
|||
#else |
|||
// Everybody else???
|
|||
#define INT_FOR_PIN2 0 |
|||
#define INT_FOR_PIN3 1 |
|||
#endif |
|||
#define UHS_MAX3421E_INT_ 3 |
|||
#else |
|||
// Non-avr
|
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
// UNO32 External Interrupts:
|
|||
// Pin 38 (INT0), Pin 2 (INT1), Pin 7 (INT2), Pin 8 (INT3), Pin 35 (INT4)
|
|||
#define UHS_MAX3421E_INT_ 7 |
|||
#else |
|||
#define UHS_MAX3421E_INT_ 9 |
|||
#endif |
|||
#endif |
|||
#endif |
|||
#endif |
|||
|
|||
|
|||
|
|||
#if defined(NO_AUTO_SPEED) |
|||
// Ugly details section...
|
|||
// MAX3421E characteristics
|
|||
// SPI Serial - Clock Input. An external SPI master supplies SCLK with frequencies up to 26MHz. The
|
|||
// logic level is referenced to the voltage on VL. Data is clocked into the SPI slave inter face on the
|
|||
// rising edge of SCLK. Data is clocked out of the SPI slave interface on the falling edge of SCLK.
|
|||
// Serial Clock (SCLK) Period 38.4ns minimum. 17ns minimum pulse width. VL >2.5V
|
|||
// SCLK Fall to MISO Propagation Delay 14.2ns
|
|||
// SCLK Fall to MOSI Propagation Delay 14.2ns
|
|||
// SCLK Fall to MOSI Drive 3.5ns
|
|||
// Theoretical deadline for reply 17.7ns
|
|||
// 26MHz 38.4615ns period <-- MAX3421E theoretical maximum
|
|||
|
|||
#if !defined(UHS_MAX3421E_SPD) |
|||
#if defined(ARDUINO_SAMD_ZERO) |
|||
// Zero violates spec early, needs a long setup time, or doesn't like high latency.
|
|||
#define UHS_MAX3421E_SPD 10000000 |
|||
#elif defined(ARDUINO_ARCH_PIC32) |
|||
// PIC MX 5/6/7 characteristics
|
|||
// 25MHZ 40ns period <-- PIC MX 5/6/7 theoretical maximum
|
|||
// pulse width minimum Tsclk/2ns
|
|||
// Trise/fall 10ns maximum. 5ns is typical but not guaranteed.
|
|||
// Tsetup minimum for MISO 10ns.
|
|||
// We are in violation by 7.7ns @ 25MHz due to latency alone.
|
|||
// Even reading at end of data cycle, we only have a 2.3ns window.
|
|||
// This is too narrow to to compensate for capacitance, trace lengths, and noise.
|
|||
|
|||
// 17.7ns + 10ns = 27.7ns
|
|||
// 18MHz fits and has enough slack time to compensate for capacitance, trace lengths, and noise.
|
|||
// For high speeds the SMP bit is recommended too, which samples at the end instead of the middle.
|
|||
// 20Mhz seems to work.
|
|||
|
|||
#define UHS_MAX3421E_SPD 20000000 |
|||
#else |
|||
#define UHS_MAX3421E_SPD 25000000 |
|||
#endif |
|||
#endif |
|||
#else |
|||
// We start at 25MHz, and back down until hardware can take it.
|
|||
// Of course, SPI library can adjust this for us too.
|
|||
// Why not 26MHz? Because I have not found any MCU board that
|
|||
// can actually go that fast without problems.
|
|||
// Could be a shield limitation too.
|
|||
#if !defined(UHS_MAX3421E_SPD) |
|||
#define UHS_MAX3421E_SPD 25000000 |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef UHS_MAX3421E_INT |
|||
#define UHS_MAX3421E_INT UHS_MAX3421E_INT_ |
|||
#endif |
|||
|
|||
#ifndef UHS_MAX3421E_SS |
|||
#define UHS_MAX3421E_SS UHS_MAX3421E_SS_ |
|||
#endif |
|||
|
|||
// NOTE: On the max3421e the irq enable and irq bits are in the same position.
|
|||
|
|||
// IRQs used if CPU polls
|
|||
#define ENIBITSPOLLED (bmCONDETIE | bmBUSEVENTIE | bmFRAMEIE) |
|||
// IRQs used if CPU is interrupted
|
|||
#define ENIBITSISR (bmCONDETIE | bmBUSEVENTIE | bmFRAMEIE /* | bmRCVDAVIRQ | bmSNDBAVIRQ | bmHXFRDNIRQ */ ) |
|||
|
|||
#if !USB_HOST_SHIELD_USE_ISR |
|||
#define IRQ_CHECK_MASK (ENIBITSPOLLED & ICLRALLBITS) |
|||
#define IRQ_IS_EDGE 0 |
|||
#else |
|||
#define IRQ_CHECK_MASK (ENIBITSISR & ICLRALLBITS) |
|||
#endif |
|||
|
|||
#if IRQ_IS_EDGE |
|||
// Note: UNO32 Interrupts can only be RISING, or FALLING.
|
|||
// This poses an interesting problem, since we want to use a LOW level.
|
|||
// The MAX3421E provides for pulse width control for an IRQ.
|
|||
// We do need to watch the timing on this, as a second IRQ could cause
|
|||
// a missed IRQ, since we read the level of the line to check if the IRQ
|
|||
// is actually for this chip. The only other alternative is to add a capacitor
|
|||
// and an NPN transistor, and use two lines. We can try this first, though.
|
|||
// Worse case, we can ignore reading the pin for verification on UNO32.
|
|||
// Too bad there is no minimum low width setting.
|
|||
//
|
|||
// Single Clear First Second Clear first Clear last
|
|||
// IRQ Single IRQ IRQ Second active pending IRQ
|
|||
// | | | | | |
|
|||
// V V V V V V
|
|||
// _____ _________ _ _ _______
|
|||
// |______| |______| |______| |______________|
|
|||
//
|
|||
#define IRQ_SENSE FALLING |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
//#define bmPULSEWIDTH PUSLEWIDTH10_6
|
|||
#define bmPULSEWIDTH 0 |
|||
#define bmIRQ_SENSE 0 |
|||
#else |
|||
#define bmPULSEWIDTH PUSLEWIDTH1_3 |
|||
#define bmIRQ_SENSE 0 |
|||
#endif |
|||
#else |
|||
#if !defined(IRQ_SENSE) |
|||
#define IRQ_SENSE LOW |
|||
#endif |
|||
#if !defined(bmPULSEWIDTH) |
|||
#define bmPULSEWIDTH 0 |
|||
#endif |
|||
#if !defined(bmIRQ_SENSE) |
|||
#define bmIRQ_SENSE bmINTLEVEL |
|||
#endif |
|||
#endif |
|||
|
|||
class MAX3421E_HOST : |
|||
public UHS_USB_HOST_BASE |
|||
#if defined(SWI_IRQ_NUM) |
|||
, public dyn_SWI |
|||
#endif |
|||
{ |
|||
// TO-DO: move these into the parent class.
|
|||
volatile uint8_t vbusState; |
|||
volatile uint16_t sof_countdown; |
|||
|
|||
// TO-DO: pack into a struct/union and use one byte
|
|||
volatile bool busevent; |
|||
volatile bool sofevent; |
|||
volatile bool counted; |
|||
volatile bool condet; |
|||
volatile bool doingreset; |
|||
|
|||
#ifdef USB_HOST_MANUAL_POLL |
|||
volatile bool frame_irq_enabled = false; |
|||
|
|||
bool enable_frame_irq(bool enable) { |
|||
const bool prev_state = frame_irq_enabled; |
|||
if(prev_state != enable) { |
|||
if(enable) |
|||
regWr(rHIEN, regRd(rHIEN) | bmFRAMEIE); |
|||
else |
|||
regWr(rHIEN, regRd(rHIEN) & ~bmFRAMEIE); |
|||
frame_irq_enabled = enable; |
|||
} |
|||
return prev_state; |
|||
} |
|||
#endif |
|||
|
|||
public: |
|||
SPISettings MAX3421E_SPI_Settings; |
|||
uint8_t ss_pin; |
|||
uint8_t irq_pin; |
|||
// Will use the defaults UHS_MAX3421E_SS, UHS_MAX3421E_INT and speed
|
|||
|
|||
UHS_NI MAX3421E_HOST(void) { |
|||
sof_countdown = 0; |
|||
busevent = false; |
|||
doingreset = false; |
|||
sofevent = false; |
|||
condet = false; |
|||
ss_pin = UHS_MAX3421E_SS; |
|||
irq_pin = UHS_MAX3421E_INT; |
|||
MAX3421E_SPI_Settings = SPISettings(UHS_MAX3421E_SPD, MSBFIRST, SPI_MODE0); |
|||
hub_present = 0; |
|||
}; |
|||
|
|||
// Will use user supplied pins, and UHS_MAX3421E_SPD
|
|||
|
|||
UHS_NI MAX3421E_HOST(uint8_t pss, uint8_t pirq) { |
|||
sof_countdown = 0; |
|||
busevent = false; |
|||
doingreset = false; |
|||
sofevent = false; |
|||
condet = false; |
|||
ss_pin = pss; |
|||
irq_pin = pirq; |
|||
MAX3421E_SPI_Settings = SPISettings(UHS_MAX3421E_SPD, MSBFIRST, SPI_MODE0); |
|||
hub_present = 0; |
|||
}; |
|||
|
|||
// Will use user supplied pins, and speed
|
|||
|
|||
UHS_NI MAX3421E_HOST(uint8_t pss, uint8_t pirq, uint32_t pspd) { |
|||
sof_countdown = 0; |
|||
doingreset = false; |
|||
busevent = false; |
|||
sofevent = false; |
|||
condet = false; |
|||
ss_pin = pss; |
|||
irq_pin = pirq; |
|||
MAX3421E_SPI_Settings = SPISettings(pspd, MSBFIRST, SPI_MODE0); |
|||
hub_present = 0; |
|||
}; |
|||
|
|||
virtual bool UHS_NI sof_delay(uint16_t x) { |
|||
#ifdef USB_HOST_MANUAL_POLL |
|||
const bool saved_irq_state = enable_frame_irq(true); |
|||
#endif |
|||
sof_countdown = x; |
|||
while((sof_countdown != 0) && !condet) { |
|||
SYSTEM_OR_SPECIAL_YIELD(); |
|||
#if !USB_HOST_SHIELD_USE_ISR |
|||
Task(); |
|||
#endif |
|||
} |
|||
#ifdef USB_HOST_MANUAL_POLL |
|||
enable_frame_irq(saved_irq_state); |
|||
#endif |
|||
// Serial.println("...Wake");
|
|||
return (!condet); |
|||
}; |
|||
|
|||
virtual UHS_EpInfo *ctrlReqOpen(uint8_t addr, uint64_t Request, uint8_t* dataptr); |
|||
|
|||
virtual void UHS_NI vbusPower(VBUS_t state) { |
|||
regWr(rPINCTL, (bmFDUPSPI | bmIRQ_SENSE) | (uint8_t)(state)); |
|||
}; |
|||
|
|||
void UHS_NI Task(void); |
|||
|
|||
virtual uint8_t SetAddress(uint8_t addr, uint8_t ep, UHS_EpInfo **ppep, uint16_t &nak_limit); |
|||
virtual uint8_t OutTransfer(UHS_EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); |
|||
virtual uint8_t InTransfer(UHS_EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); |
|||
virtual uint8_t ctrlReqClose(UHS_EpInfo *pep, uint8_t bmReqType, uint16_t left, uint16_t nbytes, uint8_t *dataptr); |
|||
virtual uint8_t ctrlReqRead(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint16_t nbytes, uint8_t *dataptr); |
|||
virtual uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit); |
|||
|
|||
void UHS_NI ReleaseChildren(void) { |
|||
for(uint8_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) |
|||
if(devConfig[i]) |
|||
devConfig[i]->Release(); |
|||
hub_present = 0; |
|||
}; |
|||
|
|||
virtual bool IsHub(uint8_t klass) { |
|||
if(klass == UHS_USB_CLASS_HUB) { |
|||
hub_present = bmHUBPRE; |
|||
return true; |
|||
} |
|||
return false; |
|||
}; |
|||
|
|||
virtual void VBUS_changed(void); |
|||
|
|||
virtual void UHS_NI doHostReset(void) { |
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
// Enable interrupts
|
|||
noInterrupts(); |
|||
#endif |
|||
doingreset = true; |
|||
busevent = true; |
|||
regWr(rHIRQ, bmBUSEVENTIRQ); // see data sheet.
|
|||
regWr(rHCTL, bmBUSRST); //issue bus reset
|
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
DDSB(); |
|||
// Enable interrupts
|
|||
interrupts(); |
|||
#endif |
|||
while(busevent) { |
|||
DDSB(); |
|||
SYSTEM_OR_SPECIAL_YIELD(); |
|||
} |
|||
#endif |
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
// Enable interrupts
|
|||
noInterrupts(); |
|||
#endif |
|||
#ifdef USB_HOST_MANUAL_POLL |
|||
enable_frame_irq(true); |
|||
#endif |
|||
sofevent = true; |
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
DDSB(); |
|||
// Enable interrupts
|
|||
interrupts(); |
|||
#endif |
|||
// Wait for SOF
|
|||
while(sofevent) { |
|||
} |
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
// Enable interrupts
|
|||
noInterrupts(); |
|||
#endif |
|||
doingreset = false; |
|||
#if USB_HOST_SHIELD_USE_ISR |
|||
DDSB(); |
|||
// Enable interrupts
|
|||
interrupts(); |
|||
}; |
|||
|
|||
|
|||
int16_t UHS_NI Init(int16_t mseconds); |
|||
|
|||
int16_t UHS_NI Init(void) { |
|||
return Init(INT16_MIN); |
|||
}; |
|||
|
|||
void ISRTask(void); |
|||
void ISRbottom(void); |
|||
void busprobe(void); |
|||
uint16_t reset(void); |
|||
|
|||
// MAX3421e specific
|
|||
void regWr(uint8_t reg, uint8_t data); |
|||
void gpioWr(uint8_t data); |
|||
uint8_t regRd(uint8_t reg); |
|||
uint8_t gpioRd(void); |
|||
uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p); |
|||
uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p); |
|||
|
|||
// ARM/NVIC specific, used to emulate reentrant ISR.
|
|||
#if defined(SWI_IRQ_NUM) |
|||
|
|||
void dyn_SWISR(void) { |
|||
ISRbottom(); |
|||
}; |
|||
#endif |
|||
|
|||
virtual void UHS_NI suspend_host(void) { |
|||
// Used on MCU that lack control of IRQ priority (AVR).
|
|||
// Suspends ISRs, for critical code. IRQ will be serviced after it is resumed.
|
|||
// NOTE: you must track the state yourself!
|
|||
#if defined(__AVR__) |
|||
noInterrupts(); |
|||
detachInterrupt(UHS_GET_DPI(irq_pin)); |
|||
interrupts(); |
|||
#endif |
|||
}; |
|||
|
|||
virtual void UHS_NI resume_host(void); |
|||
}; |
|||
#if !defined(SPIclass) |
|||
#define SPIclass SPI |
|||
#endif |
|||
#if !defined(USB_HOST_SHIELD_LOADED) |
|||
#include "USB_HOST_SHIELD_INLINE.h" |
|||
#endif |
|||
#else |
|||
#error "define LOAD_USB_HOST_SHIELD in your sketch, never include USB_HOST_SHIELD.h in a driver." |
|||
#endif |
|||
#endif /* USB_HOST_SHIELD_H */ |
File diff suppressed because it is too large
@ -0,0 +1,153 @@ |
|||
/*
|
|||
* File: macro_logic.h |
|||
* Author: root |
|||
* |
|||
* Created on December 22, 2018, 4:49 AM |
|||
* |
|||
* To test: |
|||
* gcc -DAJK_TEST_MACRO_LOGIC -E macro_logic.h |
|||
* |
|||
*/ |
|||
|
|||
#ifndef MACRO_LOGIC_H |
|||
#define MACRO_LOGIC_H |
|||
|
|||
#define AJK_CAT(a, ...) AJK_PRIMITIVE_CAT(a, __VA_ARGS__) |
|||
#define AJK_PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ |
|||
|
|||
#define AJK_COMPL(b) AJK_PRIMITIVE_CAT(AJK_COMPL_, b) |
|||
#define AJK_COMPL_0 1 |
|||
#define AJK_COMPL_1 0 |
|||
|
|||
#define AJK_BITAND(x) AJK_PRIMITIVE_CAT(AJK_BITAND_, x) |
|||
#define AJK_BITAND_0(y) 0 |
|||
#define AJK_BITAND_1(y) y |
|||
|
|||
#define AJK_INC(x) AJK_PRIMITIVE_CAT(AJK_INC_, x) |
|||
#define AJK_INC_0 1 |
|||
#define AJK_INC_1 2 |
|||
#define AJK_INC_2 3 |
|||
#define AJK_INC_3 4 |
|||
#define AJK_INC_4 5 |
|||
#define AJK_INC_5 6 |
|||
#define AJK_INC_6 7 |
|||
#define AJK_INC_7 8 |
|||
#define AJK_INC_8 9 |
|||
#define AJK_INC_9 10 |
|||
#define AJK_INC_10 10 |
|||
|
|||
#define AJK_DEC(x) AJK_PRIMITIVE_CAT(AJK_DEC_, x) |
|||
#define AJK_DEC_0 0 |
|||
#define AJK_DEC_1 0 |
|||
#define AJK_DEC_2 1 |
|||
#define AJK_DEC_3 2 |
|||
#define AJK_DEC_4 3 |
|||
#define AJK_DEC_5 4 |
|||
#define AJK_DEC_6 5 |
|||
#define AJK_DEC_7 6 |
|||
#define AJK_DEC_8 7 |
|||
#define AJK_DEC_9 8 |
|||
#define AJK_DEC_10 9 |
|||
|
|||
#define AJK_CHECK_N(x, n, ...) n |
|||
#define AJK_CHECK(...) AJK_CHECK_N(__VA_ARGS__, 0,) |
|||
#define AJK_PROBE(x) x, 1, |
|||
|
|||
#define AJK_IS_PAREN(x) AJK_CHECK(AJK_IS_PAREN_PROBE x) |
|||
#define AJK_IS_PAREN_PROBE(...) AJK_PROBE(~) |
|||
|
|||
#define AJK_NOT(x) AJK_CHECK(AJK_PRIMITIVE_CAT(AJK_NOT_, x)) |
|||
#define AJK_NOT_0 AJK_PROBE(~) |
|||
|
|||
#define AJK_COMPL(b) AJK_PRIMITIVE_CAT(AJK_COMPL_, b) |
|||
#define AJK_COMPL_0 1 |
|||
#define AJK_COMPL_1 0 |
|||
|
|||
#define AJK_BOOL(x) AJK_COMPL(AJK_NOT(x)) |
|||
|
|||
#define AJK_IIF(c) AJK_PRIMITIVE_CAT(AJK_IIF_, c) |
|||
#define AJK_IIF_0(t, ...) __VA_ARGS__ |
|||
#define AJK_IIF_1(t, ...) t |
|||
|
|||
#define AJK_IF(c) AJK_IIF(AJK_BOOL(c)) |
|||
|
|||
#define AJK_EAT(...) |
|||
#define AJK_EXPAND(...) __VA_ARGS__ |
|||
#define AJK_WHEN(c) AJK_IF(c)(AJK_EXPAND, AJK_EAT) |
|||
|
|||
#define AJK_EMPTY() |
|||
#define AJK_DEFER(id) id AJK_EMPTY() |
|||
#define AJK_OBSTRUCT(id) id AJK_DEFER(AJK_EMPTY)() |
|||
|
|||
#define AJK_EVAL(...) AJK_EVAL1(AJK_EVAL1(AJK_EVAL1(__VA_ARGS__))) |
|||
#define AJK_EVAL1(...) AJK_EVAL2(AJK_EVAL2(AJK_EVAL2(__VA_ARGS__))) |
|||
#define AJK_EVAL2(...) AJK_EVAL3(AJK_EVAL3(AJK_EVAL3(__VA_ARGS__))) |
|||
#define AJK_EVAL3(...) AJK_EVAL4(AJK_EVAL4(AJK_EVAL4(__VA_ARGS__))) |
|||
#define AJK_EVAL4(...) AJK_EVAL5(AJK_EVAL5(AJK_EVAL5(__VA_ARGS__))) |
|||
#define AJK_EVAL5(...) __VA_ARGS__ |
|||
|
|||
#define AJK_REPEAT(AJK_count, AJK_macro, ...) \ |
|||
AJK_WHEN(AJK_count) \ |
|||
( \ |
|||
AJK_OBSTRUCT(AJK_REPEAT_INDIRECT) () \ |
|||
( \ |
|||
AJK_DEC(AJK_count), AJK_macro, __VA_ARGS__ \ |
|||
) \ |
|||
AJK_OBSTRUCT(AJK_macro) \ |
|||
( \ |
|||
AJK_DEC(AJK_count), __VA_ARGS__ \ |
|||
) \ |
|||
) |
|||
#define AJK_REPEAT_INDIRECT() AJK_REPEAT |
|||
|
|||
#define AJK_WHILE(AJK_pred, AJK_op, ...) \ |
|||
IF(AJK_pred(__VA_ARGS__)) \ |
|||
( \ |
|||
AJK_OBSTRUCT(AJK_WHILE_INDIRECT) () \ |
|||
( \ |
|||
AJK_pred, AJK_op, AJK_op(__VA_ARGS__) \ |
|||
), \ |
|||
__VA_ARGS__ \ |
|||
) |
|||
#define AJK_WHILE_INDIRECT() AJK_WHILE |
|||
|
|||
#define AJK_PRIMITIVE_COMPARE(x, y) AJK_IS_PAREN \ |
|||
( \ |
|||
AJK_COMPARE_ ## x ( AJK_COMPARE_ ## y) (()) \ |
|||
) |
|||
|
|||
#define AJK_IS_COMPARABLE(x) AJK_IS_PAREN( AJK_CAT(AJK_COMPARE_, x) (()) ) |
|||
|
|||
#define AJK_NOT_EQUAL(x, y) \ |
|||
AJK_IIF(AJK_BITAND(AJK_IS_COMPARABLE(x))(AJK_IS_COMPARABLE(y)) ) \ |
|||
( \ |
|||
AJK_PRIMITIVE_COMPARE, \ |
|||
1 AJK_EAT \ |
|||
)(x, y) |
|||
|
|||
#define AJK_EQUAL(x, y) AJK_COMPL(AJK_NOT_EQUAL(x, y)) |
|||
|
|||
|
|||
#define AJK_COMMA() , |
|||
|
|||
#define AJK_COMMA_IF(n) AJK_IF(n)(AJK_COMMA, AJK_EAT)() |
|||
|
|||
|
|||
#define AJK_COMMA_VAR(AJK_count, AJK_v) AJK_COMMA_IF(AJK_count) AJK_v ## AJK_count |
|||
|
|||
#define AJK_MAKE_LIST(AJK_v, AJK_count) AJK_EVAL(AJK_REPEAT(AJK_count, AJK_COMMA_VAR, AJK_v)) |
|||
|
|||
#define AJK_FUN(AJK_count, AJK_v, AJK_args, AJK_body) AJK_v ## AJK_count (AJK_args) { AJK_body(AJK_count) } |
|||
#define AJK_MAKE_FUNS(AJK_v, AJK_args, AJK_count, AJK_body) AJK_EVAL(AJK_REPEAT(AJK_count, AJK_FUN, AJK_v, AJK_args, AJK_body)) |
|||
#if defined(AJK_TEST_MACRO_LOGIC) |
|||
|
|||
#define BODY(AJKindex) some(C, statement); contaning(a, test[AJKindex]); |
|||
#define ZERO_TIMES_TEST 0 |
|||
#define THREE_TIMES_TEST 3 |
|||
blank > AJK_MAKE_LIST(VARIABLE_, ZERO_TIMES_TEST) < because zero repeats |
|||
Make 3 comma separated indexed variables : AJK_MAKE_LIST(VARIABLE_, THREE_TIMES_TEST) |
|||
Make 3 bogus function bodies |
|||
AJK_MAKE_FUNS(unsigned Cfunc,(arg1, arg2),3,BODY) |
|||
#endif |
|||
|
|||
#endif /* MACRO_LOGIC_H */ |
@ -0,0 +1,246 @@ |
|||
/*
|
|||
* File: SWI_INLINE.h |
|||
* Author: xxxajk@gmail.com |
|||
* |
|||
* Created on December 5, 2014, 9:40 AM |
|||
* |
|||
* This is the actual library. |
|||
* There are no 'c' or 'cpp' files. |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
|
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
*/ |
|||
#ifdef DYN_SWI_H |
|||
#ifndef SWI_INLINE_H |
|||
#define SWI_INLINE_H |
|||
|
|||
#ifndef SWI_MAXIMUM_ALLOWED |
|||
#define SWI_MAXIMUM_ALLOWED 4 |
|||
#endif |
|||
|
|||
|
|||
|
|||
#if defined(__arm__) || defined(ARDUINO_ARCH_PIC32) |
|||
static char dyn_SWI_initied = 0; |
|||
static dyn_SWI* dyn_SWI_LIST[SWI_MAXIMUM_ALLOWED]; |
|||
static dyn_SWI* dyn_SWI_EXEC[SWI_MAXIMUM_ALLOWED]; |
|||
#if defined(__arm__) |
|||
#if defined(__USE_CMSIS_VECTORS__) |
|||
extern "C" { |
|||
void (*_VectorsRam[VECTORTABLE_SIZE])(void)__attribute__((aligned(VECTORTABLE_ALIGNMENT))); |
|||
} |
|||
#else |
|||
|
|||
__attribute__((always_inline)) static inline void __DSB(void) { |
|||
__asm__ volatile ("dsb"); |
|||
} |
|||
#endif // defined(__USE_CMSIS_VECTORS__)
|
|||
#else // defined(__arm__)
|
|||
__attribute__((always_inline)) static inline void __DSB(void) { |
|||
__asm__ volatile ("sync" : : : "memory"); |
|||
} |
|||
#endif // defined(__arm__)
|
|||
|
|||
/**
|
|||
* Execute queued class ISR routines. |
|||
*/ |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
static p32_regset *ifs = ((p32_regset *) & IFS0) + (SWI_IRQ_NUM / 32); //interrupt flag register set
|
|||
static p32_regset *iec = ((p32_regset *) & IEC0) + (SWI_IRQ_NUM / 32); //interrupt enable control reg set
|
|||
static uint32_t swibit = 1 << (SWI_IRQ_NUM % 32); |
|||
|
|||
void |
|||
#if defined(__PIC32MZXX__) |
|||
__attribute__((nomips16,at_vector(SWI_VECTOR),interrupt(SWI_IPL))) |
|||
#else |
|||
__attribute__((interrupt(),nomips16)) |
|||
#endif |
|||
softISR(void) { |
|||
#else |
|||
#if defined(ARDUINO_spresense_ast) |
|||
unsigned int softISR(void) { |
|||
#else |
|||
void softISR(void) { |
|||
#endif |
|||
#endif |
|||
|
|||
//
|
|||
// TO-DO: Perhaps limit to 8, and inline this?
|
|||
//
|
|||
|
|||
|
|||
// Make a working copy, while clearing the queue.
|
|||
noInterrupts(); |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
//ifs->clr = swibit;
|
|||
#endif |
|||
for(int i = 0; i < SWI_MAXIMUM_ALLOWED; i++) { |
|||
dyn_SWI_EXEC[i] = dyn_SWI_LIST[i]; |
|||
dyn_SWI_LIST[i] = NULL; |
|||
} |
|||
__DSB(); |
|||
interrupts(); |
|||
|
|||
// Execute each class SWI
|
|||
for(int i = 0; i < SWI_MAXIMUM_ALLOWED; i++) { |
|||
if(dyn_SWI_EXEC[i]) { |
|||
#if defined(__DYN_SWI_DEBUG_LED__) |
|||
digitalWrite(__DYN_SWI_DEBUG_LED__, HIGH); |
|||
#endif |
|||
dyn_SWI_EXEC[i]->dyn_SWISR(); |
|||
#if defined(__DYN_SWI_DEBUG_LED__) |
|||
digitalWrite(__DYN_SWI_DEBUG_LED__, LOW); |
|||
#endif |
|||
} |
|||
} |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
noInterrupts(); |
|||
if(!dyn_SWI_EXEC[0]) ifs->clr = swibit; |
|||
interrupts(); |
|||
#endif |
|||
#if defined(ARDUINO_spresense_ast) |
|||
return 0; |
|||
#endif |
|||
} |
|||
|
|||
#define DDSB() __DSB() |
|||
#endif |
|||
|
|||
|
|||
#if defined(__arm__) |
|||
#ifndef interruptsStatus |
|||
#define interruptsStatus() __interruptsStatus() |
|||
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused)); |
|||
|
|||
static inline unsigned char __interruptsStatus(void) { |
|||
unsigned int primask; |
|||
asm volatile ("mrs %0, primask" : "=r" (primask)); |
|||
if(primask) return 0; |
|||
return 1; |
|||
} |
|||
#endif |
|||
|
|||
/**
|
|||
* Initialize the Dynamic (class) Software Interrupt |
|||
*/ |
|||
static void Init_dyn_SWI(void) { |
|||
if(!dyn_SWI_initied) { |
|||
#if defined(__USE_CMSIS_VECTORS__) |
|||
uint32_t *X_Vectors = (uint32_t*)SCB->VTOR; |
|||
for(int i = 0; i < VECTORTABLE_SIZE; i++) { |
|||
_VectorsRam[i] = reinterpret_cast<void (*)()>(X_Vectors[i]); /* copy vector table to RAM */ |
|||
} |
|||
/* relocate vector table */ |
|||
noInterrupts(); |
|||
SCB->VTOR = reinterpret_cast<uint32_t>(&_VectorsRam); |
|||
DDSB(); |
|||
interrupts(); |
|||
#endif |
|||
#if !defined(ARDUINO_spresense_ast) |
|||
for(int i = 0; i < SWI_MAXIMUM_ALLOWED; i++) dyn_SWI_LIST[i] = NULL; |
|||
noInterrupts(); |
|||
_VectorsRam[SWI_IRQ_NUM + 16] = reinterpret_cast<void (*)()>(softISR); |
|||
DDSB(); |
|||
interrupts(); |
|||
NVIC_SET_PRIORITY(SWI_IRQ_NUM, 255); |
|||
NVIC_ENABLE_IRQ(SWI_IRQ_NUM); |
|||
#endif |
|||
#if defined(__DYN_SWI_DEBUG_LED__) |
|||
pinMode(__DYN_SWI_DEBUG_LED__, OUTPUT); |
|||
digitalWrite(__DYN_SWI_DEBUG_LED__, LOW); |
|||
#endif |
|||
dyn_SWI_initied = 1; |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* |
|||
* @param klass class that extends dyn_SWI |
|||
* @return 0 on queue full, else returns queue position (ones based) |
|||
*/ |
|||
int exec_SWI(const dyn_SWI* klass) { |
|||
int rc = 0; |
|||
|
|||
uint8_t irestore = interruptsStatus(); |
|||
// Allow use from inside a critical section...
|
|||
// ... and prevent races if also used inside an ISR
|
|||
noInterrupts(); |
|||
for(int i = 0; i < SWI_MAXIMUM_ALLOWED; i++) { |
|||
if(!dyn_SWI_LIST[i]) { |
|||
rc = 1 + i; // Success!
|
|||
dyn_SWI_LIST[i] = (dyn_SWI*)klass; |
|||
#if !defined(ARDUINO_spresense_ast) |
|||
if(!NVIC_GET_PENDING(SWI_IRQ_NUM)) NVIC_SET_PENDING(SWI_IRQ_NUM); |
|||
#else |
|||
// Launch 1-shot timer as an emulated SWI
|
|||
// Hopefully the value of Zero is legal.
|
|||
// 1 microsecond latency would suck!
|
|||
attachTimerInterrupt(softISR, 100); |
|||
#endif |
|||
DDSB(); |
|||
break; |
|||
} |
|||
} |
|||
// Restore interrupts, if they were on.
|
|||
if(irestore) interrupts(); |
|||
return rc; |
|||
} |
|||
#elif defined(ARDUINO_ARCH_PIC32) |
|||
|
|||
/**
|
|||
* Initialize the Dynamic (class) Software Interrupt |
|||
*/ |
|||
static void Init_dyn_SWI(void) { |
|||
if(!dyn_SWI_initied) { |
|||
uint32_t sreg = disableInterrupts(); |
|||
|
|||
setIntVector(SWI_VECTOR, softISR); |
|||
setIntPriority(SWI_VECTOR, 1, 1); // Lowest priority, ever.
|
|||
ifs->clr = swibit; |
|||
iec->clr = swibit; |
|||
iec->set = swibit; |
|||
restoreInterrupts(sreg); |
|||
#if defined(__DYN_SWI_DEBUG_LED__) |
|||
pinMode(__DYN_SWI_DEBUG_LED__, OUTPUT); |
|||
UHS_PIN_WRITE(__DYN_SWI_DEBUG_LED__, LOW); |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* |
|||
* @param klass class that extends dyn_SWI |
|||
* @return 0 on queue full, else returns queue position (ones based) |
|||
*/ |
|||
int exec_SWI(const dyn_SWI* klass) { |
|||
int rc = 0; |
|||
uint32_t sreg = disableInterrupts(); |
|||
for(int i = 0; i < SWI_MAXIMUM_ALLOWED; i++) { |
|||
if(!dyn_SWI_LIST[i]) { |
|||
rc = 1 + i; // Success!
|
|||
dyn_SWI_LIST[i] = (dyn_SWI*)klass; |
|||
if(!(ifs->reg & swibit)) ifs->set = swibit; |
|||
; |
|||
break; |
|||
} |
|||
} |
|||
restoreInterrupts(sreg); |
|||
return rc; |
|||
} |
|||
|
|||
#endif /* defined(__arm__) */ |
|||
#endif /* SWI_INLINE_H */ |
|||
#else |
|||
#error "Never include SWI_INLINE.h directly, include dyn_SWI.h instead" |
|||
#endif |
@ -0,0 +1,172 @@ |
|||
/*
|
|||
* File: dyn_SWI.h |
|||
* Author: xxxajk@gmail.com |
|||
* |
|||
* Created on December 5, 2014, 9:12 AM |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
|
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, write to the Free Software |
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
*/ |
|||
|
|||
#ifndef DYN_SWI_H |
|||
#define DYN_SWI_H |
|||
|
|||
|
|||
#if defined(__arm__) || defined(ARDUINO_ARCH_PIC32) |
|||
#if defined(ARDUINO_ARCH_PIC32) |
|||
#include <p32xxxx.h> |
|||
#endif |
|||
#ifdef __cplusplus |
|||
|
|||
#if defined(true) |
|||
#undef true |
|||
#endif |
|||
|
|||
#if defined(false) |
|||
#undef false |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
#if defined(ARDUINO_spresense_ast) |
|||
#define SWI_IRQ_NUM 666 // because this board is totally evil.
|
|||
#elif defined(ARDUINO_ARCH_PIC32) |
|||
#ifndef SWI_IRQ_NUM |
|||
#if defined(_DSPI0_IPL_ISR) |
|||
#define SWI_IPL _DSPI0_IPL_ISR |
|||
#define SWI_VECTOR _DSPI0_ERR_IRQ |
|||
#define SWI_IRQ_NUM _DSPI0_ERR_IRQ |
|||
#elif defined(_PMP_ERROR_IRQ) |
|||
#define SWI_IRQ_NUM _PMP_ERROR_IRQ |
|||
#define SWI_VECTOR _PMP_VECTOR |
|||
#else |
|||
#error SWI_IRQ_NUM and SWI_VECTOR need a definition |
|||
#endif |
|||
#ifdef __cplusplus |
|||
extern "C" |
|||
{ |
|||
void |
|||
#if defined(__PIC32MZXX__) |
|||
__attribute__((nomips16,at_vector(SWI_VECTOR),interrupt(SWI_IPL))) |
|||
#else |
|||
__attribute__((interrupt(),nomips16)) |
|||
#endif |
|||
softISR(void); |
|||
} |
|||
#endif |
|||
#endif |
|||
#elif !defined(NVIC_NUM_INTERRUPTS) |
|||
// Assume CMSIS
|
|||
#define __USE_CMSIS_VECTORS__ |
|||
#if defined(NUMBER_OF_INT_VECTORS) |
|||
#define NVIC_NUM_INTERRUPTS (NUMBER_OF_INT_VECTORS-16) |
|||
#else |
|||
#define NVIC_NUM_INTERRUPTS ((int)PERIPH_COUNT_IRQn) |
|||
#endif |
|||
#define VECTORTABLE_SIZE (NVIC_NUM_INTERRUPTS+16) |
|||
#define VECTORTABLE_ALIGNMENT (0x100ul) |
|||
#define NVIC_GET_ACTIVE(n) NVIC_GetActive((IRQn_Type)n) |
|||
#define NVIC_GET_PENDING(n) NVIC_GetPendingIRQ((IRQn_Type)n) |
|||
#define NVIC_SET_PENDING(n) NVIC_SetPendingIRQ((IRQn_Type)n) |
|||
#define NVIC_ENABLE_IRQ(n) NVIC_EnableIRQ((IRQn_Type)n) |
|||
#define NVIC_SET_PRIORITY(n ,p) NVIC_SetPriority((IRQn_Type)n, (uint32_t) p) |
|||
//extern "C" {
|
|||
// extern uint32_t _VectorsRam[VECTORTABLE_SIZE] __attribute__((aligned(VECTORTABLE_ALIGNMENT)));
|
|||
//}
|
|||
|
|||
#ifndef SWI_IRQ_NUM |
|||
#if defined(__SAM3X8E__) && defined(_VARIANT_ARDUINO_DUE_X_) |
|||
// DUE
|
|||
// Choices available:
|
|||
// HSMCI_IRQn Multimedia Card Interface (HSMCI)
|
|||
// EMAC_IRQn Ethernet MAC (EMAC)
|
|||
// EMAC is not broken out on the official DUE, but is on clones.
|
|||
// SPI0_IRQn Serial Peripheral Interface (SPI0)
|
|||
// SPI0_IRQn seems to be the best choice, as long as nobody uses an ISR based master
|
|||
#define SWI_IRQ_NUM SPI0_IRQn |
|||
#elif defined(ARDUINO_SAMD_ZERO) |
|||
// Just use sercom4's unused IRQ vector.
|
|||
#define SWI_IRQ_NUM I2S_IRQn |
|||
//#define SWI_IRQ_NUM SERCOM4_IRQn
|
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef SWI_IRQ_NUM |
|||
#error SWI_IRQ_NUM not defined (CMSIS) |
|||
#endif |
|||
|
|||
#elif defined(CORE_TEENSY) |
|||
|
|||
#ifndef NVIC_GET_ACTIVE |
|||
#define NVIC_GET_ACTIVE(n) (*((volatile uint32_t *)0xE000E300 + ((n) >> 5)) & (1 << ((n) & 31))) |
|||
#endif |
|||
#ifndef NVIC_GET_PENDING |
|||
#define NVIC_GET_PENDING(n) (*((volatile uint32_t *)0xE000E200 + ((n) >> 5)) & (1 << ((n) & 31))) |
|||
#ifndef SWI_IRQ_NUM |
|||
#if defined(__MK20DX256__) |
|||
#define SWI_IRQ_NUM 17 |
|||
#elif defined(__MK20DX128__) |
|||
#define SWI_IRQ_NUM 5 |
|||
#elif defined(__MKL26Z64__) |
|||
#define SWI_IRQ_NUM 4 |
|||
#elif defined(__MK66FX1M0__) |
|||
#define SWI_IRQ_NUM 30 |
|||
#elif defined(__MK64FX512__) |
|||
#define SWI_IRQ_NUM 30 |
|||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__) |
|||
#define SWI_IRQ_NUM 71 |
|||
#else |
|||
#error Do not know how to relocate IRQ vectors for this pjrc product |
|||
#endif |
|||
#endif |
|||
#endif |
|||
#else // Not CMSIS or PJRC CORE_TEENSY or PIC32 or SPRESENSE
|
|||
#error Do not know how to relocate IRQ vectors or perform SWI |
|||
#endif // SWI_IRQ_NUM
|
|||
|
|||
|
|||
#ifndef SWI_IRQ_NUM |
|||
#error SWI_IRQ_NUM not defined |
|||
#else |
|||
/**
|
|||
* Use this class to extend your class, in order to provide |
|||
* a C++ context callable SWI. |
|||
*/ |
|||
class dyn_SWI { |
|||
public: |
|||
|
|||
/**
|
|||
* Override this method with your code. |
|||
*/ |
|||
virtual void dyn_SWISR(void) { |
|||
}; |
|||
}; |
|||
|
|||
extern int exec_SWI(const dyn_SWI* klass); |
|||
|
|||
#include "SWI_INLINE.h" |
|||
|
|||
// IMPORTANT! Define this so that you do NOT end up with a NULL stub!
|
|||
#define SWI_NO_STUB |
|||
#endif /* SWI_IRQ_NUM */ |
|||
#endif /* __arm__ */ |
|||
|
|||
// if no SWI for CPU (e.g. AVR) make a void stub.
|
|||
#ifndef SWI_NO_STUB |
|||
#define Init_dyn_SWI() (void(0)) |
|||
#if !defined(DDSB) |
|||
#define DDSB() (void(0)) |
|||
#endif |
|||
#endif |
|||
#endif /* DYN_SWI_H */ |
@ -1,187 +0,0 @@ |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/masstorage.cpp lib/masstorage.cpp
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/masstorage.cpp 2018-09-21 10:19:36.107502252 -0600
|
|||
+++ lib/masstorage.cpp 2018-09-21 09:46:19.620175519 -0600
|
|||
@@ -24,6 +24,8 @@
|
|||
|
|||
#include "masstorage.h" |
|||
|
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+
|
|||
const uint8_t BulkOnly::epDataInIndex = 1; |
|||
const uint8_t BulkOnly::epDataOutIndex = 2; |
|||
const uint8_t BulkOnly::epInterruptInIndex = 3; |
|||
@@ -796,6 +798,9 @@
|
|||
buf[i] = 0x00; |
|||
} |
|||
WriteOk[lun] = true; |
|||
+ #if ENABLED(USB_FLASH_DRIVE_SUPPORT) && defined(SKIP_WRITE_PROTECT)
|
|||
+ return 0;
|
|||
+ #endif
|
|||
uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); |
|||
if(!rc) { |
|||
WriteOk[lun] = ((buf[2] & 0x80) == 0); |
|||
@@ -1271,3 +1276,5 @@
|
|||
return MASS_ERR_NOT_IMPLEMENTED; |
|||
#endif |
|||
} |
|||
+
|
|||
+#endif // USB_FLASH_DRIVE_SUPPORT
|
|||
\ No newline at end of file |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/message.cpp lib/message.cpp
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/message.cpp 2018-09-21 10:20:15.995647957 -0600
|
|||
+++ lib/message.cpp 2018-09-19 07:43:46.520339375 -0600
|
|||
@@ -23,6 +23,9 @@
|
|||
*/ |
|||
|
|||
#include "Usb.h" |
|||
+
|
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+
|
|||
// 0x80 is the default (i.e. trace) to turn off set this global to something lower. |
|||
// this allows for 126 other debugging levels. |
|||
// TO-DO: Allow assignment to a different serial port by software |
|||
@@ -120,4 +123,6 @@
|
|||
D_PrintHex<uint8_t > (rcode, 0x80); |
|||
Notify(PSTR("\r\n"), 0x80); |
|||
} |
|||
-#endif
|
|||
+#endif // DEBUG_USB_HOST
|
|||
+
|
|||
+#endif // USB_FLASH_DRIVE_SUPPORT
|
|||
\ No newline at end of file |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/parsetools.cpp lib/parsetools.cpp
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/parsetools.cpp 2018-09-21 10:21:16.215867769 -0600
|
|||
+++ lib/parsetools.cpp 2018-09-19 07:43:46.520339375 -0600
|
|||
@@ -23,6 +23,8 @@
|
|||
*/ |
|||
#include "Usb.h" |
|||
|
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+
|
|||
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { |
|||
if(!pBuf) { |
|||
Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); |
|||
@@ -72,3 +74,5 @@
|
|||
} |
|||
return true; |
|||
} |
|||
+
|
|||
+#endif // USB_FLASH_DRIVE_SUPPORT
|
|||
\ No newline at end of file |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/settings.h lib/settings.h
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/settings.h 2018-09-21 10:22:21.792106872 -0600
|
|||
+++ lib/settings.h 2018-09-21 10:01:53.383594081 -0600
|
|||
@@ -25,7 +25,21 @@
|
|||
#ifndef USB_HOST_SHIELD_SETTINGS_H |
|||
#define USB_HOST_SHIELD_SETTINGS_H |
|||
#include "macros.h" |
|||
-
|
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+ ////////////////////////////////////////////////////////////////////////////////
|
|||
+ /* Added by Bill Greiman to speed up mass storage initialization with USB
|
|||
+ * flash drives and simple USB hard drives.
|
|||
+ * Disable this by defining DELAY(x) to be delay(x).
|
|||
+ */
|
|||
+ #define delay(x) if((x) < 200) safe_delay(x)
|
|||
+ /* Almost all USB flash drives and simple USB hard drives fail the write
|
|||
+ * protect test and add 20 - 30 seconds to USB init. Set SKIP_WRITE_PROTECT
|
|||
+ * to nonzero to skip the test and assume the drive is writable.
|
|||
+ */
|
|||
+ #define SKIP_WRITE_PROTECT 1
|
|||
+ /* Since Marlin only cares about USB flash drives, we only need one LUN. */
|
|||
+ #define MASS_MAX_SUPPORTED_LUN 1
|
|||
+#endif
|
|||
//////////////////////////////////////////////////////////////////////////////// |
|||
// SPI Configuration |
|||
//////////////////////////////////////////////////////////////////////////////// |
|||
@@ -45,6 +59,10 @@
|
|||
* multiple serial ports are available. |
|||
* For example Serial3. |
|||
*/ |
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+ #define USB_HOST_SERIAL MYSERIAL0
|
|||
+#endif
|
|||
+
|
|||
#ifndef USB_HOST_SERIAL |
|||
#define USB_HOST_SERIAL Serial |
|||
#endif |
|||
@@ -99,7 +117,7 @@
|
|||
// No user serviceable parts below this line. |
|||
// DO NOT change anything below here unless you are a developer! |
|||
|
|||
-#include "version_helper.h"
|
|||
+//#include "version_helper.h"
|
|||
|
|||
#if defined(__GNUC__) && defined(__AVR__) |
|||
#ifndef GCC_VERSION |
|||
@@ -149,7 +167,6 @@
|
|||
#else |
|||
#define USING_SPI4TEENSY3 0 |
|||
#endif |
|||
-
|
|||
#if ((defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)) || defined(__ARDUINO_X86__) || ARDUINO >= 10600) && !USING_SPI4TEENSY3 |
|||
#include <SPI.h> // Use the Arduino SPI library for the Arduino Due, Intel Galileo 1 & 2, Intel Edison or if the SPI library with transaction is available |
|||
#endif |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/UsbCore.h lib/UsbCore.h
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/UsbCore.h 2018-09-21 10:23:09.348280107 -0600
|
|||
+++ lib/UsbCore.h 2018-09-19 07:43:46.520339375 -0600
|
|||
@@ -32,7 +32,10 @@
|
|||
//#define USB_METHODS_INLINE |
|||
|
|||
/* shield pins. First parameter - SS pin, second parameter - INT pin */ |
|||
-#ifdef BOARD_BLACK_WIDDOW
|
|||
+
|
|||
+#if defined(__MARLIN_H__)
|
|||
+typedef MAX3421e MAX3421E; // Marlin redefines this class in "../usb_host.h"
|
|||
+#elif defined(BOARD_BLACK_WIDDOW)
|
|||
typedef MAX3421e<P6, P3> MAX3421E; // Black Widow |
|||
#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) |
|||
#if EXT_RAM |
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/Usb.cpp lib/Usb.cpp
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/Usb.cpp 2018-09-21 10:23:20.732321559 -0600
|
|||
+++ lib/Usb.cpp 2018-09-19 07:43:46.520339375 -0600
|
|||
@@ -25,6 +25,8 @@
|
|||
|
|||
#include "Usb.h" |
|||
|
|||
+#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
|||
+
|
|||
static uint8_t usb_error = 0; |
|||
static uint8_t usb_task_state; |
|||
|
|||
@@ -825,3 +827,4 @@
|
|||
} |
|||
|
|||
#endif // defined(USB_METHODS_INLINE) |
|||
+#endif // USB_FLASH_DRIVE_SUPPORT
|
|||
diff -Naur /home/aleph/Downloads/USB_Host_Shield_2.0-master/Usb.h lib/Usb.h
|
|||
--- /home/aleph/Downloads/USB_Host_Shield_2.0-master/Usb.h 2018-09-21 10:23:33.756368972 -0600
|
|||
+++ lib/Usb.h 2018-09-19 07:43:46.520339375 -0600
|
|||
@@ -25,6 +25,8 @@
|
|||
#ifndef _usb_h_ |
|||
#define _usb_h_ |
|||
|
|||
+#include "../../../Marlin.h"
|
|||
+
|
|||
// WARNING: Do not change the order of includes, or stuff will break! |
|||
#include <inttypes.h> |
|||
#include <stddef.h> |
|||
@@ -34,13 +36,15 @@
|
|||
#include "settings.h" |
|||
#include "printhex.h" |
|||
#include "message.h" |
|||
+
|
|||
#include "hexdump.h" |
|||
-#include "sink_parser.h"
|
|||
+//#include "sink_parser.h"
|
|||
#include "max3421e.h" |
|||
#include "address.h" |
|||
-#include "avrpins.h"
|
|||
+//#include "avrpins.h"
|
|||
#include "usb_ch9.h" |
|||
-#include "usbhost.h"
|
|||
+//#include "usbhost.h"
|
|||
+#include "../usb_host.h"
|
|||
#include "UsbCore.h" |
|||
#include "parsetools.h" |
|||
#include "confdescparser.h" |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue