From 7b0ee818ae4ebb41374586ed53ca8dd598d7657a Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Fri, 11 Nov 2016 12:39:30 -0500 Subject: [PATCH 01/66] Read/Write direct to physical device when no cache are available --- src/diskio_impl.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/diskio_impl.cpp b/src/diskio_impl.cpp index 62f8eb85..4dcaf1e8 100755 --- a/src/diskio_impl.cpp +++ b/src/diskio_impl.cpp @@ -145,12 +145,20 @@ int DiskIO::Read(uint32_t SectNo, uint32_t SectOffset, uint8_t *pBuff, uint32_t int idx = GetCacheSect(SectNo); if (idx < 0) - return -1; - - memcpy(pBuff, vpCacheSect[idx].pSectData + SectOffset, l); + { + // No cache, do physical read + uint8_t d[DISKIO_SECT_SIZE]; + SectRead(SectNo, d); + memcpy(pBuff, d + SectOffset, l); + } + else + { + // Get it from cache + memcpy(pBuff, vpCacheSect[idx].pSectData + SectOffset, l); - // Done with cache sector, release it - vpCacheSect[idx].UseCnt--; + // Done with cache sector, release it + vpCacheSect[idx].UseCnt--; + } return l; } @@ -186,16 +194,22 @@ int DiskIO::Write(uint32_t SectNo, uint32_t SectOffset, uint8_t *pData, uint32_t int idx = GetCacheSect(SectNo, true); if (idx < 0) - return -1; - - memcpy(vpCacheSect[idx].pSectData + SectOffset, pData, l); - - // Write sector to disk -// SectWrite(SectNo, vpCacheSect[idx].pSect); + { + // No cache, do physical write + uint8_t d[DISKIO_SECT_SIZE]; + SectRead(SectNo, d); + memcpy(d + SectOffset, pData, l); + SectWrite(SectNo, d); + } + else + { + // Write to cache + memcpy(vpCacheSect[idx].pSectData + SectOffset, pData, l); - // Done with cache sector, release it - vpCacheSect[idx].UseCnt |= DISKIO_CACHE_DIRTY_BIT; - vpCacheSect[idx].UseCnt--; + // Done with cache sector, release it + vpCacheSect[idx].UseCnt |= DISKIO_CACHE_DIRTY_BIT; + vpCacheSect[idx].UseCnt--; + } return l; } From 76548fc86698974b00323da15399c2008ebc2666 Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Fri, 11 Nov 2016 17:16:24 -0500 Subject: [PATCH 02/66] remove dynamic mem allocation to favour static setting --- include/diskio.h | 30 ++++++++++++------------- include/sdcard.h | 2 +- src/diskio_impl.cpp | 53 +++++++++++++++------------------------------ src/sdcard_impl.cpp | 6 ++--- 4 files changed, 35 insertions(+), 56 deletions(-) diff --git a/include/diskio.h b/include/diskio.h index ba270c37..a212cd5d 100755 --- a/include/diskio.h +++ b/include/diskio.h @@ -35,10 +35,11 @@ Modified by Date Description #define __DISKIO_H__ #include -#include -#define DISKIO_SECT_SIZE 512 -#define DISKIO_CACHE_SECT_MAX 1 +#define DISKIO_SECT_SIZE 512 // Disk sector size in bytes +#define DISKIO_CACHE_SECT_MAX 1 // Max number of cache sector +#define DISKIO_CACHE_DIRTY_BIT (1<<31) // This bit is set in the UseCnt if there was + // write to the cache #pragma pack(push, 1) typedef struct _DiskPartition { @@ -61,14 +62,12 @@ typedef struct _MasterBootRecord { #pragma pack(push, 4) -#define DISKIO_CACHE_DIRTY_BIT (1<<31) // This bit is set in the UseCnt if there was - // write to the cache -typedef struct _Sect_Desc { - volatile int UseCnt; // semaphore - uint32_t SectNo; // sector number of this cache - uint8_t *pSectData; // sector data -} SECTDESC; +typedef struct _Cache_Desc { + volatile int UseCnt; // semaphore + uint32_t SectNo; // sector number of this cache + uint8_t SectData[DISKIO_SECT_SIZE]; // sector data +} DISKIO_CACHE_DESC; #pragma pack(pop) @@ -77,7 +76,7 @@ class DiskIO { DiskIO(); virtual int GetSectSize(void) { return DISKIO_SECT_SIZE; } - virtual uint32_t GetNbSect(void) = 0; + virtual uint32_t GetNbSect(void) { return GetSize() * 1024 / GetSectSize(); } /** * * @return total disk size in KB @@ -111,16 +110,15 @@ class DiskIO { */ virtual void Erase() {} int GetCacheSect(uint32_t SectNo, bool bLock = false); - void SetCache(uint8_t *pCacheBlk, uint32_t CacheSize); + void SetCache(DISKIO_CACHE_DESC *pCacheBlk, int NbCacheBlk); void Flush(); protected: private: - int vLastIdx; // Last cache sector used - int vNbCache; - bool vExtCache; - SECTDESC *vpCacheSect;//[DISKIO_CACHE_SECT_MAX]; + int vLastIdx; // Last cache sector accessed + int vNbCache; // Number of cache sector + DISKIO_CACHE_DESC *vpCacheSect; }; #ifdef __cplusplus diff --git a/include/sdcard.h b/include/sdcard.h index 69e50034..f258696a 100755 --- a/include/sdcard.h +++ b/include/sdcard.h @@ -78,7 +78,7 @@ class SDCard : public DiskIO { SDCard(); virtual ~SDCard(); - virtual bool Init(SerialIntrf *pSerInterf, uint8_t *pCacheBlk = NULL, size_t CacheSize = 0); + virtual bool Init(SerialIntrf *pSerInterf, DISKIO_CACHE_DESC *pCacheBlk = NULL, int NbCacheBlk = 0); int Cmd(uint8_t Cmd, uint32_t param); int GetResponse(uint8_t *pBuff, int BuffLen); int ReadData(uint8_t *pBuff, int BuffLen); diff --git a/src/diskio_impl.cpp b/src/diskio_impl.cpp index 4dcaf1e8..3b725338 100755 --- a/src/diskio_impl.cpp +++ b/src/diskio_impl.cpp @@ -42,42 +42,23 @@ Modified by Date Description using namespace std; -DiskIO::DiskIO() : vLastIdx(1), vNbCache(1), vExtCache(false) +DiskIO::DiskIO() : vLastIdx(1), vNbCache(0), vpCacheSect(NULL) { - vpCacheSect = new SECTDESC[vNbCache]; - - for (int i = 0; i < vNbCache; i++) - { - vpCacheSect[i].UseCnt = 0; - vpCacheSect[i].SectNo = -1; - vpCacheSect[i].pSectData = new uint8_t[DISKIO_SECT_SIZE]; - } } -void DiskIO::SetCache(uint8_t *pCacheBlk, uint32_t CacheSize) +void DiskIO::SetCache(DISKIO_CACHE_DESC *pCacheBlk, int NbCacheBlk) { - if (pCacheBlk == NULL || CacheSize < DISKIO_SECT_SIZE) + if (pCacheBlk == NULL || NbCacheBlk <= 0) return; - if (vExtCache == false) - { - for (int i = 0; i < vNbCache; i++) - { - delete[] vpCacheSect[i].pSectData; - } - } - - delete[] vpCacheSect; + vNbCache = NbCacheBlk; - vNbCache = CacheSize / DISKIO_SECT_SIZE; - - vpCacheSect = new SECTDESC[vNbCache]; + vpCacheSect = pCacheBlk; for (int i = 0; i < vNbCache; i++) { vpCacheSect[i].UseCnt = 0; vpCacheSect[i].SectNo = -1; - vpCacheSect[i].pSectData = pCacheBlk + i * DISKIO_SECT_SIZE; } } @@ -93,7 +74,7 @@ void DiskIO::Reset() int DiskIO::GetCacheSect(uint32_t SectNo, bool bLock) { // Try to find sector in cache - for (int i = 0; i < DISKIO_CACHE_SECT_MAX; i++) + for (int i = 0; i < vNbCache; i++) { // Grab first cache vpCacheSect[i].UseCnt++; @@ -104,13 +85,13 @@ int DiskIO::GetCacheSect(uint32_t SectNo, bool bLock) } // Not in cache, try to pick unused cache - int i = DISKIO_CACHE_SECT_MAX; + int i = vNbCache; - do + while (i > 0) { vLastIdx++; - if (vLastIdx >= DISKIO_CACHE_SECT_MAX) + if (vLastIdx >= vNbCache) vLastIdx = 0; if ((vpCacheSect[vLastIdx].UseCnt & ~DISKIO_CACHE_DIRTY_BIT) == 0) @@ -119,18 +100,18 @@ int DiskIO::GetCacheSect(uint32_t SectNo, bool bLock) // Flush cache is dirty if (vpCacheSect[vLastIdx].UseCnt & DISKIO_CACHE_DIRTY_BIT) - SectWrite(vpCacheSect[vLastIdx].SectNo, vpCacheSect[vLastIdx].pSectData); + SectWrite(vpCacheSect[vLastIdx].SectNo, vpCacheSect[vLastIdx].SectData); vpCacheSect[vLastIdx].UseCnt = 1; // Fill cache - SectRead(SectNo, vpCacheSect[vLastIdx].pSectData); + SectRead(SectNo, vpCacheSect[vLastIdx].SectData); vpCacheSect[vLastIdx].SectNo = SectNo; return vLastIdx; } - // Cache in use, release it - } while (--i > 0); + i--; + } // No Cache avail return -1; @@ -154,7 +135,7 @@ int DiskIO::Read(uint32_t SectNo, uint32_t SectOffset, uint8_t *pBuff, uint32_t else { // Get it from cache - memcpy(pBuff, vpCacheSect[idx].pSectData + SectOffset, l); + memcpy(pBuff, vpCacheSect[idx].SectData + SectOffset, l); // Done with cache sector, release it vpCacheSect[idx].UseCnt--; @@ -204,7 +185,7 @@ int DiskIO::Write(uint32_t SectNo, uint32_t SectOffset, uint8_t *pData, uint32_t else { // Write to cache - memcpy(vpCacheSect[idx].pSectData + SectOffset, pData, l); + memcpy(vpCacheSect[idx].SectData + SectOffset, pData, l); // Done with cache sector, release it vpCacheSect[idx].UseCnt |= DISKIO_CACHE_DIRTY_BIT; @@ -238,11 +219,11 @@ int DiskIO::Write(uint64_t Offset, uint8_t *pData, uint32_t Len) void DiskIO::Flush() { - for (int i = 0; i < DISKIO_CACHE_SECT_MAX; i++) + for (int i = 0; i < vNbCache; i++) { if (vpCacheSect[i].UseCnt & DISKIO_CACHE_DIRTY_BIT) { - SectWrite(vpCacheSect[i].SectNo, vpCacheSect[i].pSectData); + SectWrite(vpCacheSect[i].SectNo, vpCacheSect[i].SectData); vpCacheSect[i].UseCnt &= ~DISKIO_CACHE_DIRTY_BIT; } } diff --git a/src/sdcard_impl.cpp b/src/sdcard_impl.cpp index 1f357743..11512bd7 100755 --- a/src/sdcard_impl.cpp +++ b/src/sdcard_impl.cpp @@ -49,7 +49,7 @@ SDCard::~SDCard() } -bool SDCard::Init(SerialIntrf *pSerInterf, uint8_t *pCacheBlk, size_t CacheSize) +bool SDCard::Init(SerialIntrf *pSerInterf, DISKIO_CACHE_DESC *pCacheBlk, int NbCacheBlk) { uint8_t data[4]; uint16_t r = 0xffff; @@ -121,9 +121,9 @@ bool SDCard::Init(SerialIntrf *pSerInterf, uint8_t *pCacheBlk, size_t CacheSize) vDev.SectSize = 512; // Default always vDev.TotalSect = GetSize() * 1024LL / vDev.SectSize; - if (pCacheBlk && CacheSize > 0) + if (pCacheBlk && NbCacheBlk > 0) { - SetCache(pCacheBlk, CacheSize); + SetCache(pCacheBlk, NbCacheBlk); } return true; } From 16db20e2dcf3abfbb1e58f61e42e30f0aee73cf9 Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Fri, 11 Nov 2016 17:25:43 -0500 Subject: [PATCH 03/66] generic flash disk --- include/diskio_flash.h | 67 +++++++++++++- src/diskio_flash.cpp | 205 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 src/diskio_flash.cpp diff --git a/include/diskio_flash.h b/include/diskio_flash.h index bd0bc154..2bbf0701 100755 --- a/include/diskio_flash.h +++ b/include/diskio_flash.h @@ -36,26 +36,61 @@ Modified by Date Description #include #include "diskio.h" +#include "serialintrf.h" +#define FLASH_CMD_WRITE 0x2 +#define FLASH_CMD_READ 0x3 +#define FLASH_CMD_WRDISABLE 0x4 +#define FLASH_CMD_READSTATUS 0x5 +#define FLASH_CMD_WRENABLE 0x6 +#define FLASH_CMD_BLOCK_ERASE 0xD8 +#define FLASH_CMD_BULK_ERASE 0xC7 + +#define FLASH_STATUS_WIP (1<<0) // Write In Progress + +typedef void (*FLASHDISKIO_INIT)(SerialIntrf *pInterf); + +typedef struct { + int DevNo; + uint64_t TotalSize; // Total Flash size in bytes + uint32_t EraseSize; // Min erasable block size in byte + uint32_t WriteSize; // Writable page size in bytes + int AddrSize; // Address size in bytes + FLASHDISKIO_INIT FlashInit; // Flash initialization function pointer +} FLASHDISKIO_CFG; class FlashDiskIO : public DiskIO { public: FlashDiskIO() : DiskIO() {} virtual ~FlashDiskIO() {} - /** + bool Init(FLASHDISKIO_CFG &Cfg, SerialIntrf *pInterf, + DISKIO_CACHE_DESC *pCacheBlk = NULL, int NbChaceBlk = 0); + + /** + * + * @return total disk size in KB + */ + virtual uint32_t GetSize(void) { return vTotalSize / 1024; } + + /** * Device specific minimum erase size in bytes * * @return */ - virtual uint32_t GetMinEraseSize() = 0; + virtual uint32_t GetMinEraseSize() { return vEraseSize; } /** * Device specific minimum write size in bytes * * @return */ - virtual uint32_t GetMinWriteSize() { return 0;} + virtual uint32_t GetMinWriteSize() { return vWriteSize; } + + /** + * Mass erase + */ + virtual void Erase(); /** * Erase Flash block. @@ -63,8 +98,30 @@ class FlashDiskIO : public DiskIO { * @param BlkNo : Starting block number to erase. * NbBlk : Number of consecutive blocks to erase */ - virtual void EraseBlock(uint32_t BlkNo, int NbBlk) = 0; - virtual bool EraseUptoAddress(uint64_t addr) { return false; } + virtual void EraseBlock(uint32_t BlkNo, int NbBlk); + + /** + * Read one sector from physical device + */ + virtual bool SectRead(uint32_t SectNo, uint8_t *pData); + + /** + * Write one sector to physical device + */ + virtual bool SectWrite(uint32_t SectNo, uint8_t *pData); + +protected: + void WriteDisable(); + bool WriteEnable(uint32_t Timeout = 10000); + bool WaitReady(uint32_t Timeout = 10000); + +private: + uint32_t vEraseSize; // Min erasable block size in byte + uint32_t vWriteSize; // Min writable size in bytes + uint64_t vTotalSize; // Total Flash size in bytes + int vAddrSize; // Address size in bytes + int vDevNo; + SerialIntrf *vpInterf; }; #ifdef __cplusplus diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp new file mode 100644 index 00000000..cfbd07eb --- /dev/null +++ b/src/diskio_flash.cpp @@ -0,0 +1,205 @@ +/*-------------------------------------------------------------------------- +File : diskio_flash.cpp + +Author : Hoang Nguyen Hoan Aug. 30, 2016 + +Desc : Generic flash disk I/O driver class + +Copyright (c) 2016, Motsai, all rights reserved + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies, and none of the +names : I-SYST or its contributors may be used to endorse or +promote products derived from this software without specific prior written +permission. + +For info or contributing contact : nh.hoang at motsai dot com + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- +Modified by Date Description + +----------------------------------------------------------------------------*/ +#include "diskio_flash.h" + +bool FlashDiskIO::Init(FLASHDISKIO_CFG &Cfg, SerialIntrf *pInterf, + DISKIO_CACHE_DESC *pCacheBlk, int NbCacheBlk) +{ + if (pInterf == NULL) + return false; + + if (Cfg.FlashInit) + Cfg.FlashInit(vpInterf); + + vDevNo = Cfg.DevNo; + vEraseSize = Cfg.EraseSize; + if (Cfg.WriteSize == 0) + vWriteSize = DISKIO_SECT_SIZE; + else + vWriteSize = Cfg.WriteSize; + vTotalSize = Cfg.TotalSize; + vAddrSize = Cfg.AddrSize; + vpInterf = pInterf; + + if (pCacheBlk && NbCacheBlk > 0) + { + SetCache(pCacheBlk, NbCacheBlk); + } + + return true; +} + +bool FlashDiskIO::WaitReady(uint32_t Timeout) +{ + uint8_t d; + + do { + d = FLASH_CMD_READSTATUS; + vpInterf->StartRx(0); + vpInterf->TxData(&d, 1); + vpInterf->RxData(&d, 1); + vpInterf->StopRx(); + if (!(d & FLASH_STATUS_WIP)) + return true; + } while (Timeout-- > 0); + + return false; +} + +void FlashDiskIO::WriteDisable() +{ + uint8_t d = FLASH_CMD_WRDISABLE; + vpInterf->Tx(vDevNo, &d, 1); +} + +bool FlashDiskIO::WriteEnable(uint32_t Timeout) +{ + uint8_t d; + + WaitReady(Timeout); + + d = FLASH_CMD_WRENABLE; + int cnt = vpInterf->Tx(vDevNo, &d, 1); + + return false; +} + +void FlashDiskIO::Erase() +{ + uint8_t d; + + WriteEnable(); + WaitReady(); + + d = FLASH_CMD_BULK_ERASE; + + int cnt = vpInterf->Tx(vDevNo, &d, 1); + + WaitReady(-1); + WriteDisable(); +} + +/** + * Erase Flash block. + * + * @param BlkNo : Starting block number to erase. + * NbBlk : Number of consecutive blocks to erase + */ +void FlashDiskIO::EraseBlock(uint32_t BlkNo, int NbBlk) +{ + uint8_t d[8]; + + BlkNo *= vEraseSize; + uint8_t *p = (uint8_t*)BlkNo; + + WriteEnable(); + WaitReady(); + + for (int i = 0; i < NbBlk; i++) + { + d[0] = FLASH_CMD_BLOCK_ERASE; + d[1] = p[2]; + d[2] = p[1]; + d[3] = p[0]; + vpInterf->Tx(vDevNo, d, 4); + BlkNo += vEraseSize; + } + WaitReady(-1); + WriteDisable(); +} + +/** + * Read one sector from physical device + */ +bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) +{ + uint8_t d[4]; + uint32_t addr = SectNo * DISKIO_SECT_SIZE; + uint8_t *p = (uint8_t*)&addr; + int cnt = 0; + + WaitReady(10000); + + d[0] = FLASH_CMD_READ; + + d[1] = p[2]; + d[2] = p[1]; + d[3] = p[0]; + + vpInterf->StartRx(vDevNo); + vpInterf->TxData((uint8_t*)d, 4); + int l = vpInterf->RxData(pBuff, DISKIO_SECT_SIZE); + vpInterf->StopRx(); + + return true; +} + +/** + * Write one sector to physical device + */ +bool FlashDiskIO::SectWrite(uint32_t SectNo, uint8_t *pData) +{ + uint8_t d[4]; + uint32_t addr = SectNo * DISKIO_SECT_SIZE; + uint8_t *p = (uint8_t*)&addr; + + int cnt = 0; + + WaitReady(); + WriteEnable(); + + d[0] = FLASH_CMD_WRITE; + d[1] = p[2]; + d[2] = p[1]; + d[3] = p[0]; + + cnt = DISKIO_SECT_SIZE; + while (cnt > 0) + { + int l = min(cnt, vWriteSize); + vpInterf->StartTx(vDevNo); + vpInterf->TxData((uint8_t*)d, 4); + l = vpInterf->TxData(pData, l); + vpInterf->StopTx(); + + cnt -= l; + pData += l; + addr += l; + } + WriteDisable(); + + return true; +} + + From 16562605855c6b1474ebcf75303648b97ed0cd0c Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Sun, 13 Nov 2016 10:14:33 -0500 Subject: [PATCH 04/66] File renaming --- OSX/EHAL/EHAL.xcodeproj/project.pbxproj | 16 ++++++++-------- .../UserInterfaceState.xcuserstate | Bin 37475 -> 39398 bytes .../{usbhiddev_impl.h => usb_hidhost_impl.h} | 2 +- ...sbhiddev_impl.cpp => usb_hidhost_impl.cpp} | 8 ++++---- include/{usbhiddev.h => usb_hidhost.h} | 0 5 files changed, 13 insertions(+), 13 deletions(-) rename OSX/EHAL/include/{usbhiddev_impl.h => usb_hidhost_impl.h} (99%) rename OSX/EHAL/src/{usbhiddev_impl.cpp => usb_hidhost_impl.cpp} (97%) rename include/{usbhiddev.h => usb_hidhost.h} (100%) diff --git a/OSX/EHAL/EHAL.xcodeproj/project.pbxproj b/OSX/EHAL/EHAL.xcodeproj/project.pbxproj index 43a4528e..59d5b0ba 100644 --- a/OSX/EHAL/EHAL.xcodeproj/project.pbxproj +++ b/OSX/EHAL/EHAL.xcodeproj/project.pbxproj @@ -20,7 +20,6 @@ 401FBF9D1D9CAC96004A39FF /* utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = 401FBF911D9CAC96004A39FF /* utf8.c */; }; 401FBF9E1D9CAC96004A39FF /* utf8cvt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 401FBF921D9CAC96004A39FF /* utf8cvt.cpp */; }; 401FBFA11D9CAD53004A39FF /* uart_osx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 401FBF9F1D9CAD53004A39FF /* uart_osx.cpp */; }; - 401FBFA21D9CAD53004A39FF /* usbhiddev_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 401FBFA01D9CAD53004A39FF /* usbhiddev_impl.cpp */; }; 401FBFEC1DA01F47004A39FF /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFDE1DA01F47004A39FF /* base64.h */; }; 401FBFED1DA01F47004A39FF /* cfifo.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFDF1DA01F47004A39FF /* cfifo.h */; }; 401FBFEE1DA01F47004A39FF /* convutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFE01DA01F47004A39FF /* convutil.h */; }; @@ -32,9 +31,10 @@ 401FBFF41DA01F47004A39FF /* sha1.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFE61DA01F47004A39FF /* sha1.h */; }; 401FBFF51DA01F47004A39FF /* sha256.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFE71DA01F47004A39FF /* sha256.h */; }; 401FBFF61DA01F47004A39FF /* uart.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFE81DA01F47004A39FF /* uart.h */; }; - 401FBFF71DA01F47004A39FF /* usbhiddev.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFE91DA01F47004A39FF /* usbhiddev.h */; }; 401FBFF81DA01F47004A39FF /* utf8.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFEA1DA01F47004A39FF /* utf8.h */; }; 401FBFF91DA01F47004A39FF /* utf8cvt.h in Headers */ = {isa = PBXBuildFile; fileRef = 401FBFEB1DA01F47004A39FF /* utf8cvt.h */; }; + 4047E3CE1DD8B9E8005634A1 /* usb_hidhost.h in Headers */ = {isa = PBXBuildFile; fileRef = 4047E3CD1DD8B9E8005634A1 /* usb_hidhost.h */; }; + 4047E3D01DD8BA20005634A1 /* usb_hidhost_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4047E3CF1DD8BA20005634A1 /* usb_hidhost_impl.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -52,7 +52,6 @@ 401FBF911D9CAC96004A39FF /* utf8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utf8.c; path = ../../src/utf8.c; sourceTree = ""; }; 401FBF921D9CAC96004A39FF /* utf8cvt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utf8cvt.cpp; path = ../../src/utf8cvt.cpp; sourceTree = ""; }; 401FBF9F1D9CAD53004A39FF /* uart_osx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = uart_osx.cpp; path = src/uart_osx.cpp; sourceTree = ""; }; - 401FBFA01D9CAD53004A39FF /* usbhiddev_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = usbhiddev_impl.cpp; path = src/usbhiddev_impl.cpp; sourceTree = ""; }; 401FBFDE1DA01F47004A39FF /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base64.h; path = ../../include/base64.h; sourceTree = ""; }; 401FBFDF1DA01F47004A39FF /* cfifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cfifo.h; path = ../../include/cfifo.h; sourceTree = ""; }; 401FBFE01DA01F47004A39FF /* convutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convutil.h; path = ../../include/convutil.h; sourceTree = ""; }; @@ -64,9 +63,10 @@ 401FBFE61DA01F47004A39FF /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha1.h; path = ../../include/sha1.h; sourceTree = ""; }; 401FBFE71DA01F47004A39FF /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha256.h; path = ../../include/sha256.h; sourceTree = ""; }; 401FBFE81DA01F47004A39FF /* uart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uart.h; path = ../../include/uart.h; sourceTree = ""; }; - 401FBFE91DA01F47004A39FF /* usbhiddev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = usbhiddev.h; path = ../../include/usbhiddev.h; sourceTree = ""; }; 401FBFEA1DA01F47004A39FF /* utf8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utf8.h; path = ../../include/utf8.h; sourceTree = ""; }; 401FBFEB1DA01F47004A39FF /* utf8cvt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utf8cvt.h; path = ../../include/utf8cvt.h; sourceTree = ""; }; + 4047E3CD1DD8B9E8005634A1 /* usb_hidhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = usb_hidhost.h; path = ../../include/usb_hidhost.h; sourceTree = ""; }; + 4047E3CF1DD8BA20005634A1 /* usb_hidhost_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = usb_hidhost_impl.cpp; path = src/usb_hidhost_impl.cpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -83,6 +83,8 @@ 401FBF771D9CAC42004A39FF = { isa = PBXGroup; children = ( + 4047E3CF1DD8BA20005634A1 /* usb_hidhost_impl.cpp */, + 4047E3CD1DD8B9E8005634A1 /* usb_hidhost.h */, 401FBFDE1DA01F47004A39FF /* base64.h */, 401FBFDF1DA01F47004A39FF /* cfifo.h */, 401FBFE01DA01F47004A39FF /* convutil.h */, @@ -94,11 +96,9 @@ 401FBFE61DA01F47004A39FF /* sha1.h */, 401FBFE71DA01F47004A39FF /* sha256.h */, 401FBFE81DA01F47004A39FF /* uart.h */, - 401FBFE91DA01F47004A39FF /* usbhiddev.h */, 401FBFEA1DA01F47004A39FF /* utf8.h */, 401FBFEB1DA01F47004A39FF /* utf8cvt.h */, 401FBF9F1D9CAD53004A39FF /* uart_osx.cpp */, - 401FBFA01D9CAD53004A39FF /* usbhiddev_impl.cpp */, 401FBF871D9CAC96004A39FF /* base64.c */, 401FBF881D9CAC96004A39FF /* cfifo.c */, 401FBF891D9CAC96004A39FF /* crc.c */, @@ -131,6 +131,7 @@ buildActionMask = 2147483647; files = ( 401FBFF81DA01F47004A39FF /* utf8.h in Headers */, + 4047E3CE1DD8B9E8005634A1 /* usb_hidhost.h in Headers */, 401FBFED1DA01F47004A39FF /* cfifo.h in Headers */, 401FBFEC1DA01F47004A39FF /* base64.h in Headers */, 401FBFF91DA01F47004A39FF /* utf8cvt.h in Headers */, @@ -143,7 +144,6 @@ 401FBFEF1DA01F47004A39FF /* crc.h in Headers */, 401FBFF31DA01F47004A39FF /* serialintrf.h in Headers */, 401FBFF01DA01F47004A39FF /* intelhex.h in Headers */, - 401FBFF71DA01F47004A39FF /* usbhiddev.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -204,7 +204,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 401FBFA21D9CAD53004A39FF /* usbhiddev_impl.cpp in Sources */, 401FBF9E1D9CAC96004A39FF /* utf8cvt.cpp in Sources */, 401FBF971D9CAC96004A39FF /* prbs.c in Sources */, 401FBF981D9CAC96004A39FF /* sbuffer.c in Sources */, @@ -213,6 +212,7 @@ 401FBF961D9CAC96004A39FF /* intelhex.c in Sources */, 401FBF9A1D9CAC96004A39FF /* sha1.c in Sources */, 401FBF9C1D9CAC96004A39FF /* uart.c in Sources */, + 4047E3D01DD8BA20005634A1 /* usb_hidhost_impl.cpp in Sources */, 401FBF951D9CAC96004A39FF /* crc.c in Sources */, 401FBF931D9CAC96004A39FF /* base64.c in Sources */, 401FBF9B1D9CAC96004A39FF /* sha256.c in Sources */, diff --git a/OSX/EHAL/EHAL.xcodeproj/project.xcworkspace/xcuserdata/hoan.xcuserdatad/UserInterfaceState.xcuserstate b/OSX/EHAL/EHAL.xcodeproj/project.xcworkspace/xcuserdata/hoan.xcuserdatad/UserInterfaceState.xcuserstate index c9801bdd6e890317f6949cd506938b8aaa8780c5..999bbcfe7514e6afab1cb8bb6a19afb7e7ae2484 100644 GIT binary patch delta 17922 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 delta 15989 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 #include -#include "usbhiddev.h" +#include "usb_hidhost.h" typedef void (*HIDINTRPTINCB)(UsbHidDevice *pDev, char *pBuf, uint32_t DataLen); diff --git a/OSX/EHAL/src/usbhiddev_impl.cpp b/OSX/EHAL/src/usb_hidhost_impl.cpp similarity index 97% rename from OSX/EHAL/src/usbhiddev_impl.cpp rename to OSX/EHAL/src/usb_hidhost_impl.cpp index 938ef4f6..37f7fe11 100755 --- a/OSX/EHAL/src/usbhiddev_impl.cpp +++ b/OSX/EHAL/src/usb_hidhost_impl.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- - File : usbhiddev_impl.h + File : usb_hidhost_impl.h Author : Hoang Nguyen Hoan July 9, 2009 @@ -9,7 +9,7 @@ ---------------------------------------------------------------------------- Modified by Date Description ----------------------------------------------------------------------------*/ -#include "usbhiddev_impl.h" +#include "usb_hidhost_impl.h" void UsbHidDevice_Impl::IOHIDDeviceReportCallback(void *inContext, // context from IOHIDDeviceRegisterInputReportCallback IOReturn inResult, // completion result for the input report operation @@ -126,8 +126,8 @@ bool UsbHidDevice_Impl::WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t Buf IOReturn res = IOHIDDeviceSetReport(vHidDev, kIOHIDReportTypeOutput, RepNo, (const uint8_t *)pBuf, BufSize); - if (res != kIOReturnSuccess) - printf("WriteReport Error %x\n", res); + //if (res != kIOReturnSuccess) + // printf("WriteReport Error %x\n", res); return res == kIOReturnSuccess; } diff --git a/include/usbhiddev.h b/include/usb_hidhost.h similarity index 100% rename from include/usbhiddev.h rename to include/usb_hidhost.h From bd58f4f4c986672a293d0a53d9226c1ca24e5f69 Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Sun, 13 Nov 2016 11:12:20 -0500 Subject: [PATCH 05/66] Renaming --- .../UserInterfaceState.xcuserstate | Bin 39398 -> 39925 bytes OSX/EHAL/include/usb_hidhost_impl.h | 35 ++- OSX/EHAL/src/usb_hidhost_impl.cpp | 31 ++- Win/EHAL/EHAL.sln | 44 ++-- Win/EHAL/EHAL.vcxproj | 244 +++++++++--------- Win/EHAL/include/usb_hidhost_impl.h | 82 ++++++ Win/EHAL/include/usbhiddev_impl.h | 54 ---- ...sbhiddev_impl.cpp => usb_hidhost_impl.cpp} | 38 ++- include/usb_hidhost.h | 2 +- 9 files changed, 313 insertions(+), 217 deletions(-) create mode 100644 Win/EHAL/include/usb_hidhost_impl.h delete mode 100644 Win/EHAL/include/usbhiddev_impl.h rename Win/EHAL/src/{usbhiddev_impl.cpp => usb_hidhost_impl.cpp} (83%) diff --git a/OSX/EHAL/EHAL.xcodeproj/project.xcworkspace/xcuserdata/hoan.xcuserdatad/UserInterfaceState.xcuserstate b/OSX/EHAL/EHAL.xcodeproj/project.xcworkspace/xcuserdata/hoan.xcuserdatad/UserInterfaceState.xcuserstate index 999bbcfe7514e6afab1cb8bb6a19afb7e7ae2484..74a3d6e63e7b119c1749131882301da978dbe7f8 100644 GIT binary patch delta 17029 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 diff --git a/OSX/EHAL/include/usb_hidhost_impl.h b/OSX/EHAL/include/usb_hidhost_impl.h index 5df9bdbe..4eeccbc4 100755 --- a/OSX/EHAL/include/usb_hidhost_impl.h +++ b/OSX/EHAL/include/usb_hidhost_impl.h @@ -1,16 +1,37 @@ -/*-------------------------------------------------------------------------- - File : usbhiddev_impl.h +/*--------------------------------------------------------------------------- + File : usb_hidhost_implt.h Author : Hoang Nguyen Hoan July 9, 2009 - Desc : Implementation class for USB device on MAC OS X + Desc : Generic class of Host side USB HID device access + Implementation class for USB device on MAC OS X + Copyright (c) 2009-16, I-SYST, all rights reserved Copyright (c) 2009, Ekomini Inc, all rights reserved + + Permission to use, copy, modify, and distribute this software for any purpose + with or without fee is hereby granted, provided that the above copyright + notice and this permission notice appear in all copies, and none of the + names : I-SYST, TidalStream or its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- - Modified by Date Description + Modified by Date Description ----------------------------------------------------------------------------*/ -#ifndef __USBHIDDEV_IMPL_H__ -#define __USBHIDDEV_IMPL_H__ +#ifndef __USB_HIDHOST_IMPL_H__ +#define __USB_HIDHOST_IMPL_H__ #include #include @@ -61,4 +82,4 @@ class UsbHidDevice_Impl : public UsbHidDevice { uint8_t *vpInRepData; }; -#endif // __USBHIDDEV_IMPL_H__ +#endif // __USB_HIDHOST_IMPL_H__ diff --git a/OSX/EHAL/src/usb_hidhost_impl.cpp b/OSX/EHAL/src/usb_hidhost_impl.cpp index 37f7fe11..1418d996 100755 --- a/OSX/EHAL/src/usb_hidhost_impl.cpp +++ b/OSX/EHAL/src/usb_hidhost_impl.cpp @@ -1,13 +1,34 @@ -/*-------------------------------------------------------------------------- - File : usb_hidhost_impl.h +/*--------------------------------------------------------------------------- + File : usb_hidhost_implt.cpp Author : Hoang Nguyen Hoan July 9, 2009 - Desc : Implementation class for USB device on MAC OS X - + Desc : Generic class of Host side USB HID device access + Implementation class for USB device on MAC OS X + + Copyright (c) 2008-16, I-SYST, all rights reserved Copyright (c) 2009, Ekomini Inc, all rights reserved + + Permission to use, copy, modify, and distribute this software for any purpose + with or without fee is hereby granted, provided that the above copyright + notice and this permission notice appear in all copies, and none of the + names : I-SYST, TidalStream or its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- - Modified by Date Description + Modified by Date Description ----------------------------------------------------------------------------*/ #include "usb_hidhost_impl.h" diff --git a/Win/EHAL/EHAL.sln b/Win/EHAL/EHAL.sln index d7553855..53caece6 100644 --- a/Win/EHAL/EHAL.sln +++ b/Win/EHAL/EHAL.sln @@ -1,22 +1,22 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EHAL", "EHAL.vcxproj", "{D89EF789-E520-476E-A345-B12BE9310693}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D89EF789-E520-476E-A345-B12BE9310693}.Debug|Win32.ActiveCfg = Debug|Win32 - {D89EF789-E520-476E-A345-B12BE9310693}.Debug|Win32.Build.0 = Debug|Win32 - {D89EF789-E520-476E-A345-B12BE9310693}.Release|Win32.ActiveCfg = Release|Win32 - {D89EF789-E520-476E-A345-B12BE9310693}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2013 for Windows Desktop +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EHAL", "EHAL.vcxproj", "{DE882088-60C9-4753-AC1C-AE9763E2D453}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DE882088-60C9-4753-AC1C-AE9763E2D453}.Debug|Win32.ActiveCfg = Debug|Win32 + {DE882088-60C9-4753-AC1C-AE9763E2D453}.Debug|Win32.Build.0 = Debug|Win32 + {DE882088-60C9-4753-AC1C-AE9763E2D453}.Release|Win32.ActiveCfg = Release|Win32 + {DE882088-60C9-4753-AC1C-AE9763E2D453}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Win/EHAL/EHAL.vcxproj b/Win/EHAL/EHAL.vcxproj index 69ce812a..7f9da88a 100644 --- a/Win/EHAL/EHAL.vcxproj +++ b/Win/EHAL/EHAL.vcxproj @@ -1,123 +1,123 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {D89EF789-E520-476E-A345-B12BE9310693} - Win32Proj - OHAL - - - - StaticLibrary - true - v120_xp - Unicode - - - StaticLibrary - false - v120_xp - true - Unicode - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - include;../../include;C:\WinDDK\7600.16385.0\inc\api - Sync - MultiThreaded - false - false - Cdecl - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - include;../../include;C:\WinDDK\7600.16385.0\inc\api - Sync - MultiThreaded - false - false - Cdecl - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + {DE882088-60C9-4753-AC1C-AE9763E2D453} + Win32Proj + OHAL + + + + StaticLibrary + true + v120_xp + Unicode + + + StaticLibrary + false + v120_xp + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + include;../../include;C:\WinDDK\7600.16385.0\inc\api + Sync + MultiThreaded + false + false + Cdecl + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + include;../../include;C:\WinDDK\7600.16385.0\inc\api + Sync + MultiThreaded + false + false + Cdecl + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Win/EHAL/include/usb_hidhost_impl.h b/Win/EHAL/include/usb_hidhost_impl.h new file mode 100644 index 00000000..499cae87 --- /dev/null +++ b/Win/EHAL/include/usb_hidhost_impl.h @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------------------- +File : usb_hidhost_implt.h + +Author : Hoang Nguyen Hoan Oct 9, 2008 + +Desc : Generic class of Host side USB HID device access + Implementation class for USB device on Windows + +Copyright (c) 2008-16, I-SYST, all rights reserved + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies, and none of the +names : I-SYST, TidalStream or its contributors may be used to endorse or +promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- +Modified by Date Description +----------------------------------------------------------------------------*/ +#ifndef __USB_HIDHOST_IMPL_H__ +#define __USB_HIDHOST_IMPL_H__ + +#include +#include "Windows.h" +#include + +extern "C" { +#include "hidsdi.h" +#include "hidpi.h" +} + +#include "usb_hidhost.h" + +typedef struct { + +} HIDDEV_DATA; + +class UsbHidDevice_Impl : public UsbHidDevice { +public: + UsbHidDevice_Impl(); + virtual ~UsbHidDevice_Impl(); + + bool Init(HANDLE hDev); + bool RegisterWindowNotifications(HWND hWnd); + bool RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService); + void GetDeviceCapabilities(); + int ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans = true); + bool WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t Bufsize, bool CtrlTrans = true); + int ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); + bool WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); + bool WaitResponse(int TimeoutSec); + bool GetSerialNumber(std::wstring &sn); + bool GetSerialNumber(std::string &sn); + bool GetProductString(std::wstring &pd); + virtual bool ProcessInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) { return true; } + +protected: + virtual void ReadDeviceInfo() {} + +private: + HANDLE vhDevice; + HANDLE vhDevNotification; + HIDP_CAPS vCaps; + HANDLE vhEvent; + OVERLAPPED vRdOverlapped; + OVERLAPPED vWrOverlapped; + int vTempBufSize; + char *vpTempBuf; +}; +#endif // __USB_HIDHOST_IMPL_H diff --git a/Win/EHAL/include/usbhiddev_impl.h b/Win/EHAL/include/usbhiddev_impl.h deleted file mode 100644 index 8ff30502..00000000 --- a/Win/EHAL/include/usbhiddev_impl.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2008, I-SYST, All rights reserved -//--------------------------------------------------------------------------- - -#ifndef __USBHIDDEV_IMPL_H__ -#define __USBHIDDEV_IMPL_H__ - -#include -#include "Windows.h" -#include - -extern "C" { -#include "hidsdi.h" -#include "hidpi.h" -} - -#include "UsbHidDev.h" - -typedef struct { - -} HIDDEV_DATA; - -class UsbHidDevice_Impl : public UsbHidDevice { -public: - UsbHidDevice_Impl(); - virtual ~UsbHidDevice_Impl(); - - bool Init(HANDLE hDev); - bool RegisterWindowNotifications(HWND hWnd); - bool RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService); - void GetDeviceCapabilities(); - int ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans = true); - bool WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t Bufsize, bool CtrlTrans = true); - int ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); - bool WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); - bool WaitResponse(int TimeoutSec); - bool GetSerialNumber(std::wstring &sn); - bool GetSerialNumber(std::string &sn); - bool GetProductString(std::wstring &pd); - virtual bool ProcessInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) { return true; } - -protected: - virtual void ReadDeviceInfo() {} - -private: - HANDLE vhDevice; - HANDLE vhDevNotification; - HIDP_CAPS vCaps; - HANDLE vhEvent; - OVERLAPPED vRdOverlapped; - OVERLAPPED vWrOverlapped; - int vTempBufSize; - char *vpTempBuf; -}; -#endif diff --git a/Win/EHAL/src/usbhiddev_impl.cpp b/Win/EHAL/src/usb_hidhost_impl.cpp similarity index 83% rename from Win/EHAL/src/usbhiddev_impl.cpp rename to Win/EHAL/src/usb_hidhost_impl.cpp index eb0249c4..4e77677f 100644 --- a/Win/EHAL/src/usbhiddev_impl.cpp +++ b/Win/EHAL/src/usb_hidhost_impl.cpp @@ -1,8 +1,34 @@ -// -// Copyright (c) 2009, Ekomini Inc., All rights reserved -// Copyright (c) 2008, I-SYST, All rights reserved -//--------------------------------------------------------------------------- -//#include +/*--------------------------------------------------------------------------- +File : usb_hidhost_implt.cpp + +Author : Hoang Nguyen Hoan Oct 9, 2008 + +Desc : Generic class of Host side USB HID device access + Implementation class for USB device on Windows + +Copyright (c) 2008-16, I-SYST, all rights reserved + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies, and none of the +names : I-SYST, TidalStream or its contributors may be used to endorse or +promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- +Modified by Date Description +----------------------------------------------------------------------------*/ #include #include @@ -16,7 +42,7 @@ #pragma comment (lib, "Setupapi.lib") #pragma comment (lib, "hid.lib") -#include "usbhiddev_impl.h" +#include "usb_hidhost_impl.h" using namespace std; //--------------------------------------------------------------------------- diff --git a/include/usb_hidhost.h b/include/usb_hidhost.h index b56f40b3..b069e6dc 100644 --- a/include/usb_hidhost.h +++ b/include/usb_hidhost.h @@ -1,5 +1,5 @@ /*--------------------------------------------------------------------------- -File : usbhiddev.h +File : usb_hidhost.h Author : Hoang Nguyen Hoan Jan. 16, 2009 From 6a5968554b07ca5e1ce4c15e92e49c5b9f86cccf Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Sun, 13 Nov 2016 20:21:43 -0500 Subject: [PATCH 06/66] Add UsbHidFIndDev in EHAL Windows --- Win/EHAL/EHAL.vcxproj | 2 +- Win/EHAL/include/usb_hidhost_impl.h | 107 ++-- Win/EHAL/src/usb_hidhost_impl.cpp | 826 ++++++++++++++++------------ 3 files changed, 524 insertions(+), 411 deletions(-) diff --git a/Win/EHAL/EHAL.vcxproj b/Win/EHAL/EHAL.vcxproj index 7f9da88a..59357492 100644 --- a/Win/EHAL/EHAL.vcxproj +++ b/Win/EHAL/EHAL.vcxproj @@ -49,7 +49,7 @@ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) include;../../include;C:\WinDDK\7600.16385.0\inc\api Sync - MultiThreaded + MultiThreadedDebug false false Cdecl diff --git a/Win/EHAL/include/usb_hidhost_impl.h b/Win/EHAL/include/usb_hidhost_impl.h index 499cae87..5a0d01af 100644 --- a/Win/EHAL/include/usb_hidhost_impl.h +++ b/Win/EHAL/include/usb_hidhost_impl.h @@ -29,54 +29,59 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- Modified by Date Description ----------------------------------------------------------------------------*/ -#ifndef __USB_HIDHOST_IMPL_H__ -#define __USB_HIDHOST_IMPL_H__ - -#include -#include "Windows.h" -#include - -extern "C" { -#include "hidsdi.h" -#include "hidpi.h" -} - -#include "usb_hidhost.h" - -typedef struct { - -} HIDDEV_DATA; - -class UsbHidDevice_Impl : public UsbHidDevice { -public: - UsbHidDevice_Impl(); - virtual ~UsbHidDevice_Impl(); - - bool Init(HANDLE hDev); - bool RegisterWindowNotifications(HWND hWnd); - bool RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService); - void GetDeviceCapabilities(); - int ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans = true); - bool WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t Bufsize, bool CtrlTrans = true); - int ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); - bool WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); - bool WaitResponse(int TimeoutSec); - bool GetSerialNumber(std::wstring &sn); - bool GetSerialNumber(std::string &sn); - bool GetProductString(std::wstring &pd); - virtual bool ProcessInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) { return true; } - -protected: - virtual void ReadDeviceInfo() {} - -private: - HANDLE vhDevice; - HANDLE vhDevNotification; - HIDP_CAPS vCaps; - HANDLE vhEvent; - OVERLAPPED vRdOverlapped; - OVERLAPPED vWrOverlapped; - int vTempBufSize; - char *vpTempBuf; -}; -#endif // __USB_HIDHOST_IMPL_H +#ifndef __USB_HIDHOST_IMPL_H__ +#define __USB_HIDHOST_IMPL_H__ + +#include +#include "Windows.h" +#include + +extern "C" { +#include "hidsdi.h" +#include "hidpi.h" +} + +#include "usb_hidhost.h" + +typedef struct { + +} HIDDEV_DATA; + +class UsbHidDevice_Impl : public UsbHidDevice { +public: + UsbHidDevice_Impl(); + virtual ~UsbHidDevice_Impl(); + + bool Init(HANDLE hDev); + bool RegisterWindowNotifications(HWND hWnd); + bool RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService); + void GetDeviceCapabilities(); + int ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans = true); + bool WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t Bufsize, bool CtrlTrans = true); + int ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); + bool WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize); + bool WaitResponse(int TimeoutSec); + bool GetSerialNumber(std::wstring &sn); + bool GetSerialNumber(std::string &sn); + bool GetProductString(std::wstring &pd); + virtual bool ProcessInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) { return true; } + +protected: + virtual void ReadDeviceInfo() {} + +private: + HANDLE vhDevice; + HANDLE vhDevNotification; + HIDP_CAPS vCaps; + HANDLE vhEvent; + OVERLAPPED vRdOverlapped; + OVERLAPPED vWrOverlapped; + int vTempBufSize; + char *vpTempBuf; +}; + +typedef bool(*USBHIDFOUNDCB)(HANDLE HidDev); + +int UsbHidFindDevice(int VendId, int ProdId, USBHIDFOUNDCB Callback); + +#endif // __USB_HIDHOST_IMPL_H diff --git a/Win/EHAL/src/usb_hidhost_impl.cpp b/Win/EHAL/src/usb_hidhost_impl.cpp index 4e77677f..348025c8 100644 --- a/Win/EHAL/src/usb_hidhost_impl.cpp +++ b/Win/EHAL/src/usb_hidhost_impl.cpp @@ -29,362 +29,470 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- Modified by Date Description ----------------------------------------------------------------------------*/ - -#include -#include -#include - -#include -#include -//#include -#include -#pragma hdrstop -#pragma comment (lib, "Setupapi.lib") -#pragma comment (lib, "hid.lib") - -#include "usb_hidhost_impl.h" - -using namespace std; -//--------------------------------------------------------------------------- - -//#pragma package(smart_init) - -UsbHidDevice_Impl::UsbHidDevice_Impl() : - vhDevice(INVALID_HANDLE_VALUE), - vhDevNotification(INVALID_HANDLE_VALUE), - vhEvent(INVALID_HANDLE_VALUE), - vpTempBuf(NULL), - vTempBufSize(0) -{ - memset(&vRdOverlapped, 0, sizeof(OVERLAPPED)); - memset(&vWrOverlapped, 0, sizeof(OVERLAPPED)); -} - -UsbHidDevice_Impl::~UsbHidDevice_Impl() -{ - if (vhDevNotification != INVALID_HANDLE_VALUE) - UnregisterDeviceNotification(vhDevNotification); - if (vhDevice != INVALID_HANDLE_VALUE) - CloseHandle(vhDevice); - if (vhEvent != INVALID_HANDLE_VALUE) - CloseHandle(vhEvent); - if (vpTempBuf) - delete[] vpTempBuf; -} - -bool UsbHidDevice_Impl::Init(HANDLE hDev) -{ - if (hDev == NULL || hDev == INVALID_HANDLE_VALUE) - return false; - - vhDevice = hDev; - - PHIDP_PREPARSED_DATA PreparsedData; - - HidD_GetPreparsedData(vhDevice, &PreparsedData); - - HidP_GetCaps(PreparsedData, &vCaps); - - if (vpTempBuf) - delete[] vpTempBuf; - vTempBufSize = std::max(vCaps.InputReportByteLength, vCaps.OutputReportByteLength); - vTempBufSize = std::max(vTempBufSize, vCaps.FeatureReportByteLength); - vpTempBuf = new char[vTempBufSize]; - - HidD_FreePreparsedData(PreparsedData); - - if (vRdOverlapped.hEvent == 0) - { - vRdOverlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - } - - if (vWrOverlapped.hEvent == 0) - { - vWrOverlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - } - - ReadDeviceInfo(); - - return true; -} - -bool UsbHidDevice_Impl::RegisterWindowNotifications(HWND hWnd) -{ - DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface; -// HDEVNOTIFY DeviceNotificationHandle; - - DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface); - DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; -// DevBroadcastDeviceInterface.dbcc_classguid = vHidGuid; - - vhDevNotification = RegisterDeviceNotification(hWnd, - &DevBroadcastDeviceInterface, - DEVICE_NOTIFY_WINDOW_HANDLE); - - return vhDevNotification != NULL; -} - -bool UsbHidDevice_Impl::RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService) -{ - DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface; - HDEVNOTIFY DeviceNotificationHandle; - - DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface); - DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; -// DevBroadcastDeviceInterface.dbcc_classguid = vHidGuid; - - vhDevNotification = RegisterDeviceNotification(hService, - &DevBroadcastDeviceInterface, - DEVICE_NOTIFY_SERVICE_HANDLE); - - return vhDevNotification != NULL; -} - -void UsbHidDevice_Impl::GetDeviceCapabilities() -{ - //Get the Capabilities structure for the device. - if (vhDevice == NULL) - return; - - PHIDP_PREPARSED_DATA PreparsedData; - - HidD_GetPreparsedData(vhDevice, &PreparsedData); - - HidP_GetCaps(PreparsedData, &vCaps); - - if (vpTempBuf) - delete[] vpTempBuf; - vTempBufSize = std::max(vCaps.InputReportByteLength, vCaps.OutputReportByteLength); - vTempBufSize = std::max(vTempBufSize, vCaps.FeatureReportByteLength); - vpTempBuf = new char[vTempBufSize]; - - HidD_FreePreparsedData(PreparsedData); -} - -int UsbHidDevice_Impl::ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans) -{ - unsigned long retval = 0; - DWORD res = FALSE; - - if (vhDevice == NULL || vhDevice == INVALID_HANDLE_VALUE) - return 0; - - //The first byte is the report number. - //memset(vpTempBuf, 0, vTempBufSize); - vpTempBuf[0] = RepNo; - - if (CtrlTrans) - { - //Read a report from the device using a control transfer. - res = HidD_GetInputReport(vhDevice, vpTempBuf, vCaps.InputReportByteLength); - if (res) - { - memcpy(pBuf, vpTempBuf + 1, std::min(BufSize, vTempBufSize)); - retval = vCaps.InputReportByteLength - 1; - } - } - else - { - res = ReadFile(vhDevice, vpTempBuf, vCaps.InputReportByteLength, - &retval, (LPOVERLAPPED)&vRdOverlapped); - - res = WaitForSingleObject(vRdOverlapped.hEvent, 6000); - - switch (res) - { - case WAIT_OBJECT_0: - res = GetOverlappedResult(vhDevice, &vRdOverlapped, &retval, true); - - //memcpy(pBuf, vpTempBuf + 1, std::min(BufSize, vTempBufSize)); - ProcessInputReport(RepNo, (uint8_t*)vpTempBuf + 1, std::min(BufSize, vTempBufSize)); - break; - case WAIT_TIMEOUT: - - res = CancelIo(vhDevice); - - break; - default: - ; - } - - //ResetEvent(vhEvent); - - } - - return retval; -} - -bool UsbHidDevice_Impl::WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans) -{ - //Send a report to the device. - - DWORD BytesWritten = 0; - INT Index =0; - ULONG res; - bool retval = false; - - if (vhDevice == NULL || vhDevice == INVALID_HANDLE_VALUE) - return false; - - //The first byte is the report number. - vpTempBuf[0] = RepNo; - int len = BufSize;//std::min(BufSize, vCaps.OutputReportByteLength); - memcpy(vpTempBuf + 1, pBuf, len); - - if (CtrlTrans) - { - // Send a control report to the device. - res = HidD_SetOutputReport(vhDevice, vpTempBuf, vCaps.OutputReportByteLength); - if (res) - { - retval = true; - } - } - else - { - res = WriteFile(vhDevice, vpTempBuf, vCaps.OutputReportByteLength, - &BytesWritten, (LPOVERLAPPED)&vWrOverlapped); - res = WaitForSingleObject(vWrOverlapped.hEvent, 6000); - - switch (res) - { - case WAIT_OBJECT_0: - retval = true; - break; - case WAIT_TIMEOUT: - res = CancelIo(vhDevice); - - break; - default: - ; - } - //ResetEvent(vhEvent); - - } - - return retval; -} - -int UsbHidDevice_Impl::ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) -{ - // Read a Feature report from the device. - bool res = false; - int retval = 0; - - //The first byte is the report number. - memset(vpTempBuf, 0, vTempBufSize); - vpTempBuf[0] = RepNo; - - //Read a report from the device. - - /* - HidD_GetFeature - Returns: - True on success - Requires: - A device handle returned by CreateFile. - A buffer to hold the report. - The report length returned by HidP_GetCaps in Capabilities.InputReportByteLength. - */ - - if (vhDevice != INVALID_HANDLE_VALUE) - res = HidD_GetFeature(vhDevice, vpTempBuf, vCaps.FeatureReportByteLength); - if (res) - { - memcpy(pBuf, vpTempBuf + 1, min(vCaps.FeatureReportByteLength, (unsigned short)BufSize)); - retval = vCaps.FeatureReportByteLength; - } - else - { - //The read attempt failed, so close the handles, display a message, - //and set MyDeviceDetected to FALSE so the next attempt will look for the device. - - } - - return retval; -} - -bool UsbHidDevice_Impl::WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) -{ - //Send a report to the device. - DWORD BytesWritten = 0; - INT Index =0; - ULONG res = 0; - - //The first byte is the report number. - memset(vpTempBuf, 0, vTempBufSize); - vpTempBuf[0] = RepNo; - - memcpy(&vpTempBuf[1], pBuf, min(BufSize, (uint32_t)vCaps.FeatureReportByteLength)); - - //Send a report to the device. - - /* - HidD_SetFeature - Sends a report to the device. - Returns: success or failure. - Requires: - A device handle returned by CreateFile. - A buffer that holds the report. - The Output Report length returned by HidP_GetCaps, - */ - - if (vhDevice != INVALID_HANDLE_VALUE) - res = HidD_SetFeature(vhDevice, vpTempBuf, vCaps.FeatureReportByteLength); - - if (!res) - { - //The write attempt failed, so close the handles, display a message, - //and set MyDeviceDetected to FALSE so the next attempt will look for the device. - - } - else - { - } - - return res; -} - -bool UsbHidDevice_Impl::WaitResponse(int TimeoutSec) -{ - return true; -} - -bool UsbHidDevice_Impl::GetSerialNumber(std::wstring &sn) -{ - wchar_t buf[256]; - bool retval = HidD_GetSerialNumberString(vhDevice, buf, 255*2); - if (retval) - { - sn = buf; - } - - return retval; -} - -bool UsbHidDevice_Impl::GetSerialNumber(std::string &sn) -{ - wchar_t buf[256]; - bool retval = HidD_GetSerialNumberString(vhDevice, buf, 255*2); - if (retval) - { - sn.assign(&buf[0], &buf[wcslen(buf)]); - } - - return retval; -} - -bool UsbHidDevice_Impl::GetProductString(std::wstring &pd) -{ - wchar_t buf[256]; - bool retval = HidD_GetProductString(vhDevice, buf, 255*2); - if (retval) - { - pd = buf; - } - - return retval; -} - - - + +#include +#include +#include + +#include +#include +//#include +#include +#pragma hdrstop +#pragma comment (lib, "Setupapi.lib") +#pragma comment (lib, "hid.lib") + +#include "usb_hidhost_impl.h" + +using namespace std; +//--------------------------------------------------------------------------- + +//#pragma package(smart_init) + +UsbHidDevice_Impl::UsbHidDevice_Impl() : + vhDevice(INVALID_HANDLE_VALUE), + vhDevNotification(INVALID_HANDLE_VALUE), + vhEvent(INVALID_HANDLE_VALUE), + vpTempBuf(NULL), + vTempBufSize(0) +{ + memset(&vRdOverlapped, 0, sizeof(OVERLAPPED)); + memset(&vWrOverlapped, 0, sizeof(OVERLAPPED)); +} + +UsbHidDevice_Impl::~UsbHidDevice_Impl() +{ + if (vhDevNotification != INVALID_HANDLE_VALUE) + UnregisterDeviceNotification(vhDevNotification); + if (vhDevice != INVALID_HANDLE_VALUE) + CloseHandle(vhDevice); + if (vhEvent != INVALID_HANDLE_VALUE) + CloseHandle(vhEvent); + if (vpTempBuf) + delete[] vpTempBuf; +} + +bool UsbHidDevice_Impl::Init(HANDLE hDev) +{ + if (hDev == NULL || hDev == INVALID_HANDLE_VALUE) + return false; + + vhDevice = hDev; + + PHIDP_PREPARSED_DATA PreparsedData; + + HidD_GetPreparsedData(vhDevice, &PreparsedData); + + HidP_GetCaps(PreparsedData, &vCaps); + + if (vpTempBuf) + delete[] vpTempBuf; + vTempBufSize = std::max(vCaps.InputReportByteLength, vCaps.OutputReportByteLength); + vTempBufSize = std::max(vTempBufSize, vCaps.FeatureReportByteLength); + vpTempBuf = new char[vTempBufSize]; + + HidD_FreePreparsedData(PreparsedData); + + if (vRdOverlapped.hEvent == 0) + { + vRdOverlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + + if (vWrOverlapped.hEvent == 0) + { + vWrOverlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + + ReadDeviceInfo(); + + return true; +} + +bool UsbHidDevice_Impl::RegisterWindowNotifications(HWND hWnd) +{ + DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface; +// HDEVNOTIFY DeviceNotificationHandle; + + DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface); + DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; +// DevBroadcastDeviceInterface.dbcc_classguid = vHidGuid; + + vhDevNotification = RegisterDeviceNotification(hWnd, + &DevBroadcastDeviceInterface, + DEVICE_NOTIFY_WINDOW_HANDLE); + + return vhDevNotification != NULL; +} + +bool UsbHidDevice_Impl::RegisterServiceNotifications(SERVICE_STATUS_HANDLE hService) +{ + DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface; + HDEVNOTIFY DeviceNotificationHandle; + + DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface); + DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; +// DevBroadcastDeviceInterface.dbcc_classguid = vHidGuid; + + vhDevNotification = RegisterDeviceNotification(hService, + &DevBroadcastDeviceInterface, + DEVICE_NOTIFY_SERVICE_HANDLE); + + return vhDevNotification != NULL; +} + +void UsbHidDevice_Impl::GetDeviceCapabilities() +{ + //Get the Capabilities structure for the device. + if (vhDevice == NULL) + return; + + PHIDP_PREPARSED_DATA PreparsedData; + + HidD_GetPreparsedData(vhDevice, &PreparsedData); + + HidP_GetCaps(PreparsedData, &vCaps); + + if (vpTempBuf) + delete[] vpTempBuf; + vTempBufSize = std::max(vCaps.InputReportByteLength, vCaps.OutputReportByteLength); + vTempBufSize = std::max(vTempBufSize, vCaps.FeatureReportByteLength); + vpTempBuf = new char[vTempBufSize]; + + HidD_FreePreparsedData(PreparsedData); +} + +int UsbHidDevice_Impl::ReadInputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans) +{ + unsigned long retval = 0; + DWORD res = FALSE; + + if (vhDevice == NULL || vhDevice == INVALID_HANDLE_VALUE) + return 0; + + //The first byte is the report number. + //memset(vpTempBuf, 0, vTempBufSize); + vpTempBuf[0] = RepNo; + + if (CtrlTrans) + { + //Read a report from the device using a control transfer. + res = HidD_GetInputReport(vhDevice, vpTempBuf, vCaps.InputReportByteLength); + if (res) + { + memcpy(pBuf, vpTempBuf + 1, std::min(BufSize, vTempBufSize)); + retval = vCaps.InputReportByteLength - 1; + } + } + else + { + res = ReadFile(vhDevice, vpTempBuf, vCaps.InputReportByteLength, + &retval, (LPOVERLAPPED)&vRdOverlapped); + + res = WaitForSingleObject(vRdOverlapped.hEvent, 6000); + + switch (res) + { + case WAIT_OBJECT_0: + res = GetOverlappedResult(vhDevice, &vRdOverlapped, &retval, true); + + //memcpy(pBuf, vpTempBuf + 1, std::min(BufSize, vTempBufSize)); + ProcessInputReport(RepNo, (uint8_t*)vpTempBuf + 1, std::min(BufSize, vTempBufSize)); + break; + case WAIT_TIMEOUT: + + res = CancelIo(vhDevice); + + break; + default: + ; + } + + //ResetEvent(vhEvent); + + } + + return retval; +} + +bool UsbHidDevice_Impl::WriteOutputReport(int RepNo, uint8_t *pBuf, uint32_t BufSize, bool CtrlTrans) +{ + //Send a report to the device. + + DWORD BytesWritten = 0; + INT Index =0; + ULONG res; + bool retval = false; + + if (vhDevice == NULL || vhDevice == INVALID_HANDLE_VALUE) + return false; + + //The first byte is the report number. + vpTempBuf[0] = RepNo; + int len = BufSize;//std::min(BufSize, vCaps.OutputReportByteLength); + memcpy(vpTempBuf + 1, pBuf, len); + + if (CtrlTrans) + { + // Send a control report to the device. + res = HidD_SetOutputReport(vhDevice, vpTempBuf, vCaps.OutputReportByteLength); + if (res) + { + retval = true; + } + } + else + { + res = WriteFile(vhDevice, vpTempBuf, vCaps.OutputReportByteLength, + &BytesWritten, (LPOVERLAPPED)&vWrOverlapped); + res = WaitForSingleObject(vWrOverlapped.hEvent, 6000); + + switch (res) + { + case WAIT_OBJECT_0: + retval = true; + break; + case WAIT_TIMEOUT: + res = CancelIo(vhDevice); + + break; + default: + ; + } + //ResetEvent(vhEvent); + + } + + return retval; +} + +int UsbHidDevice_Impl::ReadFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) +{ + // Read a Feature report from the device. + bool res = false; + int retval = 0; + + //The first byte is the report number. + memset(vpTempBuf, 0, vTempBufSize); + vpTempBuf[0] = RepNo; + + //Read a report from the device. + + /* + HidD_GetFeature + Returns: + True on success + Requires: + A device handle returned by CreateFile. + A buffer to hold the report. + The report length returned by HidP_GetCaps in Capabilities.InputReportByteLength. + */ + + if (vhDevice != INVALID_HANDLE_VALUE) + res = HidD_GetFeature(vhDevice, vpTempBuf, vCaps.FeatureReportByteLength); + if (res) + { + memcpy(pBuf, vpTempBuf + 1, min(vCaps.FeatureReportByteLength, (unsigned short)BufSize)); + retval = vCaps.FeatureReportByteLength; + } + else + { + //The read attempt failed, so close the handles, display a message, + //and set MyDeviceDetected to FALSE so the next attempt will look for the device. + + } + + return retval; +} + +bool UsbHidDevice_Impl::WriteFeatureReport(int RepNo, uint8_t *pBuf, uint32_t BufSize) +{ + //Send a report to the device. + DWORD BytesWritten = 0; + INT Index =0; + ULONG res = 0; + + //The first byte is the report number. + memset(vpTempBuf, 0, vTempBufSize); + vpTempBuf[0] = RepNo; + + memcpy(&vpTempBuf[1], pBuf, min(BufSize, (uint32_t)vCaps.FeatureReportByteLength)); + + //Send a report to the device. + + /* + HidD_SetFeature + Sends a report to the device. + Returns: success or failure. + Requires: + A device handle returned by CreateFile. + A buffer that holds the report. + The Output Report length returned by HidP_GetCaps, + */ + + if (vhDevice != INVALID_HANDLE_VALUE) + res = HidD_SetFeature(vhDevice, vpTempBuf, vCaps.FeatureReportByteLength); + + if (!res) + { + //The write attempt failed, so close the handles, display a message, + //and set MyDeviceDetected to FALSE so the next attempt will look for the device. + + } + else + { + } + + return res; +} + +bool UsbHidDevice_Impl::WaitResponse(int TimeoutSec) +{ + return true; +} + +bool UsbHidDevice_Impl::GetSerialNumber(std::wstring &sn) +{ + wchar_t buf[256]; + bool retval = HidD_GetSerialNumberString(vhDevice, buf, 255*2); + if (retval) + { + sn = buf; + } + + return retval; +} + +bool UsbHidDevice_Impl::GetSerialNumber(std::string &sn) +{ + wchar_t buf[256]; + bool retval = HidD_GetSerialNumberString(vhDevice, buf, 255*2); + if (retval) + { + sn.assign(&buf[0], &buf[wcslen(buf)]); + } + + return retval; +} + +bool UsbHidDevice_Impl::GetProductString(std::wstring &pd) +{ + wchar_t buf[256]; + bool retval = HidD_GetProductString(vhDevice, buf, 255*2); + if (retval) + { + pd = buf; + } + + return retval; +} + + +int UsbHidFindDevice(int VendId, int ProdId, USBHIDFOUNDCB Callback) +{ + bool retval = false; + HIDD_ATTRIBUTES hidatt; + DWORD DeviceUsage; + SP_DEVICE_INTERFACE_DATA devdata; + PSP_DEVICE_INTERFACE_DETAIL_DATA devdetaildata = NULL; + LONG res; + std::string UsageDescription; + GUID hidguid; + DWORD length = 0; + HANDLE hiddev = NULL; + int idx = 0; + int devcnt = 0; + + HidD_GetHidGuid(&hidguid); + + HDEVINFO hdevinfo = SetupDiGetClassDevs(&hidguid, NULL, NULL, + DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); + + devdata.cbSize = sizeof(devdata); + + do + { + res = SetupDiEnumDeviceInterfaces(hdevinfo, 0, &hidguid, idx, &devdata); + + if (res != 0) + { + // A device has been detected, so get more information about it. + + // Get the Length value. + // The call will return with a "buffer too small" error which can be ignored. + + res = SetupDiGetDeviceInterfaceDetail(hdevinfo, &devdata, + NULL, 0, &length, NULL); + + // Allocate memory for the hDevInfo structure, using the returned Length. + + devdetaildata = (SP_DEVICE_INTERFACE_DETAIL_DATA*) new char[length]; + + // Set cbSize in the detailData structure. + + devdetaildata->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + // Call the function again, this time passing it the returned buffer size. + ULONG Required; + + res = SetupDiGetDeviceInterfaceDetail(hdevinfo, &devdata, + devdetaildata, length, + &Required, NULL); + if (devdetaildata->DevicePath) + // Open a handle to the device. + // To enable retrieving information about a system mouse or keyboard, + // don't request Read or Write access for this handle. + + hiddev = CreateFile(devdetaildata->DevicePath, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + + hidatt.Size = sizeof(hidatt); + + HidD_GetAttributes(hiddev, &hidatt); + + if (hidatt.VendorID == VendId && hidatt.ProductID == ProdId) + { + // Found our device + PHIDP_PREPARSED_DATA PreparsedData; + if (HidD_GetPreparsedData(hiddev, &PreparsedData)) + { + //HIDP_CAPS caps; + //NTSTATUS res = HidP_GetCaps(PreparsedData, &caps); + //if (res == HIDP_STATUS_SUCCESS) + { + } + bool res = Callback(hiddev); + if (res == false) + { + // Rejected + CloseHandle(hiddev); + hiddev = NULL; + } + else + devcnt++; + } + else + { + // Not our device. + CloseHandle(hiddev); + hiddev = NULL; + } + } + else + { + // Not our device. + CloseHandle(hiddev); + hiddev = NULL; + } + delete devdetaildata; + } + + idx++; + } while (res != 0); + + SetupDiDestroyDeviceInfoList(hdevinfo); + + return devcnt; +} + From a7667cdb5d42dad743ff47a204f743b025fd04b2 Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Mon, 14 Nov 2016 14:17:27 -0500 Subject: [PATCH 07/66] Adding loop when read/write is less than sector size --- include/diskio_flash.h | 28 +++++++++++++++++++++++++--- src/diskio_flash.cpp | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/include/diskio_flash.h b/include/diskio_flash.h index 2bbf0701..78300758 100755 --- a/include/diskio_flash.h +++ b/include/diskio_flash.h @@ -4,6 +4,10 @@ File : diskio_flash.h Author : Hoang Nguyen Hoan Aug. 30, 2016 Desc : Generic flash disk I/O driver class + NOTE : Most Flash devices work in MSB bit order + This implementation only support MSB. + Make sure that the Flash is configure + for MSB mode Copyright (c) 2016, Motsai, all rights reserved @@ -48,17 +52,35 @@ Modified by Date Description #define FLASH_STATUS_WIP (1<<0) // Write In Progress -typedef void (*FLASHDISKIO_INIT)(SerialIntrf *pInterf); +/** + * @brief FlashDiskIO_Init callback function + * This function is called at initialization to allow special + * initialization as require for example setting MSB mode which + * is required by this implementation + * + * @param DevNo : Device number or address used by the interface + * @param pInterf : Interface used to access the flash (SPI, I2C or whatever + * @return true - Success + * false - Failed. + */ +typedef bool (*FLASHDISKIO_INIT)(int DevNo, SerialIntrf *pInterf); typedef struct { - int DevNo; + int DevNo; // Device number or address for interface use uint64_t TotalSize; // Total Flash size in bytes uint32_t EraseSize; // Min erasable block size in byte uint32_t WriteSize; // Writable page size in bytes int AddrSize; // Address size in bytes - FLASHDISKIO_INIT FlashInit; // Flash initialization function pointer + FLASHDISKIO_INIT FlashInit; // Flash initialization function pointer. + // Set to NULL if not used } FLASHDISKIO_CFG; +/* + * NOTE : Most Flash devices work in MSB bit order. This implementation + * only supports MSB mode. Make sure that the Flash is configured + * for MSB mode. + * + */ class FlashDiskIO : public DiskIO { public: FlashDiskIO() : DiskIO() {} diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp index cfbd07eb..89aa0d9a 100644 --- a/src/diskio_flash.cpp +++ b/src/diskio_flash.cpp @@ -40,7 +40,10 @@ bool FlashDiskIO::Init(FLASHDISKIO_CFG &Cfg, SerialIntrf *pInterf, return false; if (Cfg.FlashInit) - Cfg.FlashInit(vpInterf); + { + if (Cfg.FlashInit(Cfg.DevNo, pInterf) == false) + return false; + } vDevNo = Cfg.DevNo; vEraseSize = Cfg.EraseSize; @@ -52,6 +55,7 @@ bool FlashDiskIO::Init(FLASHDISKIO_CFG &Cfg, SerialIntrf *pInterf, vAddrSize = Cfg.AddrSize; vpInterf = pInterf; + if (pCacheBlk && NbCacheBlk > 0) { SetCache(pCacheBlk, NbCacheBlk); @@ -147,21 +151,28 @@ bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) uint8_t d[4]; uint32_t addr = SectNo * DISKIO_SECT_SIZE; uint8_t *p = (uint8_t*)&addr; - int cnt = 0; + int cnt = DISKIO_SECT_SIZE; WaitReady(10000); d[0] = FLASH_CMD_READ; - d[1] = p[2]; - d[2] = p[1]; - d[3] = p[0]; - - vpInterf->StartRx(vDevNo); - vpInterf->TxData((uint8_t*)d, 4); - int l = vpInterf->RxData(pBuff, DISKIO_SECT_SIZE); - vpInterf->StopRx(); + while (cnt > 0) + { + d[1] = p[2]; + d[2] = p[1]; + d[3] = p[0]; + vpInterf->StartRx(vDevNo); + vpInterf->TxData((uint8_t*)d, 4); + int l = vpInterf->RxData(pBuff, DISKIO_SECT_SIZE); + vpInterf->StopRx(); + if (l <= 0) + return false; + cnt -= l; + addr += l; + pBuff += l; + } return true; } @@ -180,19 +191,20 @@ bool FlashDiskIO::SectWrite(uint32_t SectNo, uint8_t *pData) WriteEnable(); d[0] = FLASH_CMD_WRITE; - d[1] = p[2]; - d[2] = p[1]; - d[3] = p[0]; cnt = DISKIO_SECT_SIZE; while (cnt > 0) { + d[1] = p[2]; + d[2] = p[1]; + d[3] = p[0]; int l = min(cnt, vWriteSize); vpInterf->StartTx(vDevNo); vpInterf->TxData((uint8_t*)d, 4); l = vpInterf->TxData(pData, l); vpInterf->StopTx(); - + if (l <= 0) + false; cnt -= l; pData += l; addr += l; From 8b0d614585a7a15a4ee434a81931fc65955cdb9f Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Mon, 14 Nov 2016 14:39:15 -0500 Subject: [PATCH 08/66] Support variable address length --- src/diskio_flash.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp index 89aa0d9a..c1a7af0f 100644 --- a/src/diskio_flash.cpp +++ b/src/diskio_flash.cpp @@ -159,9 +159,8 @@ bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) while (cnt > 0) { - d[1] = p[2]; - d[2] = p[1]; - d[3] = p[0]; + for (int i = 1; i <= vAddrSize; i++) + d[i+1] = p[vAddrSize - i - 1]; vpInterf->StartRx(vDevNo); vpInterf->TxData((uint8_t*)d, 4); @@ -195,9 +194,9 @@ bool FlashDiskIO::SectWrite(uint32_t SectNo, uint8_t *pData) cnt = DISKIO_SECT_SIZE; while (cnt > 0) { - d[1] = p[2]; - d[2] = p[1]; - d[3] = p[0]; + for (int i = 1; i <= vAddrSize; i++) + d[i+1] = p[vAddrSize - i - 1]; + int l = min(cnt, vWriteSize); vpInterf->StartTx(vDevNo); vpInterf->TxData((uint8_t*)d, 4); From 7c21f535f091b720cce4ca66995dd25504cdc36e Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Mon, 14 Nov 2016 14:40:56 -0500 Subject: [PATCH 09/66] Increase array size for addressing --- src/diskio_flash.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp index c1a7af0f..4aff150b 100644 --- a/src/diskio_flash.cpp +++ b/src/diskio_flash.cpp @@ -148,7 +148,7 @@ void FlashDiskIO::EraseBlock(uint32_t BlkNo, int NbBlk) */ bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) { - uint8_t d[4]; + uint8_t d[9]; uint32_t addr = SectNo * DISKIO_SECT_SIZE; uint8_t *p = (uint8_t*)&addr; int cnt = DISKIO_SECT_SIZE; @@ -180,7 +180,7 @@ bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) */ bool FlashDiskIO::SectWrite(uint32_t SectNo, uint8_t *pData) { - uint8_t d[4]; + uint8_t d[9]; uint32_t addr = SectNo * DISKIO_SECT_SIZE; uint8_t *p = (uint8_t*)&addr; From c3d2c5c68143fa38b2b7226a55da9373313648ae Mon Sep 17 00:00:00 2001 From: souellet-ms Date: Tue, 15 Nov 2016 11:10:19 -0500 Subject: [PATCH 10/66] Fixed EHAL nRF52 project compilation. --- ARM/Nordic/nRF52/EHAL/.project | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ARM/Nordic/nRF52/EHAL/.project b/ARM/Nordic/nRF52/EHAL/.project index 3236107c..9481bcfc 100755 --- a/ARM/Nordic/nRF52/EHAL/.project +++ b/ARM/Nordic/nRF52/EHAL/.project @@ -230,6 +230,11 @@ 1 PARENT-4-PROJECT_LOC/src/crc.c + + src/diskio_flash.cpp + 1 + PARENT-4-PROJECT_LOC/src/diskio_flash.cpp + src/diskio_impl.cpp 1 From 825a13e1da0e361615be0aa70c391ae3ae50256b Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Tue, 15 Nov 2016 12:56:33 -0500 Subject: [PATCH 11/66] Fix address setup --- src/diskio_flash.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp index 4aff150b..ea14ba10 100644 --- a/src/diskio_flash.cpp +++ b/src/diskio_flash.cpp @@ -130,12 +130,12 @@ void FlashDiskIO::EraseBlock(uint32_t BlkNo, int NbBlk) WriteEnable(); WaitReady(); + d[0] = FLASH_CMD_BLOCK_ERASE; + for (int i = 0; i < NbBlk; i++) { - d[0] = FLASH_CMD_BLOCK_ERASE; - d[1] = p[2]; - d[2] = p[1]; - d[3] = p[0]; + for (int i = 1; i <= vAddrSize; i++) + d[i] = p[vAddrSize - i]; vpInterf->Tx(vDevNo, d, 4); BlkNo += vEraseSize; } @@ -153,14 +153,14 @@ bool FlashDiskIO::SectRead(uint32_t SectNo, uint8_t *pBuff) uint8_t *p = (uint8_t*)&addr; int cnt = DISKIO_SECT_SIZE; - WaitReady(10000); + WaitReady(100000); d[0] = FLASH_CMD_READ; while (cnt > 0) { for (int i = 1; i <= vAddrSize; i++) - d[i+1] = p[vAddrSize - i - 1]; + d[i] = p[vAddrSize - i]; vpInterf->StartRx(vDevNo); vpInterf->TxData((uint8_t*)d, 4); @@ -195,7 +195,7 @@ bool FlashDiskIO::SectWrite(uint32_t SectNo, uint8_t *pData) while (cnt > 0) { for (int i = 1; i <= vAddrSize; i++) - d[i+1] = p[vAddrSize - i - 1]; + d[i] = p[vAddrSize - i]; int l = min(cnt, vWriteSize); vpInterf->StartTx(vDevNo); From 8356457ea781e8c526175c2f56ab6318e09343bd Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Tue, 15 Nov 2016 17:06:42 -0500 Subject: [PATCH 12/66] Add manual select to SPI --- include/spi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/spi.h b/include/spi.h index ca61aa07..08f05941 100755 --- a/include/spi.h +++ b/include/spi.h @@ -96,6 +96,7 @@ typedef struct _SPI_Config { SPIDATABIT BitOrder; // Data bit ordering SPIDATAPHASE DataPhase; // Data Out Phase. SPICLKPOL ClkPol; // Clock Out Polarity. + bool bManSel; // Manual chip select int IntPrio; // Interrupt priority SERINTRFEVCB EvtCB; // Event callback } SPICFG; From 0f5055d72d577c48c7171fb882db4bc7dd1e1138 Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Tue, 15 Nov 2016 17:08:15 -0500 Subject: [PATCH 13/66] Add read id --- include/diskio_flash.h | 8 ++++++-- src/diskio_flash.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/include/diskio_flash.h b/include/diskio_flash.h index 78300758..9a075861 100755 --- a/include/diskio_flash.h +++ b/include/diskio_flash.h @@ -42,6 +42,7 @@ Modified by Date Description #include "diskio.h" #include "serialintrf.h" +#define FLASH_CMD_READID 0x9F #define FLASH_CMD_WRITE 0x2 #define FLASH_CMD_READ 0x3 #define FLASH_CMD_WRDISABLE 0x4 @@ -132,10 +133,13 @@ class FlashDiskIO : public DiskIO { */ virtual bool SectWrite(uint32_t SectNo, uint8_t *pData); + uint32_t ReadId(); + uint8_t ReadStatus(); + protected: void WriteDisable(); - bool WriteEnable(uint32_t Timeout = 10000); - bool WaitReady(uint32_t Timeout = 10000); + bool WriteEnable(uint32_t Timeout = 100000); + bool WaitReady(uint32_t Timeout = 100000); private: uint32_t vEraseSize; // Min erasable block size in byte diff --git a/src/diskio_flash.cpp b/src/diskio_flash.cpp index ea14ba10..b438a0c3 100644 --- a/src/diskio_flash.cpp +++ b/src/diskio_flash.cpp @@ -64,13 +64,43 @@ bool FlashDiskIO::Init(FLASHDISKIO_CFG &Cfg, SerialIntrf *pInterf, return true; } +uint32_t FlashDiskIO::ReadId() +{ + uint32_t id = -1; + uint8_t cmd; + + WaitReady(); + + cmd = FLASH_CMD_READID; + + vpInterf->StartRx(vDevNo); + vpInterf->TxData(&cmd, 1); + vpInterf->RxData((uint8_t*)&id, 4); + vpInterf->StopRx(); + + return id; +} + +uint8_t FlashDiskIO::ReadStatus() +{ + uint8_t d; + + d = FLASH_CMD_READSTATUS; + vpInterf->StartRx(vDevNo); + vpInterf->TxData(&d, 1); + vpInterf->RxData(&d, 1); + vpInterf->StopRx(); + + return d; +} + bool FlashDiskIO::WaitReady(uint32_t Timeout) { uint8_t d; do { d = FLASH_CMD_READSTATUS; - vpInterf->StartRx(0); + vpInterf->StartRx(vDevNo); vpInterf->TxData(&d, 1); vpInterf->RxData(&d, 1); vpInterf->StopRx(); From a56c526e596db07510176f85b712aac6938f3e5a Mon Sep 17 00:00:00 2001 From: Hoan Hoang Date: Tue, 15 Nov 2016 17:10:09 -0500 Subject: [PATCH 14/66] add diskio_impl.cpp to project --- ARM/Freescale/KL26xx/EHAL/.project | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ARM/Freescale/KL26xx/EHAL/.project b/ARM/Freescale/KL26xx/EHAL/.project index da54caab..65b2aaf9 100755 --- a/ARM/Freescale/KL26xx/EHAL/.project +++ b/ARM/Freescale/KL26xx/EHAL/.project @@ -45,6 +45,11 @@ 1 PARENT-4-PROJECT_LOC/src/crc.c + + src/diskio_flash.cpp + 1 + PARENT-4-PROJECT_LOC/src/diskio_flash.cpp + src/diskio_impl.cpp 1 @@ -70,6 +75,11 @@ 1 PARENT-4-PROJECT_LOC/src/ledmxfont.c + + src/prbs.c + 1 + PARENT-4-PROJECT_LOC/src/prbs.c + src/sdcard_impl.cpp 1 From f8dd0731666c9d7c5e4f08a7916e3a8df72c36fe Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Tue, 15 Nov 2016 21:09:05 -0500 Subject: [PATCH 15/66] generic muilti-platform uart example --- exemples/uart/uart_prbs_tx.cpp | 132 +++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 exemples/uart/uart_prbs_tx.cpp diff --git a/exemples/uart/uart_prbs_tx.cpp b/exemples/uart/uart_prbs_tx.cpp new file mode 100644 index 00000000..a9e64f39 --- /dev/null +++ b/exemples/uart/uart_prbs_tx.cpp @@ -0,0 +1,132 @@ +/*-------------------------------------------------------------------------- +File : uart_prbs_tx.cpp + +Author : Hoang Nguyen Hoan Aug. 31, 2016 + +Desc : UART PRBS transmit test + Demo code using EHAL library to do PRBS transmit test using UART + +Copyright (c) 2016, I-SYST inc., all rights reserved + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies, and none of the +names : I-SYST or its contributors may be used to endorse or +promote products derived from this software without specific prior written +permission. + +For info or contributing contact : hnhoan at i-syst dot com + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- +Modified by Date Description + +----------------------------------------------------------------------------*/ + +#include + +#include "iopincfg.h" +#include "uart.h" +#include "blueio_board.h" +#include "prbs.h" + +// This include contain i/o definition the board in use +#include "board.h" + +int nRFUartEvthandler(UARTDEV *pDev, UART_EVT EvtId, uint8_t *pBuffer, int BufferLen); + +#define FIFOSIZE CFIFO_MEMSIZE(256) + +uint8_t g_TxBuff[FIFOSIZE]; + +static IOPINCFG s_UartPins[] = { + {0, UART_RX_PIN, 0, IOPINDIR_INPUT, IOPINRES_NONE, IOPINTYPE_NORMAL}, // RX + {0, UART_TX_PIN, 0, IOPINDIR_OUTPUT, IOPINRES_NONE, IOPINTYPE_NORMAL}, // TX + {0, UART_CTS_PIN, 0, IOPINDIR_INPUT, IOPINRES_NONE, IOPINTYPE_NORMAL}, // CTS + {0, UART_RTS_PIN, 0, IOPINDIR_OUTPUT, IOPINRES_NONE, IOPINTYPE_NORMAL}, // RTS +}; + +// UART configuration data +const UARTCFG g_UartCfg = { + 0, + s_UartPins, + sizeof(s_UartPins) / sizeof(IOPINCFG), + 1000000, // Rate + 8, + UART_PARITY_NONE, + 1, // Stop bit + UART_FLWCTRL_NONE, + true, + 1, // use APP_IRQ_PRIORITY_LOW with Softdevice + nRFUartEvthandler, + 0, + NULL, + FIFOSIZE, + g_TxBuff, +}; + +#ifdef DEMO_C +// For C programming +UARTDEV g_UartDev; +#else +// For C++ object programming +// UART object instance +UART g_Uart; +#endif + +int nRFUartEvthandler(UARTDEV *pDev, UART_EVT EvtId, uint8_t *pBuffer, int BufferLen) +{ + int cnt = 0; + uint8_t buff[20]; + + switch (EvtId) + { + case UART_EVT_RXTIMEOUT: + case UART_EVT_RXDATA: + + break; + case UART_EVT_TXREADY: + break; + case UART_EVT_LINESTATE: + break; + } + + return cnt; +} + +int main() +{ + bool res; + +#ifdef DEMO_C + res = UARTInit(&g_UartDev, &g_UartCfg); +#else + res = g_Uart.Init(g_UartCfg); +#endif + + uint8_t d = 0xff; + + while(1) + { +#ifdef DEMO_C + if (UARTTx(&g_UartDev, &d, 1) > 0) +#else + if (g_Uart.Tx(&d, 1) > 0) +#endif + { + // If success send next code + d = Prbs8(d); + } + } + return 0; +} From 5aed98caf3c5908a1b4f15784d45cefb4ef77977 Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Tue, 15 Nov 2016 21:10:13 -0500 Subject: [PATCH 16/66] uart example for nRF51 --- .../nRF51/exemples/UartPrbsTest/.cproject | 2 +- .../nRF51/exemples/UartPrbsTest/.project | 7 + .../nRF51/exemples/UartPrbsTest/src/board.h | 29 ++++ .../nRF51/exemples/UartPrbsTest/src/main.cpp | 163 ------------------ 4 files changed, 37 insertions(+), 164 deletions(-) create mode 100644 ARM/Nordic/nRF51/exemples/UartPrbsTest/src/board.h delete mode 100644 ARM/Nordic/nRF51/exemples/UartPrbsTest/src/main.cpp diff --git a/ARM/Nordic/nRF51/exemples/UartPrbsTest/.cproject b/ARM/Nordic/nRF51/exemples/UartPrbsTest/.cproject index 56982cf4..8d8b4b74 100644 --- a/ARM/Nordic/nRF51/exemples/UartPrbsTest/.cproject +++ b/ARM/Nordic/nRF51/exemples/UartPrbsTest/.cproject @@ -14,7 +14,7 @@ - +