Update USB_FLASH_DRIVE_SUPPORT (#15021)
parent
20fc66f875
commit
da601d5114
@ -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
Load Diff
@ -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
Load Diff
@ -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
Load Diff
@ -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
Load Diff
@ -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 have changed in this diff Show More
Loading…
Reference in New Issue